Skip to content

Commit 77b5b04

Browse files
committed
refactor(core): split release creation in two steps
First step create a release context (from release, to, newVersion) Second step use this information to really make the release
1 parent 27e99ba commit 77b5b04

File tree

1 file changed

+71
-34
lines changed

1 file changed

+71
-34
lines changed

packages/core/src/auto.ts

Lines changed: 71 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,17 @@ interface NextContext extends DryRunOption {
142142
releaseNotes: string;
143143
}
144144

145+
interface MakeReleaseContext extends DryRunOption {
146+
/** Is current context stand for a pre-release */
147+
isPrerelease: boolean;
148+
/** Last release name like : "vx.y.z" */
149+
lastRelease: string;
150+
/** Commit to calculate the release to */
151+
to?: string;
152+
/** Version to release */
153+
newVersion?: string;
154+
}
155+
145156
type PublishResponse = RestEndpointMethodTypes["repos"]["createRelease"]["response"];
146157

147158
export interface IAutoHooks {
@@ -1214,7 +1225,13 @@ export default class Auto {
12141225
*/
12151226
async runRelease(options: IReleaseOptions = {}) {
12161227
this.logger.verbose.info("Using command: 'release'");
1217-
await this.makeRelease(options);
1228+
1229+
try {
1230+
const releasedVersion = await this.makeReleaseContext(options);
1231+
await this.makeRelease(releasedVersion);
1232+
} catch (e) {
1233+
this.logger.log.warn("Cannot proceed to release", e);
1234+
}
12181235
}
12191236

12201237
/** Create a canary (or test) version of the project */
@@ -1738,11 +1755,6 @@ export default class Auto {
17381755
return;
17391756
}
17401757

1741-
const lastRelease = options.from || (await this.git.getLatestRelease());
1742-
const commitsInRelease = await this.release.getCommitsInRelease(
1743-
lastRelease
1744-
);
1745-
17461758
await this.makeChangelog({
17471759
...options,
17481760
quiet: undefined,
@@ -1760,6 +1772,10 @@ export default class Auto {
17601772
dryRun: options.dryRun,
17611773
quiet: options.quiet,
17621774
});
1775+
1776+
// New new version must be computed, so make release context
1777+
const releaseArgs = await this.makeReleaseContext();
1778+
17631779
this.logger.verbose.info("Calling after version hook");
17641780
await this.hooks.afterVersion.promise({ dryRun: options.dryRun });
17651781

@@ -1773,9 +1789,11 @@ export default class Auto {
17731789
await this.hooks.afterPublish.promise();
17741790
}
17751791

1792+
const release = await this.makeRelease(releaseArgs);
1793+
17761794
return {
1777-
newVersion: await this.makeRelease(options),
1778-
commitsInRelease,
1795+
newVersion: release?.newVersion,
1796+
commitsInRelease: release?.commitsInRelease || [],
17791797
context: "latest",
17801798
};
17811799
}
@@ -1945,12 +1963,16 @@ export default class Auto {
19451963
await this.hooks.afterChangelog.promise(context);
19461964
}
19471965

1948-
/** Make a release over a range of commits */
1949-
private async makeRelease(args: IReleaseOptions = {}) {
1966+
/** Retrieve the current releasing context */
1967+
private async makeReleaseContext(args: IReleaseOptions = {}): Promise<MakeReleaseContext> {
19501968
const options = { ...this.getCommandDefault("release"), ...args };
1951-
const { dryRun, from, to, useVersion, prerelease = false } = options;
1969+
const {
1970+
dryRun,
1971+
from,
1972+
to,
1973+
useVersion, prerelease = false } = options;
19521974

1953-
if (!this.release || !this.git) {
1975+
if (!this.git) {
19541976
throw this.createErrorMessage();
19551977
}
19561978

@@ -1961,24 +1983,26 @@ export default class Auto {
19611983
// tags indicates that something would definitely go wrong.
19621984
if (err?.message.includes("No names found") && !args.dryRun) {
19631985
this.logger.log.error(
1964-
endent`
1986+
endent`
19651987
Could not find any tags in the local repository. Exiting early.
19661988
19671989
The "release" command creates GitHub releases for tags that have already been created in your repo.
19681990
19691991
If there are no tags there is nothing to release. If you don't use "shipit" ensure you tag your releases with the new version number.
19701992
`,
1971-
"\n"
1993+
"\n"
19721994
);
19731995
this.logger.verbose.error(err);
1974-
return process.exit(1);
1996+
process.exit(1);
1997+
// Only for unit testing while process.exit is mocked
1998+
throw err;
19751999
}
19762000

19772001
const isPrerelease = prerelease || this.inPrereleaseBranch();
19782002
let lastRelease =
1979-
from ||
1980-
(isPrerelease && (await this.git.getPreviousTagInBranch())) ||
1981-
(await this.git.getLatestRelease());
2003+
from ||
2004+
(isPrerelease && (await this.git.getPreviousTagInBranch())) ||
2005+
(await this.git.getLatestRelease());
19822006

19832007
// Find base commit or latest release to generate the changelog to HEAD (new tag)
19842008
this.logger.veryVerbose.info(`Using ${lastRelease} as previous release.`);
@@ -1989,33 +2013,46 @@ export default class Auto {
19892013

19902014
this.logger.log.info('Current "Latest Release" on Github:', lastRelease);
19912015

2016+
const rawVersion =
2017+
useVersion ||
2018+
(isPrerelease && latestTag) ||
2019+
(await this.getCurrentVersion(lastRelease)) ||
2020+
latestTag;
2021+
2022+
if (!rawVersion) {
2023+
return { dryRun, to, lastRelease, newVersion: undefined, isPrerelease };
2024+
}
2025+
2026+
const newVersion = parse(rawVersion)
2027+
? this.prefixRelease(rawVersion)
2028+
: rawVersion;
2029+
2030+
return { dryRun, to, lastRelease, newVersion, isPrerelease };
2031+
}
2032+
2033+
/** Make a release over a range of commits */
2034+
private async makeRelease(makeReleaseContext: MakeReleaseContext) {
2035+
if (!this.release) {
2036+
throw this.createErrorMessage();
2037+
}
2038+
2039+
const { dryRun, to, lastRelease, newVersion, isPrerelease } = makeReleaseContext;
19922040
const commitsInRelease = await this.release.getCommitsInRelease(
19932041
lastRelease,
19942042
to
19952043
);
2044+
19962045
const releaseNotes = await this.release.generateReleaseNotes(
19972046
lastRelease,
19982047
to,
19992048
this.versionBump
20002049
);
20012050

2002-
this.logger.log.info(`Using release notes:\n${releaseNotes}`);
2003-
2004-
const rawVersion =
2005-
useVersion ||
2006-
(isPrerelease && latestTag) ||
2007-
(await this.getCurrentVersion(lastRelease)) ||
2008-
latestTag;
2009-
2010-
if (!rawVersion) {
2051+
if (!newVersion) {
20112052
this.logger.log.error("Could not calculate next version from last tag.");
20122053
return;
20132054
}
20142055

2015-
const newVersion = parse(rawVersion)
2016-
? this.prefixRelease(rawVersion)
2017-
: rawVersion;
2018-
20192056
if (
20202057
!dryRun &&
20212058
parse(newVersion) &&
@@ -2031,8 +2068,8 @@ export default class Auto {
20312068
const release = await this.hooks.makeRelease.promise({
20322069
dryRun,
20332070
from: lastRelease,
2034-
to: to || (await this.git.getSha()),
2035-
useVersion,
2071+
to: to || (await this.git!.getSha()),
2072+
useVersion: newVersion,
20362073
isPrerelease,
20372074
newVersion,
20382075
fullReleaseNotes: releaseNotes,
@@ -2049,7 +2086,7 @@ export default class Auto {
20492086
});
20502087
}
20512088

2052-
return newVersion;
2089+
return { newVersion, commitsInRelease };
20532090
}
20542091

20552092
/** Check if `git status` is clean. */

0 commit comments

Comments
 (0)