|
1 |
| -import chalk from "chalk"; |
2 |
| -import { isEnumValue, isSemanticVersion } from "complete-common"; |
3 |
| -import { |
4 |
| - $o, |
5 |
| - $op, |
6 |
| - $s, |
7 |
| - $sq, |
8 |
| - echo, |
9 |
| - exit, |
10 |
| - fatalError, |
11 |
| - getArgs, |
12 |
| - getElapsedSeconds, |
13 |
| - getPackageJSONScripts, |
14 |
| - getPackageJSONVersion, |
15 |
| - isDirectory, |
16 |
| - isGitRepositoryClean, |
17 |
| - isLoggedInToNPM, |
18 |
| -} from "complete-node"; |
19 |
| -import path from "node:path"; |
20 |
| -import { updateIsaacScriptMonorepo } from "./update.js"; |
| 1 | +import { monorepoPublish } from "complete-node"; // eslint-disable-line import-x/no-extraneous-dependencies |
21 | 2 |
|
22 |
| -enum VersionBump { |
23 |
| - major = "major", |
24 |
| - minor = "minor", |
25 |
| - patch = "patch", |
26 |
| - dev = "dev", |
27 |
| -} |
28 |
| - |
29 |
| -const UPDATES_ENABLED = true as boolean; |
30 |
| -const REPO_ROOT = path.join(import.meta.dirname, ".."); |
31 |
| - |
32 |
| -const startTime = Date.now(); |
33 |
| - |
34 |
| -// Validate that we are on the correct branch. |
35 |
| -const branch = $o`git branch --show-current`; |
36 |
| -if (branch !== "main") { |
37 |
| - echo("Error: You must be on the main branch before publishing."); |
38 |
| - exit(1); |
39 |
| -} |
40 |
| - |
41 |
| -// Validate that we can push and pull to the repository. |
42 |
| -$s`git branch --set-upstream-to=origin/main main --quiet`; |
43 |
| -$s`git pull --rebase --quiet`; |
44 |
| -$s`git push --set-upstream origin main --quiet`; |
45 |
| - |
46 |
| -// Validate that we are logged in to npm. |
47 |
| -if (!isLoggedInToNPM()) { |
48 |
| - fatalError( |
49 |
| - `You are not logged into npm. Please run: ${chalk.green("npm adduser")}`, |
50 |
| - ); |
51 |
| -} |
52 |
| - |
53 |
| -// Validate command-line arguments. |
54 |
| -const args = getArgs(); |
55 |
| -const packageName = args[0]; |
56 |
| -if (packageName === undefined || packageName === "") { |
57 |
| - echo("Error: The package name is required as an argument."); |
58 |
| - exit(1); |
59 |
| -} |
60 |
| - |
61 |
| -const packagePath = path.join(REPO_ROOT, "packages", packageName); |
62 |
| -if (!isDirectory(packagePath)) { |
63 |
| - echo(`Error: The directory of "${chalk.green(packagePath)}" does not exist.`); |
64 |
| - exit(1); |
65 |
| -} |
66 |
| - |
67 |
| -const versionBump = args[1]; |
68 |
| -if (versionBump === undefined || versionBump === "") { |
69 |
| - echo("Error: The version bump description is required as an argument."); |
70 |
| - exit(1); |
71 |
| -} |
72 |
| -if (!isEnumValue(versionBump, VersionBump) && !isSemanticVersion(versionBump)) { |
73 |
| - echo(`Error: The following version bump is not valid: ${versionBump}`); |
74 |
| - exit(1); |
75 |
| -} |
76 |
| - |
77 |
| -const $$ = $op({ cwd: packagePath }); |
78 |
| - |
79 |
| -// Before bumping the version, check to see if this package compiles and lints and tests (so that we |
80 |
| -// can avoid unnecessary version bumps). |
81 |
| -const scripts = getPackageJSONScripts(packagePath); |
82 |
| -if (scripts !== undefined) { |
83 |
| - const promises: Array<Promise<unknown>> = []; |
84 |
| - |
85 |
| - for (const scriptName of ["build", "lint", "test"]) { |
86 |
| - const scriptCommand = scripts[scriptName]; |
87 |
| - if (typeof scriptCommand === "string") { |
88 |
| - promises.push($$`npm run ${scriptName}`); |
89 |
| - } |
90 |
| - } |
91 |
| - |
92 |
| - await Promise.all(promises); |
93 |
| -} |
94 |
| - |
95 |
| -/** |
96 |
| - * Normally, the "version" command of the packager manager will automatically make a Git commit for |
97 |
| - * you. However: |
98 |
| - * |
99 |
| - * - The npm version command is bugged with subdirectories: https://github.com/npm/cli/issues/2010 |
100 |
| - * - The yarn version command is bugged with with spaces inside of the --message" flag. |
101 |
| - * |
102 |
| - * Thus, we manually revert to doing a commit ourselves. |
103 |
| - */ |
104 |
| -if (isEnumValue(versionBump, VersionBump) && versionBump === VersionBump.dev) { |
105 |
| - $$.sync`npm version prerelease --preid=dev --commit-hooks=false`; |
106 |
| -} else { |
107 |
| - $$.sync`npm version ${versionBump} --commit-hooks=false`; |
108 |
| -} |
109 |
| - |
110 |
| -// Manually make a Git commit. (See above comment.) |
111 |
| -const packageJSONPath = path.join(packagePath, "package.json"); |
112 |
| -$sq`git add ${packageJSONPath}`; |
113 |
| -const newVersion = getPackageJSONVersion(packagePath); |
114 |
| -const tag = `${packageName}-${newVersion}`; |
115 |
| -const commitMessage = `chore(release): ${tag}`; |
116 |
| -$sq`git commit --message ${commitMessage}`; |
117 |
| -$sq`git tag ${tag}`; |
118 |
| -// (Defer doing a "git push" until the end so that we only trigger a single CI run.) |
119 |
| - |
120 |
| -// Upload the package to npm. |
121 |
| -const npmTag = |
122 |
| - isEnumValue(versionBump, VersionBump) && versionBump === VersionBump.dev |
123 |
| - ? "next" |
124 |
| - : "latest"; |
125 |
| -// - The "--access=public" flag is only technically needed for the first publish (unless the package |
126 |
| -// is a scoped package), but it is saved here for posterity. |
127 |
| -// - The "--ignore-scripts" flag is needed since the "npm publish" command will run the "publish" |
128 |
| -// script in the "package.json" file, causing an infinite loop. |
129 |
| -$$.sync`npm publish --access=public --ignore-scripts --tag=${npmTag}`; |
130 |
| - |
131 |
| -const elapsedSeconds = getElapsedSeconds(startTime); |
132 |
| -const secondsText = elapsedSeconds === 1 ? "second" : "seconds"; |
133 |
| -const version = getPackageJSONVersion(packagePath); |
134 |
| -console.log( |
135 |
| - `Successfully published package "${chalk.green( |
136 |
| - packageName, |
137 |
| - )}" version "${chalk.green(version)}" in ${elapsedSeconds} ${secondsText}.`, |
138 |
| -); |
139 |
| - |
140 |
| -// Finally, check for dependency updates to ensure that we keep the monorepo up to date. |
141 |
| -if (UPDATES_ENABLED) { |
142 |
| - console.log("Checking for monorepo updates..."); |
143 |
| - updateIsaacScriptMonorepo(); |
144 |
| - |
145 |
| - if (!isGitRepositoryClean(REPO_ROOT)) { |
146 |
| - const gitCommitMessage = "chore: updating dependencies"; |
147 |
| - $sq`git add --all`; |
148 |
| - $sq`git commit --message ${gitCommitMessage}`; |
149 |
| - } |
150 |
| -} |
151 |
| - |
152 |
| -$sq`git push --set-upstream origin main`; |
| 3 | +await monorepoPublish(); |
0 commit comments