@dbx-tools/projen 0.9.18 → 0.9.19
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 +19 -19
- package/index.ts +1 -1
- package/package.json +4 -4
- package/src/_rust-release-workflow.ts +25 -202
- package/src/project-py.ts +60 -71
- package/src/project-rs.ts +1 -24
- package/src/release.ts +85 -142
- package/tasks/publish-npm.ts +63 -11
- package/tasks/publish-python.ts +101 -26
- package/tasks/publish.ts +22 -3
- package/tasks/release-candidate.ts +383 -0
- package/tasks/release-manifest.ts +273 -0
- package/tasks/release-pr.ts +68 -151
package/README.md
CHANGED
|
@@ -274,28 +274,28 @@ architecture. Omit both filters to regenerate the complete maintained matrix.
|
|
|
274
274
|
`DBX_TOOLS_RELEASE_PLATFORMS` can select the generated matrix without repeating
|
|
275
275
|
environment parsing in a consumer.
|
|
276
276
|
|
|
277
|
-
`bun run release
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
`bun run release:assets --version <version> --tag <tag> --
|
|
285
|
-
|
|
277
|
+
`bun run release` always prepares the production candidate locally. After the
|
|
278
|
+
reviewed release pull request merges, the local process checks out the exact
|
|
279
|
+
merge commit, builds the complete npm, Python, native binding, and Rust binary
|
|
280
|
+
artifact set, then creates an annotated tag and draft GitHub Release. The draft
|
|
281
|
+
contains `release-manifest.json`, `SHA256SUMS`, and every registry or binary
|
|
282
|
+
artifact bound to that commit. A manager can rebuild an interrupted draft from
|
|
283
|
+
the exact source with
|
|
284
|
+
`bun run release:assets --version <version> --tag <tag> --sha <commit> --upload`.
|
|
285
|
+
Publishing the draft is the production promotion event; `release.yml` verifies
|
|
286
|
+
the tag, commit, version, manifest, checksums, and asset set before publishing
|
|
287
|
+
the approved npm archives, Python distributions, and Cargo crates. GitHub-hosted
|
|
288
|
+
runners never rebuild native release artifacts for singular-version releases.
|
|
286
289
|
|
|
287
290
|
Public UniFFI facades are marked with `dbxToolsConfig.uniffi = true` in Node
|
|
288
291
|
manifests and `[tool.dbx_tools.config] uniffi = true` in Python manifests. The
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
source builds, then publishes each distribution through its own PyPI
|
|
297
|
-
trusted-publisher environment. Binding publishers wait for their dependencies.
|
|
298
|
-
Trusted-publisher instructions name `release.yml` and the release branch policy.
|
|
292
|
+
approved npm archives are dependency-ordered and published through npm OIDC
|
|
293
|
+
Trusted Publishing with provenance. Local Verdaccio publication does not enable
|
|
294
|
+
provenance. Python publishes the exact approved wheels and source distributions
|
|
295
|
+
through package-specific PyPI trusted-publisher environments; binding publishers
|
|
296
|
+
wait for their dependencies. Trusted-publisher instructions name `release.yml`
|
|
297
|
+
and the `v*` deployment tag policy. Cargo publication checks the approved source
|
|
298
|
+
commit and skips an already-published version during recovery.
|
|
299
299
|
The docs jobs generate README and TypeScript API content and deploy GitHub Pages
|
|
300
300
|
from the same workflow. When a conventional Node binding path already belongs
|
|
301
301
|
to a root subproject, Rust mapping reuses that project and adds binding
|
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.19";
|
|
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
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@clack/prompts": "^1.7.0",
|
|
32
|
-
"@dbx-tools/core": "^0.9.
|
|
33
|
-
"@dbx-tools/path": "^0.9.
|
|
34
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
32
|
+
"@dbx-tools/core": "^0.9.19",
|
|
33
|
+
"@dbx-tools/path": "^0.9.19",
|
|
34
|
+
"@dbx-tools/shared-core": "^0.9.19",
|
|
35
35
|
"commander": "^15.0.0",
|
|
36
36
|
"concurrently": "^10.0.3",
|
|
37
37
|
"constructs": "^10.6.0",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"main": "index.ts",
|
|
54
54
|
"license": "Apache-2.0",
|
|
55
|
-
"version": "0.9.
|
|
55
|
+
"version": "0.9.19",
|
|
56
56
|
"types": "index.ts",
|
|
57
57
|
"type": "module",
|
|
58
58
|
"exports": {
|
|
@@ -17,19 +17,11 @@ import type {
|
|
|
17
17
|
UniFFIReleaseTarget,
|
|
18
18
|
} from "./project-rs.ts";
|
|
19
19
|
import { defaultReleaseUnitId } from "./release-catalog.ts";
|
|
20
|
-
import {
|
|
21
|
-
RELEASE_SHA,
|
|
22
|
-
RELEASE_SUMMARY_FILE,
|
|
23
|
-
RELEASE_TAG,
|
|
24
|
-
RELEASE_VERSION,
|
|
25
|
-
releaseSourceSteps,
|
|
26
|
-
} from "./release-dispatch.ts";
|
|
20
|
+
import { RELEASE_VERSION, releaseSourceSteps } from "./release-dispatch.ts";
|
|
27
21
|
import {
|
|
28
22
|
independentReleaseSetupSteps,
|
|
29
23
|
npmPublishEnvironment,
|
|
30
|
-
|
|
31
|
-
releaseArtifactSteps,
|
|
32
|
-
releaseStageCondition,
|
|
24
|
+
releasePublishCondition,
|
|
33
25
|
} from "./release.ts";
|
|
34
26
|
|
|
35
27
|
const require = createRequire(import.meta.url);
|
|
@@ -460,32 +452,24 @@ function rustCargoBuildCommand(plan: RustReleasePlan): string {
|
|
|
460
452
|
].join("\n");
|
|
461
453
|
}
|
|
462
454
|
|
|
463
|
-
export function rustBuildJob(plan: RustReleasePlan,
|
|
464
|
-
const
|
|
465
|
-
const
|
|
466
|
-
const binaryCommands = rustBinaryCommands(plan, independent);
|
|
455
|
+
export function rustBuildJob(plan: RustReleasePlan, setup: readonly JobStep[]): Job {
|
|
456
|
+
const bindingCommands = rustBindingCommands(plan, true);
|
|
457
|
+
const binaryCommands = rustBinaryCommands(plan, true);
|
|
467
458
|
return {
|
|
468
|
-
if:
|
|
469
|
-
? "${{ needs.release-plan.outputs.rust_targets != '[]' && (github.event_name == 'push' || inputs.stage != 'docs') }}"
|
|
470
|
-
: "${{ needs.verify-context.outputs.build_mode == 'remote' && (github.event_name == 'push' || inputs.stage == 'all') }}",
|
|
459
|
+
if: "${{ needs.release-plan.outputs.rust_targets != '[]' && (github.event_name == 'push' || inputs.stage != 'docs') }}",
|
|
471
460
|
name: "Rust / ${{ matrix.node }}",
|
|
472
|
-
needs: [
|
|
461
|
+
needs: ["release-plan"],
|
|
473
462
|
runsOn: ["${{ matrix.runner }}"],
|
|
474
463
|
permissions: { contents: JobPermission.READ },
|
|
475
|
-
env: {
|
|
476
|
-
...RUST_BUILD_ENV,
|
|
477
|
-
...(independentSetup ? { BUN_VERSION } : {}),
|
|
478
|
-
},
|
|
464
|
+
env: { ...RUST_BUILD_ENV, BUN_VERSION },
|
|
479
465
|
strategy: {
|
|
480
466
|
failFast: false,
|
|
481
467
|
matrix: {
|
|
482
|
-
include:
|
|
483
|
-
? ("${{ fromJSON(needs.release-plan.outputs.rust_targets) }}" as never)
|
|
484
|
-
: ([...plan.targets] as never),
|
|
468
|
+
include: "${{ fromJSON(needs.release-plan.outputs.rust_targets) }}" as never,
|
|
485
469
|
},
|
|
486
470
|
},
|
|
487
471
|
steps: [
|
|
488
|
-
...
|
|
472
|
+
...setup,
|
|
489
473
|
...(plan.hasPythonBindings ? [{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" }] : []),
|
|
490
474
|
{
|
|
491
475
|
name: "Setup Rust",
|
|
@@ -516,7 +500,6 @@ export function rustBuildJob(plan: RustReleasePlan, independentSetup?: readonly
|
|
|
516
500
|
{
|
|
517
501
|
name: "Package UniFFI outputs",
|
|
518
502
|
shell: "bash",
|
|
519
|
-
...(independentSetup ? {} : { env: { VERSION: RELEASE_VERSION } }),
|
|
520
503
|
run: timedBash("uniffi_packaging", bindingCommands.join("\n")),
|
|
521
504
|
},
|
|
522
505
|
]
|
|
@@ -535,50 +518,12 @@ export function rustBuildJob(plan: RustReleasePlan, independentSetup?: readonly
|
|
|
535
518
|
};
|
|
536
519
|
}
|
|
537
520
|
|
|
538
|
-
|
|
539
|
-
export function rustAssetsJob(): Job {
|
|
521
|
+
export function rustCargoPublishJob(plan: RustReleasePlan): Job {
|
|
540
522
|
return {
|
|
541
|
-
if: "
|
|
542
|
-
needs: ["verify-context"
|
|
523
|
+
if: releasePublishCondition("cargo", ["needs.verify-context.result == 'success'"]),
|
|
524
|
+
needs: ["verify-context"],
|
|
543
525
|
runsOn: ["ubuntu-latest"],
|
|
544
526
|
permissions: { contents: JobPermission.READ },
|
|
545
|
-
steps: [
|
|
546
|
-
{
|
|
547
|
-
name: "Wait for locally uploaded release assets",
|
|
548
|
-
if: "${{ needs.verify-context.outputs.build_mode == 'local' }}",
|
|
549
|
-
env: {
|
|
550
|
-
GH_TOKEN: "${{ github.token }}",
|
|
551
|
-
RELEASE_TAG: RELEASE_TAG,
|
|
552
|
-
},
|
|
553
|
-
shell: "bash",
|
|
554
|
-
run: [
|
|
555
|
-
"mkdir -p dist/local-release",
|
|
556
|
-
"for ATTEMPT in $(seq 1 360); do",
|
|
557
|
-
' if gh release download "$RELEASE_TAG" --pattern rust-assets.json --dir dist/local-release --clobber; then exit 0; fi',
|
|
558
|
-
' echo "waiting for local release assets ($ATTEMPT/360)"',
|
|
559
|
-
" sleep 5",
|
|
560
|
-
"done",
|
|
561
|
-
'echo "::error::local release assets were not uploaded"',
|
|
562
|
-
"exit 1",
|
|
563
|
-
].join("\n"),
|
|
564
|
-
},
|
|
565
|
-
{
|
|
566
|
-
name: "Confirm native release assets",
|
|
567
|
-
run: "true",
|
|
568
|
-
},
|
|
569
|
-
],
|
|
570
|
-
};
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
export function rustCargoPublishJob(plan: RustReleasePlan, local: boolean): Job {
|
|
574
|
-
const registry = local ? '"${{ vars.LOCAL_CARGO_REGISTRY }}"' : "crates-io";
|
|
575
|
-
return {
|
|
576
|
-
if: local
|
|
577
|
-
? "${{ github.event_name == 'push' && vars.LOCAL_REPOSITORIES == 'true' }}"
|
|
578
|
-
: "${{ github.event_name == 'push' }}",
|
|
579
|
-
needs: ["verify-context", ...(plan.hasTargetOutputs ? ["rust-assets"] : [])],
|
|
580
|
-
runsOn: [local ? "self-hosted" : "ubuntu-latest"],
|
|
581
|
-
permissions: { contents: JobPermission.READ },
|
|
582
527
|
steps: [
|
|
583
528
|
...releaseSourceSteps(),
|
|
584
529
|
{
|
|
@@ -586,14 +531,21 @@ export function rustCargoPublishJob(plan: RustReleasePlan, local: boolean): Job
|
|
|
586
531
|
uses: `dtolnay/rust-toolchain@${plan.releaseRustVersion}`,
|
|
587
532
|
},
|
|
588
533
|
{
|
|
589
|
-
name:
|
|
534
|
+
name: "Publish public crates",
|
|
590
535
|
env: {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
: "${{ secrets.CARGO_REGISTRY_TOKEN }}",
|
|
536
|
+
RELEASE_VERSION,
|
|
537
|
+
CARGO_REGISTRY_TOKEN: "${{ secrets.CARGO_REGISTRY_TOKEN }}",
|
|
594
538
|
},
|
|
595
539
|
run: plan.publicCrates
|
|
596
|
-
.map((crate) =>
|
|
540
|
+
.map((crate) =>
|
|
541
|
+
[
|
|
542
|
+
`if cargo info "${crate}@$RELEASE_VERSION" >/dev/null 2>&1; then`,
|
|
543
|
+
` echo "skip published ${crate}@$RELEASE_VERSION"`,
|
|
544
|
+
"else",
|
|
545
|
+
` cargo publish --package "${crate}" --registry crates-io --no-verify`,
|
|
546
|
+
"fi",
|
|
547
|
+
].join("\n"),
|
|
548
|
+
)
|
|
597
549
|
.join("\n"),
|
|
598
550
|
},
|
|
599
551
|
],
|
|
@@ -681,50 +633,6 @@ export function independentRustGitHubReleaseJob(
|
|
|
681
633
|
};
|
|
682
634
|
}
|
|
683
635
|
|
|
684
|
-
export function rustGitHubReleaseJob(plan: RustReleasePlan): Job {
|
|
685
|
-
return {
|
|
686
|
-
if: "${{ github.event_name == 'push' }}",
|
|
687
|
-
needs: ["verify-context", ...(plan.hasTargetOutputs ? ["rust-assets"] : [])],
|
|
688
|
-
runsOn: ["ubuntu-latest"],
|
|
689
|
-
permissions: { contents: JobPermission.WRITE },
|
|
690
|
-
steps: [
|
|
691
|
-
...releaseSourceSteps(),
|
|
692
|
-
{
|
|
693
|
-
name: "Download release binaries",
|
|
694
|
-
if: "${{ needs.verify-context.outputs.build_mode == 'remote' }}",
|
|
695
|
-
uses: "actions/download-artifact@v8",
|
|
696
|
-
with: {
|
|
697
|
-
pattern: "*-binary",
|
|
698
|
-
path: "dist/rust-release",
|
|
699
|
-
"merge-multiple": true,
|
|
700
|
-
},
|
|
701
|
-
},
|
|
702
|
-
{
|
|
703
|
-
name: "Publish GitHub release assets",
|
|
704
|
-
if: "${{ needs.verify-context.outputs.build_mode == 'remote' }}",
|
|
705
|
-
uses: "softprops/action-gh-release@v2",
|
|
706
|
-
with: {
|
|
707
|
-
files: "dist/rust-release/*",
|
|
708
|
-
body_path: RELEASE_SUMMARY_FILE,
|
|
709
|
-
generate_release_notes: true,
|
|
710
|
-
tag_name: RELEASE_TAG,
|
|
711
|
-
target_commitish: RELEASE_SHA,
|
|
712
|
-
},
|
|
713
|
-
},
|
|
714
|
-
{
|
|
715
|
-
name: "Publish locally built GitHub release",
|
|
716
|
-
if: "${{ needs.verify-context.outputs.build_mode == 'local' }}",
|
|
717
|
-
env: {
|
|
718
|
-
GH_TOKEN: "${{ github.token }}",
|
|
719
|
-
RELEASE_NOTES: RELEASE_SUMMARY_FILE,
|
|
720
|
-
RELEASE_TAG,
|
|
721
|
-
},
|
|
722
|
-
run: 'gh release edit "$RELEASE_TAG" --draft=false --latest --notes-file "$RELEASE_NOTES"',
|
|
723
|
-
},
|
|
724
|
-
],
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
|
|
728
636
|
export function independentRustNativeNpmPublishJob(project: DBXToolsJavaScriptProject): Job {
|
|
729
637
|
return {
|
|
730
638
|
if: "${{ needs.release-plan.outputs.node == 'true' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'node') }}",
|
|
@@ -788,88 +696,3 @@ export function independentRustNodeFacadePublishJob(
|
|
|
788
696
|
],
|
|
789
697
|
};
|
|
790
698
|
}
|
|
791
|
-
|
|
792
|
-
export function rustNativeNpmPublishJob(project: DBXToolsJavaScriptProject): Job {
|
|
793
|
-
return {
|
|
794
|
-
if: "${{ always() && needs.verify-context.result == 'success' && needs.rust-assets.result == 'success' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'node') }}",
|
|
795
|
-
needs: ["verify-context", "rust-assets"],
|
|
796
|
-
runsOn: ["ubuntu-latest"],
|
|
797
|
-
permissions: {
|
|
798
|
-
actions: JobPermission.READ,
|
|
799
|
-
contents: JobPermission.READ,
|
|
800
|
-
idToken: JobPermission.WRITE,
|
|
801
|
-
},
|
|
802
|
-
timeoutMinutes: 15,
|
|
803
|
-
env: { BUN_VERSION, CI: "true" },
|
|
804
|
-
steps: [
|
|
805
|
-
...nodeReleaseSetupSteps(project),
|
|
806
|
-
...releaseArtifactSteps({
|
|
807
|
-
currentName: "Download native npm packages",
|
|
808
|
-
recoveredName: "Download recovered native npm packages",
|
|
809
|
-
pattern: "*-npm",
|
|
810
|
-
path: "dist/uniffi/native",
|
|
811
|
-
condition: "needs.verify-context.outputs.build_mode == 'remote'",
|
|
812
|
-
}),
|
|
813
|
-
{
|
|
814
|
-
name: "Download locally built native npm packages",
|
|
815
|
-
if: "${{ needs.verify-context.outputs.build_mode == 'local' }}",
|
|
816
|
-
env: { GH_TOKEN: "${{ github.token }}", RELEASE_TAG },
|
|
817
|
-
run: [
|
|
818
|
-
"mkdir -p dist/uniffi/native",
|
|
819
|
-
'gh release download "$RELEASE_TAG" --pattern "*.tgz" --dir dist/uniffi/native',
|
|
820
|
-
].join("\n"),
|
|
821
|
-
},
|
|
822
|
-
{
|
|
823
|
-
name: "Publish native npm packages",
|
|
824
|
-
env: { RELEASE_VERSION, ...npmPublishEnvironment() },
|
|
825
|
-
run: 'bun node_modules/@dbx-tools/projen/tasks/publish-npm.ts --directory dist/uniffi/native --version "$RELEASE_VERSION" $DRY_RUN',
|
|
826
|
-
},
|
|
827
|
-
],
|
|
828
|
-
};
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
export function rustNodeFacadePublishJob(
|
|
832
|
-
project: DBXToolsJavaScriptProject,
|
|
833
|
-
bindings: readonly RustReleaseBinding[],
|
|
834
|
-
): Job {
|
|
835
|
-
return {
|
|
836
|
-
if: releaseStageCondition("node"),
|
|
837
|
-
needs: ["verify-context", "publish-node"],
|
|
838
|
-
runsOn: ["ubuntu-latest"],
|
|
839
|
-
permissions: { contents: JobPermission.READ, idToken: JobPermission.WRITE },
|
|
840
|
-
timeoutMinutes: 30,
|
|
841
|
-
env: { BUN_VERSION, CI: "true" },
|
|
842
|
-
steps: [
|
|
843
|
-
...nodeReleaseSetupSteps(project),
|
|
844
|
-
{
|
|
845
|
-
name: "Build and publish UniFFI npm facades",
|
|
846
|
-
env: { RELEASE_VERSION, ...npmPublishEnvironment() },
|
|
847
|
-
run: bindings
|
|
848
|
-
.flatMap((binding) => {
|
|
849
|
-
const output = `dist/uniffi/facades/${binding.crate}`;
|
|
850
|
-
return [
|
|
851
|
-
`node .projen/uniffi-release.mjs facade --node "${binding.node}" --node-package "${binding.nodePackage}" --node-triple "linux-x64-gnu" --version "$RELEASE_VERSION" --output "${output}"`,
|
|
852
|
-
`bun node_modules/@dbx-tools/projen/tasks/publish-npm.ts --directory "${output}/npm-facade" --version "$RELEASE_VERSION" $DRY_RUN`,
|
|
853
|
-
];
|
|
854
|
-
})
|
|
855
|
-
.join("\n"),
|
|
856
|
-
},
|
|
857
|
-
{
|
|
858
|
-
name: "Smoke test published UniFFI npm facades",
|
|
859
|
-
if: "${{ github.event_name == 'push' && vars.UNIFFI_FACADE_SMOKE == 'true' }}",
|
|
860
|
-
continueOnError: true,
|
|
861
|
-
env: { RELEASE_VERSION },
|
|
862
|
-
run: [
|
|
863
|
-
'SMOKE_DIR="$(mktemp -d)"',
|
|
864
|
-
"trap 'rm -rf \"$SMOKE_DIR\"' EXIT",
|
|
865
|
-
'cd "$SMOKE_DIR"',
|
|
866
|
-
"npm init --yes >/dev/null",
|
|
867
|
-
...bindings.flatMap((binding) => [
|
|
868
|
-
`npm install --ignore-scripts --no-audit --no-fund --package-lock=false "${binding.nodePackage}@$RELEASE_VERSION"`,
|
|
869
|
-
`node -e 'import("${binding.nodePackage}")'`,
|
|
870
|
-
]),
|
|
871
|
-
].join("\n"),
|
|
872
|
-
},
|
|
873
|
-
],
|
|
874
|
-
};
|
|
875
|
-
}
|
package/src/project-py.ts
CHANGED
|
@@ -4,14 +4,19 @@ import { stringUtils } from "@dbx-tools/shared-core";
|
|
|
4
4
|
import { Component, License, TextFile, type Project, javascript, python, vscode } from "projen";
|
|
5
5
|
import { JobPermission } from "projen/lib/github/workflows-model";
|
|
6
6
|
import { BUN_VERSION, bunCacheRestoreSteps, bunCacheSaveStep } from "./bun-workflow.ts";
|
|
7
|
-
import { DBX_TOOLS_LICENSE,
|
|
7
|
+
import { DBX_TOOLS_LICENSE, projectRepositoryUrl } from "./project-js.ts";
|
|
8
8
|
import { isDBXToolsJavaScriptProject } from "./project-predicate.ts";
|
|
9
9
|
import type { DBXToolsProject, DBXToolsProjectOptions } from "./project.ts";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
RELEASE_SHA,
|
|
12
|
+
RELEASE_TAG,
|
|
13
|
+
RELEASE_VERSION,
|
|
14
|
+
releaseSourceSteps,
|
|
15
|
+
} from "./release-dispatch.ts";
|
|
11
16
|
import {
|
|
12
17
|
independentReleaseSetupSteps,
|
|
13
18
|
registerIndependentPublicationJob,
|
|
14
|
-
|
|
19
|
+
releaseTagPattern,
|
|
15
20
|
releasePublishCondition,
|
|
16
21
|
releaseStageCondition,
|
|
17
22
|
tryReleaseWorkflow,
|
|
@@ -545,12 +550,10 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
545
550
|
return;
|
|
546
551
|
}
|
|
547
552
|
workflow.addJob("build-python", {
|
|
548
|
-
if:
|
|
549
|
-
|
|
550
|
-
: releaseStageCondition("python"),
|
|
551
|
-
needs: ["verify-context", ...(usesRustArtifacts ? ["rust-assets"] : [])],
|
|
553
|
+
if: releaseStageCondition("python", ["needs.verify-context.result == 'success'"]),
|
|
554
|
+
needs: ["verify-context"],
|
|
552
555
|
runsOn: ["ubuntu-latest"],
|
|
553
|
-
permissions: {
|
|
556
|
+
permissions: { contents: JobPermission.READ },
|
|
554
557
|
timeoutMinutes: 20,
|
|
555
558
|
env: { BUN_VERSION },
|
|
556
559
|
steps: [
|
|
@@ -561,76 +564,60 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
561
564
|
{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" },
|
|
562
565
|
{ name: "Install release helpers", run: "bun install" },
|
|
563
566
|
bunCacheSaveStep(),
|
|
564
|
-
...uniffiPublications.flatMap((publication) =>
|
|
565
|
-
releaseArtifactSteps({
|
|
566
|
-
currentName: `Download ${publication.distribution} native wheels`,
|
|
567
|
-
recoveredName: `Download recovered ${publication.distribution} native wheels`,
|
|
568
|
-
pattern: `${publication.distribution}--*--python-wheel`,
|
|
569
|
-
path: `dist/${publication.directory}`,
|
|
570
|
-
condition: "needs.verify-context.outputs.build_mode == 'remote'",
|
|
571
|
-
}),
|
|
572
|
-
),
|
|
573
|
-
...(uniffiPublications.length
|
|
574
|
-
? [
|
|
575
|
-
{
|
|
576
|
-
name: "Download locally built native wheels",
|
|
577
|
-
if: "${{ needs.verify-context.outputs.build_mode == 'local' }}",
|
|
578
|
-
env: { GH_TOKEN: "${{ github.token }}", RELEASE_TAG },
|
|
579
|
-
shell: "bash",
|
|
580
|
-
run: [
|
|
581
|
-
"mkdir -p dist/local-wheels",
|
|
582
|
-
'gh release download "$RELEASE_TAG" --pattern "*.whl" --dir dist/local-wheels',
|
|
583
|
-
...uniffiPublications.flatMap((publication) => [
|
|
584
|
-
`mkdir -p dist/${publication.directory}`,
|
|
585
|
-
`cp dist/local-wheels/${publication.distribution.replaceAll("-", "_")}-*.whl dist/${publication.directory}/`,
|
|
586
|
-
]),
|
|
587
|
-
].join("\n"),
|
|
588
|
-
},
|
|
589
|
-
]
|
|
590
|
-
: []),
|
|
591
567
|
{
|
|
592
|
-
name: "
|
|
593
|
-
env: {
|
|
594
|
-
run:
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
.map(
|
|
600
|
-
(publication) =>
|
|
601
|
-
`uv build --package ${publication.distribution} --out-dir dist/${publication.directory}`,
|
|
602
|
-
)
|
|
603
|
-
.join("\n"),
|
|
568
|
+
name: "Download approved Python distributions",
|
|
569
|
+
env: { GH_TOKEN: "${{ github.token }}", RELEASE_TAG },
|
|
570
|
+
run: [
|
|
571
|
+
"rm -rf dist/release-download",
|
|
572
|
+
"mkdir -p dist/release-download",
|
|
573
|
+
'gh release download "$RELEASE_TAG" --pattern release-manifest.json --pattern SHA256SUMS --pattern "*.whl" --pattern "*.tar.gz" --dir dist/release-download',
|
|
574
|
+
].join("\n"),
|
|
604
575
|
},
|
|
605
|
-
{
|
|
606
|
-
name:
|
|
576
|
+
...allPublications.map((publication) => ({
|
|
577
|
+
name: `Select ${publication.distribution} distributions`,
|
|
578
|
+
env: {
|
|
579
|
+
PACKAGE_NAME: publication.distribution.replaceAll("_", "-").toLowerCase(),
|
|
580
|
+
RELEASE_SHA,
|
|
581
|
+
RELEASE_TAG,
|
|
582
|
+
RELEASE_VERSION,
|
|
583
|
+
},
|
|
607
584
|
run: [
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
"find dist -type f \\( -name '*.whl' -o -name '*.tar.gz' \\) -print0 | xargs -0 uvx twine check",
|
|
585
|
+
"bun node_modules/@dbx-tools/projen/tasks/release-manifest.ts verify \\",
|
|
586
|
+
" --directory dist/release-download \\",
|
|
587
|
+
' --tag "$RELEASE_TAG" \\',
|
|
588
|
+
' --sha "$RELEASE_SHA" \\',
|
|
589
|
+
' --version "$RELEASE_VERSION" \\',
|
|
590
|
+
" --kind pypi \\",
|
|
591
|
+
' --package "$PACKAGE_NAME" \\',
|
|
592
|
+
` --output dist/${publication.directory}`,
|
|
617
593
|
].join("\n"),
|
|
594
|
+
})),
|
|
595
|
+
{
|
|
596
|
+
name: "Validate approved distributions",
|
|
597
|
+
run: `find ${allPublications.map((publication) => `dist/${publication.directory}`).join(" ")} -type f \\( -name '*.whl' -o -name '*.tar.gz' \\) -print0 | xargs -0 uvx twine check`,
|
|
618
598
|
},
|
|
619
599
|
{
|
|
620
600
|
name: "Upload distributions",
|
|
621
601
|
uses: "actions/upload-artifact@v7",
|
|
622
|
-
with: {
|
|
602
|
+
with: {
|
|
603
|
+
name: "python-distributions",
|
|
604
|
+
path: allPublications.map((publication) => `dist/${publication.directory}`).join("\n"),
|
|
605
|
+
"retention-days": 7,
|
|
606
|
+
},
|
|
623
607
|
},
|
|
624
608
|
],
|
|
625
609
|
});
|
|
626
610
|
for (const publication of allPublications) {
|
|
611
|
+
const dependencyJobs = (publication.dependencies ?? []).map(
|
|
612
|
+
(dependency) => `publish-pypi-${dependency}`,
|
|
613
|
+
);
|
|
627
614
|
workflow.addJob(`publish-pypi-${publication.directory}`, {
|
|
628
|
-
if: releasePublishCondition("python"
|
|
629
|
-
|
|
630
|
-
"
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
],
|
|
615
|
+
if: releasePublishCondition("python", [
|
|
616
|
+
"needs.verify-context.result == 'success'",
|
|
617
|
+
"needs.build-python.result == 'success'",
|
|
618
|
+
...dependencyJobs.map((job) => `needs['${job}'].result == 'success'`),
|
|
619
|
+
]),
|
|
620
|
+
needs: ["verify-context", "build-python", ...dependencyJobs],
|
|
634
621
|
environment: {
|
|
635
622
|
name: publication.environment,
|
|
636
623
|
url:
|
|
@@ -710,15 +697,17 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
710
697
|
): void {
|
|
711
698
|
const repository = this.githubRepository();
|
|
712
699
|
const publications = this.trustedPublisherPublications(options);
|
|
713
|
-
const
|
|
714
|
-
?
|
|
715
|
-
|
|
700
|
+
const releaseTag = isDBXToolsJavaScriptProject()(project)
|
|
701
|
+
? project.releaseCatalog.mode === "independent"
|
|
702
|
+
? "*-v*"
|
|
703
|
+
: releaseTagPattern(project)
|
|
704
|
+
: "v*";
|
|
716
705
|
const linesBeforeAuthentication = [
|
|
717
706
|
"# PyPI Trusted Publisher Setup Instructions",
|
|
718
707
|
"",
|
|
719
708
|
"Use the system browser to audit and configure the PyPI trusted publishers below.",
|
|
720
709
|
"Do not use an in-app browser or embedded webview.",
|
|
721
|
-
"Do not visit GitHub or use the GitHub API or CLI. Every required GitHub owner, repository, workflow, environment, and
|
|
710
|
+
"Do not visit GitHub or use the GitHub API or CLI. Every required GitHub owner, repository, workflow, environment, and tag value is provided below and is authoritative.",
|
|
722
711
|
"Use only PyPI pages for this task.",
|
|
723
712
|
"",
|
|
724
713
|
"## Audit and confirmation",
|
|
@@ -736,7 +725,7 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
736
725
|
"",
|
|
737
726
|
"## GitHub environment policy",
|
|
738
727
|
"",
|
|
739
|
-
`- The supplied
|
|
728
|
+
`- The supplied deployment tag policy value is ${releaseTag}.`,
|
|
740
729
|
"- Do not inspect or configure GitHub environments during this task.",
|
|
741
730
|
"- GitHub environment administration is a separate task; use the supplied values only when comparing PyPI publisher entries.",
|
|
742
731
|
"",
|
|
@@ -777,7 +766,7 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
777
766
|
`- Repository name: ${repository.name}`,
|
|
778
767
|
"- Workflow name: release.yml",
|
|
779
768
|
`- Environment name: ${publication.environment}`,
|
|
780
|
-
`- GitHub environment
|
|
769
|
+
`- GitHub environment tag: ${releaseTag}`,
|
|
781
770
|
...(publication.artifacts ? [`- Artifacts: ${publication.artifacts}`] : []),
|
|
782
771
|
"",
|
|
783
772
|
];
|
package/src/project-rs.ts
CHANGED
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
type RustOpenApiOptions as RustOpenApiConfiguration,
|
|
20
20
|
} from "./_rust-project.ts";
|
|
21
21
|
import {
|
|
22
|
-
rustAssetsJob,
|
|
23
22
|
configureRustReleaseTask,
|
|
24
23
|
independentRustCargoPublishJob,
|
|
25
24
|
independentRustGitHubReleaseJob,
|
|
@@ -29,9 +28,6 @@ import {
|
|
|
29
28
|
planRustRelease,
|
|
30
29
|
rustBuildJob,
|
|
31
30
|
rustCargoPublishJob,
|
|
32
|
-
rustGitHubReleaseJob,
|
|
33
|
-
rustNativeNpmPublishJob,
|
|
34
|
-
rustNodeFacadePublishJob,
|
|
35
31
|
} from "./_rust-release-workflow.ts";
|
|
36
32
|
import { toPosix } from "./packages.ts";
|
|
37
33
|
import {
|
|
@@ -1124,27 +1120,8 @@ export class DBXToolsRustWorkspace extends Component {
|
|
|
1124
1120
|
}
|
|
1125
1121
|
return;
|
|
1126
1122
|
}
|
|
1127
|
-
if (plan.targets.length) {
|
|
1128
|
-
workflow.addJob("rust-build", rustBuildJob(plan));
|
|
1129
|
-
workflow.addJob("rust-assets", rustAssetsJob());
|
|
1130
|
-
}
|
|
1131
1123
|
if (plan.publicCrates.length) {
|
|
1132
|
-
workflow.addJob("publish-cargo", rustCargoPublishJob(plan
|
|
1133
|
-
workflow.addJob("publish-local-cargo", rustCargoPublishJob(plan, true));
|
|
1134
|
-
}
|
|
1135
|
-
if (plan.hasTargetOutputs) {
|
|
1136
|
-
workflow.addJob("publish-github-release", rustGitHubReleaseJob(plan));
|
|
1137
|
-
}
|
|
1138
|
-
if (plan.nodeBindings.length && hasNodeRelease(project)) {
|
|
1139
|
-
workflow.addJob("publish-native-npm", rustNativeNpmPublishJob(project));
|
|
1140
|
-
const nodeJob = workflow.getJob("publish-node");
|
|
1141
|
-
if ("uses" in nodeJob) throw new Error("publish-node must be a workflow job");
|
|
1142
|
-
workflow.updateJob("publish-node", {
|
|
1143
|
-
...nodeJob,
|
|
1144
|
-
if: "${{ always() && needs.verify-context.result == 'success' && needs.publish-native-npm.result == 'success' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'node') }}",
|
|
1145
|
-
needs: ["verify-context", "publish-native-npm"],
|
|
1146
|
-
});
|
|
1147
|
-
workflow.addJob("publish-node-facades", rustNodeFacadePublishJob(project, plan.nodeBindings));
|
|
1124
|
+
workflow.addJob("publish-cargo", rustCargoPublishJob(plan));
|
|
1148
1125
|
}
|
|
1149
1126
|
}
|
|
1150
1127
|
}
|