diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..b6a7d89c --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +16 diff --git a/lib/plugin/git/Git.js b/lib/plugin/git/Git.js index a9c1acf5..a6b5992f 100644 --- a/lib/plugin/git/Git.js +++ b/lib/plugin/git/Git.js @@ -56,8 +56,11 @@ class Git extends GitBase { const { tagName } = this.config.getContext(); const { isCommitted, isTagged } = this.getContext(); if (isTagged) { + this.log.info(`Deleting local tag ${tagName}`); this.exec(`git tag --delete ${tagName}`); } + + this.log.info(`Resetting local changes made`); this.exec(`git reset --hard HEAD${isCommitted ? '~1' : ''}`); } @@ -207,9 +210,23 @@ class Git extends GitBase { async push({ args = this.options.pushArgs } = {}) { const { pushRepo } = this.options; const upstreamArgs = await this.getUpstreamArgs(pushRepo); - const push = await this.exec(['git', 'push', ...fixArgs(args), ...upstreamArgs]); - this.disableRollback(); - return push; + try { + const push = await this.exec(['git', 'push', ...fixArgs(args), ...upstreamArgs]); + this.disableRollback(); + return push; + } catch (error) { + await this.rollbackTagPush(); + throw error; + } + } + + async rollbackTagPush() { + const { isTagged } = this.getContext(); + if (isTagged) { + const { tagName } = this.config.getContext(); + this.log.info(`Rolling back remote tag push ${tagName}`); + await this.exec(`git push origin --delete ${tagName}`); + } } afterRelease() { diff --git a/test/git.js b/test/git.js index 898a94dc..6d43a898 100644 --- a/test/git.js +++ b/test/git.js @@ -298,6 +298,35 @@ test.serial('should roll back when cancelled', async t => { t.is(exec.args[12][0], 'git reset --hard HEAD~1'); }); +test.serial('should remove remote tag when push to branch failed', async t => { + sh.exec('git init'); + sh.exec(`git remote add origin file://foo`); + const version = '1.2.3'; + gitAdd(`{"version":"${version}"}`, 'package.json', 'Add package.json'); + const options = { git: { requireCleanWorkingDir: true, commit: true, tag: true, tagName: 'v${version}' } }; + const gitClient = factory(Git, { options }); + const exec = sinon.spy(gitClient.shell, 'execFormattedCommand'); + sh.exec(`git push`); + sh.exec(`git checkout HEAD~1`); + gitAdd('line', 'file', 'Add file'); + + await gitClient.init(); + + sh.exec('npm --no-git-tag-version version patch'); + + gitClient.bump('1.2.4'); + await gitClient.beforeRelease(); + await gitClient.stage('package.json'); + await gitClient.commit({ message: 'Add this' }); + await gitClient.tag(); + try { + await gitClient.push(); + } catch (e) { + // push would fail with an error since HEAD is behind origin + } + t.is(exec.args[15][0], 'git push origin --delete v1.2.4'); +}); + test.serial('should not touch existing history when rolling back', async t => { sh.exec('git init'); const version = '1.2.3';