1 | #!/usr/bin/env node
|
2 |
|
3 | import * as chalk from 'chalk';
|
4 | import * as yargsParser from 'yargs-parser';
|
5 |
|
6 | import * as AutoPublishIfApplicable from './commands/internal/auto-publish-if-applicable';
|
7 | import * as CommitAndTagVersion from './commands/commit-and-tag-version';
|
8 | import * as CopyAndCommitVersionForSubpackage from './commands/copy-and-commit-version-for-subpackage';
|
9 | import * as CreateChangelog from './commands/internal/create-changelog';
|
10 | import * as CreateReleaseAnnouncement from './commands/internal/create-release-announcement';
|
11 | import * as FailOnPreVersionDependencies from './commands/fail-on-pre-version-dependencies';
|
12 | import * as NpmInstallOnly from './commands/npm-install-only';
|
13 | import * as PrepareVersion from './commands/prepare-version';
|
14 | import * as PublishNpmPackage from './commands/publish-npm-package';
|
15 | import * as SetupGitAndNpmConnections from './commands/internal/setup-git-and-npm-connections';
|
16 | import * as UpdateGithubRelease from './commands/update-github-release';
|
17 | import * as UpgradeDependenciesWithPreVersions from './commands/upgrade-dependencies-with-pre-versions';
|
18 | import * as PublishReleasenotesOnSlack from './commands/publish-releasenotes-on-slack';
|
19 | import * as GetVersion from './commands/get-version';
|
20 | import * as SetVersion from './commands/set-version';
|
21 | import * as IsNugetPackagePublished from './legacy/is-nuget-package-published';
|
22 | import * as ReplaceDistTagsWithRealVersions from './commands/replace-dist-tags-with-real-versions';
|
23 |
|
24 | import { getGitBranch } from './git/git';
|
25 | import { PRIMARY_BRANCHES } from './versions/increment_version';
|
26 | import { PACKAGE_MODE_DOTNET, PACKAGE_MODE_NODE, PACKAGE_MODE_PYTHON } from './contracts/modes';
|
27 |
|
28 | const COMMAND_HANDLERS = {
|
29 | 'commit-and-tag-version': CommitAndTagVersion,
|
30 | 'copy-and-commit-version-for-subpackage': CopyAndCommitVersionForSubpackage,
|
31 | 'fail-on-pre-version-dependencies': FailOnPreVersionDependencies,
|
32 | 'prepare-version': PrepareVersion,
|
33 | 'publish-npm-package': PublishNpmPackage,
|
34 | 'npm-install-only': NpmInstallOnly,
|
35 | 'update-github-release': UpdateGithubRelease,
|
36 | 'upgrade-dependencies-with-pre-versions': UpgradeDependenciesWithPreVersions,
|
37 | 'publish-releasenotes-on-slack': PublishReleasenotesOnSlack,
|
38 | 'get-version': GetVersion,
|
39 | 'set-version': SetVersion,
|
40 | 'is-nuget-package-published': IsNugetPackagePublished,
|
41 | 'replace-dist-tags-with-real-versions': ReplaceDistTagsWithRealVersions,
|
42 | };
|
43 |
|
44 |
|
45 | const INTERNAL_COMMAND_HANDLERS = {
|
46 | 'auto-publish-if-applicable': AutoPublishIfApplicable,
|
47 | 'create-changelog': CreateChangelog,
|
48 | 'create-release-announcement': CreateReleaseAnnouncement,
|
49 | 'update-github-release': UpdateGithubRelease,
|
50 | 'setup-git-and-npm-connections': SetupGitAndNpmConnections,
|
51 | };
|
52 |
|
53 | const DEFAULT_MODE = PACKAGE_MODE_NODE;
|
54 |
|
55 | async function run(originalArgv: string[]): Promise<void> {
|
56 | const [, , ...args] = originalArgv;
|
57 | const argv = yargsParser(args, { alias: { help: ['h'] }, default: { mode: DEFAULT_MODE } });
|
58 | const mode = argv.mode;
|
59 |
|
60 | if (args.length === 0 || (args.length === 1 && argv.help === true)) {
|
61 | printHelp();
|
62 | process.exit(1);
|
63 | }
|
64 |
|
65 | if (mode !== PACKAGE_MODE_NODE && mode !== PACKAGE_MODE_DOTNET && mode !== PACKAGE_MODE_PYTHON) {
|
66 | console.error('Mode must be set to `dotnet`, `node` or `python`. \nDefault is `node`');
|
67 | process.exit(1);
|
68 | }
|
69 |
|
70 | const [commandName, ...restArgs] = args;
|
71 |
|
72 | const commandHandler = COMMAND_HANDLERS[commandName] || INTERNAL_COMMAND_HANDLERS[commandName];
|
73 |
|
74 | if (commandHandler == null) {
|
75 | console.error(`No handler found for command: ${commandName}`);
|
76 | process.exit(1);
|
77 | }
|
78 |
|
79 | enforceUniversalCommandLineSwitches(commandHandler, commandName, args);
|
80 |
|
81 | try {
|
82 | await commandHandler.run(...restArgs);
|
83 | } catch (error) {
|
84 | console.error(error);
|
85 | process.exit(1);
|
86 | }
|
87 | }
|
88 |
|
89 | function enforceUniversalCommandLineSwitches(commandHandler: any, commandName: string, args: string[]): void {
|
90 | const badge = `[${commandName}]\t`;
|
91 | const argv = yargsParser(args, { alias: { help: ['h'] } });
|
92 |
|
93 | if (argv.help) {
|
94 | printHelpForCommand(commandHandler, commandName);
|
95 | process.exit(0);
|
96 | }
|
97 |
|
98 | if (argv.onlyOnPrimaryBranches && argv.exceptOnPrimaryBranches) {
|
99 | console.error(chalk.red(`${badge}Both --only-on-primary-branches and --except-on-primary-branches given.`));
|
100 | console.error(chalk.red(`${badge}This can not work! Aborting.`));
|
101 | process.exit(1);
|
102 | } else if (argv.onlyOnPrimaryBranches) {
|
103 | ensureOnPrimaryBranchOrExit(badge);
|
104 | } else if (argv.exceptOnPrimaryBranches) {
|
105 | ensureNotOnPrimaryBranchOrExit(badge);
|
106 | }
|
107 |
|
108 | if (argv.onlyOnBranch) {
|
109 | ensureOnBranchOrExit(badge, argv.onlyOnBranch);
|
110 | }
|
111 | }
|
112 |
|
113 | function ensureOnBranchOrExit(badge: string, requestedBranchName: string): void {
|
114 | const branchName = getGitBranch();
|
115 | const currentlyOnBranch = requestedBranchName === branchName;
|
116 |
|
117 | if (!currentlyOnBranch) {
|
118 | console.log(chalk.yellow(`${badge}--only-on-branch given: ${requestedBranchName}`));
|
119 | console.log(chalk.yellow(`${badge}Current branch is '${branchName}'.`));
|
120 | console.log(chalk.yellow(`${badge}Nothing to do here. Exiting.`));
|
121 |
|
122 | process.exit(0);
|
123 | }
|
124 | }
|
125 |
|
126 | function ensureOnPrimaryBranchOrExit(badge: string): void {
|
127 | const branchName = getGitBranch();
|
128 | const currentlyOnPrimaryBranch = PRIMARY_BRANCHES.includes(branchName);
|
129 |
|
130 | if (!currentlyOnPrimaryBranch) {
|
131 | console.log(chalk.yellow(`${badge}--only-on-primary-branches given.`));
|
132 | console.log(
|
133 | chalk.yellow(`${badge}Current branch is '${branchName}' (primary branches are ${PRIMARY_BRANCHES.join(', ')}).`)
|
134 | );
|
135 | console.log(chalk.yellow(`${badge}Nothing to do here. Exiting.`));
|
136 |
|
137 | process.exit(0);
|
138 | }
|
139 | }
|
140 |
|
141 | function ensureNotOnPrimaryBranchOrExit(badge: string): void {
|
142 | const branchName = getGitBranch();
|
143 | const currentlyOnPrimaryBranch = PRIMARY_BRANCHES.includes(branchName);
|
144 |
|
145 | if (currentlyOnPrimaryBranch) {
|
146 | console.log(chalk.yellow(`${badge}--except-on-primary-branches given.`));
|
147 | console.log(
|
148 | chalk.yellow(`${badge}Current branch is '${branchName}' (primary branches are ${PRIMARY_BRANCHES.join(', ')}).`)
|
149 | );
|
150 | console.log(chalk.yellow(`${badge}Nothing to do here. Exiting.`));
|
151 |
|
152 | process.exit(0);
|
153 | }
|
154 | }
|
155 |
|
156 | function printHelp(): void {
|
157 | console.log('Usage: ci_tools <COMMAND>');
|
158 | console.log('');
|
159 | console.log('COMMAND can be any of:');
|
160 | Object.keys(COMMAND_HANDLERS).forEach((commandName: string): void => console.log(` ${commandName}`));
|
161 | }
|
162 |
|
163 | function printHelpForCommand(commandHandler: any, commandName: string): void {
|
164 | if (commandHandler.printHelp != null) {
|
165 | commandHandler.printHelp();
|
166 | return;
|
167 | }
|
168 |
|
169 | console.log(`Usage: ci_tools ${commandName}`);
|
170 | console.log('');
|
171 | console.log('No further instructions available.');
|
172 | }
|
173 |
|
174 | run(process.argv);
|