Skip to content

Commit

Permalink
feat: Skip tag creation if it already exists
Browse files Browse the repository at this point in the history
  • Loading branch information
pvdlg committed Dec 2, 2017
1 parent 21d811e commit edec102
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 24 deletions.
14 changes: 12 additions & 2 deletions lib/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,18 @@ module.exports = async (pluginConfig, {branch, repositoryUrl}, {version, gitHead
debug('release branch: %o', branch);
const ref = `refs/tags/${gitTag}`;

debug('Create git tag %o with commit %o', ref, gitHead);
await github.gitdata.createReference({owner, repo, ref, sha: gitHead});
try {
// Test if the tag already exists
await github.gitdata.getReference({owner, repo, ref: `tags/${gitTag}`});
} catch (err) {
// If the error is 404, the tag doesn't exist, otherwise it's an error
if (err.code !== 404) {
throw err;
}
debug('Create git tag %o with commit %o', ref, gitHead);
await github.gitdata.createReference({owner, repo, ref, sha: gitHead});
}

const {data: {id, html_url}} = await github.repos.createRelease(release); // eslint-disable-line camelcase
logger.log('Published Github release: %s', html_url);

Expand Down
16 changes: 10 additions & 6 deletions test/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,17 @@ test.serial('Publish a release with an array of assets', async t => {
const github = authenticate({githubToken})
.get(`/repos/${owner}/${repo}`)
.reply(200, {permissions: {push: true}})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply(404)
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({})
.post(`/repos/${owner}/${repo}/releases`, {
tag_name: nextRelease.gitTag,
target_commitish: options.branch,
name: nextRelease.gitTag,
body: nextRelease.notes,
})
.reply(200, {html_url: releaseUrl, id: releaseId})
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({});
.reply(200, {html_url: releaseUrl, id: releaseId});

const githubUpload = upload({githubToken})
.post(`/repos/${owner}/${repo}/releases/${releaseId}/assets?name=${escape('upload.txt')}`)
Expand Down Expand Up @@ -168,15 +170,17 @@ test.serial('Verify Github auth and release', async t => {
const github = authenticate({githubToken: process.env.GH_TOKEN})
.get(`/repos/${owner}/${repo}`)
.reply(200, {permissions: {push: true}})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply(404)
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({})
.post(`/repos/${owner}/${repo}/releases`, {
tag_name: nextRelease.gitTag,
target_commitish: options.branch,
name: nextRelease.gitTag,
body: nextRelease.notes,
})
.reply(200, {html_url: releaseUrl, id: releaseId})
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({});
.reply(200, {html_url: releaseUrl, id: releaseId});

const githubUpload = upload({githubToken: process.env.GH_TOKEN})
.post(`/repos/${owner}/${repo}/releases/${releaseId}/assets?name=${escape('upload.txt')}`)
Expand Down
86 changes: 70 additions & 16 deletions test/publish.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,43 @@ test.serial('Publish a release', async t => {
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;

const github = authenticate({githubToken})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply(404)
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({})
.post(`/repos/${owner}/${repo}/releases`, {
tag_name: nextRelease.gitTag,
target_commitish: options.branch,
name: nextRelease.gitTag,
body: nextRelease.notes,
})
.reply(200, {html_url: releaseUrl})
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({});
.reply(200, {html_url: releaseUrl});

await publish(pluginConfig, options, nextRelease, t.context.logger);

t.true(t.context.log.calledWith(match.string, releaseUrl));
t.true(github.isDone());
});

test.serial('Publish a release with an existing tag', async t => {
const owner = 'test_user';
const repo = 'test_repo';
const githubToken = 'github_token';
const pluginConfig = {githubToken};
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;

const github = authenticate({githubToken})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply({ref: `refs/tags/${nextRelease.gitTag}`, object: {sha: 'e23a1bd8d7240c1eb3287374956042ffbcadca84'}})
.post(`/repos/${owner}/${repo}/releases`, {
tag_name: nextRelease.gitTag,
target_commitish: options.branch,
name: nextRelease.gitTag,
body: nextRelease.notes,
})
.reply(200, {html_url: releaseUrl});

await publish(pluginConfig, options, nextRelease, t.context.logger);

Expand All @@ -74,15 +102,17 @@ test.serial('Publish a release with one asset', async t => {
githubToken: process.env.GH_TOKEN,
githubApiPathPrefix: process.env.GH_PREFIX,
})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply(404)
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({})
.post(`/repos/${owner}/${repo}/releases`, {
tag_name: nextRelease.gitTag,
target_commitish: options.branch,
name: nextRelease.gitTag,
body: nextRelease.notes,
})
.reply(200, {html_url: releaseUrl, id: releaseId})
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({});
.reply(200, {html_url: releaseUrl, id: releaseId});

const githubUpload = upload({githubUrl: process.env.GH_URL, githubToken: process.env.GH_TOKEN})
.post(`/repos/${owner}/${repo}/releases/${releaseId}/assets?name=${escape('upload.txt')}`)
Expand Down Expand Up @@ -115,15 +145,17 @@ test.serial('Publish a release with one asset and custom github url', async t =>
githubUrl: process.env.GITHUB_URL,
githubApiPathPrefix: process.env.GITHUB_PREFIX,
})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply(404)
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({})
.post(`/repos/${owner}/${repo}/releases`, {
tag_name: nextRelease.gitTag,
target_commitish: options.branch,
name: nextRelease.gitTag,
body: nextRelease.notes,
})
.reply(200, {html_url: releaseUrl, id: releaseId})
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({});
.reply(200, {html_url: releaseUrl, id: releaseId});

const githubUpload = upload({githubToken: process.env.GITHUB_TOKEN, githubUrl: process.env.GITHUB_URL})
.post(`/repos/${owner}/${repo}/releases/${releaseId}/assets?name=${escape('upload.txt')}`)
Expand Down Expand Up @@ -156,15 +188,17 @@ test.serial('Publish a release with an array of assets', async t => {
const releaseId = 1;

const github = authenticate({githubToken})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply(404)
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({})
.post(`/repos/${owner}/${repo}/releases`, {
tag_name: nextRelease.gitTag,
target_commitish: options.branch,
name: nextRelease.gitTag,
body: nextRelease.notes,
})
.reply(200, {html_url: releaseUrl, id: releaseId})
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({});
.reply(200, {html_url: releaseUrl, id: releaseId});

const githubUpload = upload({githubToken})
.post(`/repos/${owner}/${repo}/releases/${releaseId}/assets?name=${escape('upload.txt')}`)
Expand All @@ -185,7 +219,7 @@ test.serial('Publish a release with an array of assets', async t => {
t.true(githubUpload.isDone());
});

test.serial('Publish a release with an array of misconfigured assets', async t => {
test.serial('Publish a release with an array of missing assets', async t => {
const owner = 'test_user';
const repo = 'test_repo';
const githubToken = 'github_token';
Expand All @@ -199,15 +233,17 @@ test.serial('Publish a release with an array of misconfigured assets', async t =
const releaseId = 1;

const github = authenticate({githubToken})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply(404)
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({})
.post(`/repos/${owner}/${repo}/releases`, {
tag_name: nextRelease.gitTag,
target_commitish: options.branch,
name: nextRelease.gitTag,
body: nextRelease.notes,
})
.reply(200, {html_url: releaseUrl, id: releaseId})
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
.reply({});
.reply(200, {html_url: releaseUrl, id: releaseId});

await publish(pluginConfig, options, nextRelease, t.context.logger);

Expand All @@ -216,3 +252,21 @@ test.serial('Publish a release with an array of misconfigured assets', async t =
t.true(t.context.error.calledWith(match.string, 'test/fixtures'));
t.true(github.isDone());
});

test.serial('Throw Error if get tag call return an error other than 404', async t => {
const owner = 'test_user';
const repo = 'test_repo';
const githubToken = 'github_token';
const pluginConfig = {githubToken};
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};

const github = authenticate({githubToken})
.get(`/repos/${owner}/${repo}/git/refs/tags/${nextRelease.gitTag}`)
.reply(500);

const error = await t.throws(publish(pluginConfig, options, nextRelease, t.context.logger), Error);

t.is(error.code, 500);
t.true(github.isDone());
});

0 comments on commit edec102

Please sign in to comment.