@dbx-tools/projen 0.9.6 → 0.9.8
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 -1
- package/index.ts +2 -1
- package/package.json +4 -4
- package/src/_rust-project.ts +46 -0
- package/src/_rust-release-workflow.ts +157 -52
- package/src/barrels.ts +3 -4
- package/src/bun-app.ts +96 -85
- package/src/bun-workflow.ts +60 -52
- package/src/openapi.ts +15 -8
- package/src/project-py.ts +22 -17
- package/src/project-rs.ts +48 -11
- package/src/release-catalog.ts +4 -1
- package/src/release.ts +206 -170
- package/src/watch.ts +4 -1
- package/src/workspace-lock.ts +22 -0
- package/tasks/publish-uniffi-local.ts +80 -7
- package/tasks/release-pr.ts +215 -204
- package/tasks/sync.ts +6 -5
package/README.md
CHANGED
|
@@ -254,7 +254,11 @@ and select `rust-lld` for the workspace build. Rust release rows restore and
|
|
|
254
254
|
update dependency-only Cargo caches in the release branch's cache scope. The
|
|
255
255
|
cache key excludes workspace version changes, and manual tag recovery restores
|
|
256
256
|
without saving a tag-scoped copy. There is no separate cache workflow or
|
|
257
|
-
sccache layer.
|
|
257
|
+
sccache layer. After publishing the current raw Rust bundles and build manifests,
|
|
258
|
+
the GitHub release job deletes those internal assets from published
|
|
259
|
+
`vMAJOR.MINOR.PATCH` releases strictly lower than the current version while
|
|
260
|
+
leaving versioned consumer binaries in place. Phase timings are written to each
|
|
261
|
+
build log. Python generation executes the already-built
|
|
258
262
|
`target/<triple>/release/<crate>-uniffi-bindgen` directly. Artifact packaging therefore
|
|
259
263
|
does no Rust compilation after the main workspace build.
|
|
260
264
|
|
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.9.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.8";
|
|
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";
|
|
@@ -36,6 +36,7 @@ export * as tsconfig from "./src/tsconfig.ts";
|
|
|
36
36
|
export * as uniffi from "./src/uniffi.ts";
|
|
37
37
|
export * as vscode from "./src/vscode.ts";
|
|
38
38
|
export * as watch from "./src/watch.ts";
|
|
39
|
+
export * as workspaceLock from "./src/workspace-lock.ts";
|
|
39
40
|
export * as workspaceVersion from "./src/workspace-version.ts";
|
|
40
41
|
export { BUN_DEV_OVERRIDE, BUN_BUILD_OVERRIDE, BUN_APP_OVERRIDES, RootBunfigFile, BunfigFile, BunDevServerFile, BunBuildFile } from "./src/bun-app.ts";
|
|
41
42
|
export { BUN_VERSION } from "./src/bun-workflow.ts";
|
package/package.json
CHANGED
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@clack/prompts": "^1.7.0",
|
|
33
|
-
"@dbx-tools/core": "^0.9.
|
|
34
|
-
"@dbx-tools/path": "^0.9.
|
|
35
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
33
|
+
"@dbx-tools/core": "^0.9.8",
|
|
34
|
+
"@dbx-tools/path": "^0.9.8",
|
|
35
|
+
"@dbx-tools/shared-core": "^0.9.8",
|
|
36
36
|
"commander": "^15.0.0",
|
|
37
37
|
"concurrently": "^10.0.3",
|
|
38
38
|
"constructs": "^10.6.0",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"main": "index.ts",
|
|
55
55
|
"license": "Apache-2.0",
|
|
56
|
-
"version": "0.9.
|
|
56
|
+
"version": "0.9.8",
|
|
57
57
|
"types": "index.ts",
|
|
58
58
|
"type": "module",
|
|
59
59
|
"exports": {
|
package/src/_rust-project.ts
CHANGED
|
@@ -26,6 +26,19 @@ export interface RustCliOptions {
|
|
|
26
26
|
readonly command?: string;
|
|
27
27
|
/** Root CLI help text. Defaults to the Rust package description. */
|
|
28
28
|
readonly description?: string;
|
|
29
|
+
/** Keep the binary installable by registry lookup without exposing a root command. */
|
|
30
|
+
readonly hidden?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** One explicit Cargo binary target and its optional release registration. */
|
|
34
|
+
export interface RustBinaryOptions {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly path: string;
|
|
37
|
+
readonly requiredFeatures?: readonly string[];
|
|
38
|
+
readonly release?: boolean;
|
|
39
|
+
readonly releaseExcludeOs?: readonly RustReleaseOs[];
|
|
40
|
+
readonly description?: string;
|
|
41
|
+
readonly cli?: boolean | RustCliOptions;
|
|
29
42
|
}
|
|
30
43
|
|
|
31
44
|
/** Explicit Cargo example target and the feature gate required to compile it. */
|
|
@@ -47,6 +60,8 @@ export interface RustCrateOptions {
|
|
|
47
60
|
/** Omit this crate and any release binary artifact from these operating systems. */
|
|
48
61
|
readonly releaseExcludeOs?: readonly RustReleaseOs[];
|
|
49
62
|
readonly dependencies?: Readonly<Record<string, CargoDependency>>;
|
|
63
|
+
/** Cargo dependencies scoped by a target cfg expression. */
|
|
64
|
+
readonly targetDependencies?: Readonly<Record<string, Readonly<Record<string, CargoDependency>>>>;
|
|
50
65
|
readonly devDependencies?: Readonly<Record<string, CargoDependency>>;
|
|
51
66
|
readonly features?: Readonly<Record<string, readonly string[]>>;
|
|
52
67
|
readonly defaultFeatures?: readonly string[];
|
|
@@ -54,6 +69,10 @@ export interface RustCrateOptions {
|
|
|
54
69
|
readonly examples?: readonly CargoExampleOptions[];
|
|
55
70
|
/** Cargo and release executable name. Defaults to the generated package name. */
|
|
56
71
|
readonly binaryName?: string;
|
|
72
|
+
/** Additional Cargo binary targets owned by this crate. */
|
|
73
|
+
readonly binaries?: readonly RustBinaryOptions[];
|
|
74
|
+
/** Cargo binary selected by `cargo run` when this crate has multiple binaries. */
|
|
75
|
+
readonly defaultRun?: string;
|
|
57
76
|
/** Publish this release binary through the generated `dbx` command registry. */
|
|
58
77
|
readonly cli?: boolean | RustCliOptions;
|
|
59
78
|
readonly bindings?: readonly ("node" | "python")[];
|
|
@@ -187,10 +206,12 @@ function packageOptions(
|
|
|
187
206
|
...(options.release !== undefined ? { release: options.release } : {}),
|
|
188
207
|
...(options.releaseExcludeOs ? { releaseExcludeOs: options.releaseExcludeOs } : {}),
|
|
189
208
|
...(options.dependencies ? { dependencies: options.dependencies } : {}),
|
|
209
|
+
...(options.targetDependencies ? { targetDependencies: options.targetDependencies } : {}),
|
|
190
210
|
...(options.devDependencies ? { devDependencies: options.devDependencies } : {}),
|
|
191
211
|
...(options.features ? { features: options.features } : {}),
|
|
192
212
|
...(options.defaultFeatures ? { defaultFeatures: options.defaultFeatures } : {}),
|
|
193
213
|
...(options.binaryName ? { binaryName: options.binaryName } : {}),
|
|
214
|
+
...(options.binaries ? { binaries: options.binaries } : {}),
|
|
194
215
|
...(options.cli !== undefined ? { cli: options.cli } : {}),
|
|
195
216
|
...(options.bindings ? { bindings: options.bindings } : {}),
|
|
196
217
|
...(options.uniffiConfig ? { uniffiConfig: options.uniffiConfig } : {}),
|
|
@@ -244,6 +265,7 @@ export class RustProject extends Project implements DBXToolsProject {
|
|
|
244
265
|
...(!workspace ? { workspace: {} } : {}),
|
|
245
266
|
package: {
|
|
246
267
|
name: this.crateName,
|
|
268
|
+
...(options.defaultRun ? { "default-run": options.defaultRun } : {}),
|
|
247
269
|
version: inheritedCargoValue(workspace, options.version, "0.1.0"),
|
|
248
270
|
edition: inheritedCargoValue(workspace, options.edition, "2021"),
|
|
249
271
|
"rust-version": inheritedCargoValue(workspace, options.rustVersion, "1.82"),
|
|
@@ -272,6 +294,13 @@ export class RustProject extends Project implements DBXToolsProject {
|
|
|
272
294
|
? [{ name: `${this.crateName}-uniffi-bindgen`, path: "uniffi-bindgen.rs" }]
|
|
273
295
|
: []),
|
|
274
296
|
...(binary ? [{ name: binaryName, path: "src/main.rs" }] : []),
|
|
297
|
+
...(options.binaries ?? []).map((target) => ({
|
|
298
|
+
name: target.name,
|
|
299
|
+
path: target.path,
|
|
300
|
+
...(target.requiredFeatures?.length
|
|
301
|
+
? { "required-features": [...target.requiredFeatures] }
|
|
302
|
+
: {}),
|
|
303
|
+
})),
|
|
275
304
|
],
|
|
276
305
|
}
|
|
277
306
|
: {}),
|
|
@@ -304,6 +333,23 @@ export class RustProject extends Project implements DBXToolsProject {
|
|
|
304
333
|
),
|
|
305
334
|
}
|
|
306
335
|
: {}),
|
|
336
|
+
...(options.targetDependencies
|
|
337
|
+
? {
|
|
338
|
+
target: Object.fromEntries(
|
|
339
|
+
Object.entries(options.targetDependencies).map(([target, dependencies]) => [
|
|
340
|
+
target,
|
|
341
|
+
{
|
|
342
|
+
dependencies: Object.fromEntries(
|
|
343
|
+
Object.entries(dependencies).map(([name, value]) => [
|
|
344
|
+
name,
|
|
345
|
+
cargoDependency(value, dependencyVersion),
|
|
346
|
+
]),
|
|
347
|
+
),
|
|
348
|
+
},
|
|
349
|
+
]),
|
|
350
|
+
),
|
|
351
|
+
}
|
|
352
|
+
: {}),
|
|
307
353
|
...(options.devDependencies
|
|
308
354
|
? {
|
|
309
355
|
"dev-dependencies": Object.fromEntries(
|
|
@@ -3,6 +3,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { stringUtils } from "@dbx-tools/shared-core";
|
|
6
7
|
import { TextFile, javascript } from "projen";
|
|
7
8
|
import { JobPermission, type Job, type JobStep } from "projen/lib/github/workflows-model";
|
|
8
9
|
import type { RustProject } from "./_rust-project.ts";
|
|
@@ -127,6 +128,7 @@ interface RustReleaseBinaryPlan {
|
|
|
127
128
|
readonly crate: string;
|
|
128
129
|
readonly binary: string;
|
|
129
130
|
readonly excludedOs: readonly RustReleaseOs[];
|
|
131
|
+
readonly requiredFeatures: readonly string[];
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
type RustReleaseTargetPlan = Readonly<Record<string, string | boolean | number>>;
|
|
@@ -164,13 +166,26 @@ export function planRustRelease(
|
|
|
164
166
|
nodePackage: binding.nodePackage ?? "",
|
|
165
167
|
pythonPackage: binding.pythonPackage ?? "",
|
|
166
168
|
}));
|
|
167
|
-
const releaseBinaries = packages
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
169
|
+
const releaseBinaries = packages.flatMap((pkg) => [
|
|
170
|
+
...(pkg.packageOptions.release
|
|
171
|
+
? [
|
|
172
|
+
{
|
|
173
|
+
crate: pkg.crateName,
|
|
174
|
+
binary: pkg.packageOptions.binaryName ?? pkg.crateName,
|
|
175
|
+
excludedOs: pkg.packageOptions.releaseExcludeOs ?? [],
|
|
176
|
+
requiredFeatures: [],
|
|
177
|
+
},
|
|
178
|
+
]
|
|
179
|
+
: []),
|
|
180
|
+
...(pkg.packageOptions.binaries ?? [])
|
|
181
|
+
.filter((binary) => binary.release)
|
|
182
|
+
.map((binary) => ({
|
|
183
|
+
crate: pkg.crateName,
|
|
184
|
+
binary: binary.name,
|
|
185
|
+
excludedOs: binary.releaseExcludeOs ?? [],
|
|
186
|
+
requiredFeatures: binary.requiredFeatures ?? [],
|
|
187
|
+
})),
|
|
188
|
+
]);
|
|
174
189
|
const publicCrates = orderRustBindings(
|
|
175
190
|
packages
|
|
176
191
|
.filter((pkg) => !pkg.packageOptions.private)
|
|
@@ -337,7 +352,31 @@ function rustBinaryCommands(plan: RustReleasePlan, independent: boolean): string
|
|
|
337
352
|
});
|
|
338
353
|
}
|
|
339
354
|
|
|
355
|
+
function rustAdditionalBinaryBuildCommands(plan: RustReleasePlan, independent: boolean): string[] {
|
|
356
|
+
return plan.releaseBinaries
|
|
357
|
+
.filter((binary) => binary.requiredFeatures.length)
|
|
358
|
+
.flatMap((binary) => {
|
|
359
|
+
const command = `cargo build --release --package "${binary.crate}" --bin "${binary.binary}" --features "${binary.requiredFeatures.join(",")}"${
|
|
360
|
+
plan.usesCargoLock ? " --locked" : ""
|
|
361
|
+
} --target "\${{ matrix.cargo }}"`;
|
|
362
|
+
const excludedCondition = binary.excludedOs
|
|
363
|
+
.map((os) => `[ "\${{ matrix.os }}" != "${os}" ]`)
|
|
364
|
+
.join(" && ");
|
|
365
|
+
const platformCommands = excludedCondition
|
|
366
|
+
? [`if ${excludedCondition}; then`, ` ${command}`, "fi"]
|
|
367
|
+
: [command];
|
|
368
|
+
if (!independent) return platformCommands;
|
|
369
|
+
const unit = defaultReleaseUnitId("rust", binary.crate);
|
|
370
|
+
return [
|
|
371
|
+
`if jq -e --arg unit "${unit}" '.units[] | select(.id == $unit)' dist/release-plan.json >/dev/null; then`,
|
|
372
|
+
...platformCommands.map((line) => ` ${line}`),
|
|
373
|
+
"fi",
|
|
374
|
+
];
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
340
378
|
function rustArtifactSteps(plan: RustReleasePlan): JobStep[] {
|
|
379
|
+
const binaryCrates = [...new Set(plan.releaseBinaries.map((binary) => binary.crate))];
|
|
341
380
|
return [
|
|
342
381
|
...plan.bindings.flatMap((binding) => [
|
|
343
382
|
...(binding.node
|
|
@@ -367,24 +406,35 @@ function rustArtifactSteps(plan: RustReleasePlan): JobStep[] {
|
|
|
367
406
|
]
|
|
368
407
|
: []),
|
|
369
408
|
]),
|
|
370
|
-
...
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
name:
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
409
|
+
...binaryCrates.map((crate) => {
|
|
410
|
+
const binaries = plan.releaseBinaries.filter((binary) => binary.crate === crate);
|
|
411
|
+
const excludedOs =
|
|
412
|
+
binaries[0]?.excludedOs.filter((os) =>
|
|
413
|
+
binaries.every((binary) => binary.excludedOs.includes(os)),
|
|
414
|
+
) ?? [];
|
|
415
|
+
return {
|
|
416
|
+
name: `Upload ${crate} release binary`,
|
|
417
|
+
uses: "actions/upload-artifact@v7",
|
|
418
|
+
...(rustReleaseBinaryCondition(excludedOs)
|
|
419
|
+
? { if: rustReleaseBinaryCondition(excludedOs) }
|
|
420
|
+
: {}),
|
|
421
|
+
with: {
|
|
422
|
+
name: `${crate}-\${{ matrix.node }}-binary`,
|
|
423
|
+
path: `dist/release/${crate}/\${{ matrix.node }}/binary/*`,
|
|
424
|
+
"retention-days": 7,
|
|
425
|
+
},
|
|
426
|
+
};
|
|
427
|
+
}),
|
|
382
428
|
];
|
|
383
429
|
}
|
|
384
430
|
|
|
385
431
|
export function rustBuildJob(plan: RustReleasePlan, independentSetup?: readonly JobStep[]): Job {
|
|
386
432
|
const bindingCommands = rustBindingCommands(plan, Boolean(independentSetup));
|
|
387
433
|
const binaryCommands = rustBinaryCommands(plan, Boolean(independentSetup));
|
|
434
|
+
const additionalBinaryBuildCommands = rustAdditionalBinaryBuildCommands(
|
|
435
|
+
plan,
|
|
436
|
+
Boolean(independentSetup),
|
|
437
|
+
);
|
|
388
438
|
return {
|
|
389
439
|
if: independentSetup
|
|
390
440
|
? "${{ needs.release-plan.outputs.rust_targets != '[]' && (github.event_name == 'push' || inputs.stage != 'docs') }}"
|
|
@@ -482,29 +532,34 @@ export function rustBuildJob(plan: RustReleasePlan, independentSetup?: readonly
|
|
|
482
532
|
id: "raw-native",
|
|
483
533
|
shell: "bash",
|
|
484
534
|
env: { GH_TOKEN: "${{ github.token }}" },
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
"
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
"
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
535
|
+
// prettier-ignore
|
|
536
|
+
run: stringUtils.dedent(
|
|
537
|
+
// ============================================================================
|
|
538
|
+
/*bash*/`
|
|
539
|
+
KEY="\${{ steps.rust-fingerprint.outputs.key }}"
|
|
540
|
+
test -n "$KEY"
|
|
541
|
+
ASSET="rust-raw-\${{ matrix.node }}-$KEY.tar.gz"
|
|
542
|
+
mkdir -p dist/rust-raw
|
|
543
|
+
MATCH="$(gh api --paginate "repos/\${{ github.repository }}/releases?per_page=100" --jq '.[] | select(.draft == false) | . as $release | .assets[] | select(.name == "'"$ASSET"'") | [$release.tag_name, .url] | @tsv' | head -n 1)"
|
|
544
|
+
if [ -n "$MATCH" ]; then
|
|
545
|
+
TAG="\${MATCH%%$'\\t'*}"
|
|
546
|
+
URL="\${MATCH#*$'\\t'}"
|
|
547
|
+
CHECKSUM_URL="$(gh api "repos/\${{ github.repository }}/releases/tags/$TAG" --jq '.assets[] | select(.name == "'"$ASSET.sha256"'") | .url')"
|
|
548
|
+
rm -rf "target/\${{ matrix.cargo }}/release"
|
|
549
|
+
if test -n "$CHECKSUM_URL" && gh api "$URL" -H "Accept: application/octet-stream" > "dist/rust-raw/$ASSET" && gh api "$CHECKSUM_URL" -H "Accept: application/octet-stream" > "dist/rust-raw/$ASSET.sha256" && (cd dist/rust-raw && if command -v sha256sum >/dev/null 2>&1; then sha256sum --check "$ASSET.sha256"; else shasum -a 256 --check "$ASSET.sha256"; fi) && tar -xzf "dist/rust-raw/$ASSET"; then
|
|
550
|
+
echo "hit=true" >> "$GITHUB_OUTPUT"
|
|
551
|
+
else
|
|
552
|
+
rm -rf "target/\${{ matrix.cargo }}/release" "dist/rust-raw/$ASSET" "dist/rust-raw/$ASSET.sha256"
|
|
553
|
+
echo "::warning::matching raw Rust bundle failed validation; rebuilding"
|
|
554
|
+
echo "hit=false" >> "$GITHUB_OUTPUT"
|
|
555
|
+
fi
|
|
556
|
+
else
|
|
557
|
+
echo "hit=false" >> "$GITHUB_OUTPUT"
|
|
558
|
+
fi
|
|
559
|
+
echo "asset=$ASSET" >> "$GITHUB_OUTPUT"
|
|
560
|
+
`
|
|
561
|
+
// ============================================================================
|
|
562
|
+
),
|
|
508
563
|
},
|
|
509
564
|
]
|
|
510
565
|
: []),
|
|
@@ -518,16 +573,19 @@ export function rustBuildJob(plan: RustReleasePlan, independentSetup?: readonly
|
|
|
518
573
|
},
|
|
519
574
|
run: timedBash(
|
|
520
575
|
"rust_workspace",
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
576
|
+
[
|
|
577
|
+
independentSetup
|
|
578
|
+
? [
|
|
579
|
+
"mapfile -t PACKAGES < <(jq -r '.[]' <<<'${{ toJSON(matrix.packages) }}')",
|
|
580
|
+
"PACKAGE_ARGS=()",
|
|
581
|
+
'for PACKAGE in "${PACKAGES[@]}"; do PACKAGE_ARGS+=(--package "$PACKAGE"); done',
|
|
582
|
+
`cargo build --release --timings "\${PACKAGE_ARGS[@]}"${plan.usesCargoLock ? " --locked" : ""} --target "\${{ matrix.cargo }}"`,
|
|
583
|
+
].join("\n")
|
|
584
|
+
: `cargo build --release --timings --workspace${plan.usesCargoLock ? " --locked" : ""} --target "\${{ matrix.cargo }}"${
|
|
585
|
+
plan.hasReleaseExclusions ? " ${{ matrix.cargoExcludes }}" : ""
|
|
586
|
+
}`,
|
|
587
|
+
...additionalBinaryBuildCommands,
|
|
588
|
+
].join("\n"),
|
|
531
589
|
),
|
|
532
590
|
},
|
|
533
591
|
...(!independentSetup
|
|
@@ -757,6 +815,53 @@ export function rustGitHubReleaseJob(): Job {
|
|
|
757
815
|
target_commitish: RELEASE_SHA,
|
|
758
816
|
},
|
|
759
817
|
},
|
|
818
|
+
{
|
|
819
|
+
name: "Delete superseded raw Rust release assets",
|
|
820
|
+
uses: "actions/github-script@v8",
|
|
821
|
+
env: { CURRENT_RELEASE_TAG: RELEASE_TAG },
|
|
822
|
+
with: {
|
|
823
|
+
// prettier-ignore
|
|
824
|
+
script: stringUtils.dedent(
|
|
825
|
+
// ============================================================================
|
|
826
|
+
/*js*/`
|
|
827
|
+
const currentTag = process.env.CURRENT_RELEASE_TAG;
|
|
828
|
+
if (!currentTag) throw new Error("CURRENT_RELEASE_TAG is required");
|
|
829
|
+
const parseVersion = (tag) => {
|
|
830
|
+
const match = /^v(\\d+)\\.(\\d+)\\.(\\d+)$/.exec(tag);
|
|
831
|
+
return match ? match.slice(1).map(Number) : undefined;
|
|
832
|
+
};
|
|
833
|
+
const compareVersions = (left, right) => {
|
|
834
|
+
for (let index = 0; index < 3; index += 1) {
|
|
835
|
+
if (left[index] !== right[index]) return left[index] - right[index];
|
|
836
|
+
}
|
|
837
|
+
return 0;
|
|
838
|
+
};
|
|
839
|
+
const currentVersion = parseVersion(currentTag);
|
|
840
|
+
if (!currentVersion) throw new Error(\`Unsupported release tag: \${currentTag}\`);
|
|
841
|
+
const releases = await github.paginate(github.rest.repos.listReleases, {
|
|
842
|
+
...context.repo,
|
|
843
|
+
per_page: 100,
|
|
844
|
+
});
|
|
845
|
+
const assets = releases.flatMap((release) => {
|
|
846
|
+
const version = parseVersion(release.tag_name);
|
|
847
|
+
if (release.draft || !version || compareVersions(version, currentVersion) >= 0) {
|
|
848
|
+
return [];
|
|
849
|
+
}
|
|
850
|
+
return release.assets.filter((asset) => /^rust-(?:raw|build)-/.test(asset.name));
|
|
851
|
+
});
|
|
852
|
+
for (const asset of assets) {
|
|
853
|
+
core.info(\`Deleting \${asset.name} (\${asset.id})\`);
|
|
854
|
+
await github.rest.repos.deleteReleaseAsset({
|
|
855
|
+
...context.repo,
|
|
856
|
+
asset_id: asset.id,
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
core.info(\`Deleted \${assets.length} superseded raw Rust release assets\`);
|
|
860
|
+
`
|
|
861
|
+
// ============================================================================
|
|
862
|
+
),
|
|
863
|
+
},
|
|
864
|
+
},
|
|
760
865
|
],
|
|
761
866
|
};
|
|
762
867
|
}
|
package/src/barrels.ts
CHANGED
|
@@ -523,10 +523,9 @@ const WRITE_ATTEMPTS = 3;
|
|
|
523
523
|
* and the projenrc watcher's post-synth `generateBarrels()` sweep), so any gap
|
|
524
524
|
* between `makeWritable` and the write is a window in which another process's
|
|
525
525
|
* `makeReadonly` lands and this write fails with
|
|
526
|
-
* `EACCES: permission denied, open '<pkg>/index.ts'`.
|
|
527
|
-
* the
|
|
528
|
-
*
|
|
529
|
-
* and a retry absorbs what is left.
|
|
526
|
+
* `EACCES: permission denied, open '<pkg>/index.ts'`. Keeping the unlock adjacent
|
|
527
|
+
* to the write avoids a gap during export parsing, and a retry absorbs what is
|
|
528
|
+
* left.
|
|
530
529
|
*
|
|
531
530
|
* Do NOT "simplify" this back to a single unlock-then-write: the failure is
|
|
532
531
|
* timing-dependent, so it looks fine until a full-repo sweep runs against a
|