Skip to content

Commit

Permalink
fix(version): Add friendly error message when remote branch doesn't e…
Browse files Browse the repository at this point in the history
…xist (#1741)
  • Loading branch information
danielcondemarin authored and evocateur committed Nov 23, 2018
1 parent 96e329e commit cd34b48
Show file tree
Hide file tree
Showing 18 changed files with 79 additions and 0 deletions.
1 change: 1 addition & 0 deletions commands/publish/__tests__/publish-command.test.js
Expand Up @@ -8,6 +8,7 @@ jest.mock("../lib/get-npm-username");
jest.mock("../../version/lib/git-push");
jest.mock("../../version/lib/is-anything-committed");
jest.mock("../../version/lib/is-behind-upstream");
jest.mock("../../version/lib/remote-branch-exists");

// mocked or stubbed modules
const npmDistTag = require("@lerna/npm-dist-tag");
Expand Down
1 change: 1 addition & 0 deletions commands/publish/__tests__/publish-licenses.test.js
Expand Up @@ -9,6 +9,7 @@ jest.mock("../lib/remove-temp-licenses", () => jest.fn(() => Promise.resolve()))
jest.mock("../../version/lib/git-push");
jest.mock("../../version/lib/is-anything-committed");
jest.mock("../../version/lib/is-behind-upstream");
jest.mock("../../version/lib/remote-branch-exists");

const path = require("path");

Expand Down
Expand Up @@ -8,6 +8,7 @@ jest.mock("../lib/get-npm-username");
jest.mock("../../version/lib/git-push");
jest.mock("../../version/lib/is-anything-committed");
jest.mock("../../version/lib/is-behind-upstream");
jest.mock("../../version/lib/remote-branch-exists");

// mocked modules
const runLifecycle = require("@lerna/run-lifecycle");
Expand Down
Expand Up @@ -11,6 +11,7 @@ jest.mock("../lib/get-npm-username");
jest.mock("../../version/lib/git-push");
jest.mock("../../version/lib/is-anything-committed");
jest.mock("../../version/lib/is-behind-upstream");
jest.mock("../../version/lib/remote-branch-exists");

const fs = require("fs-extra");
const path = require("path");
Expand Down
1 change: 1 addition & 0 deletions commands/publish/__tests__/publish-tagging.test.js
Expand Up @@ -8,6 +8,7 @@ jest.mock("../lib/get-npm-username");
jest.mock("../../version/lib/git-push");
jest.mock("../../version/lib/is-anything-committed");
jest.mock("../../version/lib/is-behind-upstream");
jest.mock("../../version/lib/remote-branch-exists");

// mocked modules
const collectUpdates = require("@lerna/collect-updates");
Expand Down
16 changes: 16 additions & 0 deletions commands/version/__tests__/remote-branch-exists.test.js
@@ -0,0 +1,16 @@
"use strict";

const execa = require("execa");
const cloneFixture = require("@lerna-test/clone-fixture")(__dirname);
const remoteBranchExists = require("../lib/remote-branch-exists");

test("remoteBranchExists", async () => {
const { cwd } = await cloneFixture("root-manifest-only");

expect(remoteBranchExists("origin", "new-branch", { cwd })).toBe(false);

await execa("git", ["checkout", "-b", "new-branch"], { cwd });
await execa("git", ["push", "-u", "origin", "new-branch"], { cwd });

expect(remoteBranchExists("origin", "new-branch", { cwd })).toBe(true);
});
1 change: 1 addition & 0 deletions commands/version/__tests__/version-allow-branch.test.js
Expand Up @@ -4,6 +4,7 @@
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const path = require("path");
const execa = require("execa");
Expand Down
1 change: 1 addition & 0 deletions commands/version/__tests__/version-bump-prerelease.test.js
Expand Up @@ -8,6 +8,7 @@ jest.unmock("@lerna/conventional-commits");
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const fs = require("fs-extra");
const path = require("path");
Expand Down
1 change: 1 addition & 0 deletions commands/version/__tests__/version-bump.test.js
Expand Up @@ -4,6 +4,7 @@
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const path = require("path");

Expand Down
16 changes: 16 additions & 0 deletions commands/version/__tests__/version-command.test.js
Expand Up @@ -4,6 +4,7 @@
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const fs = require("fs-extra");
const path = require("path");
Expand All @@ -18,6 +19,7 @@ const checkWorkingTree = require("@lerna/check-working-tree");
const libPush = require("../lib/git-push");
const isAnythingCommitted = require("../lib/is-anything-committed");
const isBehindUpstream = require("../lib/is-behind-upstream");
const remoteBranchExists = require("../lib/remote-branch-exists");

// helpers
const loggingOutput = require("@lerna-test/logging-output");
Expand Down Expand Up @@ -82,6 +84,20 @@ describe("VersionCommand", () => {
}
});

