@dbx-tools/projen 0.6.200 → 0.6.202
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 +5 -3
- package/index.ts +1 -1
- package/package.json +4 -4
- package/src/project-js.ts +27 -26
- package/tasks/release-pr.ts +40 -10
package/README.md
CHANGED
|
@@ -406,9 +406,11 @@ release branch when needed, and pushes it. It prepares the dedicated
|
|
|
406
406
|
checkout on its current branch throughout validation, local publication, and
|
|
407
407
|
PR creation. Failed preparation can resume from that worktree; success removes
|
|
408
408
|
it. `--message` sets the source commit message. The task never merges
|
|
409
|
-
the PR unless `--approve` is passed; that option
|
|
410
|
-
|
|
411
|
-
|
|
409
|
+
the PR unless `--approve` is passed; that option merges the release branch
|
|
410
|
+
directly through GitHub's merge API so no PR checks are created. A repository
|
|
411
|
+
that blocks direct merges falls back to an immediate admin-merged PR. The task
|
|
412
|
+
then fast-forwards the still-active source branch to the release commit. npm
|
|
413
|
+
uses `npm config get registry` and publishes to a local Verdaccio automatically.
|
|
412
414
|
Publishable JavaScript members compile once
|
|
413
415
|
from the root in parallel, then upload through a bounded pool without rerunning
|
|
414
416
|
their `prepack` tasks. Python prefers uv's default index and only
|
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.202";
|
|
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.202",
|
|
29
|
+
"@dbx-tools/path": "0.6.202",
|
|
30
|
+
"@dbx-tools/shared-core": "0.6.202",
|
|
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.202",
|
|
51
51
|
"types": "index.ts",
|
|
52
52
|
"type": "module",
|
|
53
53
|
"exports": {
|
package/src/project-js.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { ignore, match } from "@dbx-tools/path";
|
|
|
13
13
|
import { object, string, type OneOrMany } from "@dbx-tools/shared-core";
|
|
14
14
|
import { type IConstruct } from "constructs";
|
|
15
15
|
import { Component, IgnoreFile, Project, type TaskOptions, javascript, typescript } from "projen";
|
|
16
|
-
import type
|
|
16
|
+
import { JobPermission, type JobStep } from "projen/lib/github/workflows-model";
|
|
17
17
|
import { ReleaseTrigger } from "projen/lib/release";
|
|
18
18
|
import { mixin } from "..";
|
|
19
19
|
import { generateBarrels } from "./barrels.ts";
|
|
@@ -456,6 +456,10 @@ function defaultProjectOptions(
|
|
|
456
456
|
}
|
|
457
457
|
: {}),
|
|
458
458
|
...options,
|
|
459
|
+
githubOptions: {
|
|
460
|
+
...options.githubOptions,
|
|
461
|
+
pullRequestLint: false,
|
|
462
|
+
},
|
|
459
463
|
...copiedGitIgnoreOptions(options),
|
|
460
464
|
};
|
|
461
465
|
}
|
|
@@ -861,6 +865,23 @@ class WorkflowDefaults extends Component {
|
|
|
861
865
|
? () => rewrite(configuredSteps())
|
|
862
866
|
: rewrite(configuredSteps);
|
|
863
867
|
}
|
|
868
|
+
workflow.addJob("pr-title", {
|
|
869
|
+
name: "Validate PR title",
|
|
870
|
+
runsOn: ["ubuntu-latest"],
|
|
871
|
+
permissions: { pullRequests: JobPermission.READ },
|
|
872
|
+
if: "${{ github.event_name == 'pull_request' && github.event.action != 'closed' }}",
|
|
873
|
+
steps: [
|
|
874
|
+
{
|
|
875
|
+
name: "Validate semantic title",
|
|
876
|
+
uses: "amannn/action-semantic-pull-request@v6",
|
|
877
|
+
env: { GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" },
|
|
878
|
+
with: {
|
|
879
|
+
types: ["feat", "fix", "chore"].join("\n"),
|
|
880
|
+
requireScope: false,
|
|
881
|
+
},
|
|
882
|
+
},
|
|
883
|
+
],
|
|
884
|
+
});
|
|
864
885
|
}
|
|
865
886
|
const build = this.project.tryFindObjectFile(".github/workflows/build.yml");
|
|
866
887
|
build?.addOverride("on.pull_request.types", ["opened", "synchronize", "reopened", "closed"]);
|
|
@@ -871,31 +892,11 @@ class WorkflowDefaults extends Component {
|
|
|
871
892
|
for (const job of ["build", "self-mutation"]) {
|
|
872
893
|
build?.addOverride(`jobs.${job}.timeout-minutes`, 30);
|
|
873
894
|
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
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);
|
|
891
|
-
for (const name of ["build", "pull-request-lint"]) {
|
|
892
|
-
const workflow = this.project.tryFindObjectFile(`.github/workflows/${name}.yml`);
|
|
893
|
-
workflow?.addOverride("permissions", { contents: "read" });
|
|
894
|
-
workflow?.addOverride("concurrency", {
|
|
895
|
-
group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}",
|
|
896
|
-
"cancel-in-progress": true,
|
|
897
|
-
});
|
|
898
|
-
}
|
|
895
|
+
build?.addOverride("permissions", { contents: "read" });
|
|
896
|
+
build?.addOverride("concurrency", {
|
|
897
|
+
group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}",
|
|
898
|
+
"cancel-in-progress": true,
|
|
899
|
+
});
|
|
899
900
|
}
|
|
900
901
|
}
|
|
901
902
|
|
package/tasks/release-pr.ts
CHANGED
|
@@ -105,11 +105,11 @@ function runIgnoringStdout(root: string, command: string, args: string[]): void
|
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
function githubAccount(root: string): { owner: string; token: string } {
|
|
108
|
+
function githubAccount(root: string): { owner: string; repository: string; token: string } {
|
|
109
109
|
const repository = project.repositoryUrl(root);
|
|
110
110
|
if (!repository) throw new Error("Release preparation requires a GitHub repository");
|
|
111
|
-
const owner = new URL(repository).pathname.split("/").filter(Boolean)
|
|
112
|
-
if (!owner) throw new Error(`Cannot determine GitHub
|
|
111
|
+
const [owner, name] = new URL(repository).pathname.split("/").filter(Boolean);
|
|
112
|
+
if (!owner || !name) throw new Error(`Cannot determine GitHub identity from ${repository}`);
|
|
113
113
|
const token = exec
|
|
114
114
|
.spawnSync("gh", ["auth", "token", "--user", owner], {
|
|
115
115
|
cwd: root,
|
|
@@ -120,7 +120,7 @@ function githubAccount(root: string): { owner: string; token: string } {
|
|
|
120
120
|
})
|
|
121
121
|
.stdout?.trim();
|
|
122
122
|
if (!token) throw new Error(`No GitHub CLI authentication found for ${owner}`);
|
|
123
|
-
return { owner, token };
|
|
123
|
+
return { owner, repository: name.replace(/\.git$/, ""), token };
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
const program = new Command();
|
|
@@ -148,7 +148,7 @@ program
|
|
|
148
148
|
.option("--local-pypi <value>", "local PyPI index: auto, false, or an explicit URL", "auto")
|
|
149
149
|
.option("--python-root <path>", "Python workspace package root", "packages/py")
|
|
150
150
|
.option("--no-local-cargo", "skip local Cargo publication")
|
|
151
|
-
.option("--approve", "merge the release
|
|
151
|
+
.option("--approve", "merge the release branch directly into the release base")
|
|
152
152
|
.action(
|
|
153
153
|
async (opts: {
|
|
154
154
|
level: VersionLevel;
|
|
@@ -209,7 +209,6 @@ program
|
|
|
209
209
|
throw new Error(`Release branch already exists without its worktree: ${releaseBranch}`);
|
|
210
210
|
}
|
|
211
211
|
git(root, ["worktree", "add", "-b", releaseBranch, releaseRoot, "HEAD"]);
|
|
212
|
-
run(releaseRoot, process.execPath, ["install"]);
|
|
213
212
|
} else {
|
|
214
213
|
const releaseStatus = git(
|
|
215
214
|
releaseRoot,
|
|
@@ -227,6 +226,7 @@ program
|
|
|
227
226
|
}
|
|
228
227
|
logger.info(`resuming ${releaseBranch} in ${releaseRoot}`);
|
|
229
228
|
}
|
|
229
|
+
run(releaseRoot, process.execPath, ["install"]);
|
|
230
230
|
|
|
231
231
|
const bumpScript = fileURLToPath(new URL("./bump.ts", import.meta.url));
|
|
232
232
|
const versionCheckScript = fileURLToPath(new URL("./version-check.ts", import.meta.url));
|
|
@@ -272,7 +272,10 @@ program
|
|
|
272
272
|
} else if (!worktreeExists) {
|
|
273
273
|
throw new Error("Release preparation produced no changes");
|
|
274
274
|
}
|
|
275
|
-
|
|
275
|
+
// The source push and release commit hooks have already scanned every new
|
|
276
|
+
// byte. A new remote branch has no upstream comparison point, so the
|
|
277
|
+
// managed pre-push hook would rescan the repository's complete history.
|
|
278
|
+
git(releaseRoot, ["push", "--no-verify", "--set-upstream", "origin", releaseBranch]);
|
|
276
279
|
|
|
277
280
|
const title = `chore(release): ${next.version}`;
|
|
278
281
|
const body = [
|
|
@@ -283,7 +286,8 @@ program
|
|
|
283
286
|
"Merging this PR updates VERSION on main and starts the public release workflow.",
|
|
284
287
|
].join("\n");
|
|
285
288
|
const githubEnvironment = { ...process.env, GH_TOKEN: account.token };
|
|
286
|
-
|
|
289
|
+
const ensurePullRequest = (): void => {
|
|
290
|
+
if (commandSucceeds(root, "gh", ["pr", "view", releaseBranch], githubEnvironment)) return;
|
|
287
291
|
run(
|
|
288
292
|
root,
|
|
289
293
|
"gh",
|
|
@@ -301,9 +305,35 @@ program
|
|
|
301
305
|
],
|
|
302
306
|
githubEnvironment,
|
|
303
307
|
);
|
|
304
|
-
}
|
|
308
|
+
};
|
|
305
309
|
if (opts.approve) {
|
|
306
|
-
|
|
310
|
+
const merged = commandSucceeds(
|
|
311
|
+
root,
|
|
312
|
+
"gh",
|
|
313
|
+
[
|
|
314
|
+
"api",
|
|
315
|
+
"--method",
|
|
316
|
+
"POST",
|
|
317
|
+
`repos/${account.owner}/${account.repository}/merges`,
|
|
318
|
+
"-f",
|
|
319
|
+
`base=${opts.base}`,
|
|
320
|
+
"-f",
|
|
321
|
+
`head=${releaseBranch}`,
|
|
322
|
+
"-f",
|
|
323
|
+
`commit_message=Merge ${releaseTag}`,
|
|
324
|
+
],
|
|
325
|
+
githubEnvironment,
|
|
326
|
+
);
|
|
327
|
+
if (!merged) {
|
|
328
|
+
ensurePullRequest();
|
|
329
|
+
run(root, "gh", ["pr", "merge", releaseBranch, "--admin", "--merge"], githubEnvironment);
|
|
330
|
+
}
|
|
331
|
+
git(releaseRoot, ["push", "--no-verify", "origin", "--delete", releaseBranch]);
|
|
332
|
+
git(root, ["fetch", "origin", opts.base]);
|
|
333
|
+
git(root, ["merge", "--ff-only", `origin/${opts.base}`]);
|
|
334
|
+
git(root, ["push", "origin", currentBranch]);
|
|
335
|
+
} else {
|
|
336
|
+
ensurePullRequest();
|
|
307
337
|
}
|
|
308
338
|
git(root, ["worktree", "remove", "--force", releaseRoot]);
|
|
309
339
|
git(root, ["branch", "--delete", "--force", releaseBranch]);
|