diff --git a/packages/cli/src/parse-args.ts b/packages/cli/src/parse-args.ts index c4f4919fa..dcf927a8a 100644 --- a/packages/cli/src/parse-args.ts +++ b/packages/cli/src/parse-args.ts @@ -467,7 +467,11 @@ export const commands: AutoCommand[] = [ { name: "release", group: "Release Commands", - description: "Auto-generate a github release", + description: endent` + Create a GitHub release for a tag. Defaults to last tag in branch. + + > NOTE: The tag must already be pushed to GitHub. If it isn't GitHub will create a tag pointing to the "to" option value. + `, options: [ dryRun, noVersionPrefix, @@ -485,7 +489,7 @@ export const commands: AutoCommand[] = [ type: String, group: "main", description: - "Git revision (tag, commit sha, ...) to end release notes at. Defaults to HEAD", + "Git revision (tag, commit sha, ...) to end release notes at. Defaults to HEAD.", }, { name: "use-version", @@ -499,7 +503,12 @@ export const commands: AutoCommand[] = [ ], examples: [ "{green $} auto release", - "{green $} auto release --from v0.20.1 --use-version v0.21.0", + { + desc: + "This command can be used in isolation easily. This example will: tag the release version at 'to' and create a GitHub release changelog over the commits range", + example: + "{green $} auto release --from v0.20.1 --to HEAD --use-version v0.21.0", + }, ], }, { diff --git a/packages/core/src/__tests__/auto.test.ts b/packages/core/src/__tests__/auto.test.ts index 642d6e500..0fd28aed1 100644 --- a/packages/core/src/__tests__/auto.test.ts +++ b/packages/core/src/__tests__/auto.test.ts @@ -948,7 +948,8 @@ describe("Auto", () => { expect(auto.git!.publish).toHaveBeenCalledWith( "releaseNotes", "v1.2.4", - false + false, + "" ); expect(afterRelease).toHaveBeenCalledWith( expect.objectContaining({ @@ -958,6 +959,35 @@ describe("Auto", () => { ); }); + + test("should use --to commit target", async () => { + const auto = new Auto({ ...defaults, plugins: [] }); + auto.logger = dummyLog(); + await auto.loadConfig(); + auto.git!.getLatestRelease = () => Promise.resolve("1.2.3"); + + jest.spyOn(auto.git!, "publish").mockReturnValueOnce({ data: {} } as any); + jest + .spyOn(auto.release!, "generateReleaseNotes") + .mockImplementation(() => Promise.resolve("releaseNotes")); + auto.release!.getCommitsInRelease = () => + Promise.resolve([makeCommitFromMsg("Test Commit")]); + + auto.hooks.getPreviousVersion.tap("test", () => "1.2.4"); + const afterRelease = jest.fn(); + auto.hooks.afterRelease.tap("test", afterRelease); + jest.spyOn(auto.release!, "getCommits").mockImplementation(); + + await auto.runRelease({ to: 'abc'}); + + expect(auto.git!.publish).toHaveBeenCalledWith( + "releaseNotes", + "v1.2.4", + false, + "abc" + ); + }); + test("should publish to a tag", async () => { const auto = new Auto({ ...defaults, plugins: [] }); auto.logger = dummyLog(); @@ -1013,7 +1043,8 @@ describe("Auto", () => { expect(auto.git!.publish).toHaveBeenCalledWith( "releaseNotes", "v1.2.4", - true + true, + "" ); expect(afterRelease).toHaveBeenCalledWith( expect.objectContaining({ @@ -1052,7 +1083,8 @@ describe("Auto", () => { expect(auto.git!.publish).toHaveBeenCalledWith( "releaseNotes", "v1.2.4", - false + false, + "" ); expect(afterRelease).toHaveBeenCalledWith( expect.objectContaining({ @@ -1091,7 +1123,8 @@ describe("Auto", () => { expect(auto.git!.publish).toHaveBeenCalledWith( "releaseNotes", "v1.3.0", - false + false, + "" ); expect(afterRelease).toHaveBeenCalledWith( expect.objectContaining({ @@ -1130,7 +1163,8 @@ describe("Auto", () => { expect(auto.git!.publish).toHaveBeenCalledWith( "releaseNotes", "v1.2.3+1", - false + false, + "" ); expect(afterRelease).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/packages/core/src/auto.ts b/packages/core/src/auto.ts index b86559e59..a0fff348e 100644 --- a/packages/core/src/auto.ts +++ b/packages/core/src/auto.ts @@ -193,6 +193,8 @@ export interface IAutoHooks { DryRunOption & { /** Commit to start calculating the version from */ from: string; + /** Commit to end calculating the version from */ + to: string; /** The version being released */ newVersion: string; /** Whether the release being made is a prerelease */ @@ -551,7 +553,8 @@ export default class Auto { const release = await this.git!.publish( options.fullReleaseNotes, options.newVersion, - options.isPrerelease + options.isPrerelease, + options.to ); this.logger.log.info(release.data.html_url); @@ -1472,6 +1475,7 @@ export default class Auto { const release = await this.hooks.makeRelease.promise({ commits, from: lastTag, + to: await this.git.getSha(), isPrerelease: true, newVersion, fullReleaseNotes: releaseNotes, @@ -1983,6 +1987,7 @@ export default class Auto { const release = await this.hooks.makeRelease.promise({ dryRun, from: lastRelease, + to: to || (await this.git.getSha()), isPrerelease, newVersion, fullReleaseNotes: releaseNotes, diff --git a/packages/core/src/git.ts b/packages/core/src/git.ts index cdc3a59bd..758b838cb 100644 --- a/packages/core/src/git.ts +++ b/packages/core/src/git.ts @@ -845,13 +845,19 @@ export default class Git { } /** Create a release for the GitHub project */ - async publish(releaseNotes: string, tag: string, prerelease = false) { + async publish( + releaseNotes: string, + tag: string, + prerelease = false, + fallbackCommit?: string, + ) { this.logger.verbose.info("Creating release on GitHub for tag:", tag); const result = await this.github.repos.createRelease({ owner: this.options.owner, repo: this.options.repo, tag_name: tag, + target_commitish: fallbackCommit, name: tag, body: releaseNotes, prerelease,