diff --git a/commands/version/__tests__/git-push.test.js b/commands/version/__tests__/git-push.test.js index e49323ff27..3241a76ce7 100644 --- a/commands/version/__tests__/git-push.test.js +++ b/commands/version/__tests__/git-push.test.js @@ -47,12 +47,14 @@ test("remote that does not support --atomic", async () => { // the first time the command is executed, simulate remote error childProcess.exec.mockImplementationOnce(async () => { - throw new Error( - [ - "Command failed: git push --follow-tags --atomic --no-verify origin master", - "fatal: the receiving end does not support --atomic push", - ].join("\n") + const stderr = "fatal: the receiving end does not support --atomic push"; + const error = new Error( + ["Command failed: git push --follow-tags --atomic --no-verify origin master", stderr].join("\n") ); + + error.stderr = stderr; + + throw error; }); // this call should _not_ throw @@ -69,16 +71,41 @@ test("remote that does not support --atomic", async () => { expect(list).toMatch("v4.5.6"); }); +test("git cli that does not support --atomic", async () => { + const { cwd } = await cloneFixture("root-manifest-only"); + + await execa("git", ["commit", "--allow-empty", "-m", "change"], { cwd }); + await execa("git", ["tag", "v7.8.9", "-m", "v7.8.9"], { cwd }); + + // the first time the command is executed, simulate remote error + childProcess.exec.mockImplementationOnce(async () => { + const stderr = "error: unknown option `atomic'"; + const error = new Error( + ["Command failed: git push --follow-tags --atomic --no-verify origin master", stderr].join("\n") + ); + + error.stderr = stderr; + + throw error; + }); + + await gitPush("origin", "master", { cwd }); + + await expect(listRemoteTags(cwd)).resolves.toMatch("v7.8.9"); +}); + test("unexpected git error", async () => { const { cwd } = await cloneFixture("root-manifest-only"); childProcess.exec.mockImplementationOnce(async () => { - throw new Error( - [ - "Command failed: git push --follow-tags --atomic --no-verify origin master", - "fatal: some unexpected error", - ].join("\n") + const stderr = "fatal: some unexpected error"; + const error = new Error( + ["Command failed: git push --follow-tags --atomic --no-verify origin master", stderr].join("\n") ); + + error.stderr = stderr; + + throw error; }); await expect(gitPush("origin", "master", { cwd })).rejects.toThrowError(/some unexpected error/); diff --git a/commands/version/lib/git-push.js b/commands/version/lib/git-push.js index 09314548bc..b78a1091c5 100644 --- a/commands/version/lib/git-push.js +++ b/commands/version/lib/git-push.js @@ -12,12 +12,12 @@ function gitPush(remote, branch, opts) { .exec("git", ["push", "--follow-tags", "--no-verify", "--atomic", remote, branch], opts) .catch(error => { // @see https://github.com/sindresorhus/execa/blob/v1.0.0/index.js#L159-L179 - // the error message _should_ be on stderr, but I don't trust Windows to do anything right - if (/fatal:(.*)--atomic/.test(error.message)) { + // the error message _should_ be on stderr, and I don't care if Windows does it wrong + if (/atomic/.test(error.stderr)) { // --atomic is only supported in git >=2.4.0, which some crusty CI environments deem unnecessary to upgrade. // so let's try again without attempting to pass an option that is almost 5 years old as of this writing... - log.warn("gitPush", "failed to pass --atomic (unsupported by remote), attempting non-atomic push"); - log.verbose("", error.message); + log.warn("gitPush", "--atomic failed, attempting non-atomic push"); + log.warn("gitPush", error.stderr); return childProcess.exec("git", ["push", "--follow-tags", "--no-verify", remote, branch], opts); }