Skip to content

Commit

Permalink
fix(version): Loosen --atomic fallback to catch incompatible CLI ve…
Browse files Browse the repository at this point in the history
…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 6f0e2bb
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
47 changes: 37 additions & 10 deletions commands/version/__tests__/git-push.test.js
Expand Up @@ -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
Expand All @@ -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/);
Expand Down
8 changes: 4 additions & 4 deletions commands/version/lib/git-push.js
Expand Up @@ -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);
}
Expand Down

0 comments on commit 6f0e2bb

Please sign in to comment.