Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next/Canary Support for Gradle #1842

Merged
merged 11 commits into from Mar 18, 2021
164 changes: 163 additions & 1 deletion plugins/gradle/__tests__/gradle.test.ts
Expand Up @@ -19,12 +19,22 @@ describe("Gradle Plugin", () => {
(version) => `v${version}`
);
const options: IGradleReleasePluginPluginOptions = {};
const logger = dummyLog();

beforeEach(() => {
exec.mockClear();
const plugin = new GradleReleasePlugin(options);
hooks = makeHooks();
plugin.apply({ hooks, logger: dummyLog(), prefixRelease } as Auto.Auto);
plugin.apply(({
hooks,
logger,
remote: "stubRemote",
prefixRelease,
git: {
getLastTagNotInBaseBranch: async () => undefined,
getLatestRelease: async () => "0.0.1",
},
getCurrentVersion: async () => "0.0.1" } as unknown) as Auto.Auto);
});

describe("getPreviousVersion", () => {
Expand Down Expand Up @@ -141,6 +151,158 @@ describe("Gradle Plugin", () => {
]);
});

test("should only log on dryRun - canary", async () => {
const properties = "version: 1.0.0";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();
exec.mockReturnValueOnce(properties).mockImplementation(spy);
const mockLog = jest.spyOn(logger.log, "info");

await hooks.canary.promise({ bump: Auto.SEMVER.patch, canaryIdentifier: "canary123" , dryRun: true});

expect(spy).toHaveBeenCalledTimes(0)
expect(mockLog).toHaveBeenCalledTimes(1)
});

test("should not increment version - canary", async () => {
const properties = "version: 1.0.0";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();
exec.mockReturnValueOnce(properties).mockImplementation(spy);

const canaryVersion = await hooks.canary.promise({ bump: Auto.SEMVER.patch, canaryIdentifier: "canary123" });

expect(canaryVersion).toBe("1.0.0-canary123")
});

test("should not increment version - canary w/ default snapshot", async () => {
const properties = "version: 1.0.0-SNAPSHOT";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();
exec.mockReturnValueOnce(properties).mockImplementation(spy);

const canaryVersion = await hooks.canary.promise({ bump: Auto.SEMVER.patch, canaryIdentifier: "canary123" });

expect(canaryVersion).toBe("1.0.0-canary123")
});

test("should publish if available - canary", async () => {
const properties = "publish: yes";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();
exec.mockReturnValueOnce(properties).mockImplementation(spy);

await hooks.canary.promise({ bump: Auto.SEMVER.patch, canaryIdentifier: "canary123" });

expect(spy).toHaveBeenCalledWith(expect.stringMatching("gradle"), [
"publish",
]);
});

test("should log warning if publish isn't available - canary", async () => {
const properties = "version: 1.0.0";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();
exec.mockReturnValueOnce(properties).mockImplementation(spy);
const mockLog = jest.spyOn(logger.log, "warn");

await hooks.canary.promise({ bump: Auto.SEMVER.patch, canaryIdentifier: "canary123" });

expect(mockLog).toHaveBeenCalledWith(expect.stringMatching("Publish task not found in gradle"));
});

test("do nothing on dryRun - canary", async () => {
const properties = "version: 1.0.0";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();
exec.mockReturnValueOnce(properties).mockImplementation(spy);

await hooks.next.promise([], { bump: Auto.SEMVER.minor, commits: [], fullReleaseNotes: "", releaseNotes: "", dryRun: true });

expect(spy).toHaveBeenCalledTimes(0)
});

test("version does not depend on project gradle properties - next", async () => {
await hooks.beforeRun.promise({} as any);

const nextVersion = await hooks.next.promise([], { bump: Auto.SEMVER.minor, commits: [], fullReleaseNotes: "", releaseNotes: "" });

expect(nextVersion[0]).toBe("0.1.0-next.0")
});

test("version does not depend on project gradle properties - next w/ default snapshot", async () => {
const properties = "version: 1.1.0-SNAPSHOT";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();

exec.mockReturnValueOnce(properties).mockImplementation(spy);

const nextVersion = await hooks.next.promise([], { bump: Auto.SEMVER.major, commits: [], fullReleaseNotes: "", releaseNotes: "" });

expect(nextVersion[0]).toBe("1.0.0-next.0")
});

test("should version release with snapshot suffix - next", async () => {
const properties = "this doesn't matter";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();

exec.mockReturnValueOnce(properties).mockImplementation(spy);

await hooks.next.promise([], { bump: Auto.SEMVER.major, commits: [], fullReleaseNotes: "", releaseNotes: "" });

expect(spy).toHaveBeenCalledWith(expect.stringMatching("gradle"), [
"release",
"-Prelease.useAutomaticVersion=true",
`-Prelease.newVersion=1.0.0-SNAPSHOT`,
"-x createReleaseTag",
"-x preTagCommit",
"-x commitNewVersion",
]);
});

test("should publish if available - next", async () => {
const properties = "publish: yes";
exec.mockReturnValueOnce(properties);
await hooks.beforeRun.promise({} as any);

const spy = jest.fn();

exec.mockReturnValueOnce(properties).mockImplementation(spy);

await hooks.next.promise([], { bump: Auto.SEMVER.major, commits: [], fullReleaseNotes: "", releaseNotes: "" });

expect(spy).toHaveBeenCalledWith(expect.stringMatching("gradle"), [
"publish",
]);
});

test("should log warning if publish isn't available - next", async () => {
await hooks.beforeRun.promise({} as any);

const mockLog = jest.spyOn(logger.log, "warn");

await hooks.next.promise([], { bump: Auto.SEMVER.major, commits: [], fullReleaseNotes: "", releaseNotes: "" });

expect(mockLog).toHaveBeenCalledWith(expect.stringMatching("Publish task not found in gradle"));
});

test("should version release - patch w/ custom snapshot", async () => {
const properties = `
version: 1.0.0.SNAP
Expand Down
113 changes: 105 additions & 8 deletions plugins/gradle/src/index.ts
Expand Up @@ -3,6 +3,9 @@ import {
IPlugin,
execPromise,
validatePluginConfiguration,
getCurrentBranch,
DEFAULT_PRERELEASE_BRANCHES,
determineNextVersion
} from "@auto-it/core";
import { IExtendedCommit } from "@auto-it/core/dist/log-parse";

Expand Down Expand Up @@ -103,6 +106,7 @@ export default class GradleReleasePluginPlugin implements IPlugin {
private readonly updateGradleVersion = async (
version: string,
commitMsg?: string,
commit = true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sentony93 Adding a new param in the middle breaks existing callers. See line #356. This breaks the actual release since it no longer commits the prepared version. You should reorder the new argument to the end to ensure that you don't break existing call-sites.

buildFlag = true
) => {
if (buildFlag) {
Expand All @@ -125,12 +129,14 @@ export default class GradleReleasePluginPlugin implements IPlugin {
]);
}

await execPromise("git", [
"commit",
"-am",
`"${commitMsg || `update version: ${version} [skip ci]"`}"`,
"--no-verify",
]);
if (commit) {
await execPromise("git", [
"commit",
"-am",
`"${commitMsg || `update version: ${version} [skip ci]"`}"`,
"--no-verify",
]);
}
};

/** Tap into auto plugin points. */
Expand Down Expand Up @@ -238,8 +244,99 @@ export default class GradleReleasePluginPlugin implements IPlugin {
]);
});

auto.hooks.afterShipIt.tapPromise(this.name, async ({ dryRun }) => {
if (!this.snapshotRelease || dryRun) {
auto.hooks.canary.tapPromise(
this.name,
async ({ dryRun, canaryIdentifier }) => {
const releaseVersion = await getVersion(
this.options.gradleCommand,
this.options.gradleOptions
);

const canaryVersion = `${releaseVersion}-${canaryIdentifier}`;

if (dryRun) {
auto.logger.log.info(`Would have published: ${canaryVersion}`);
return canaryVersion;
}

const { publish } = this.properties;

if (publish) {
await execPromise(this.options.gradleCommand, [
"publish",
...this.options.gradleOptions,
]);
} else {
auto.logger.log.warn(`Publish task not found in gradle`);
}
hipstersmoothie marked this conversation as resolved.
Show resolved Hide resolved

return canaryVersion;
}
);

auto.hooks.next.tapPromise(
this.name,
async (preReleaseVersions, { dryRun, bump }) => {
const prereleaseBranches =
auto.config?.prereleaseBranches ?? DEFAULT_PRERELEASE_BRANCHES;
const branch = getCurrentBranch() || "";
const prereleaseBranch = prereleaseBranches.includes(branch)
? branch
: prereleaseBranches[0];
const lastRelease = await auto.git?.getLatestRelease();
const current =
(await auto.git?.getLastTagNotInBaseBranch(prereleaseBranch)) ||
(await auto.getCurrentVersion(lastRelease ?? ""));
const nextVersion = determineNextVersion(
lastRelease ?? "",
current,
bump,
prereleaseBranch
);

if (nextVersion) {
preReleaseVersions.push(nextVersion);
}

const nextRegex = /(-next).*/;
const preReleaseSnapshotVersion = nextVersion.replace(nextRegex, defaultSnapshotSuffix)

if (dryRun) {
return preReleaseVersions;
}

await execPromise("git", [
"tag",
nextVersion ?? "",
"-m",
`"Tag pre-release: ${nextVersion}"`,
]);

await execPromise("git", ["push", auto.remote, branch, "--tags"]);

await this.updateGradleVersion(
preReleaseSnapshotVersion,
`Prerelease version: ${preReleaseSnapshotVersion} [skip ci]`,
false
);

const { publish } = this.properties;

if (publish) {
await execPromise(this.options.gradleCommand, [
"publish",
...this.options.gradleOptions,
]);
} else {
auto.logger.log.warn(`Publish task not found in gradle`);
}

return preReleaseVersions;
}
);

auto.hooks.afterShipIt.tapPromise(this.name, async ({ dryRun, context }) => {
if (!this.snapshotRelease || dryRun || context !== "latest") {
return;
}

Expand Down