@dbx-tools/projen 0.6.198 → 0.6.200
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/README.md +15 -12
- package/index.ts +1 -1
- package/package.json +4 -4
- package/src/project-js.ts +23 -4
- package/src/project-rs.ts +1 -1
- package/tasks/release-pr.ts +65 -36
package/README.md
CHANGED
|
@@ -130,8 +130,9 @@ without Rust crates start no Rust watcher. When Rust projects are detected,
|
|
|
130
130
|
Cargo is required and the focused task fails immediately if it is unavailable.
|
|
131
131
|
`rs:bindings` is explicit rather than part of root `pre-compile`, so ordinary
|
|
132
132
|
JavaScript PR builds type-check committed generated bindings without performing
|
|
133
|
-
a host Rust build.
|
|
134
|
-
|
|
133
|
+
a host Rust build. Regenerate bindings through the focused watcher or explicit
|
|
134
|
+
task while changing a UniFFI API. Release preparation runs Cargo workspace tests
|
|
135
|
+
without invoking UBRN.
|
|
135
136
|
|
|
136
137
|
The workspace generates one `release.yml` workflow for every ecosystem. A push
|
|
137
138
|
to the configured release branch starts it only when `VERSION` changed. The
|
|
@@ -399,14 +400,16 @@ a new package is covered without a re-synth. Work from the root:
|
|
|
399
400
|
| `bun run version:check` | verify every version surface matches `VERSION` |
|
|
400
401
|
| `bun run release` | run full local preflight and open a reviewed release PR |
|
|
401
402
|
|
|
402
|
-
`release` commits pending work on the current branch,
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
403
|
+
`release` commits pending work on the current branch, merges the latest remote
|
|
404
|
+
release branch when needed, and pushes it. It prepares the dedicated
|
|
405
|
+
`release/v<version>` branch inside `.worktrees/<tag>`, leaving the source
|
|
406
|
+
checkout on its current branch throughout validation, local publication, and
|
|
407
|
+
PR creation. Failed preparation can resume from that worktree; success removes
|
|
408
|
+
it. `--message` sets the source commit message. The task never merges
|
|
409
|
+
the PR unless `--approve` is passed; that option requests an immediate admin
|
|
410
|
+
merge so the main release can start without waiting for PR checks. npm uses
|
|
411
|
+
`npm config get registry` and publishes to a local Verdaccio automatically.
|
|
412
|
+
Publishable JavaScript members compile once
|
|
410
413
|
from the root in parallel, then upload through a bounded pool without rerunning
|
|
411
414
|
their `prepack` tasks. Python prefers uv's default index and only
|
|
412
415
|
treats a loopback `.../+simple/` URL as writable devpi; a read-only cache such as
|
|
@@ -422,8 +425,8 @@ auto-detection; `--python-root` defaults to `packages/py`.
|
|
|
422
425
|
|
|
423
426
|
The GitHub PR workflow runs synth plus the workspace TypeScript compile rather
|
|
424
427
|
than the complete root build. Release preparation has already run Rust tests,
|
|
425
|
-
|
|
426
|
-
|
|
428
|
+
workspace type-checking, and local package preflight before opening the PR.
|
|
429
|
+
JavaScript behavior tests remain an explicit developer task.
|
|
427
430
|
|
|
428
431
|
The configured release branch publishes only when a reviewed PR changes
|
|
429
432
|
`VERSION`. Its workflow creates the annotated `v*` public release boundary.
|
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/projen";
|
|
6
|
-
export const PACKAGE_VERSION = "0.6.
|
|
6
|
+
export const PACKAGE_VERSION = "0.6.200";
|
|
7
7
|
export * as barrels from "./src/barrels.ts";
|
|
8
8
|
export * as bunApp from "./src/bun-app.ts";
|
|
9
9
|
export * as bunWorkflow from "./src/bun-workflow.ts";
|
package/package.json
CHANGED
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@clack/prompts": "^1.7.0",
|
|
28
|
-
"@dbx-tools/core": "0.6.
|
|
29
|
-
"@dbx-tools/path": "0.6.
|
|
30
|
-
"@dbx-tools/shared-core": "0.6.
|
|
28
|
+
"@dbx-tools/core": "0.6.200",
|
|
29
|
+
"@dbx-tools/path": "0.6.200",
|
|
30
|
+
"@dbx-tools/shared-core": "0.6.200",
|
|
31
31
|
"commander": "^15.0.0",
|
|
32
32
|
"concurrently": "^10.0.3",
|
|
33
33
|
"constructs": "^10.6.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"main": "index.ts",
|
|
49
49
|
"license": "Apache-2.0",
|
|
50
|
-
"version": "0.6.
|
|
50
|
+
"version": "0.6.200",
|
|
51
51
|
"types": "index.ts",
|
|
52
52
|
"type": "module",
|
|
53
53
|
"exports": {
|
package/src/project-js.ts
CHANGED
|
@@ -863,17 +863,36 @@ class WorkflowDefaults extends Component {
|
|
|
863
863
|
}
|
|
864
864
|
}
|
|
865
865
|
const build = this.project.tryFindObjectFile(".github/workflows/build.yml");
|
|
866
|
+
build?.addOverride("on.pull_request.types", ["opened", "synchronize", "reopened", "closed"]);
|
|
867
|
+
build?.addOverride(
|
|
868
|
+
"jobs.build.if",
|
|
869
|
+
"${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}",
|
|
870
|
+
);
|
|
866
871
|
for (const job of ["build", "self-mutation"]) {
|
|
867
872
|
build?.addOverride(`jobs.${job}.timeout-minutes`, 30);
|
|
868
873
|
}
|
|
869
|
-
this.project
|
|
870
|
-
|
|
871
|
-
|
|
874
|
+
const pullRequestLint = this.project.tryFindObjectFile(
|
|
875
|
+
".github/workflows/pull-request-lint.yml",
|
|
876
|
+
);
|
|
877
|
+
pullRequestLint?.addOverride("on.pull_request_target.types", [
|
|
878
|
+
"labeled",
|
|
879
|
+
"opened",
|
|
880
|
+
"synchronize",
|
|
881
|
+
"reopened",
|
|
882
|
+
"ready_for_review",
|
|
883
|
+
"edited",
|
|
884
|
+
"closed",
|
|
885
|
+
]);
|
|
886
|
+
pullRequestLint?.addOverride(
|
|
887
|
+
"jobs.validate.if",
|
|
888
|
+
"(github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.action != 'closed'",
|
|
889
|
+
);
|
|
890
|
+
pullRequestLint?.addOverride("jobs.validate.timeout-minutes", 10);
|
|
872
891
|
for (const name of ["build", "pull-request-lint"]) {
|
|
873
892
|
const workflow = this.project.tryFindObjectFile(`.github/workflows/${name}.yml`);
|
|
874
893
|
workflow?.addOverride("permissions", { contents: "read" });
|
|
875
894
|
workflow?.addOverride("concurrency", {
|
|
876
|
-
group: "${{ github.workflow }}-${{ github.ref }}",
|
|
895
|
+
group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}",
|
|
877
896
|
"cancel-in-progress": true,
|
|
878
897
|
});
|
|
879
898
|
}
|
package/src/project-rs.ts
CHANGED
|
@@ -340,7 +340,7 @@ if (process.env.GITHUB_OUTPUT) {
|
|
|
340
340
|
/** Keep tracked workspace package versions in Cargo.lock aligned with VERSION. */
|
|
341
341
|
class RustWorkspaceVersionLock extends Component {
|
|
342
342
|
public override postSynthesize(): void {
|
|
343
|
-
exec.spawnSync("cargo", ["metadata", "--format-version", "1"
|
|
343
|
+
exec.spawnSync("cargo", ["metadata", "--format-version", "1"], {
|
|
344
344
|
cwd: this.project.outdir,
|
|
345
345
|
stdout: "ignore",
|
|
346
346
|
stderr: "inherit",
|
package/tasks/release-pr.ts
CHANGED
|
@@ -95,6 +95,16 @@ function run(root: string, command: string, args: string[], env?: NodeJS.Process
|
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
function runIgnoringStdout(root: string, command: string, args: string[]): void {
|
|
99
|
+
exec.spawnSync(command, args, {
|
|
100
|
+
cwd: root,
|
|
101
|
+
stdout: "ignore",
|
|
102
|
+
stderr: "inherit",
|
|
103
|
+
stdin: "ignore",
|
|
104
|
+
check: true,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
98
108
|
function githubAccount(root: string): { owner: string; token: string } {
|
|
99
109
|
const repository = project.repositoryUrl(root);
|
|
100
110
|
if (!repository) throw new Error("Release preparation requires a GitHub repository");
|
|
@@ -161,9 +171,9 @@ program
|
|
|
161
171
|
const next = resolveNextVersion(root, [opts.prefix], opts.level, { fetch: false });
|
|
162
172
|
const releaseTag = `${opts.prefix}${next.version}`;
|
|
163
173
|
const releaseBranch = `release/${releaseTag}`;
|
|
164
|
-
const
|
|
165
|
-
if (currentBranch.startsWith("release/")
|
|
166
|
-
throw new Error(
|
|
174
|
+
const releaseRoot = join(root, ".worktrees", releaseTag);
|
|
175
|
+
if (currentBranch.startsWith("release/")) {
|
|
176
|
+
throw new Error("Release preparation must start from a source branch");
|
|
167
177
|
}
|
|
168
178
|
if (
|
|
169
179
|
git(root, ["ls-remote", "--tags", "origin", `refs/tags/${releaseTag}`], {
|
|
@@ -174,19 +184,21 @@ program
|
|
|
174
184
|
throw new Error(`Release tag already exists: ${releaseTag}`);
|
|
175
185
|
}
|
|
176
186
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
pushCurrentBranch(root, currentBranch);
|
|
187
|
+
const status = git(root, ["status", "--porcelain=v1", "--untracked-files=all"], {
|
|
188
|
+
capture: true,
|
|
189
|
+
});
|
|
190
|
+
if (status) {
|
|
191
|
+
git(root, ["add", "-A"]);
|
|
192
|
+
git(root, ["commit", "-m", opts.message]);
|
|
193
|
+
}
|
|
194
|
+
if (!gitSucceeds(root, ["merge-base", "--is-ancestor", `origin/${opts.base}`, "HEAD"])) {
|
|
195
|
+
git(root, ["merge", "--no-edit", `origin/${opts.base}`]);
|
|
196
|
+
}
|
|
197
|
+
pushCurrentBranch(root, currentBranch);
|
|
189
198
|
|
|
199
|
+
const worktreeExists = existsSync(join(releaseRoot, ".git"));
|
|
200
|
+
if (!worktreeExists) {
|
|
201
|
+
git(root, ["worktree", "prune"]);
|
|
190
202
|
const localBranch = git(root, ["branch", "--list", releaseBranch], { capture: true });
|
|
191
203
|
const remoteBranch = git(
|
|
192
204
|
root,
|
|
@@ -194,16 +206,31 @@ program
|
|
|
194
206
|
{ capture: true, check: false },
|
|
195
207
|
);
|
|
196
208
|
if (localBranch || remoteBranch) {
|
|
197
|
-
throw new Error(`Release branch already exists: ${releaseBranch}`);
|
|
209
|
+
throw new Error(`Release branch already exists without its worktree: ${releaseBranch}`);
|
|
198
210
|
}
|
|
199
|
-
git(root, ["
|
|
211
|
+
git(root, ["worktree", "add", "-b", releaseBranch, releaseRoot, "HEAD"]);
|
|
212
|
+
run(releaseRoot, process.execPath, ["install"]);
|
|
200
213
|
} else {
|
|
201
|
-
|
|
214
|
+
const releaseStatus = git(
|
|
215
|
+
releaseRoot,
|
|
216
|
+
["status", "--porcelain=v1", "--untracked-files=all"],
|
|
217
|
+
{ capture: true },
|
|
218
|
+
);
|
|
219
|
+
if (releaseStatus) {
|
|
220
|
+
git(releaseRoot, ["stash", "push", "--include-untracked", "--message", "release-resume"]);
|
|
221
|
+
}
|
|
222
|
+
if (!gitSucceeds(releaseRoot, ["merge-base", "--is-ancestor", currentBranch, "HEAD"])) {
|
|
223
|
+
git(releaseRoot, ["merge", "--no-edit", currentBranch]);
|
|
224
|
+
}
|
|
225
|
+
if (releaseStatus) {
|
|
226
|
+
git(releaseRoot, ["stash", "pop"]);
|
|
227
|
+
}
|
|
228
|
+
logger.info(`resuming ${releaseBranch} in ${releaseRoot}`);
|
|
202
229
|
}
|
|
203
230
|
|
|
204
231
|
const bumpScript = fileURLToPath(new URL("./bump.ts", import.meta.url));
|
|
205
232
|
const versionCheckScript = fileURLToPath(new URL("./version-check.ts", import.meta.url));
|
|
206
|
-
run(
|
|
233
|
+
run(releaseRoot, process.execPath, [
|
|
207
234
|
bumpScript,
|
|
208
235
|
"--level",
|
|
209
236
|
opts.level,
|
|
@@ -212,45 +239,46 @@ program
|
|
|
212
239
|
...opts.os.flatMap((value) => ["--os", value]),
|
|
213
240
|
...opts.arch.flatMap((value) => ["--arch", value]),
|
|
214
241
|
]);
|
|
215
|
-
if (readWorkspaceVersion(
|
|
242
|
+
if (readWorkspaceVersion(releaseRoot) !== next.version) {
|
|
216
243
|
throw new Error(`Release preparation did not produce ${next.version}`);
|
|
217
244
|
}
|
|
218
245
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
246
|
+
if (existsSync(join(releaseRoot, "Cargo.toml"))) {
|
|
247
|
+
runIgnoringStdout(releaseRoot, "cargo", ["metadata", "--format-version", "1"]);
|
|
248
|
+
}
|
|
249
|
+
run(releaseRoot, process.execPath, [versionCheckScript]);
|
|
250
|
+
if (existsSync(join(releaseRoot, "Cargo.toml"))) {
|
|
251
|
+
run(releaseRoot, "cargo", [
|
|
222
252
|
"test",
|
|
223
253
|
"--workspace",
|
|
224
|
-
...(existsSync(join(
|
|
254
|
+
...(existsSync(join(releaseRoot, "Cargo.lock")) ? ["--locked"] : []),
|
|
225
255
|
]);
|
|
226
|
-
run(root, process.execPath, ["run", "rs:bindings"]);
|
|
227
256
|
}
|
|
228
|
-
run(
|
|
229
|
-
run(root, process.execPath, ["run", "test"]);
|
|
257
|
+
run(releaseRoot, process.execPath, ["run", "compile"]);
|
|
230
258
|
await publishLocalRelease({
|
|
231
|
-
root,
|
|
259
|
+
root: releaseRoot,
|
|
232
260
|
version: next.version,
|
|
233
261
|
localRegistry: opts.localRegistry,
|
|
234
262
|
localPypi: opts.localPypi,
|
|
235
263
|
pythonRoot: opts.pythonRoot,
|
|
236
264
|
localCargo: opts.localCargo,
|
|
237
265
|
});
|
|
238
|
-
run(
|
|
266
|
+
run(releaseRoot, process.execPath, [versionCheckScript]);
|
|
239
267
|
|
|
240
|
-
git(
|
|
241
|
-
const staged = git(
|
|
268
|
+
git(releaseRoot, ["add", "-A"]);
|
|
269
|
+
const staged = git(releaseRoot, ["diff", "--cached", "--name-only"], { capture: true });
|
|
242
270
|
if (staged) {
|
|
243
|
-
git(
|
|
244
|
-
} else if (!
|
|
271
|
+
git(releaseRoot, ["commit", "-m", `chore(release): ${next.version}`]);
|
|
272
|
+
} else if (!worktreeExists) {
|
|
245
273
|
throw new Error("Release preparation produced no changes");
|
|
246
274
|
}
|
|
247
|
-
git(
|
|
275
|
+
git(releaseRoot, ["push", "--set-upstream", "origin", releaseBranch]);
|
|
248
276
|
|
|
249
277
|
const title = `chore(release): ${next.version}`;
|
|
250
278
|
const body = [
|
|
251
279
|
`Release ${releaseTag}.`,
|
|
252
280
|
"",
|
|
253
|
-
`Source commit: ${git(
|
|
281
|
+
`Source commit: ${git(releaseRoot, ["rev-parse", `${releaseBranch}^`], { capture: true })}`,
|
|
254
282
|
"",
|
|
255
283
|
"Merging this PR updates VERSION on main and starts the public release workflow.",
|
|
256
284
|
].join("\n");
|
|
@@ -277,7 +305,8 @@ program
|
|
|
277
305
|
if (opts.approve) {
|
|
278
306
|
run(root, "gh", ["pr", "merge", releaseBranch, "--admin", "--merge"], githubEnvironment);
|
|
279
307
|
}
|
|
280
|
-
|
|
308
|
+
git(root, ["worktree", "remove", "--force", releaseRoot]);
|
|
309
|
+
git(root, ["branch", "--delete", "--force", releaseBranch]);
|
|
281
310
|
logger.success(`${opts.approve ? "merged" : "opened"} ${releaseBranch} for ${releaseTag}`);
|
|
282
311
|
},
|
|
283
312
|
);
|