@regardio/dev 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/ship/hotfix.bin.mjs +18 -24
- package/dist/bin/ship/production.bin.mjs +19 -25
- package/dist/bin/ship/staging.bin.mjs +1 -1
- package/dist/bin/ship/{utils-CGXmpKxp.mjs → utils-rnvdLrkF.mjs} +41 -4
- package/dist/playwright/index.d.mts +3 -3
- package/dist/vitest/node.d.mts +3 -3
- package/dist/vitest/react.d.mts +3 -3
- package/docs/en/tools/releases.md +15 -11
- package/package.json +1 -5
- package/src/typescript/base.json +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as git, c as runScript, i as getWorkspacePackages, n as
|
|
2
|
+
import { a as git, c as runScript, i as getWorkspacePackages, n as chooseForEach, o as gitRead, s as runQualityChecks, t as branchExists } from "./utils-rnvdLrkF.mjs";
|
|
3
3
|
//#region src/bin/ship/hotfix.ts
|
|
4
4
|
/**
|
|
5
5
|
* ship-hotfix: Manage hotfix branches based on production code.
|
|
@@ -65,30 +65,23 @@ function runShipHotfix(subcommand, subArgs, cwd = process.cwd()) {
|
|
|
65
65
|
console.error("No publishable workspace packages found.");
|
|
66
66
|
process.exit(1);
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
console.error("Could not determine package to ship.");
|
|
74
|
-
process.exit(1);
|
|
68
|
+
console.log("\nSelect a version bump for each package (or skip):");
|
|
69
|
+
const bumps = chooseForEach(packages);
|
|
70
|
+
if (bumps.length === 0) {
|
|
71
|
+
console.log("\nNo packages selected for release. Aborted.");
|
|
72
|
+
process.exit(0);
|
|
75
73
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
label: "major — breaking changes",
|
|
87
|
-
value: "major"
|
|
74
|
+
console.log("\nBumping versions and updating CHANGELOGs...");
|
|
75
|
+
for (const { package: pkg, bump } of bumps) {
|
|
76
|
+
const originalCwd = process.cwd();
|
|
77
|
+
process.chdir(pkg.path);
|
|
78
|
+
try {
|
|
79
|
+
runScript(`--filter-root release:${bump}`);
|
|
80
|
+
} catch {
|
|
81
|
+
runScript(`commit-and-tag-version ${bump === "patch" ? "" : `--release-as ${bump}`}`);
|
|
88
82
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
runScript(`--filter ${packageName} release:${bumpType}`);
|
|
83
|
+
process.chdir(originalCwd);
|
|
84
|
+
}
|
|
92
85
|
console.log("\nFetching latest state from origin...");
|
|
93
86
|
git("fetch", "origin");
|
|
94
87
|
console.log("\nMerging hotfix into production...");
|
|
@@ -110,7 +103,8 @@ function runShipHotfix(subcommand, subArgs, cwd = process.cwd()) {
|
|
|
110
103
|
try {
|
|
111
104
|
git("push", "origin", "--delete", currentBranch);
|
|
112
105
|
} catch {}
|
|
113
|
-
|
|
106
|
+
const shipped = bumps.map((b) => b.package.name).join(", ");
|
|
107
|
+
console.log(`\n✅ Hotfix ${shipped} shipped to production → staging → main`);
|
|
114
108
|
console.log("CI will publish changed packages to npm.");
|
|
115
109
|
console.log("You are on main and ready to keep working.");
|
|
116
110
|
process.exit(0);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as git, c as runScript, i as getWorkspacePackages, n as
|
|
2
|
+
import { a as git, c as runScript, i as getWorkspacePackages, n as chooseForEach, o as gitRead, r as confirm, s as runQualityChecks, t as branchExists } from "./utils-rnvdLrkF.mjs";
|
|
3
3
|
//#region src/bin/ship/production.ts
|
|
4
4
|
/**
|
|
5
5
|
* ship-production: Promote main to production following the GitLab workflow.
|
|
@@ -47,15 +47,13 @@ function runShipProduction(cwd = process.cwd()) {
|
|
|
47
47
|
console.error("No publishable workspace packages found.");
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
console.error("Could not determine package to ship.");
|
|
56
|
-
process.exit(1);
|
|
50
|
+
console.log("\nSelect a version bump for each package (or skip):");
|
|
51
|
+
const bumps = chooseForEach(packages);
|
|
52
|
+
if (bumps.length === 0) {
|
|
53
|
+
console.log("\nNo packages selected for release. Aborted.");
|
|
54
|
+
process.exit(0);
|
|
57
55
|
}
|
|
58
|
-
if (!confirm(
|
|
56
|
+
if (!confirm(`\nShip to production?\n${bumps.map((b) => ` ${b.package.name} → ${b.bump}`).join("\n")}\n`)) {
|
|
59
57
|
console.log("Aborted.");
|
|
60
58
|
process.exit(0);
|
|
61
59
|
}
|
|
@@ -67,22 +65,17 @@ function runShipProduction(cwd = process.cwd()) {
|
|
|
67
65
|
process.exit(1);
|
|
68
66
|
}
|
|
69
67
|
console.log("✅ Quality checks passed");
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
label: "major — breaking changes",
|
|
81
|
-
value: "major"
|
|
68
|
+
console.log("\nBumping versions and updating CHANGELOGs...");
|
|
69
|
+
for (const { package: pkg, bump } of bumps) {
|
|
70
|
+
const originalCwd = process.cwd();
|
|
71
|
+
process.chdir(pkg.path);
|
|
72
|
+
try {
|
|
73
|
+
runScript(`--filter-root release:${bump}`);
|
|
74
|
+
} catch {
|
|
75
|
+
runScript(`commit-and-tag-version ${bump === "patch" ? "" : `--release-as ${bump}`}`);
|
|
82
76
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
runScript(`--filter ${packageName} release:${bumpType}`);
|
|
77
|
+
process.chdir(originalCwd);
|
|
78
|
+
}
|
|
86
79
|
console.log("\nMerging main into production...");
|
|
87
80
|
git("checkout", "production");
|
|
88
81
|
git("pull", "--ff-only", "origin", "production");
|
|
@@ -95,7 +88,8 @@ function runShipProduction(cwd = process.cwd()) {
|
|
|
95
88
|
git("push", "origin", "staging");
|
|
96
89
|
git("checkout", "main");
|
|
97
90
|
git("push", "--follow-tags", "origin", "main");
|
|
98
|
-
|
|
91
|
+
const shipped = bumps.map((b) => b.package.name).join(", ");
|
|
92
|
+
console.log(`\n✅ Shipped ${shipped} to production. CI will publish changed packages to npm.`);
|
|
99
93
|
console.log("You are on main and ready to keep working.");
|
|
100
94
|
}
|
|
101
95
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as git, o as gitRead, s as runQualityChecks, t as branchExists } from "./utils-
|
|
2
|
+
import { a as git, o as gitRead, s as runQualityChecks, t as branchExists } from "./utils-rnvdLrkF.mjs";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
//#region src/bin/ship/staging.ts
|
|
@@ -20,7 +20,7 @@ const runScript = (script) => {
|
|
|
20
20
|
execSync(`pnpm ${script}`, { stdio: "inherit" });
|
|
21
21
|
};
|
|
22
22
|
const runQualityChecks = () => {
|
|
23
|
-
runScript("
|
|
23
|
+
runScript("lint");
|
|
24
24
|
runScript("typecheck");
|
|
25
25
|
runScript("test");
|
|
26
26
|
};
|
|
@@ -40,6 +40,43 @@ const getWorkspacePackages = (cwd = process.cwd()) => {
|
|
|
40
40
|
path
|
|
41
41
|
}));
|
|
42
42
|
};
|
|
43
|
+
const chooseForEach = (packages, ttyPath = "/dev/tty") => {
|
|
44
|
+
const bumps = [];
|
|
45
|
+
const options = [
|
|
46
|
+
{
|
|
47
|
+
label: "0) skip",
|
|
48
|
+
value: "0"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
label: "1) patch — bug fixes",
|
|
52
|
+
value: "1"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: "2) minor — new features",
|
|
56
|
+
value: "2"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: "3) major — breaking changes",
|
|
60
|
+
value: "3"
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
for (const pkg of packages) {
|
|
64
|
+
const answer = choose(`\n${pkg.name}:`, [...options], ttyPath);
|
|
65
|
+
if (answer === "1") bumps.push({
|
|
66
|
+
bump: "patch",
|
|
67
|
+
package: pkg
|
|
68
|
+
});
|
|
69
|
+
else if (answer === "2") bumps.push({
|
|
70
|
+
bump: "minor",
|
|
71
|
+
package: pkg
|
|
72
|
+
});
|
|
73
|
+
else if (answer === "3") bumps.push({
|
|
74
|
+
bump: "major",
|
|
75
|
+
package: pkg
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return bumps;
|
|
79
|
+
};
|
|
43
80
|
const branchExists = (name) => gitRead("branch", "--list", name) !== "" || gitRead("branch", "--list", "--remotes", `origin/${name}`) !== "";
|
|
44
81
|
const confirm = (prompt, ttyPath = "/dev/tty") => {
|
|
45
82
|
process.stdout.write(`${prompt} (y/N) `);
|
|
@@ -58,8 +95,8 @@ const confirm = (prompt, ttyPath = "/dev/tty") => {
|
|
|
58
95
|
return answer === "y" || answer === "Y";
|
|
59
96
|
};
|
|
60
97
|
const choose = (prompt, options, ttyPath = "/dev/tty") => {
|
|
61
|
-
const keys = options.map((
|
|
62
|
-
const optionList = options.map((o
|
|
98
|
+
const keys = options.map((o) => o.value);
|
|
99
|
+
const optionList = options.map((o) => ` ${o.label}`).join("\n");
|
|
63
100
|
process.stdout.write(`${prompt}\n${optionList}\nChoice [${keys.join("/")}]: `);
|
|
64
101
|
const buf = Buffer.alloc(1024);
|
|
65
102
|
let fd;
|
|
@@ -83,4 +120,4 @@ const choose = (prompt, options, ttyPath = "/dev/tty") => {
|
|
|
83
120
|
return chosen.value;
|
|
84
121
|
};
|
|
85
122
|
//#endregion
|
|
86
|
-
export { git as a, runScript as c, getWorkspacePackages as i,
|
|
123
|
+
export { git as a, runScript as c, getWorkspacePackages as i, chooseForEach as n, gitRead as o, confirm as r, runQualityChecks as s, branchExists as t };
|
|
@@ -10,9 +10,9 @@ interface BuildPlaywrightBaseConfigParams {
|
|
|
10
10
|
webServerCommand: string;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
* Build a base Playwright config object with Regardio defaults.
|
|
14
|
+
* Consumers should wrap with defineConfig() in their local playwright.config.ts
|
|
15
|
+
*/
|
|
16
16
|
declare function buildPlaywrightBaseConfig({
|
|
17
17
|
appUrl,
|
|
18
18
|
appPort,
|
package/dist/vitest/node.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
//#region src/vitest/node.d.ts
|
|
2
2
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
* Base Vitest configuration for Node.js packages.
|
|
4
|
+
* Use with defineConfig() in your vitest.config.ts
|
|
5
|
+
*/
|
|
6
6
|
declare const vitestNodeConfig: {
|
|
7
7
|
coverage: {
|
|
8
8
|
provider: "v8";
|
package/dist/vitest/react.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
//#region src/vitest/react.d.ts
|
|
2
2
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
* Vitest configuration for React packages with jsdom environment.
|
|
4
|
+
* Use with defineConfig() in your vitest.config.ts
|
|
5
|
+
*/
|
|
6
6
|
declare const vitestReactConfig: {
|
|
7
7
|
coverage: {
|
|
8
8
|
provider: "v8";
|
|
@@ -25,17 +25,17 @@ main → staging (optional) → production
|
|
|
25
25
|
- **`staging`** — optional validation environment. No versioning happens here.
|
|
26
26
|
- **`production`** — versioned, published code only.
|
|
27
27
|
|
|
28
|
-
When `ship-production` runs, it discovers publishable workspace packages
|
|
28
|
+
When `ship-production` runs, it discovers all publishable workspace packages and asks you to assign a bump type — `0` (skip), `1` (patch), `2` (minor), or `3` (major) — to each one individually. Packages you skip are left untouched. For each package with a bump, it first tries to run the release script from the root package.json (using `--filter-root release:<type>`), and if that fails, falls back to running `commit-and-tag-version` directly with the appropriate bump flag. This bumps that package's version, rewrites its `CHANGELOG.md` using commits since its last scoped tag, and commits on `main`. The branches merge once after all bumps are applied. CI on `production` publishes only the packages whose version changed.
|
|
29
29
|
|
|
30
30
|
## How It Works
|
|
31
31
|
|
|
32
32
|
### Design principles
|
|
33
33
|
|
|
34
34
|
1. **Branches mirror environments.** `staging` reflects what is deployed to the staging server (when used); `production` always reflects what is published to npm. There is never ambiguity about what is running where.
|
|
35
|
-
2. **You choose the bump at ship time.** When running `ship-production` or `ship-hotfix finish`, you
|
|
35
|
+
2. **You choose the bump per package at ship time.** When running `ship-production` or `ship-hotfix finish`, every publishable package is listed and you assign it `0` (skip), `1` (patch), `2` (minor), or `3` (major). Packages you skip are untouched. The conventional commits in the log inform each choice; the decisions are always explicit.
|
|
36
36
|
3. **Version numbers are a production guarantee.** Bumps are applied only at `ship-production` time. Every version tag in git and every release on npm corresponds to code that has been validated and shipped.
|
|
37
37
|
4. **Staging is optional.** You can ship directly from `main` to `production`. Use `ship-staging` when you want to test changes in a staging environment first.
|
|
38
|
-
5. **Tests are a local gate, not a CI gate.** Quality checks (`
|
|
38
|
+
5. **Tests are a local gate, not a CI gate.** Quality checks (`lint`, `typecheck`, `test`) run on your machine before any commit is made. Broken code cannot enter the repository.
|
|
39
39
|
6. **You always land back on `main`.** Every command returns you to `main` when it finishes.
|
|
40
40
|
|
|
41
41
|
### Full flow diagram
|
|
@@ -136,14 +136,14 @@ This will:
|
|
|
136
136
|
|
|
137
137
|
1. Guard: must be on `main`, working tree clean
|
|
138
138
|
2. Fetch and verify `staging` + `production` branches exist
|
|
139
|
-
3. Show commits to be shipped
|
|
140
|
-
4.
|
|
141
|
-
5.
|
|
142
|
-
6.
|
|
143
|
-
7.
|
|
139
|
+
3. Show commits to be shipped
|
|
140
|
+
4. For each publishable package: choose `0 (skip) / 1 (patch) / 2 (minor) / 3 (major)`
|
|
141
|
+
5. Confirm the planned bumps — abort if declined or all skipped
|
|
142
|
+
6. Run full quality suite on `main` — aborts on failure
|
|
143
|
+
7. For each non-skipped package: run release script from root (if defined) or `commit-and-tag-version` directly — bumps version, rewrites `CHANGELOG.md`, commits
|
|
144
144
|
8. Fast-forward merge `main` into `production` and push
|
|
145
145
|
9. Sync `staging` with `production`
|
|
146
|
-
10. Push `main` with `--follow-tags` to push
|
|
146
|
+
10. Push `main` with `--follow-tags` to push all new version tags
|
|
147
147
|
11. Return to `main`
|
|
148
148
|
|
|
149
149
|
CI on `production` runs `pnpm -r publish` to push changed packages to npm.
|
|
@@ -167,13 +167,15 @@ git add . && git commit -m "fix: ..."
|
|
|
167
167
|
pnpm ship:hotfix finish
|
|
168
168
|
```
|
|
169
169
|
|
|
170
|
-
`finish`
|
|
170
|
+
`finish` asks you to assign a bump type (`0` (skip), `1` (patch), `2` (minor), or `3` (major)) to each publishable package, runs the release script from root (if defined) or `commit-and-tag-version` directly for each non-skipped one to bump versions and update `CHANGELOG.md`, then merges `hotfix → production → staging → main` and deletes the hotfix branch. CI publishes from `production`.
|
|
171
171
|
|
|
172
172
|
## Adoption
|
|
173
173
|
|
|
174
174
|
Install `@regardio/dev` and:
|
|
175
175
|
|
|
176
|
-
1. **Add the scripts to `package.json
|
|
176
|
+
1. **Add the scripts to `package.json`** (optional, for monorepos):
|
|
177
|
+
|
|
178
|
+
In a monorepo, you can define release scripts in the root `package.json` to centralize version management. The ship scripts will use these if available, and fall back to running `commit-and-tag-version` directly if not.
|
|
177
179
|
|
|
178
180
|
```json
|
|
179
181
|
{
|
|
@@ -189,6 +191,8 @@ Install `@regardio/dev` and:
|
|
|
189
191
|
}
|
|
190
192
|
```
|
|
191
193
|
|
|
194
|
+
For single-package repos or when you prefer direct `commit-and-tag-version` usage, you can omit the release scripts — the ship commands will call `commit-and-tag-version` directly.
|
|
195
|
+
|
|
192
196
|
2. **Add a `.versionrc.json` to each publishable package** with a scoped `tagPrefix` so tags and changelogs stay isolated per package:
|
|
193
197
|
|
|
194
198
|
```bash
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://www.schemastore.org/package.json",
|
|
3
3
|
"name": "@regardio/dev",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.4.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Regardio development presets: biome, typescript, commitlint, markdownlint, vitest, playwright, sqlfluff, husky, and GitLab-flow ship tooling",
|
|
7
7
|
"keywords": [
|
|
@@ -98,10 +98,6 @@
|
|
|
98
98
|
"clean": "rimraf .turbo dist",
|
|
99
99
|
"dev": "tsdown --watch",
|
|
100
100
|
"fix": "run-s fix:pkg fix:md fix:biome",
|
|
101
|
-
"release": "commit-and-tag-version",
|
|
102
|
-
"release:major": "commit-and-tag-version --release-as major",
|
|
103
|
-
"release:minor": "commit-and-tag-version --release-as minor",
|
|
104
|
-
"release:patch": "commit-and-tag-version --release-as patch",
|
|
105
101
|
"fix:biome": "biome check --write --unsafe .",
|
|
106
102
|
"fix:md": "markdownlint-cli2 --config ../../.markdownlint-cli2.jsonc --fix",
|
|
107
103
|
"fix:pkg": "sort-package-json",
|
package/src/typescript/base.json
CHANGED
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
"allowUnusedLabels": false,
|
|
8
8
|
"alwaysStrict": true,
|
|
9
9
|
"checkJs": false,
|
|
10
|
+
"declaration": true,
|
|
10
11
|
"esModuleInterop": true,
|
|
11
12
|
"exactOptionalPropertyTypes": false,
|
|
12
13
|
"forceConsistentCasingInFileNames": true,
|
|
13
14
|
"incremental": false,
|
|
14
15
|
"inlineSources": false,
|
|
15
|
-
"isolatedDeclarations":
|
|
16
|
+
"isolatedDeclarations": true,
|
|
16
17
|
"isolatedModules": true,
|
|
17
18
|
"module": "ESNext",
|
|
18
19
|
"moduleDetection": "force",
|