@dbx-tools/projen 0.6.222 → 0.6.224
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 +41 -7
- package/index.ts +4 -2
- package/package.json +5 -5
- package/src/barrels.ts +10 -4
- package/src/bun-workflow.ts +36 -17
- package/src/clean.ts +3 -3
- package/src/codegen.ts +16 -8
- package/src/packages.ts +14 -13
- package/src/project-js.ts +316 -147
- package/src/project-py.ts +8 -25
- package/src/project-rs.ts +98 -71
- package/src/release-github.ts +37 -0
- package/src/release.ts +25 -36
- package/src/tsconfig.ts +17 -17
- package/tasks/local-publish.ts +3 -3
- package/tasks/publish-npm.ts +75 -4
- package/tasks/publish-python.ts +13 -29
- package/tasks/publish-uniffi-local.ts +12 -9
- package/tasks/publish.ts +2 -2
- package/tasks/release-pr.ts +27 -10
- package/tasks/uniffi-python.d.ts +56 -0
- package/tasks/uniffi-python.js +160 -0
- package/tasks/uniffi-release.mjs +25 -49
- package/tasks/uniffi.ts +11 -45
package/src/project-py.ts
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
import { project as coreProject } from "@dbx-tools/core";
|
|
3
3
|
import { string } from "@dbx-tools/shared-core";
|
|
4
4
|
import { Component, License, TextFile, type Project, javascript, python, vscode } from "projen";
|
|
5
|
-
import type { IResolver } from "projen/lib/file";
|
|
6
5
|
import { JobPermission } from "projen/lib/github/workflows-model";
|
|
7
|
-
import { parse, stringify } from "smol-toml";
|
|
8
6
|
import { BUN_VERSION, bunCacheRestoreSteps, bunCacheSaveStep } from "./bun-workflow.ts";
|
|
9
7
|
import { DBX_TOOLS_LICENSE, projectReleaseBranch, projectRepositoryUrl } from "./project-js.ts";
|
|
10
8
|
import { isDBXToolsJavaScriptProject } from "./project-predicate.ts";
|
|
@@ -14,7 +12,7 @@ import {
|
|
|
14
12
|
releaseArtifactSteps,
|
|
15
13
|
releasePublishCondition,
|
|
16
14
|
releaseStageCondition,
|
|
17
|
-
|
|
15
|
+
tryReleaseWorkflow,
|
|
18
16
|
} from "./release.ts";
|
|
19
17
|
import { readWorkspaceVersion } from "./workspace-version.ts";
|
|
20
18
|
|
|
@@ -111,24 +109,6 @@ const DEFAULT_DEV_DEPENDENCIES = [
|
|
|
111
109
|
|
|
112
110
|
const quote = (value: string): string => JSON.stringify(value);
|
|
113
111
|
|
|
114
|
-
interface TomlSynthesizer {
|
|
115
|
-
synthesizeContent(resolver: IResolver): string | undefined;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function formatPyproject(file: python.PyprojectTomlFile): void {
|
|
119
|
-
const target = file as unknown as TomlSynthesizer;
|
|
120
|
-
const synthesize = target.synthesizeContent.bind(file);
|
|
121
|
-
target.synthesizeContent = (resolver) => {
|
|
122
|
-
const content = synthesize(resolver);
|
|
123
|
-
if (!content) return content;
|
|
124
|
-
const marker = content.startsWith("# ") ? content.slice(0, content.indexOf("\n")) : undefined;
|
|
125
|
-
const body = stringify(parse(content))
|
|
126
|
-
.trimEnd()
|
|
127
|
-
.replace(/ = \[ (.*) \]$/gm, " = [$1]");
|
|
128
|
-
return `${marker ? `${marker}\n\n` : ""}${body}\n`;
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
112
|
/** Repository-relative path for a Python package directory. */
|
|
133
113
|
export function pythonPackagePath(repository: PythonRepositoryOptions, directory: string): string {
|
|
134
114
|
return `${repository.root ?? "packages/py"}/${directory}`;
|
|
@@ -222,7 +202,6 @@ export class DBXToolsPythonProject extends python.PythonProject implements DBXTo
|
|
|
222
202
|
if (pkg.uniffi !== undefined) {
|
|
223
203
|
this.uv.file.addOverride("tool.dbx_tools.config.uniffi", pkg.uniffi);
|
|
224
204
|
}
|
|
225
|
-
formatPyproject(this.uv.file);
|
|
226
205
|
this.uv.file.readonly = true;
|
|
227
206
|
|
|
228
207
|
for (const path of [".gitattributes", ".gitignore"]) {
|
|
@@ -397,7 +376,6 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
397
376
|
"tool.uv.sources",
|
|
398
377
|
Object.fromEntries(options.packages.map((pkg) => [pkg.name, { workspace: true }])),
|
|
399
378
|
);
|
|
400
|
-
formatPyproject(file);
|
|
401
379
|
file.readonly = true;
|
|
402
380
|
return file;
|
|
403
381
|
}
|
|
@@ -433,7 +411,10 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
433
411
|
const allPublications = [...publications, ...uniffiPublications];
|
|
434
412
|
if (allPublications.length === 0) return;
|
|
435
413
|
const usesRustArtifacts = uniffiPublications.length > 0;
|
|
436
|
-
const workflow =
|
|
414
|
+
const workflow = tryReleaseWorkflow(project);
|
|
415
|
+
if (!workflow) {
|
|
416
|
+
throw new Error("Python release requires the root dbx-tools release mode");
|
|
417
|
+
}
|
|
437
418
|
workflow.addJob("build-python", {
|
|
438
419
|
if: usesRustArtifacts
|
|
439
420
|
? "${{ always() && needs.verify-context.result == 'success' && needs.rust-build.result != 'failure' && needs.rust-build.result != 'cancelled' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'python') }}"
|
|
@@ -445,7 +426,9 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
445
426
|
env: { BUN_VERSION },
|
|
446
427
|
steps: [
|
|
447
428
|
...releaseSourceSteps(),
|
|
448
|
-
...bunCacheRestoreSteps(project
|
|
429
|
+
...bunCacheRestoreSteps(project, {
|
|
430
|
+
ignorePaths: project.workflowCacheIgnorePaths,
|
|
431
|
+
}),
|
|
449
432
|
{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" },
|
|
450
433
|
{ name: "Install release helpers", run: "bun install" },
|
|
451
434
|
bunCacheSaveStep(),
|
package/src/project-rs.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/** Filesystem-discovered Rust workspaces and UniFFI binding package wiring. */
|
|
2
2
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
3
4
|
import { dirname, join, relative, resolve } from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
6
|
import { exec, project as coreProject } from "@dbx-tools/core";
|
|
6
7
|
import { string } from "@dbx-tools/shared-core";
|
|
7
|
-
import { Component, Project, TextFile, javascript } from "projen";
|
|
8
|
+
import { Component, Project, TextFile, TomlFile, javascript } from "projen";
|
|
8
9
|
import { JobPermission, type Job, type JobStep } from "projen/lib/github/workflows-model";
|
|
9
10
|
import { BUN_VERSION } from "./bun-workflow.ts";
|
|
10
11
|
import {
|
|
@@ -28,7 +29,7 @@ import {
|
|
|
28
29
|
nodeReleaseSetupSteps,
|
|
29
30
|
releaseArtifactSteps,
|
|
30
31
|
releaseStageCondition,
|
|
31
|
-
|
|
32
|
+
tryReleaseWorkflow,
|
|
32
33
|
} from "./release.ts";
|
|
33
34
|
import { readWorkspaceVersion } from "./workspace-version.ts";
|
|
34
35
|
|
|
@@ -180,6 +181,7 @@ export const UNIFFI_RELEASE_TARGETS: readonly UniFFIReleaseTarget[] = [
|
|
|
180
181
|
|
|
181
182
|
const UBRN_VERSION = "0.31.0-5";
|
|
182
183
|
const RELEASE_PLATFORMS_ENV = "DBX_TOOLS_RELEASE_PLATFORMS";
|
|
184
|
+
const require = createRequire(import.meta.url);
|
|
183
185
|
const RUST_CACHE_ENV = {
|
|
184
186
|
CARGO_INCREMENTAL: "0",
|
|
185
187
|
CARGO_TERM_COLOR: "always",
|
|
@@ -262,17 +264,25 @@ function rustCliRegistrySource(binaries: readonly RustReleaseBinaryMapping[]): s
|
|
|
262
264
|
].join("\n");
|
|
263
265
|
}
|
|
264
266
|
|
|
265
|
-
function
|
|
267
|
+
function taskSource(name: string): string {
|
|
266
268
|
const sourceDirectory = dirname(fileURLToPath(import.meta.url));
|
|
267
269
|
const candidates = [
|
|
268
|
-
resolve(sourceDirectory,
|
|
269
|
-
resolve(sourceDirectory,
|
|
270
|
+
resolve(sourceDirectory, `../tasks/${name}`),
|
|
271
|
+
resolve(sourceDirectory, `../../tasks/${name}`),
|
|
270
272
|
];
|
|
271
273
|
const source = candidates.find(existsSync);
|
|
272
|
-
if (!source) throw new Error(
|
|
274
|
+
if (!source) throw new Error(`Could not locate tasks/${name}`);
|
|
273
275
|
return readFileSync(source, "utf8");
|
|
274
276
|
}
|
|
275
277
|
|
|
278
|
+
function smolTomlSource(name: "dist/index.cjs" | "LICENSE"): string {
|
|
279
|
+
const entry = require.resolve("smol-toml");
|
|
280
|
+
return readFileSync(
|
|
281
|
+
resolve(dirname(entry), name === "LICENSE" ? "../LICENSE" : "index.cjs"),
|
|
282
|
+
"utf8",
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
276
286
|
/** Keep tracked workspace package versions in Cargo.lock aligned with VERSION. */
|
|
277
287
|
class RustWorkspaceVersionLock extends Component {
|
|
278
288
|
public override postSynthesize(): void {
|
|
@@ -390,26 +400,23 @@ function cargoDependency(
|
|
|
390
400
|
};
|
|
391
401
|
}
|
|
392
402
|
|
|
393
|
-
function
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if (!entries || typeof entries !== "object" || Array.isArray(entries)) continue;
|
|
409
|
-
const rows = Object.entries(entries).map(([key, entry]) => `${key} = ${tomlValue(entry)}`);
|
|
410
|
-
blocks.push(`${section === "bin" ? "[[bin]]" : `[${section}]`}\n${rows.join("\n")}`);
|
|
403
|
+
function structuredTomlSections(value: Readonly<Record<string, unknown>>): Record<string, unknown> {
|
|
404
|
+
const result: Record<string, unknown> = {};
|
|
405
|
+
for (const [section, contents] of Object.entries(value)) {
|
|
406
|
+
const path = section.split(".");
|
|
407
|
+
let target = result;
|
|
408
|
+
for (const part of path.slice(0, -1)) {
|
|
409
|
+
const current = target[part];
|
|
410
|
+
if (current === undefined) {
|
|
411
|
+
target[part] = {};
|
|
412
|
+
} else if (!current || typeof current !== "object" || Array.isArray(current)) {
|
|
413
|
+
throw new Error(`Conflicting TOML section ${section}`);
|
|
414
|
+
}
|
|
415
|
+
target = target[part] as Record<string, unknown>;
|
|
416
|
+
}
|
|
417
|
+
target[path.at(-1)!] = contents;
|
|
411
418
|
}
|
|
412
|
-
return
|
|
419
|
+
return result;
|
|
413
420
|
}
|
|
414
421
|
|
|
415
422
|
/** One generated Cargo workspace member. */
|
|
@@ -455,9 +462,11 @@ export class DBXToolsRustProject extends Project implements DBXToolsProject {
|
|
|
455
462
|
: {}),
|
|
456
463
|
...(this.uniffi || binary
|
|
457
464
|
? {
|
|
458
|
-
bin:
|
|
459
|
-
|
|
460
|
-
|
|
465
|
+
bin: [
|
|
466
|
+
this.uniffi
|
|
467
|
+
? { name: `${crateName}-uniffi-bindgen`, path: "uniffi-bindgen.rs" }
|
|
468
|
+
: { name: binaryName, path: "src/main.rs" },
|
|
469
|
+
],
|
|
461
470
|
}
|
|
462
471
|
: {}),
|
|
463
472
|
...(options.features || options.defaultFeatures
|
|
@@ -489,20 +498,19 @@ export class DBXToolsRustProject extends Project implements DBXToolsProject {
|
|
|
489
498
|
}
|
|
490
499
|
: {}),
|
|
491
500
|
};
|
|
492
|
-
new
|
|
501
|
+
new TomlFile(this, "Cargo.toml", { marker: false, obj: manifest });
|
|
493
502
|
if (this.uniffi) {
|
|
494
503
|
new TextFile(this, "uniffi-bindgen.rs", {
|
|
495
504
|
lines: ["fn main() {", " uniffi::uniffi_bindgen_main();", "}", ""],
|
|
496
505
|
});
|
|
497
|
-
new
|
|
498
|
-
|
|
506
|
+
new TomlFile(this, "uniffi.toml", {
|
|
507
|
+
marker: false,
|
|
508
|
+
obj: structuredTomlSections(
|
|
499
509
|
options.uniffiConfig ?? {
|
|
500
510
|
"bindings.python": { cdylib_name: crateName.replaceAll("-", "_") },
|
|
501
511
|
"bindings.typescript": { strictTypeChecking: true },
|
|
502
512
|
},
|
|
503
|
-
)
|
|
504
|
-
.trimEnd()
|
|
505
|
-
.split("\n"),
|
|
513
|
+
),
|
|
506
514
|
});
|
|
507
515
|
}
|
|
508
516
|
}
|
|
@@ -833,8 +841,9 @@ function configureRustBindingFiles(
|
|
|
833
841
|
const dependencies = bindingDependencies(plan, pkg, "python");
|
|
834
842
|
if (dependencies.length === 0) continue;
|
|
835
843
|
pkg.tryRemoveFile("uniffi.toml");
|
|
836
|
-
new
|
|
837
|
-
|
|
844
|
+
new TomlFile(pkg, "uniffi.toml", {
|
|
845
|
+
marker: false,
|
|
846
|
+
obj: structuredTomlSections({
|
|
838
847
|
"bindings.python": { cdylib_name: pkg.crateName.replaceAll("-", "_") },
|
|
839
848
|
"bindings.typescript": { strictTypeChecking: true },
|
|
840
849
|
...pkg.packageOptions.uniffiConfig,
|
|
@@ -847,9 +856,7 @@ function configureRustBindingFiles(
|
|
|
847
856
|
)}.bindings`,
|
|
848
857
|
]),
|
|
849
858
|
),
|
|
850
|
-
})
|
|
851
|
-
.trimEnd()
|
|
852
|
-
.split("\n"),
|
|
859
|
+
}),
|
|
853
860
|
});
|
|
854
861
|
}
|
|
855
862
|
}
|
|
@@ -936,39 +943,41 @@ function configureRustWorkspaceFiles(
|
|
|
936
943
|
.filter((pkg) => !pkg.uniffi)
|
|
937
944
|
.map((pkg) => `${resolved.root}/${pkg.packageOptions.directory}`),
|
|
938
945
|
resolver: "2",
|
|
946
|
+
package: {
|
|
947
|
+
version: readWorkspaceVersion(project.outdir),
|
|
948
|
+
edition: options.edition ?? "2021",
|
|
949
|
+
"rust-version": options.rustVersion ?? "1.82",
|
|
950
|
+
license: options.license ?? DBX_TOOLS_LICENSE,
|
|
951
|
+
repository: resolved.repository,
|
|
952
|
+
},
|
|
953
|
+
...(options.workspaceDependencies
|
|
954
|
+
? {
|
|
955
|
+
dependencies: Object.fromEntries(
|
|
956
|
+
Object.entries(options.workspaceDependencies).map(([name, value]) => [
|
|
957
|
+
name,
|
|
958
|
+
cargoDependency(value),
|
|
959
|
+
]),
|
|
960
|
+
),
|
|
961
|
+
}
|
|
962
|
+
: {}),
|
|
939
963
|
},
|
|
940
|
-
"workspace.package": {
|
|
941
|
-
version: readWorkspaceVersion(project.outdir),
|
|
942
|
-
edition: options.edition ?? "2021",
|
|
943
|
-
"rust-version": options.rustVersion ?? "1.82",
|
|
944
|
-
license: options.license ?? DBX_TOOLS_LICENSE,
|
|
945
|
-
repository: resolved.repository,
|
|
946
|
-
},
|
|
947
|
-
...(options.workspaceDependencies
|
|
948
|
-
? {
|
|
949
|
-
"workspace.dependencies": Object.fromEntries(
|
|
950
|
-
Object.entries(options.workspaceDependencies).map(([name, value]) => [
|
|
951
|
-
name,
|
|
952
|
-
cargoDependency(value),
|
|
953
|
-
]),
|
|
954
|
-
),
|
|
955
|
-
}
|
|
956
|
-
: {}),
|
|
957
964
|
};
|
|
958
|
-
new
|
|
959
|
-
|
|
965
|
+
new TomlFile(project, "Cargo.toml", {
|
|
966
|
+
marker: false,
|
|
967
|
+
obj: manifest,
|
|
960
968
|
});
|
|
961
|
-
new
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
969
|
+
new TomlFile(project, ".cargo/config.toml", {
|
|
970
|
+
marker: false,
|
|
971
|
+
obj: {
|
|
972
|
+
target: {
|
|
973
|
+
"x86_64-pc-windows-msvc": {
|
|
974
|
+
rustflags: ["-C", "target-feature=+crt-static"],
|
|
975
|
+
},
|
|
976
|
+
"aarch64-pc-windows-msvc": {
|
|
977
|
+
rustflags: ["-C", "target-feature=+crt-static"],
|
|
978
|
+
},
|
|
968
979
|
},
|
|
969
|
-
}
|
|
970
|
-
.trimEnd()
|
|
971
|
-
.split("\n"),
|
|
980
|
+
},
|
|
972
981
|
});
|
|
973
982
|
new RustWorkspaceVersionLock(project);
|
|
974
983
|
}
|
|
@@ -1086,12 +1095,27 @@ function planRustRelease(
|
|
|
1086
1095
|
}
|
|
1087
1096
|
|
|
1088
1097
|
function configureRustReleaseTask(project: javascript.NodeProject, plan: RustReleasePlan): void {
|
|
1098
|
+
const supportFiles = [
|
|
1099
|
+
plan.releaseTask,
|
|
1100
|
+
".projen/uniffi-python.js",
|
|
1101
|
+
".projen/smol-toml.cjs",
|
|
1102
|
+
".projen/smol-toml.LICENSE",
|
|
1103
|
+
] as const;
|
|
1089
1104
|
if (plan.bindings.length) {
|
|
1090
1105
|
new TextFile(project, plan.releaseTask, {
|
|
1091
|
-
lines:
|
|
1106
|
+
lines: taskSource("uniffi-release.mjs").trimEnd().split("\n"),
|
|
1107
|
+
});
|
|
1108
|
+
new TextFile(project, supportFiles[1], {
|
|
1109
|
+
lines: taskSource("uniffi-python.js").trimEnd().split("\n"),
|
|
1110
|
+
});
|
|
1111
|
+
new TextFile(project, supportFiles[2], {
|
|
1112
|
+
lines: smolTomlSource("dist/index.cjs").trimEnd().split("\n"),
|
|
1113
|
+
});
|
|
1114
|
+
new TextFile(project, supportFiles[3], {
|
|
1115
|
+
lines: smolTomlSource("LICENSE").trimEnd().split("\n"),
|
|
1092
1116
|
});
|
|
1093
1117
|
} else {
|
|
1094
|
-
project.tryRemoveFile(
|
|
1118
|
+
for (const path of supportFiles) project.tryRemoveFile(path);
|
|
1095
1119
|
}
|
|
1096
1120
|
}
|
|
1097
1121
|
|
|
@@ -1476,8 +1500,11 @@ export class DBXToolsRustWorkspace {
|
|
|
1476
1500
|
): void {
|
|
1477
1501
|
if (!project.github || !isDBXToolsJavaScriptProject()(project)) return;
|
|
1478
1502
|
const plan = planRustRelease(project, options, targets, this.packages, this.bindingMappings);
|
|
1503
|
+
const workflow = tryReleaseWorkflow(project);
|
|
1504
|
+
if (!workflow) {
|
|
1505
|
+
throw new Error("Rust release requires the root dbx-tools release mode");
|
|
1506
|
+
}
|
|
1479
1507
|
configureRustReleaseTask(project, plan);
|
|
1480
|
-
const workflow = releaseWorkflow(project);
|
|
1481
1508
|
if (plan.hasTargetOutputs && plan.targets.length) {
|
|
1482
1509
|
workflow.addJob("rust-build", rustBuildJob(plan));
|
|
1483
1510
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** GitHub repository identity used by release preparation. */
|
|
2
|
+
export interface GithubRepositoryIdentity {
|
|
3
|
+
hostname: string;
|
|
4
|
+
owner: string;
|
|
5
|
+
repository: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Parse a GitHub repository URL without treating its owner as the authenticated actor. */
|
|
9
|
+
export function githubRepositoryIdentity(repositoryUrl: string): GithubRepositoryIdentity {
|
|
10
|
+
const url = new URL(repositoryUrl);
|
|
11
|
+
const [owner, name] = url.pathname.split("/").filter(Boolean);
|
|
12
|
+
if (!owner || !name) {
|
|
13
|
+
throw new Error(`Cannot determine GitHub repository identity from ${repositoryUrl}`);
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
hostname: url.hostname,
|
|
17
|
+
owner,
|
|
18
|
+
repository: name.replace(/\.git$/, ""),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Ask GitHub CLI for the current actor's token on the repository host. */
|
|
23
|
+
export function githubTokenArguments(hostname: string): string[] {
|
|
24
|
+
return ["auth", "token", "--hostname", hostname];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** GitHub CLI token variable for a public, data-residency, or enterprise host. */
|
|
28
|
+
export function githubTokenEnvironmentName(hostname: string): "GH_TOKEN" | "GH_ENTERPRISE_TOKEN" {
|
|
29
|
+
return hostname === "github.com" || hostname.endsWith(".ghe.com")
|
|
30
|
+
? "GH_TOKEN"
|
|
31
|
+
: "GH_ENTERPRISE_TOKEN";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Host-qualified repository selector consumed by GitHub CLI. */
|
|
35
|
+
export function githubRepositorySpecifier(identity: GithubRepositoryIdentity): string {
|
|
36
|
+
return `${identity.hostname}/${identity.owner}/${identity.repository}`;
|
|
37
|
+
}
|
package/src/release.ts
CHANGED
|
@@ -20,6 +20,12 @@ export type ReleaseStage = "all" | "node" | "python" | "docs";
|
|
|
20
20
|
export interface ReleaseDocsOptions {
|
|
21
21
|
readonly siteUrl: string;
|
|
22
22
|
readonly base?: string;
|
|
23
|
+
/** Repository-defined setup and generation steps run before saving the Bun cache. */
|
|
24
|
+
readonly prepareSteps: readonly JobStep[];
|
|
25
|
+
/** Repository-defined documentation build and validation steps. */
|
|
26
|
+
readonly buildSteps: readonly JobStep[];
|
|
27
|
+
/** Directory uploaded as the GitHub Pages artifact. */
|
|
28
|
+
readonly artifactPath: string;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
/** Options for {@link DBXToolsRelease}. */
|
|
@@ -30,6 +36,8 @@ export interface DBXToolsReleaseOptions {
|
|
|
30
36
|
readonly nodeRelease?: boolean;
|
|
31
37
|
/** Build and deploy generated documentation through GitHub Pages. */
|
|
32
38
|
readonly docs?: ReleaseDocsOptions;
|
|
39
|
+
/** Python package root passed to local release preparation. */
|
|
40
|
+
readonly pythonRoot?: string;
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
/** Locate the unified workflow so attached language workspaces can add jobs. */
|
|
@@ -39,6 +47,11 @@ export function releaseWorkflow(project: DBXToolsJavaScriptProject): GithubWorkf
|
|
|
39
47
|
return workflow;
|
|
40
48
|
}
|
|
41
49
|
|
|
50
|
+
/** Locate the unified workflow when release generation is enabled. */
|
|
51
|
+
export function tryReleaseWorkflow(project: DBXToolsJavaScriptProject): GithubWorkflow | undefined {
|
|
52
|
+
return releaseWorkflows.get(project);
|
|
53
|
+
}
|
|
54
|
+
|
|
42
55
|
/** Whether the unified workflow publishes the normal npm workspace. */
|
|
43
56
|
export function hasNodeRelease(project: DBXToolsJavaScriptProject): boolean {
|
|
44
57
|
return nodeReleaseProjects.has(project);
|
|
@@ -98,7 +111,7 @@ export function releaseArtifactSteps(options: {
|
|
|
98
111
|
export function nodeReleaseSetupSteps(project: DBXToolsJavaScriptProject): readonly JobStep[] {
|
|
99
112
|
return [
|
|
100
113
|
...releaseSourceSteps(),
|
|
101
|
-
...bunCacheRestoreSteps(project),
|
|
114
|
+
...bunCacheRestoreSteps(project, { ignorePaths: project.workflowCacheIgnorePaths }),
|
|
102
115
|
{
|
|
103
116
|
name: "Setup Node.js",
|
|
104
117
|
uses: "actions/setup-node@v6",
|
|
@@ -270,44 +283,14 @@ function addDocsJobs(
|
|
|
270
283
|
},
|
|
271
284
|
steps: [
|
|
272
285
|
...releaseSourceSteps(),
|
|
273
|
-
...bunCacheRestoreSteps(project),
|
|
274
|
-
|
|
275
|
-
name: "Setup Node.js",
|
|
276
|
-
uses: "actions/setup-node@v6",
|
|
277
|
-
with: { "node-version": "22" },
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
name: "Setup Python",
|
|
281
|
-
uses: "actions/setup-python@v6",
|
|
282
|
-
with: { "python-version": "3.11" },
|
|
283
|
-
},
|
|
284
|
-
{ name: "Setup Rust", uses: "dtolnay/rust-toolchain@stable" },
|
|
285
|
-
{ name: "Configure Pages", uses: "actions/configure-pages@v5" },
|
|
286
|
-
{ name: "Install dependencies", run: "bun install" },
|
|
287
|
-
{
|
|
288
|
-
name: "Validate public source documentation",
|
|
289
|
-
run: "bun docs/scripts/check-source-docs.mjs",
|
|
290
|
-
},
|
|
291
|
-
{ name: "Generate docs from READMEs", run: "bun docs/scripts/sync-readmes.mjs" },
|
|
292
|
-
{ name: "Install docs dependencies", run: "bun install --cwd .docs-build/site" },
|
|
286
|
+
...bunCacheRestoreSteps(project, { ignorePaths: project.workflowCacheIgnorePaths }),
|
|
287
|
+
...options.prepareSteps,
|
|
293
288
|
bunCacheSaveStep(),
|
|
294
|
-
|
|
295
|
-
name: "Generate API docs",
|
|
296
|
-
run: "bun docs/scripts/generate-api-docs.mjs",
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
name: "Check generated titles",
|
|
300
|
-
run: "bun docs/scripts/check-generated-titles.mjs",
|
|
301
|
-
},
|
|
302
|
-
{ name: "Build docs", run: "bun run --cwd .docs-build/site build" },
|
|
303
|
-
{
|
|
304
|
-
name: "Check generated links",
|
|
305
|
-
run: "bun run --cwd .docs-build/site check-links",
|
|
306
|
-
},
|
|
289
|
+
...options.buildSteps,
|
|
307
290
|
{
|
|
308
291
|
name: "Upload Pages artifact",
|
|
309
292
|
uses: "actions/upload-pages-artifact@v4",
|
|
310
|
-
with: { path:
|
|
293
|
+
with: { path: options.artifactPath },
|
|
311
294
|
},
|
|
312
295
|
],
|
|
313
296
|
});
|
|
@@ -355,7 +338,13 @@ export class DBXToolsRelease extends Component {
|
|
|
355
338
|
exec: taskScript(
|
|
356
339
|
project,
|
|
357
340
|
"release-pr.ts",
|
|
358
|
-
|
|
341
|
+
[
|
|
342
|
+
`--prefix ${tagPrefix}`,
|
|
343
|
+
`--base ${releaseBranch}`,
|
|
344
|
+
...(options.pythonRoot
|
|
345
|
+
? [`--python-root ${JSON.stringify(options.pythonRoot)}`]
|
|
346
|
+
: []),
|
|
347
|
+
].join(" "),
|
|
359
348
|
),
|
|
360
349
|
receiveArgs: true,
|
|
361
350
|
description: "Prepare, validate, locally publish, and open a reviewed release PR",
|
package/src/tsconfig.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Root `tsconfig.base.json` and `tsconfig.json` for the projenrc program.
|
|
3
3
|
*/
|
|
4
|
-
import { Component,
|
|
4
|
+
import { Component, type Project, javascript, typescript } from "projen";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Compiler options for the ROOT program only (`.projenrc.ts` + the engine as
|
|
@@ -37,24 +37,24 @@ export class DBXToolsRootTsconfig extends Component {
|
|
|
37
37
|
constructor(scope: Project) {
|
|
38
38
|
super(scope);
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
obj: { compilerOptions: BASE_COMPILER_OPTIONS },
|
|
44
|
-
});
|
|
40
|
+
if (scope instanceof typescript.TypeScriptProject) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
45
43
|
|
|
46
|
-
new
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
exclude: ["node_modules", "**/dist", "**/node_modules"],
|
|
44
|
+
const base = new javascript.TypescriptConfig(scope, {
|
|
45
|
+
fileName: "tsconfig.base.json",
|
|
46
|
+
compilerOptions: BASE_COMPILER_OPTIONS,
|
|
47
|
+
});
|
|
48
|
+
base.file.readonly = true;
|
|
49
|
+
const root = new javascript.TypescriptConfig(scope, {
|
|
50
|
+
extends: javascript.TypescriptConfigExtends.fromTypescriptConfigs([base]),
|
|
51
|
+
compilerOptions: {
|
|
52
|
+
lib: ["ESNext"],
|
|
53
|
+
types: ["node"],
|
|
57
54
|
},
|
|
55
|
+
include: [".projenrc.ts"],
|
|
56
|
+
exclude: ["node_modules", "**/dist", "**/node_modules"],
|
|
58
57
|
});
|
|
58
|
+
root.file.readonly = true;
|
|
59
59
|
}
|
|
60
60
|
}
|
package/tasks/local-publish.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface LocalPublishOptions {
|
|
|
16
16
|
readonly version: string;
|
|
17
17
|
readonly localRegistry: string;
|
|
18
18
|
readonly localPypi: string;
|
|
19
|
-
readonly pythonRoot
|
|
19
|
+
readonly pythonRoot?: string;
|
|
20
20
|
readonly localCargo: boolean;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -50,7 +50,7 @@ export async function publishLocalRelease(options: LocalPublishOptions): Promise
|
|
|
50
50
|
const localRegistry = resolveLocalRegistry(options.localRegistry);
|
|
51
51
|
const activeIndexes = activePythonIndexes();
|
|
52
52
|
const localPypi = resolveLocalPypi(options.localPypi, activeIndexes);
|
|
53
|
-
const pythonRoot = resolve(options.root, options.pythonRoot);
|
|
53
|
+
const pythonRoot = options.pythonRoot ? resolve(options.root, options.pythonRoot) : undefined;
|
|
54
54
|
const localPublishes: Promise<unknown>[] = [];
|
|
55
55
|
|
|
56
56
|
if (
|
|
@@ -79,7 +79,7 @@ export async function publishLocalRelease(options: LocalPublishOptions): Promise
|
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
if (localPypi && existsSync(pythonRoot)) {
|
|
82
|
+
if (localPypi && pythonRoot && existsSync(pythonRoot)) {
|
|
83
83
|
const publishPythonScript = fileURLToPath(new URL("./publish-python.ts", import.meta.url));
|
|
84
84
|
logger.info(`publishing Python ${options.version} to local devpi ${localPypi.publishUrl}`);
|
|
85
85
|
localPublishes.push(
|