auto
Version:
CLI tools to help facilitate semantic versioning based on GitHub PR labels
552 lines (546 loc) • 19.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.commands = void 0;
const tslib_1 = require("tslib");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const command_line_application_1 = require("command-line-application");
const endent_1 = tslib_1.__importDefault(require("endent"));
const core_1 = require("@auto-it/core");
const p = chalk_1.default.hex("#870048");
const y = chalk_1.default.hex("#F1A60E");
const r = chalk_1.default.hex("#C5000B");
const g = chalk_1.default.hex("#888888");
// prettier-ignore
const logo = `
${y('_________')}
${p('/')}${y('\\ /')}${r('\\')} _______ _ _ _______ _____
${p('/')} ${y('\\_____/')} ${r('\\')} |_____| | | | | |
${p('/ /')} ${r('\\ \\')} | | |_____| | |_____|
${p('/___/')} \\▔▔\\ ${r(' \\___\\')}
${g('\\ \\')} \\_/ ${g('/ /')} ______ _______ _______ _______ _______ _______
${g('\\ \\')} ${g('/ /')} |_____/ |______ | |______ |_____| |______ |______
${g('\\ ▔▔▔▔▔ /')} | \\_ |______ |_____ |______ | | ______| |______
${g('\\ /')}
${g('▔▔▔▔▔▔▔▔▔ ')}
`.replace(/\\/g, '\\\\');
const version = {
name: "version",
alias: "V",
type: Boolean,
description: "Display auto's version",
group: "global",
};
const prerelease = {
name: "prerelease",
type: Boolean,
group: "main",
description: "Publish a prerelease on GitHub.",
config: true,
};
const onlyPublishWithReleaseLabel = {
name: "only-publish-with-release-label",
type: Boolean,
description: "Only bump version if 'release' label is on pull request",
group: "main",
};
const quiet = {
name: "quiet",
alias: "q",
type: Boolean,
description: "Print **only** the result of the command",
group: "global",
};
const defaultOptions = [
{
name: "verbose",
alias: "v",
type: Boolean,
description: "Show some more logs. Pass -vv for very verbose logs.",
group: "global",
multiple: true,
},
{
name: "repo",
type: String,
description: "The repo to set the status on. Defaults to looking in the package definition for the platform",
group: "global",
},
{
name: "owner",
type: String,
description: "The owner of the GitHub repo. Defaults to reading from the package definition for the platform",
group: "global",
},
{
name: "github-api",
type: String,
description: "GitHub API to use",
group: "global",
},
{
name: "plugins",
type: String,
multiple: true,
description: "Plugins to load auto with. (defaults to just npm)",
group: "global",
},
];
const baseBranch = {
name: "base-branch",
type: String,
description: "Branch to treat as the base branch",
group: "global",
};
const pr = {
name: "pr",
type: Number,
description: "The pull request the command should use. Detects PR number in CI",
group: "main",
};
const dryRun = {
name: "dry-run",
alias: "d",
type: Boolean,
description: "Report what command will do but do not actually do anything",
group: "main",
};
const noGitCommit = {
name: "no-git-commit",
type: Boolean,
description: "Do not commit changes",
group: "main",
};
const url = {
name: "url",
type: String,
description: "URL to associate with this status",
group: "main",
};
const noVersionPrefix = {
name: "no-version-prefix",
type: Boolean,
description: "Use the version as the tag without the 'v' prefix. WARNING: some plugins might need extra config to use this option (ex: npm)",
group: "main",
};
const name = {
name: "name",
type: String,
description: "Git name to commit with. Defaults to package definition for the platform",
group: "main",
};
const email = {
name: "email",
type: String,
description: "Git email to commit with. Defaults to package definition for the platform",
group: "main",
};
const context = {
name: "context",
type: String,
description: "A string label to differentiate this status from others",
group: "main",
};
const message = {
name: "message",
group: "main",
type: String,
alias: "m",
};
const changelogTitle = {
name: "title",
type: String,
group: "main",
description: "Override the title used in the addition to the CHANGELOG.md.",
};
const changelogCommitMessage = Object.assign(Object.assign({}, message), { description: "Message to commit the changelog with. Defaults to 'Update CHANGELOG.md [skip ci]'", config: true });
const noChangelog = {
name: "no-changelog",
type: Boolean,
group: "main",
description: "Skip creating the changelog",
config: true,
};
const force = {
name: "force",
type: Boolean,
group: "main",
config: true,
};
const useVersion = {
name: "use-version",
type: String,
group: "main",
description: "Version number to publish as. Defaults to reading from the package definition for the platform.",
};
const latestCommandArgs = [
name,
email,
onlyPublishWithReleaseLabel,
baseBranch,
dryRun,
noVersionPrefix,
prerelease,
changelogTitle,
changelogCommitMessage,
quiet,
noChangelog,
];
exports.commands = [
{
name: "init",
group: "Setup Command",
description: "Interactive setup for minimum working configuration.",
examples: ["{green $} auto init"],
},
{
name: "info",
group: "Setup Command",
description: "Determine the environment, check if auto is set up correctly, and list plugins.",
examples: ["{green $} auto info"],
options: [
{
name: "list-plugins",
type: Boolean,
description: "List the available plugins",
group: "main",
},
],
},
{
name: "create-labels",
group: "Setup Command",
description: "Create your project's labels on github. If labels exist it will update them.",
examples: ["{green $} auto create-labels"],
options: [dryRun],
},
{
name: "label",
group: "Pull Request Interaction Commands",
description: "Get the labels for a pull request. Doesn't do much, but the return value lets you write you own scripts based off of the PR labels!",
options: [
Object.assign(Object.assign({}, pr), { description: `${pr.description} (defaults to last merged PR)` }),
{
name: "exists",
type: String,
group: "main",
description: "Checks for existence of a specific label",
},
],
examples: ["{green $} auto label --pr 123"],
},
{
name: "comment",
group: "Pull Request Interaction Commands",
description: "Comment on a pull request with a markdown message. Each comment has a context, and each context only has one comment.",
require: [["message", "delete"]],
options: [
pr,
context,
{
name: "edit",
type: Boolean,
alias: "e",
group: "main",
description: "Edit old comment",
config: true,
},
{
name: "delete",
type: Boolean,
group: "main",
description: "Delete old comment",
config: true,
},
Object.assign(Object.assign({}, message), { description: "Message to post to comment" }),
dryRun,
],
examples: [
"{green $} auto comment --delete",
'{green $} auto comment --pr 123 --message "# Why you\'re wrong..."',
'{green $} auto comment --pr 123 --edit --message "This smells..." --context code-smell',
],
},
{
name: "pr-check",
group: "Pull Request Interaction Commands",
description: "Check that a pull request has a SemVer label and run all pr-check plugins.",
require: ["url"],
options: [
pr,
url,
dryRun,
Object.assign(Object.assign({}, context), { defaultValue: "ci/pr-check" }),
],
examples: ["{green $} auto pr-check --url http://your-ci.com/build/123"],
},
{
name: "pr-status",
group: "Pull Request Interaction Commands",
description: "Set the status on a PR commit",
require: ["state", "url", "description", "context"],
options: [
{
name: "sha",
type: String,
group: "main",
description: "Specify a custom git sha. Defaults to the HEAD for a git repo in the current repository",
},
Object.assign(Object.assign({}, pr), { description: "PR to set the status on. Detects PR number in CI" }),
url,
{
name: "state",
type: String,
group: "main",
description: "State of the PR. ['pending', 'success', 'error', 'failure']",
},
{
name: "description",
type: String,
group: "main",
description: "A description of the status",
},
{
name: "context",
type: String,
group: "main",
description: "A string label to differentiate this status from others",
},
dryRun,
],
examples: [
`{green $} auto pr-status \\\\ \n --state pending \\\\ \n --description "Build still running..." \\\\ \n --context build-check`,
],
},
{
name: "pr-body",
group: "Pull Request Interaction Commands",
description: "Update the body of a PR with a message. Appends to PR and will not overwrite user content. Each comment has a context, and each context only has one comment.",
require: ["message"],
options: [
pr,
context,
Object.assign(Object.assign({}, message), { description: "Message to post to PR body" }),
dryRun,
],
examples: [
"{green $} auto pr-body --delete",
'{green $} auto pr-body --pr 123 --comment "The new version is: 1.2.3"',
],
},
{
name: "version",
group: "Release Commands",
description: endent_1.default `
Calculate a semantic version bump for the given changes.
Requires all PRs to have labels for the change type.
If a PR does not have a label associated with it, it will default to \`patch\` or whatever you configure the default label to.
NOTE: This does not change the version of your project or anything in your repo. It just returns \`patch\`, \`minor\`, or \`major\`.
`,
options: [
onlyPublishWithReleaseLabel,
{
name: "from",
type: String,
group: "main",
description: "Git revision (tag, commit sha, ...) to calculate version bump from. Defaults to latest github release",
},
],
examples: [
{
desc: "Get the new version using the last release to head",
example: "{green $} auto version",
},
],
},
{
name: "changelog",
group: "Release Commands",
description: "Prepend release notes to `CHANGELOG.md`, create one if it doesn't exist, and commit the changes.",
options: [
dryRun,
noVersionPrefix,
name,
email,
{
name: "from",
type: String,
group: "main",
description: "Tag to start changelog generation on. Defaults to latest tag or if a prerelease the latest tag in the branch. Provide latest to override.",
},
{
name: "to",
type: String,
group: "main",
description: "Tag to end changelog generation on. Defaults to HEAD.",
},
changelogTitle,
changelogCommitMessage,
baseBranch,
quiet,
noGitCommit,
],
examples: [
{
desc: "Generate a changelog from the last release to head",
example: "{green $} auto changelog",
},
{
desc: "Generate a changelog across specific versions",
example: "{green $} auto changelog --from v0.20.1 --to v0.21.0",
},
],
},
{
name: "release",
group: "Release Commands",
description: endent_1.default `
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,
name,
email,
{
name: "from",
type: String,
group: "main",
description: "Tag to start changelog generation on. Defaults to latest tag or if a prerelease the latest tag in the branch. Provide latest to override.",
},
{
name: "to",
type: String,
group: "main",
description: "Git revision (tag, commit sha, ...) to end release notes at. Defaults to HEAD.",
},
useVersion,
baseBranch,
prerelease,
],
examples: [
{
desc: "Create a GitHub release",
example: "{green $} auto release",
},
{
desc: "Create a GitHub release using provided commit range and version",
example: "{green $} auto release --from v0.20.1 --to HEAD --use-version v0.21.0",
},
],
},
{
name: "shipit",
group: "Release Commands",
description: endent_1.default `
Context aware publishing.
1. call from base branch -> latest version released (LATEST)
2. call from prerelease branch -> prerelease version released (NEXT)
3. call from PR in CI -> canary version released (CANARY)
4. call locally when not on base/prerelease branch -> canary version released (CANARY)
`,
examples: ["{green $} auto shipit"],
options: [
...latestCommandArgs,
Object.assign(Object.assign({}, useVersion), { description: `${useVersion.description} Currently only supported for the **npm plugin**.` }),
{
name: "only-graduate-with-release-label",
type: Boolean,
defaultValue: false,
group: "main",
description: 'Make auto publish prerelease versions when merging to baseBranch. Only PRs merged with "release" label will generate a "latest" release. Only use this flag if you do not want to maintain a prerelease branch, and instead only want to use baseBranch.',
config: true,
},
],
},
{
name: "latest",
group: "Release Commands",
description: endent_1.default `
Run the full \`auto\` release pipeline. Force a release to latest and bypass \`shipit\` safeguards.
`,
examples: ["{green $} auto latest"],
options: latestCommandArgs,
},
{
name: "canary",
group: "Release Commands",
description: endent_1.default `
Make a canary release of the project. Useful on PRs. If ran locally, \`canary\` will release a canary version for your current git HEAD. This is ran automatically from "shipit".
1. In PR: 1.2.3-canary.123.0 + add version to PR body
2. Locally: 1.2.3-canary.1810cfd
`,
examples: [
"{green $} auto canary",
"{green $} auto canary --force",
"{green $} auto canary --pr 123 --build 5",
'{green $} auto canary --message "Install PR version: `yarn add -D my-project@%v`"',
"{green $} auto canary --message false",
],
options: [
dryRun,
Object.assign(Object.assign({}, pr), { description: "PR number to use to create the canary version. Detected in CI env" }),
{
name: "build",
type: String,
group: "main",
description: "Build number to use to create the canary version. Detected in CI env",
},
{
name: "target",
type: String,
group: "main",
defaultValue: "pr-body",
description: "How the canary version should be attached to a PR",
typeLabel: "pr-body | comment | status",
config: true,
},
Object.assign(Object.assign({}, message), { description: "Message to comment on PR with. Defaults to 'Published PR with canary version: %v'. Pass false to disable the comment", config: true }),
Object.assign(Object.assign({}, force), { description: "Force a next release, even if the last commit is marked to skip the release" }),
quiet,
],
},
{
name: "next",
group: "Release Commands",
description: endent_1.default `
Make a release for your "prerelease" release line. This is ran automatically by "shipit" in a prerelease branch.
1. Creates a prerelease on package management platform
2. Creates a "Pre Release" on GitHub releases page
3. If ran from a PR build in a CI, posts the prerelease's full releases notes and expected version of the prerelease
Calling the \`next\` command from a prerelease branch will publish a prerelease for just that branch, otherwise it will publish to the default prerelease branch.
`,
examples: ["{green $} auto next"],
options: [
dryRun,
Object.assign(Object.assign({}, message), { description: "The message used when attaching the prerelease version to a PR", config: true }),
Object.assign(Object.assign({}, force), { description: "Force a canary release, even if the PR is marked to skip the release" }),
quiet,
],
},
];
/** Parse the CLI args and return command + options provided. */
function parseArgs(testArgs) {
const mainOptions = command_line_application_1.app({
name: "auto",
logo,
description: "Generate releases based on semantic version labels on pull requests, and other pull request automation tools.",
commands: exports.commands,
options: [version, ...defaultOptions],
}, {
argv: testArgs,
});
if (!mainOptions) {
return [];
}
if (!mainOptions._command) {
if (mainOptions.version) {
const version = "11.1.6" || core_1.getAutoVersion();
console.log(`v${version}`);
}
return [];
}
return [mainOptions._command, mainOptions];
}
exports.default = parseArgs;
//# sourceMappingURL=parse-args.js.map
;