it("throws an error when remote branch doesn't exist", async () => {
remoteBranchExists.mockReturnValueOnce(false);

const testDir = await initFixture("normal");

try {
await lernaVersion(testDir)();
} catch (err) {
expect(err.message).toMatch("doesn't exist in remote");
}

expect.assertions(1);
});

it("throws an error when uncommitted changes are present", async () => {
checkWorkingTree.mockImplementationOnce(() => {
throw new Error("uncommitted");
Expand Down
Expand Up @@ -4,6 +4,7 @@
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const path = require("path");
const semver = require("semver");
Expand Down
Expand Up @@ -4,6 +4,7 @@
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const path = require("path");

Expand Down
1 change: 1 addition & 0 deletions commands/version/__tests__/version-ignore-changes.test.js
Expand Up @@ -7,6 +7,7 @@ jest.unmock("@lerna/collect-updates");
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const fs = require("fs-extra");
const path = require("path");
Expand Down
Expand Up @@ -4,6 +4,7 @@
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const path = require("path");

Expand Down
1 change: 1 addition & 0 deletions commands/version/__tests__/version-message.test.js
Expand Up @@ -4,6 +4,7 @@
jest.mock("../lib/git-push");
jest.mock("../lib/is-anything-committed");
jest.mock("../lib/is-behind-upstream");
jest.mock("../lib/remote-branch-exists");

const path = require("path");

Expand Down
11 changes: 11 additions & 0 deletions commands/version/index.js
Expand Up @@ -26,6 +26,7 @@ const gitCommit = require("./lib/git-commit");
const gitPush = require("./lib/git-push");
const gitTag = require("./lib/git-tag");
const isBehindUpstream = require("./lib/is-behind-upstream");
const remoteBranchExists = require("./lib/remote-branch-exists");
const isBreakingChange = require("./lib/is-breaking-change");
const isAnythingCommitted = require("./lib/is-anything-committed");
const makePromptVersion = require("./lib/prompt-version");
Expand Down Expand Up @@ -90,6 +91,16 @@ class VersionCommand extends Command {
throw new ValidationError("ENOGIT", "Detached git HEAD, please checkout a branch to choose versions.");
}

if (this.pushToRemote && !remoteBranchExists(this.gitRemote, this.currentBranch, this.execOpts)) {
throw new ValidationError(
"EMISSREMOTEBRANCH",
dedent`
Branch '${this.currentBranch}' doesn't exist in remote '${this.gitRemote}'.
If this is a new branch, please make sure you push it to the remote first.
`
);
}

if (
this.options.allowBranch &&
![].concat(this.options.allowBranch).some(x => minimatch(this.currentBranch, x))
Expand Down
4 changes: 4 additions & 0 deletions commands/version/lib/__mocks__/remote-branch-exists.js
@@ -0,0 +1,4 @@
"use strict";

// to mock user modules, you _must_ call `jest.mock('./path/to/module')`
module.exports = jest.fn(() => true);
19 changes: 19 additions & 0 deletions commands/version/lib/remote-branch-exists.js
@@ -0,0 +1,19 @@
"use strict";

const log = require("npmlog");
const childProcess = require("@lerna/child-process");

module.exports = remoteBranchExists;

function remoteBranchExists(gitRemote, branch, opts) {
log.silly("remoteBranchExists");

const remoteBranch = `${gitRemote}/${branch}`;

try {
childProcess.execSync("git", ["show-ref", "--verify", `refs/remotes/${remoteBranch}`], opts);
return true;
} catch (e) {
return false;
}
}

0 comments on commit cd34b48

Please sign in to comment.