-
Notifications
You must be signed in to change notification settings - Fork 208
Create new plugin : one-release-commit #2180
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
base: main
Are you sure you want to change the base?
Changes from all commits
77b5b04
c91b4ab
378a78a
d325b20
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -142,6 +142,17 @@ interface NextContext extends DryRunOption { | |
releaseNotes: string; | ||
} | ||
|
||
interface MakeReleaseContext extends DryRunOption { | ||
/** Is current context stand for a pre-release */ | ||
isPrerelease: boolean; | ||
/** Last release name like : "vx.y.z" */ | ||
lastRelease: string; | ||
/** Commit to calculate the release to */ | ||
to?: string; | ||
/** Version to release */ | ||
newVersion?: string; | ||
} | ||
|
||
type PublishResponse = RestEndpointMethodTypes["repos"]["createRelease"]["response"]; | ||
|
||
export interface IAutoHooks { | ||
|
@@ -253,7 +264,10 @@ export interface IAutoHooks { | |
] | ||
>; | ||
/** Ran after the package has been versioned. */ | ||
afterVersion: AsyncSeriesHook<[DryRunOption]>; | ||
afterVersion: AsyncSeriesHook<[DryRunOption & { | ||
/** The version to release, if any */ | ||
version?: string; | ||
}]>; | ||
/** Publish the package to some package distributor. You must push the tags to github! */ | ||
publish: AsyncSeriesHook< | ||
[ | ||
|
@@ -1214,7 +1228,13 @@ export default class Auto { | |
*/ | ||
async runRelease(options: IReleaseOptions = {}) { | ||
this.logger.verbose.info("Using command: 'release'"); | ||
await this.makeRelease(options); | ||
|
||
try { | ||
const releasedVersion = await this.makeReleaseContext(options); | ||
await this.makeRelease(releasedVersion); | ||
} catch (e) { | ||
this.logger.log.warn("Cannot proceed to release", e); | ||
} | ||
} | ||
|
||
/** Create a canary (or test) version of the project */ | ||
|
@@ -1738,11 +1758,6 @@ export default class Auto { | |
return; | ||
} | ||
|
||
const lastRelease = options.from || (await this.git.getLatestRelease()); | ||
const commitsInRelease = await this.release.getCommitsInRelease( | ||
lastRelease | ||
); | ||
|
||
await this.makeChangelog({ | ||
...options, | ||
quiet: undefined, | ||
|
@@ -1760,8 +1775,12 @@ export default class Auto { | |
dryRun: options.dryRun, | ||
quiet: options.quiet, | ||
}); | ||
|
||
// New new version must be computed, so make release context | ||
const releaseArgs = await this.makeReleaseContext(); | ||
|
||
this.logger.verbose.info("Calling after version hook"); | ||
await this.hooks.afterVersion.promise({ dryRun: options.dryRun }); | ||
await this.hooks.afterVersion.promise({ dryRun: options.dryRun, version: releaseArgs.newVersion }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OH I see why you do all of this rearranging. in the afterVersion hook if it's not a dry run it IS a release. We don't have to care about the return value of makeRelease. The undefined that it returns is for it's other usage. Here we know a release (and thus a version) has happened. You can revert all the changes to core and remove references in you plugin to version and it still all works! |
||
|
||
if (!options.dryRun) { | ||
this.logger.verbose.info("Calling publish hook"); | ||
|
@@ -1773,9 +1792,11 @@ export default class Auto { | |
await this.hooks.afterPublish.promise(); | ||
} | ||
|
||
const release = await this.makeRelease(releaseArgs); | ||
|
||
return { | ||
newVersion: await this.makeRelease(options), | ||
commitsInRelease, | ||
newVersion: release?.newVersion, | ||
commitsInRelease: release?.commitsInRelease || [], | ||
context: "latest", | ||
}; | ||
} | ||
|
@@ -1945,12 +1966,16 @@ export default class Auto { | |
await this.hooks.afterChangelog.promise(context); | ||
} | ||
|
||
/** Make a release over a range of commits */ | ||
private async makeRelease(args: IReleaseOptions = {}) { | ||
/** Retrieve the current releasing context */ | ||
private async makeReleaseContext(args: IReleaseOptions = {}): Promise<MakeReleaseContext> { | ||
const options = { ...this.getCommandDefault("release"), ...args }; | ||
const { dryRun, from, to, useVersion, prerelease = false } = options; | ||
const { | ||
dryRun, | ||
from, | ||
to, | ||
useVersion, prerelease = false } = options; | ||
|
||
if (!this.release || !this.git) { | ||
if (!this.git) { | ||
throw this.createErrorMessage(); | ||
} | ||
|
||
|
@@ -1961,24 +1986,26 @@ export default class Auto { | |
// tags indicates that something would definitely go wrong. | ||
if (err?.message.includes("No names found") && !args.dryRun) { | ||
this.logger.log.error( | ||
endent` | ||
endent` | ||
Could not find any tags in the local repository. Exiting early. | ||
|
||
The "release" command creates GitHub releases for tags that have already been created in your repo. | ||
|
||
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. | ||
`, | ||
"\n" | ||
"\n" | ||
); | ||
this.logger.verbose.error(err); | ||
return process.exit(1); | ||
process.exit(1); | ||
// Only for unit testing while process.exit is mocked | ||
throw err; | ||
} | ||
|
||
const isPrerelease = prerelease || this.inPrereleaseBranch(); | ||
let lastRelease = | ||
from || | ||
(isPrerelease && (await this.git.getPreviousTagInBranch())) || | ||
(await this.git.getLatestRelease()); | ||
from || | ||
(isPrerelease && (await this.git.getPreviousTagInBranch())) || | ||
(await this.git.getLatestRelease()); | ||
|
||
// Find base commit or latest release to generate the changelog to HEAD (new tag) | ||
this.logger.veryVerbose.info(`Using ${lastRelease} as previous release.`); | ||
|
@@ -1989,33 +2016,46 @@ export default class Auto { | |
|
||
this.logger.log.info('Current "Latest Release" on Github:', lastRelease); | ||
|
||
const rawVersion = | ||
useVersion || | ||
(isPrerelease && latestTag) || | ||
(await this.getCurrentVersion(lastRelease)) || | ||
latestTag; | ||
|
||
if (!rawVersion) { | ||
return { dryRun, to, lastRelease, newVersion: undefined, isPrerelease }; | ||
} | ||
|
||
const newVersion = parse(rawVersion) | ||
? this.prefixRelease(rawVersion) | ||
: rawVersion; | ||
|
||
return { dryRun, to, lastRelease, newVersion, isPrerelease }; | ||
} | ||
|
||
/** Make a release over a range of commits */ | ||
private async makeRelease(makeReleaseContext: MakeReleaseContext) { | ||
if (!this.release) { | ||
throw this.createErrorMessage(); | ||
} | ||
|
||
const { dryRun, to, lastRelease, newVersion, isPrerelease } = makeReleaseContext; | ||
const commitsInRelease = await this.release.getCommitsInRelease( | ||
lastRelease, | ||
to | ||
); | ||
|
||
const releaseNotes = await this.release.generateReleaseNotes( | ||
lastRelease, | ||
to, | ||
this.versionBump | ||
); | ||
|
||
this.logger.log.info(`Using release notes:\n${releaseNotes}`); | ||
|
||
const rawVersion = | ||
useVersion || | ||
(isPrerelease && latestTag) || | ||
(await this.getCurrentVersion(lastRelease)) || | ||
latestTag; | ||
|
||
if (!rawVersion) { | ||
if (!newVersion) { | ||
this.logger.log.error("Could not calculate next version from last tag."); | ||
return; | ||
} | ||
|
||
const newVersion = parse(rawVersion) | ||
? this.prefixRelease(rawVersion) | ||
: rawVersion; | ||
|
||
if ( | ||
!dryRun && | ||
parse(newVersion) && | ||
|
@@ -2031,8 +2071,8 @@ export default class Auto { | |
const release = await this.hooks.makeRelease.promise({ | ||
dryRun, | ||
from: lastRelease, | ||
to: to || (await this.git.getSha()), | ||
useVersion, | ||
to: to || (await this.git!.getSha()), | ||
useVersion: newVersion, | ||
isPrerelease, | ||
newVersion, | ||
fullReleaseNotes: releaseNotes, | ||
|
@@ -2049,7 +2089,7 @@ export default class Auto { | |
}); | ||
} | ||
|
||
return newVersion; | ||
return { newVersion, commitsInRelease }; | ||
} | ||
|
||
/** Check if `git status` is clean. */ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# One-Release-Commit Plugin | ||
|
||
Allow to create a single release commit | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Write a better description of why someone might want to use this plugin. |
||
|
||
## Installation | ||
|
||
This plugin is not included with the `auto` CLI installed via NPM. To install: | ||
|
||
```bash | ||
npm i --save-dev @auto-it/one-release-commit | ||
# or | ||
yarn add -D @auto-it/one-release-commit | ||
``` | ||
|
||
## Usage | ||
|
||
```json | ||
{ | ||
"plugins": [ | ||
[ | ||
"one-release-commit", | ||
{ | ||
// Release commit message | ||
"commitMessage": ":rocket: New release is on the way :rocket:" | ||
} | ||
] | ||
] | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is problematic I think. For the default usage this would included the commit for the changelog in the release notes since it would now be in the
commitsInRelease
. Could you make sure this doesn't augment the normal auto workflow?The changes below to for
makeRelaeaseContext
make sense and are good additions but the change in order has me worried.