@dbx-tools/projen 0.6.161 → 0.6.163
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 +6 -1
- package/index.ts +3 -0
- package/package.json +4 -4
- package/src/bun-workflow.ts +145 -0
- package/src/project-js.ts +21 -0
- package/src/project-rs.ts +10 -9
- package/src/release.ts +6 -4
- package/tasks/uniffi-release.mjs +1 -3
package/README.md
CHANGED
|
@@ -122,13 +122,18 @@ MSRV recorded in package manifests, while `releaseRustVersion` independently
|
|
|
122
122
|
defaults release compilation to `stable`. UBRN uses that same release toolchain
|
|
123
123
|
unless `ubrnRustVersion` explicitly selects another one.
|
|
124
124
|
|
|
125
|
+
Generated build and release workflows share the Bun cache helpers from
|
|
126
|
+
`bun-workflow.ts`. One `BUN_VERSION` value drives setup and cache keys, while a
|
|
127
|
+
generated dependency-only fingerprint keeps release version bumps from
|
|
128
|
+
invalidating Bun's global package cache. `node_modules` remains uncached.
|
|
129
|
+
|
|
125
130
|
The final host UBRN executable is cached by pinned UBRN version, Rust toolchain,
|
|
126
131
|
runner OS, and runner architecture. A hit skips both the workspace `bun install`
|
|
127
132
|
and the UBRN Cargo build. Release packaging passes the cached executable directly
|
|
128
133
|
to the Node binding generator and keeps the package barrel copied from source,
|
|
129
134
|
so it does not need the installed projen dependency graph. A miss saves the
|
|
130
135
|
validated executable immediately, before workspace build and packaging can fail.
|
|
131
|
-
Cargo registry caches
|
|
136
|
+
Bun runtime setup still runs because the binding generator is TypeScript. Cargo registry caches
|
|
132
137
|
and the `SCCACHE_GHA_VERSION` namespace stay stable per target/toolchain across
|
|
133
138
|
version tags. Cache keys, restore results, sccache statistics, and phase timings
|
|
134
139
|
are written to each build log. Python generation executes the already-built
|
package/index.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/projen";
|
|
6
6
|
export * as barrels from "./src/barrels.ts";
|
|
7
7
|
export * as bunApp from "./src/bun-app.ts";
|
|
8
|
+
export * as bunWorkflow from "./src/bun-workflow.ts";
|
|
8
9
|
export * as clean from "./src/clean.ts";
|
|
9
10
|
export * as codegen from "./src/codegen.ts";
|
|
10
11
|
export * as dbxToolsConfig from "./src/dbx-tools-config.ts";
|
|
@@ -31,6 +32,8 @@ export * as vscode from "./src/vscode.ts";
|
|
|
31
32
|
export * as watch from "./src/watch.ts";
|
|
32
33
|
export * as workspaceVersion from "./src/workspace-version.ts";
|
|
33
34
|
export { BUN_DEV_OVERRIDE, BUN_BUILD_OVERRIDE, BUN_APP_OVERRIDES, RootBunfigFile, BunfigFile, BunDevServerFile, BunBuildFile } from "./src/bun-app.ts";
|
|
35
|
+
export { BUN_VERSION } from "./src/bun-workflow.ts";
|
|
36
|
+
export type { BunWorkflowCacheOptions } from "./src/bun-workflow.ts";
|
|
34
37
|
export { DBXToolsConfig } from "./src/dbx-tools-config.ts";
|
|
35
38
|
export type { DBXToolsConfigOptions } from "./src/dbx-tools-config.ts";
|
|
36
39
|
export { resolvePkgRoot } from "./src/engine-root.ts";
|
package/package.json
CHANGED
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@clack/prompts": "^1.7.0",
|
|
29
|
-
"@dbx-tools/core": "0.6.
|
|
30
|
-
"@dbx-tools/path": "0.6.
|
|
31
|
-
"@dbx-tools/shared-core": "0.6.
|
|
29
|
+
"@dbx-tools/core": "0.6.163",
|
|
30
|
+
"@dbx-tools/path": "0.6.163",
|
|
31
|
+
"@dbx-tools/shared-core": "0.6.163",
|
|
32
32
|
"commander": "^15.0.0",
|
|
33
33
|
"concurrently": "^10.0.3",
|
|
34
34
|
"constructs": "^10.6.0",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"main": "index.ts",
|
|
50
50
|
"license": "Apache-2.0",
|
|
51
|
-
"version": "0.6.
|
|
51
|
+
"version": "0.6.163",
|
|
52
52
|
"types": "index.ts",
|
|
53
53
|
"type": "module",
|
|
54
54
|
"exports": {
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/** Shared Bun setup and package-cache steps for generated workflows. */
|
|
2
|
+
import { TextFile, javascript } from "projen";
|
|
3
|
+
|
|
4
|
+
export const BUN_VERSION = "1.3.14";
|
|
5
|
+
|
|
6
|
+
const cacheKeyScript = `#!/usr/bin/env node
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
|
|
11
|
+
const root = process.cwd();
|
|
12
|
+
const ignored = new Set([
|
|
13
|
+
".git",
|
|
14
|
+
".docs-build",
|
|
15
|
+
".venv",
|
|
16
|
+
".worktrees",
|
|
17
|
+
"coverage",
|
|
18
|
+
"dist",
|
|
19
|
+
"lib",
|
|
20
|
+
"node_modules",
|
|
21
|
+
"target",
|
|
22
|
+
]);
|
|
23
|
+
const manifests = [];
|
|
24
|
+
const walk = (directory) => {
|
|
25
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
26
|
+
if (ignored.has(entry.name)) continue;
|
|
27
|
+
const path = join(directory, entry.name);
|
|
28
|
+
if (entry.isDirectory()) walk(path);
|
|
29
|
+
else if (entry.name === "package.json") manifests.push(path);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
walk(root);
|
|
33
|
+
|
|
34
|
+
const dependencyFields = [
|
|
35
|
+
"catalog",
|
|
36
|
+
"dependencies",
|
|
37
|
+
"devDependencies",
|
|
38
|
+
"optionalDependencies",
|
|
39
|
+
"overrides",
|
|
40
|
+
"peerDependencies",
|
|
41
|
+
"peerDependenciesMeta",
|
|
42
|
+
"resolutions",
|
|
43
|
+
"trustedDependencies",
|
|
44
|
+
];
|
|
45
|
+
const canonical = (value) => {
|
|
46
|
+
if (Array.isArray(value)) return value.map(canonical);
|
|
47
|
+
if (!value || typeof value !== "object") return value;
|
|
48
|
+
return Object.fromEntries(
|
|
49
|
+
Object.entries(value)
|
|
50
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
51
|
+
.map(([key, child]) => [key, canonical(child)]),
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
const dependencies = manifests
|
|
55
|
+
.sort()
|
|
56
|
+
.map((path) => {
|
|
57
|
+
const manifest = JSON.parse(readFileSync(path, "utf8"));
|
|
58
|
+
return [
|
|
59
|
+
path.slice(root.length + 1),
|
|
60
|
+
Object.fromEntries(
|
|
61
|
+
dependencyFields
|
|
62
|
+
.filter((field) => manifest[field] !== undefined)
|
|
63
|
+
.map((field) => [field, canonical(manifest[field])]),
|
|
64
|
+
),
|
|
65
|
+
];
|
|
66
|
+
});
|
|
67
|
+
process.stdout.write(createHash("sha256").update(JSON.stringify(dependencies)).digest("hex"));
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
const configured = new WeakSet<javascript.NodeProject>();
|
|
71
|
+
|
|
72
|
+
function ensureCacheKeyScript(project: javascript.NodeProject): void {
|
|
73
|
+
if (configured.has(project)) return;
|
|
74
|
+
new TextFile(project.root, ".projen/bun-cache-key.mjs", {
|
|
75
|
+
lines: cacheKeyScript.trimEnd().split("\n"),
|
|
76
|
+
});
|
|
77
|
+
configured.add(project);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function stepCondition(condition: string | undefined, cacheMiss = false): string | undefined {
|
|
81
|
+
const expressions = [
|
|
82
|
+
condition,
|
|
83
|
+
...(cacheMiss ? ["steps.bun_cache.outputs.cache-hit != 'true'"] : []),
|
|
84
|
+
].filter(Boolean);
|
|
85
|
+
return expressions.length ? `\${{ ${expressions.join(" && ")} }}` : undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface BunWorkflowCacheOptions {
|
|
89
|
+
readonly setupCondition?: string;
|
|
90
|
+
readonly condition?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Set up Bun and restore its global package cache. */
|
|
94
|
+
export function bunCacheRestoreSteps(
|
|
95
|
+
project: javascript.NodeProject,
|
|
96
|
+
options: BunWorkflowCacheOptions = {},
|
|
97
|
+
): readonly Record<string, unknown>[] {
|
|
98
|
+
ensureCacheKeyScript(project);
|
|
99
|
+
const condition = stepCondition(options.condition);
|
|
100
|
+
const setupCondition = stepCondition(options.setupCondition);
|
|
101
|
+
return [
|
|
102
|
+
{
|
|
103
|
+
name: "Setup Bun",
|
|
104
|
+
...(setupCondition ? { if: setupCondition } : {}),
|
|
105
|
+
uses: "oven-sh/setup-bun@v2",
|
|
106
|
+
with: { "bun-version": "${{ env.BUN_VERSION }}" },
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "Resolve Bun cache",
|
|
110
|
+
id: "bun_cache_metadata",
|
|
111
|
+
...(condition ? { if: condition } : {}),
|
|
112
|
+
shell: "bash",
|
|
113
|
+
run: [
|
|
114
|
+
'echo "path=$(bun pm cache)" >> "$GITHUB_OUTPUT"',
|
|
115
|
+
'echo "dependency_hash=$(node .projen/bun-cache-key.mjs)" >> "$GITHUB_OUTPUT"',
|
|
116
|
+
].join("\n"),
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "Restore Bun cache",
|
|
120
|
+
id: "bun_cache",
|
|
121
|
+
...(condition ? { if: condition } : {}),
|
|
122
|
+
uses: "actions/cache/restore@v5",
|
|
123
|
+
with: {
|
|
124
|
+
path: "${{ steps.bun_cache_metadata.outputs.path }}",
|
|
125
|
+
key: `bun-\${{ runner.os }}-\${{ runner.arch }}-\${{ env.BUN_VERSION }}-\${{ steps.bun_cache_metadata.outputs.dependency_hash }}`,
|
|
126
|
+
"restore-keys": `bun-\${{ runner.os }}-\${{ runner.arch }}-\${{ env.BUN_VERSION }}-`,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Save Bun's global package cache immediately after installation. */
|
|
133
|
+
export function bunCacheSaveStep(
|
|
134
|
+
options: BunWorkflowCacheOptions = {},
|
|
135
|
+
): Readonly<Record<string, unknown>> {
|
|
136
|
+
return {
|
|
137
|
+
name: "Save Bun cache",
|
|
138
|
+
if: stepCondition(options.condition, true),
|
|
139
|
+
uses: "actions/cache/save@v5",
|
|
140
|
+
with: {
|
|
141
|
+
path: "${{ steps.bun_cache_metadata.outputs.path }}",
|
|
142
|
+
key: "${{ steps.bun_cache.outputs.cache-primary-key }}",
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
package/src/project-js.ts
CHANGED
|
@@ -13,6 +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 { JobStep } from "projen/lib/github/workflows-model";
|
|
16
17
|
import { ReleaseTrigger } from "projen/lib/release";
|
|
17
18
|
import { mixin } from "..";
|
|
18
19
|
import { generateBarrels } from "./barrels.ts";
|
|
@@ -23,6 +24,7 @@ import {
|
|
|
23
24
|
BunfigFile,
|
|
24
25
|
RootBunfigFile,
|
|
25
26
|
} from "./bun-app.ts";
|
|
27
|
+
import { BUN_VERSION, bunCacheRestoreSteps, bunCacheSaveStep } from "./bun-workflow.ts";
|
|
26
28
|
import { codegenModulePaths, generateCodegen } from "./codegen.ts";
|
|
27
29
|
import { DBXToolsConfig, type DBXToolsConfigOptions } from "./dbx-tools-config.ts";
|
|
28
30
|
import { resolvePkgRoot } from "./engine-root.ts";
|
|
@@ -642,6 +644,24 @@ export class DBXToolsNodeProject
|
|
|
642
644
|
initProject(this, options);
|
|
643
645
|
}
|
|
644
646
|
|
|
647
|
+
public override renderWorkflowSetup(options?: javascript.RenderWorkflowSetupOptions): JobStep[] {
|
|
648
|
+
const steps = super.renderWorkflowSetup(options);
|
|
649
|
+
if (this.parent) return steps;
|
|
650
|
+
return steps.flatMap((step) => {
|
|
651
|
+
if (step.uses === "oven-sh/setup-bun@v2") return [...bunCacheRestoreSteps(this)];
|
|
652
|
+
if (step.run === "bun install") {
|
|
653
|
+
return [
|
|
654
|
+
step,
|
|
655
|
+
bunCacheSaveStep({
|
|
656
|
+
condition:
|
|
657
|
+
"github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository",
|
|
658
|
+
}),
|
|
659
|
+
];
|
|
660
|
+
}
|
|
661
|
+
return [step];
|
|
662
|
+
}) as JobStep[];
|
|
663
|
+
}
|
|
664
|
+
|
|
645
665
|
public override preSynthesize(): void {
|
|
646
666
|
if (this.rootInstallOnly) this.with(ROOT_INSTALL_ONLY_MIXIN);
|
|
647
667
|
super.preSynthesize();
|
|
@@ -1066,6 +1086,7 @@ function initProject(
|
|
|
1066
1086
|
// a plain `bun` exec rather than any wrapper: the default task is spawned by
|
|
1067
1087
|
// nested installs/synths, and a wrapper that exported `npm_config_*` broke them.
|
|
1068
1088
|
project.defaultTask?.reset("bun .projenrc.ts");
|
|
1089
|
+
project.buildWorkflow?.workflow.file?.addOverride("jobs.build.env.BUN_VERSION", BUN_VERSION);
|
|
1069
1090
|
|
|
1070
1091
|
// Pin bun's hoisted linker workspace-wide (see RootBunfigFile) so a peer dep
|
|
1071
1092
|
// resolves to one copy and singletons/types stay coherent.
|
package/src/project-rs.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import { project as coreProject } from "@dbx-tools/core";
|
|
6
6
|
import { string } from "@dbx-tools/shared-core";
|
|
7
7
|
import { Project, TextFile, YamlFile, javascript } from "projen";
|
|
8
|
+
import { BUN_VERSION, bunCacheRestoreSteps, bunCacheSaveStep } from "./bun-workflow.ts";
|
|
8
9
|
import type { DBXToolsProject } from "./project.ts";
|
|
9
10
|
import {
|
|
10
11
|
DBXToolsTypeScriptProject,
|
|
@@ -766,6 +767,7 @@ export class DBXToolsRustWorkspace {
|
|
|
766
767
|
"runs-on": "${{ matrix.target.runner }}",
|
|
767
768
|
env: {
|
|
768
769
|
...RUST_CACHE_ENV,
|
|
770
|
+
BUN_VERSION,
|
|
769
771
|
SCCACHE_GHA_VERSION: `release-\${{ matrix.target.cargo }}-rust-${releaseRustVersion}`,
|
|
770
772
|
},
|
|
771
773
|
strategy: {
|
|
@@ -774,15 +776,6 @@ export class DBXToolsRustWorkspace {
|
|
|
774
776
|
},
|
|
775
777
|
steps: [
|
|
776
778
|
...releaseSourceSteps(),
|
|
777
|
-
...(hasNodeBindings
|
|
778
|
-
? [
|
|
779
|
-
{
|
|
780
|
-
name: "Setup Bun",
|
|
781
|
-
uses: "oven-sh/setup-bun@v2",
|
|
782
|
-
with: { "bun-version": "1.3.14" },
|
|
783
|
-
},
|
|
784
|
-
]
|
|
785
|
-
: []),
|
|
786
779
|
...(hasPythonBindings ? [{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" }] : []),
|
|
787
780
|
{
|
|
788
781
|
name: "Setup Rust",
|
|
@@ -803,6 +796,11 @@ export class DBXToolsRustWorkspace {
|
|
|
803
796
|
},
|
|
804
797
|
]
|
|
805
798
|
: []),
|
|
799
|
+
...(hasNodeBindings
|
|
800
|
+
? bunCacheRestoreSteps(project, {
|
|
801
|
+
condition: "steps.ubrn_cache.outputs.cache-hit != 'true'",
|
|
802
|
+
})
|
|
803
|
+
: []),
|
|
806
804
|
{
|
|
807
805
|
name: "Log cache configuration",
|
|
808
806
|
shell: "bash",
|
|
@@ -833,6 +831,9 @@ export class DBXToolsRustWorkspace {
|
|
|
833
831
|
shell: "bash",
|
|
834
832
|
run: timedBash("node_tooling", "bun install"),
|
|
835
833
|
},
|
|
834
|
+
bunCacheSaveStep({
|
|
835
|
+
condition: "steps.ubrn_cache.outputs.cache-hit != 'true'",
|
|
836
|
+
}),
|
|
836
837
|
]
|
|
837
838
|
: []),
|
|
838
839
|
...(hasNodeBindings
|
package/src/release.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { Component, YamlFile } from "projen";
|
|
|
10
10
|
import { GithubWorkflow } from "projen/lib/github";
|
|
11
11
|
import { JobPermission, type JobStep } from "projen/lib/github/workflows-model";
|
|
12
12
|
import { object } from "@dbx-tools/shared-core";
|
|
13
|
+
import { BUN_VERSION, bunCacheRestoreSteps, bunCacheSaveStep } from "./bun-workflow.ts";
|
|
13
14
|
import { applyTasks, taskScript, type DBXToolsNodeProject } from "./project.ts";
|
|
14
15
|
import {
|
|
15
16
|
DOWNSTREAM_RELEASE_EVENT,
|
|
@@ -21,7 +22,6 @@ import {
|
|
|
21
22
|
|
|
22
23
|
const NODE_VERSION = "lts/*";
|
|
23
24
|
const NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
24
|
-
const BUN_VERSION = "1.3.14";
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* The `release` workflow's version-stamp + publish step, as a shell script.
|
|
@@ -73,10 +73,10 @@ interface PublishWorkflow {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/** Shared checkout and toolchain setup for every npm publish workflow. */
|
|
76
|
-
function publishSetupSteps(): JobStep[] {
|
|
76
|
+
function publishSetupSteps(project: DBXToolsNodeProject): JobStep[] {
|
|
77
77
|
return [
|
|
78
78
|
{ name: "Checkout", uses: "actions/checkout@v6", with: { "fetch-depth": 0 } },
|
|
79
|
-
|
|
79
|
+
...bunCacheRestoreSteps(project),
|
|
80
80
|
{
|
|
81
81
|
name: "Setup Node.js",
|
|
82
82
|
uses: "actions/setup-node@v6",
|
|
@@ -88,6 +88,7 @@ function publishSetupSteps(): JobStep[] {
|
|
|
88
88
|
},
|
|
89
89
|
// Bun's install; the lockfile may be absent or stale in CI so it is not frozen.
|
|
90
90
|
{ name: "Install", run: "bun install" },
|
|
91
|
+
bunCacheSaveStep(),
|
|
91
92
|
];
|
|
92
93
|
}
|
|
93
94
|
|
|
@@ -301,7 +302,7 @@ export class DBXToolsRelease extends Component {
|
|
|
301
302
|
project: DBXToolsNodeProject,
|
|
302
303
|
{ name, tagPrefix, steps, workingDirectory, upstreamWorkflow }: PublishWorkflow,
|
|
303
304
|
): void {
|
|
304
|
-
const setupSteps = publishSetupSteps();
|
|
305
|
+
const setupSteps = publishSetupSteps(project);
|
|
305
306
|
const branchDispatch = upstreamWorkflow === undefined;
|
|
306
307
|
const workflow = new GithubWorkflow(project.github!, name, {
|
|
307
308
|
// A newer release supersedes an older run even when publication has
|
|
@@ -369,6 +370,7 @@ export class DBXToolsRelease extends Component {
|
|
|
369
370
|
// `DRY_RUN_INPUT` is `--dry-run` when the dispatch input is true, else empty;
|
|
370
371
|
// the publish script also FORCES it on any `workflow_dispatch` run.
|
|
371
372
|
env: {
|
|
373
|
+
BUN_VERSION,
|
|
372
374
|
CI: "true",
|
|
373
375
|
DRY_RUN_INPUT: "${{ github.event.inputs.dry_run == 'true' && '--dry-run' || '' }}",
|
|
374
376
|
},
|
package/tasks/uniffi-release.mjs
CHANGED
|
@@ -150,10 +150,8 @@ const packageNode = ({
|
|
|
150
150
|
required("cargo-target"),
|
|
151
151
|
"--node-package-base",
|
|
152
152
|
`${nodePackage}-`,
|
|
153
|
-
"--ubrn",
|
|
154
|
-
required("ubrn"),
|
|
153
|
+
...(parsed.values.ubrn ? ["--ubrn", parsed.values.ubrn, "--skip-barrels"] : []),
|
|
155
154
|
"--skip-build",
|
|
156
|
-
"--skip-barrels",
|
|
157
155
|
]);
|
|
158
156
|
mkdirSync(resolve(output, "npm-facade"), { recursive: true });
|
|
159
157
|
run("npm", ["pack", "--pack-destination", resolve(output, "npm-facade")], facadeDirectory);
|