Skip to content

Commit

Permalink
Merge pull request #1604 from intuit/dry-run-hooks
Browse files Browse the repository at this point in the history
Run various hooks in a --dry-run
  • Loading branch information
hipstersmoothie authored Oct 26, 2020
2 parents ea4e0b5 + e2d4f11 commit 7ffc7df
Show file tree
Hide file tree
Showing 30 changed files with 1,507 additions and 880 deletions.
74 changes: 46 additions & 28 deletions docs/pages/docs/plugins/release-lifecycle-hooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,16 @@ This hooks is required for plugin that facilitate publishing.
Here `npm` does it for us.

```ts
auto.hooks.version.tapPromise("NPM", async (version: SEMVER) => {
auto.hooks.version.tapPromise("NPM", async ({ bump, dryRun, quiet }) => {
if (dryRun) {
const { version } = await loadPackageJson();
console.log(inc(version, bump));
return;
}

await execPromise("npm", [
"version",
version,
bump,
"-m",
"Bump version to: %s [skip ci]",
]);
Expand All @@ -137,6 +143,10 @@ _Examples:_
- In Core: Used to exit early is new commits are detected on the remote
- [brew](../generated/brew) - Create a new brew formula once the package a=has been versioned

```ts
auto.hooks.afterVersion.tapPromise("NPM", async ({ dryRun }) => {});
```

## publish

Publish the package to some package distributor.
Expand Down Expand Up @@ -177,12 +187,12 @@ You can either return a string value of just the version or an object containing
- `details` - The body of the details element

```ts
auto.hooks.canary.tapPromise(this.name, async (version, postFix) => {
auto.hooks.canary.tapPromise(this.name, async ({ bump, canaryIdentifier, dryRun, quiet }) => {
const lastRelease = await auto.git!.getLatestRelease();
const current = await auto.getCurrentVersion(lastRelease);
const nextVersion = inc(current, version as ReleaseType);
const nextVersion = inc(current, bump as ReleaseType);
const isScopedPackage = name.match(/@\S+\/\S+/);
const canaryVersion = `${nextVersion}-canary${postFix}`;
const canaryVersion = `${nextVersion}-canary${canaryIdentifier}`;

await execPromise("npm", ["version", canaryVersion, "--no-git-tag-version"]);
await execPromise("npm", ["publish", "--tag", "canary"]);
Expand Down Expand Up @@ -218,29 +228,37 @@ import {
getCurrentBranch,
} from "@auto-it/core";

auto.hooks.next.tapPromise(this.name, async (preReleaseVersions, bump) => {
const branch = getCurrentBranch() || "";
const lastRelease = await auto.git.getLatestRelease();
const current =
(await auto.git.getLastTagNotInBaseBranch(branch)) ||
(await auto.getCurrentVersion(lastRelease));
// Use this helper function to determine the next prerelease version
const prerelease = determineNextVersion(lastRelease, current, bump, "next");

// Create a new tag for it
await execPromise("git", [
"tag",
prerelease,
"-m",
`"Tag pre-release: ${prerelease}"`,
]);
// Push the tag
await execPromise("git", ["push", auto.remote, "--tags"]);

// Make sure to add the version to the list
preReleaseVersions.push(prerelease);
return preReleaseVersions;
});
auto.hooks.next.tapPromise(
this.name,
async (preReleaseVersions, bump, { dryRun }) => {
const branch = getCurrentBranch() || "";
const lastRelease = await auto.git.getLatestRelease();
const current =
(await auto.git.getLastTagNotInBaseBranch(branch)) ||
(await auto.getCurrentVersion(lastRelease));
// Use this helper function to determine the next prerelease version
const prerelease = determineNextVersion(lastRelease, current, bump, "next");

// Make sure to add the version to the list
preReleaseVersions.push(prerelease);

if (dryRun) {
return preReleaseVersions;
}

// Create a new tag for it
await execPromise("git", [
"tag",
prerelease,
"-m",
`"Tag pre-release: ${prerelease}"`,
]);
// Push the tag
await execPromise("git", ["push", auto.remote, "--tags"]);

return preReleaseVersions;
}
);
```

`next` version should not produce any of the following:
Expand Down
7 changes: 6 additions & 1 deletion docs/pages/docs/plugins/writing-publishing-plugins.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,15 @@ export default class GitTagPlugin implements IPlugin {
// ...
apply(auto: Auto) {
// ...
auto.hooks.version.tapPromise(this.name, async (version) => {
auto.hooks.version.tapPromise(this.name, async ({ bump }) => {
const lastTag = await getTag();
const newTag = inc(lastTag, version as ReleaseType);

if (newTag && dryRun) {
console.log(newTag);
return;
}

if (!newTag) {
auto.logger.log.info("No release found, doing nothing");
return;
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/__tests__/auto-canary-local.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@ test("shipit should publish canary in locally when not on master", async () => {
auto.hooks.canary.tap("test", canary);

await auto.shipit();
expect(canary).toHaveBeenCalledWith(SEMVER.patch, "canary.abc");
expect(canary).toHaveBeenCalledWith(
expect.objectContaining({
bump: SEMVER.patch,
canaryIdentifier: "canary.abc",
})
);
});
24 changes: 20 additions & 4 deletions packages/core/src/__tests__/auto-in-pr-ci.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ describe("canary in ci", () => {
jest.spyOn(auto.release!, "getCommits").mockImplementation();

await auto.canary();
expect(canary).toHaveBeenCalledWith(SEMVER.patch, "canary.123.1");
expect(canary).toHaveBeenCalledWith(
expect.objectContaining({
bump: SEMVER.patch,
canaryIdentifier: "canary.123.1",
})
);
});

test("comments on PR in CI", async () => {
Expand Down Expand Up @@ -117,7 +122,10 @@ describe("canary in ci", () => {
const addToPrBody = jest.fn();
auto.git!.addToPrBody = addToPrBody;
jest.spyOn(auto.release!, "getCommits").mockImplementation();
auto.hooks.canary.tap("test", (bump, post) => `1.2.4-${post}`);
auto.hooks.canary.tap(
"test",
({ canaryIdentifier }) => `1.2.4-${canaryIdentifier}`
);

await auto.canary({ pr: 123, build: 1, message: "false" });
expect(addToPrBody).not.toHaveBeenCalled();
Expand All @@ -135,7 +143,10 @@ describe("canary in ci", () => {
const addToPrBody = jest.fn();
auto.git!.addToPrBody = addToPrBody;
jest.spyOn(auto.release!, "getCommits").mockImplementation();
auto.hooks.canary.tap("test", (bump, post) => `1.2.4-${post}`);
auto.hooks.canary.tap(
"test",
({ canaryIdentifier }) => `1.2.4-${canaryIdentifier}`
);

const version = await auto.canary({ pr: 456, build: 5 });
expect(version!.newVersion).toBe("1.2.4-canary.456.5");
Expand All @@ -159,7 +170,12 @@ describe("shipit in ci", () => {
auto.hooks.canary.tap("test", canary);

await auto.shipit();
expect(canary).toHaveBeenCalledWith(SEMVER.patch, "canary.123.1");
expect(canary).toHaveBeenCalledWith(
expect.objectContaining({
bump: SEMVER.patch,
canaryIdentifier: "canary.123.1",
})
);
});
});

Expand Down
100 changes: 33 additions & 67 deletions packages/core/src/__tests__/auto.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -903,24 +903,6 @@ describe("Auto", () => {
expect(exit).toHaveBeenCalled();
});

test("doesn't try to overwrite releases", async () => {
const auto = new Auto({ ...defaults, plugins: [] });
auto.logger = dummyLog();
await auto.loadConfig();
auto.git!.getLatestRelease = () => Promise.resolve("1.2.3");
jest.spyOn(auto.release!, "generateReleaseNotes").mockImplementation();
auto.release!.getCommitsInRelease = () =>
Promise.resolve([makeCommitFromMsg("Test Commit")]);

auto.hooks.getPreviousVersion.tap("test", () => "1.2.3");
const afterRelease = jest.fn();
auto.hooks.afterRelease.tap("test", afterRelease);
jest.spyOn(auto.release!, "getCommits").mockImplementation();

await auto.runRelease();
expect(afterRelease).not.toHaveBeenCalled();
});

test("should publish with default options", async () => {
const auto = new Auto({ ...defaults, plugins: [] });
auto.logger = dummyLog();
Expand Down Expand Up @@ -1151,24 +1133,6 @@ describe("Auto", () => {
await expect(auto.canary()).rejects.not.toBeUndefined();
});

test("does not call canary hook in dry-run", async () => {
const auto = new Auto(defaults);
// @ts-ignore
auto.checkClean = () => Promise.resolve(true);

auto.logger = dummyLog();
await auto.loadConfig();
auto.git!.getLatestRelease = () => Promise.resolve("1.2.3");
auto.release!.getCommitsInRelease = () =>
Promise.resolve([makeCommitFromMsg("Test Commit")]);
const canary = jest.fn();
auto.hooks.canary.tap("test", canary);
jest.spyOn(auto.release!, "getCommits").mockImplementation();

await auto.canary({ pr: 123, build: 1, dryRun: true });
expect(canary).not.toHaveBeenCalled();
});

test("calls the canary hook with the pr info", async () => {
const auto = new Auto({ ...defaults, plugins: [] });
// @ts-ignore
Expand All @@ -1187,7 +1151,12 @@ describe("Auto", () => {
jest.spyOn(auto.release!, "getCommits").mockImplementation();

await auto.canary({ pr: 123, build: 1 });
expect(canary).toHaveBeenCalledWith(SEMVER.patch, "canary.123.1");
expect(canary).toHaveBeenCalledWith(
expect.objectContaining({
bump: SEMVER.patch,
canaryIdentifier: "canary.123.1",
})
);
expect(auto.git!.addToPrBody).toHaveBeenCalled();
});

Expand All @@ -1207,7 +1176,12 @@ describe("Auto", () => {
jest.spyOn(auto.release!, "getCommits").mockImplementation();

await auto.canary();
expect(canary).toHaveBeenCalledWith(SEMVER.patch, "canary.abc");
expect(canary).toHaveBeenCalledWith(
expect.objectContaining({
bump: SEMVER.patch,
canaryIdentifier: "canary.abc",
})
);
});

test("doesn't comment if there is an error", async () => {
Expand Down Expand Up @@ -1246,7 +1220,12 @@ describe("Auto", () => {
auto.hooks.canary.tap("test", canary);

await auto.canary();
expect(canary).toHaveBeenCalledWith(SEMVER.patch, "canary.abcd");
expect(canary).toHaveBeenCalledWith(
expect.objectContaining({
bump: SEMVER.patch,
canaryIdentifier: "canary.abcd",
})
);
});

test('should not publish when is present "skip-release" label', async () => {
Expand Down Expand Up @@ -1290,7 +1269,12 @@ describe("Auto", () => {
auto.hooks.canary.tap("test", canary);

await auto.canary({ force: true });
expect(canary).toHaveBeenCalledWith(SEMVER.patch, "canary.abcd");
expect(canary).toHaveBeenCalledWith(
expect.objectContaining({
bump: SEMVER.patch,
canaryIdentifier: "canary.abcd",
})
);
});
});

Expand All @@ -1304,29 +1288,6 @@ describe("Auto", () => {
await expect(auto.next({})).rejects.not.toBeUndefined();
});

test("does not call next hook in dry-run", async () => {
const auto = new Auto(defaults);

// @ts-ignore
auto.checkClean = () => Promise.resolve(true);
auto.logger = dummyLog();
await auto.loadConfig();
auto.remote = "origin";
auto.git!.getProject = () => Promise.resolve({ data: {} } as any);
auto.git!.getLatestRelease = () => Promise.resolve("1.2.3");
auto.release!.generateReleaseNotes = () => Promise.resolve("notes");
auto.git!.getLatestTagInBranch = () => Promise.resolve("1.2.3");
auto.release!.getCommitsInRelease = () =>
Promise.resolve([makeCommitFromMsg("Test Commit")]);

const next = jest.fn();
auto.hooks.next.tap("test", next);
jest.spyOn(auto.release!, "getCommits").mockImplementation();

await auto.next({ dryRun: true });
expect(next).not.toHaveBeenCalled();
});

test("calls the next hook with the release info", async () => {
const auto = new Auto({ ...defaults, plugins: [] });

Expand Down Expand Up @@ -1416,7 +1377,10 @@ describe("Auto", () => {
// @ts-ignore
auto.makeChangelog = () => Promise.resolve();
auto.git!.getLatestRelease = () => Promise.resolve("1.2.3");
jest.spyOn(auto.git!, "publish").mockImplementation();
auto.git!.publish = () =>
Promise.resolve({
data: { html_url: "https://github.com/my/repo/release" },
} as any);
jest.spyOn(auto.release!, "getCommitsInRelease").mockImplementation();
jest.spyOn(auto.release!, "generateReleaseNotes").mockImplementation();
jest.spyOn(auto.release!, "addToChangelog").mockImplementation();
Expand All @@ -1436,7 +1400,10 @@ describe("Auto", () => {
auto.remote = "https://github.com/intuit/auto";

auto.git!.getLatestRelease = () => Promise.resolve("1.2.3");
jest.spyOn(auto.git!, "publish").mockImplementation();
auto.git!.publish = () =>
Promise.resolve({
data: { html_url: "https://github.com/my/repo/release" },
} as any);
jest.spyOn(auto.release!, "getCommitsInRelease").mockImplementation();
jest.spyOn(auto.release!, "generateReleaseNotes").mockImplementation();
jest.spyOn(auto.release!, "addToChangelog").mockImplementation();
Expand Down Expand Up @@ -1497,8 +1464,7 @@ describe("Auto", () => {
jest.spyOn(auto.release!, "generateReleaseNotes").mockImplementation();
jest.spyOn(auto.release!, "addToChangelog").mockImplementation();
const spy = jest.fn();
auto.hooks.version.tap("test", spy);
auto.hooks.afterRelease.tap("test", spy);
auto.hooks.publish.tap("test", spy);

await auto.shipit({ dryRun: true });
expect(spy).not.toHaveBeenCalled();
Expand Down
Loading

0 comments on commit 7ffc7df

Please sign in to comment.