Skip to content
Permalink
Browse files

fix(version): Loosen `--atomic` fallback to catch incompatible CLI ve…

…rsions

The previous check was only matching incompatible remotes, not local CLIs.

Fixes #2400
  • Loading branch information
evocateur committed Jan 2, 2020
1 parent 4e5abe1 commit 6f0e2bb1b033b0579910cedcf0be84f1474c1580
Showing with 41 additions and 14 deletions.
  1. +37 −10 commands/version/__tests__/git-push.test.js
  2. +4 −4 commands/version/lib/git-push.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/);
@@ -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);
}

0 comments on commit 6f0e2bb

Please sign in to comment.
You can’t perform that action at this time.