@dbx-tools/projen 0.6.177 → 0.6.179
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 +47 -35
- package/index.ts +3 -3
- package/package.json +4 -4
- package/src/project-js.ts +7 -16
- package/src/project-py.ts +47 -249
- package/src/project-rs.ts +210 -244
- package/src/release-dispatch.ts +9 -11
- package/src/release.ts +313 -625
- package/tasks/publish-npm.ts +197 -0
- package/tasks/publish.ts +38 -1
- package/tasks/stamp-python.ts +13 -0
package/src/project-rs.ts
CHANGED
|
@@ -4,22 +4,27 @@ import { dirname, join, relative, resolve } from "node:path";
|
|
|
4
4
|
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
|
-
import { Project, TextFile,
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
projectRepositoryUrl,
|
|
12
|
-
} from "./project-js.ts";
|
|
7
|
+
import { Project, TextFile, javascript } from "projen";
|
|
8
|
+
import { JobPermission, type JobStep } from "projen/lib/github/workflows-model";
|
|
9
|
+
import { BUN_VERSION } from "./bun-workflow.ts";
|
|
10
|
+
import { DBXToolsTypeScriptProject, projectRepositoryUrl } from "./project-js.ts";
|
|
13
11
|
import { isDBXToolsJavaScriptProject } from "./project-predicate.ts";
|
|
14
12
|
import { pythonModuleName, type PythonPackageOptions } from "./project-py.ts";
|
|
15
13
|
import type { DBXToolsProject } from "./project.ts";
|
|
16
14
|
import {
|
|
17
|
-
DOWNSTREAM_RELEASE_EVENT,
|
|
18
15
|
RELEASE_SHA,
|
|
19
16
|
RELEASE_TAG,
|
|
20
|
-
|
|
17
|
+
RELEASE_VERSION,
|
|
21
18
|
releaseSourceSteps,
|
|
22
19
|
} from "./release-dispatch.ts";
|
|
20
|
+
import {
|
|
21
|
+
hasNodeRelease,
|
|
22
|
+
npmPublishEnvironment,
|
|
23
|
+
nodeReleaseSetupSteps,
|
|
24
|
+
releaseArtifactSteps,
|
|
25
|
+
releaseStageCondition,
|
|
26
|
+
releaseWorkflow,
|
|
27
|
+
} from "./release.ts";
|
|
23
28
|
import { readWorkspaceVersion } from "./workspace-version.ts";
|
|
24
29
|
|
|
25
30
|
export interface CargoDependencyOptions {
|
|
@@ -75,12 +80,6 @@ export interface DBXToolsRustWorkspaceOptions {
|
|
|
75
80
|
readonly releaseTargets?: readonly UniFFIReleaseTarget[];
|
|
76
81
|
/** Maintained OS/CPU combinations to release. Defaults to every supported target. */
|
|
77
82
|
readonly releasePlatforms?: readonly RustReleasePlatform[];
|
|
78
|
-
/** Workflow name used by downstream release stages. Defaults to `rust-release`. */
|
|
79
|
-
readonly releaseWorkflowName?: string;
|
|
80
|
-
/** Workflow that publishes generated Python wheels. Defaults to `python-release`. */
|
|
81
|
-
readonly pythonReleaseWorkflowName?: string;
|
|
82
|
-
/** Tag prefix dispatched into the branch-scoped release workflow. Defaults to `v`. */
|
|
83
|
-
readonly releaseTagPrefix?: string;
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
export enum RustReleaseOs {
|
|
@@ -258,7 +257,6 @@ export interface RustWorkspaceMapping {
|
|
|
258
257
|
readonly root: string;
|
|
259
258
|
readonly crates: readonly string[];
|
|
260
259
|
readonly bindings: readonly RustBindingMapping[];
|
|
261
|
-
readonly releaseWorkflow?: string;
|
|
262
260
|
}
|
|
263
261
|
|
|
264
262
|
export function orderRustBindings(bindings: readonly RustBindingMapping[]): RustBindingMapping[] {
|
|
@@ -552,7 +550,6 @@ export class DBXToolsRustWorkspace {
|
|
|
552
550
|
root,
|
|
553
551
|
crates: this.packages.map((pkg) => `${root}/${pkg.packageOptions.directory}`),
|
|
554
552
|
bindings: this.bindingMappings,
|
|
555
|
-
...(releaseEnabled ? { releaseWorkflow: options.releaseWorkflowName ?? "rust-release" } : {}),
|
|
556
553
|
};
|
|
557
554
|
if (dbxToolsProject) {
|
|
558
555
|
dbxToolsProject.dbxToolsConfig.rust = this.workspaceMapping;
|
|
@@ -594,7 +591,6 @@ export class DBXToolsRustWorkspace {
|
|
|
594
591
|
`src/${module.replaceAll(".", "/")}/__init__.py`,
|
|
595
592
|
],
|
|
596
593
|
trustedPublisher: {
|
|
597
|
-
workflowName: options.pythonReleaseWorkflowName ?? "python-release",
|
|
598
594
|
environment: `pypi-${pkg.crateName}`,
|
|
599
595
|
artifacts: `platform-specific wheels for ${releaseTargets(options)
|
|
600
596
|
.map((target) => `${target.os}-${target.cpu}`)
|
|
@@ -721,11 +717,8 @@ export class DBXToolsRustWorkspace {
|
|
|
721
717
|
options: DBXToolsRustWorkspaceOptions,
|
|
722
718
|
targets: readonly UniFFIReleaseTarget[],
|
|
723
719
|
): void {
|
|
724
|
-
if (!project.github) return;
|
|
725
|
-
const workflowName = options.releaseWorkflowName ?? "rust-release";
|
|
726
|
-
const releaseTagPrefix = options.releaseTagPrefix ?? "v";
|
|
720
|
+
if (!project.github || !isDBXToolsJavaScriptProject()(project)) return;
|
|
727
721
|
const releaseRustVersion = options.releaseRustVersion ?? "stable";
|
|
728
|
-
const releaseBranch = projectReleaseBranch(project);
|
|
729
722
|
const bindings = this.bindingMappings.map((binding) => ({
|
|
730
723
|
...binding,
|
|
731
724
|
node: binding.node ?? "",
|
|
@@ -739,14 +732,19 @@ export class DBXToolsRustWorkspace {
|
|
|
739
732
|
crate: pkg.crateName,
|
|
740
733
|
binary: pkg.packageOptions.binaryName ?? pkg.crateName,
|
|
741
734
|
}));
|
|
735
|
+
const orderedBindingCrates = this.bindingMappings.map((binding) => binding.crate);
|
|
742
736
|
const publicCrates = this.packages
|
|
743
737
|
.filter((pkg) => !pkg.packageOptions.private)
|
|
744
738
|
.sort((first, second) => {
|
|
745
|
-
|
|
746
|
-
|
|
739
|
+
// Binding crates publish in topological order before release-only crates that may consume them.
|
|
740
|
+
const firstIndex = orderedBindingCrates.indexOf(first.crateName);
|
|
741
|
+
const secondIndex = orderedBindingCrates.indexOf(second.crateName);
|
|
742
|
+
if (firstIndex < 0) return secondIndex < 0 ? 0 : 1;
|
|
743
|
+
if (secondIndex < 0) return -1;
|
|
744
|
+
return firstIndex - secondIndex;
|
|
747
745
|
})
|
|
748
746
|
.map((pkg) => pkg.crateName);
|
|
749
|
-
const targetMatrix = targets.map((target) => ({ target }));
|
|
747
|
+
const targetMatrix = targets.map((target) => ({ ...target }));
|
|
750
748
|
const hasPythonBindings = bindings.some((binding) => binding.python);
|
|
751
749
|
const usePreinstalledWindowsRust = releaseRustVersion === "stable";
|
|
752
750
|
const hasTargetOutputs =
|
|
@@ -770,30 +768,30 @@ export class DBXToolsRustWorkspace {
|
|
|
770
768
|
`--python "${binding.python}"`,
|
|
771
769
|
`--node-package "${binding.nodePackage}"`,
|
|
772
770
|
`--python-package "${binding.pythonPackage}"`,
|
|
773
|
-
'--cargo-target "${{ matrix.
|
|
774
|
-
'--node-triple "${{ matrix.
|
|
775
|
-
'--python-tag "${{ matrix.
|
|
776
|
-
'--os "${{ matrix.
|
|
777
|
-
'--cpu "${{ matrix.
|
|
778
|
-
'--libc "${{ matrix.
|
|
779
|
-
|
|
780
|
-
`--output "dist/release/${binding.crate}/\${{ matrix.
|
|
771
|
+
'--cargo-target "${{ matrix.cargo }}"',
|
|
772
|
+
'--node-triple "${{ matrix.node }}"',
|
|
773
|
+
'--python-tag "${{ matrix.python }}"',
|
|
774
|
+
'--os "${{ matrix.os }}"',
|
|
775
|
+
'--cpu "${{ matrix.cpu }}"',
|
|
776
|
+
'--libc "${{ matrix.libc }}"',
|
|
777
|
+
'--version "$VERSION"',
|
|
778
|
+
`--output "dist/release/${binding.crate}/\${{ matrix.node }}"`,
|
|
781
779
|
"--skip-build",
|
|
782
780
|
].join(" \\\n "),
|
|
783
781
|
);
|
|
784
782
|
const binaryCommands = releaseBinaries.flatMap((pkg) => [
|
|
785
|
-
`mkdir -p "dist/release/${pkg.crate}/\${{ matrix.
|
|
786
|
-
`SOURCE="target/\${{ matrix.
|
|
787
|
-
`DESTINATION="dist/release/${pkg.crate}/\${{ matrix.
|
|
783
|
+
`mkdir -p "dist/release/${pkg.crate}/\${{ matrix.node }}/binary/stage"`,
|
|
784
|
+
`SOURCE="target/\${{ matrix.cargo }}/release/${pkg.binary}\${{ matrix.os == 'win32' && '.exe' || '' }}"`,
|
|
785
|
+
`DESTINATION="dist/release/${pkg.crate}/\${{ matrix.node }}/binary/stage/${pkg.binary}\${{ matrix.os == 'win32' && '.exe' || '' }}"`,
|
|
788
786
|
'cp "$SOURCE" "$DESTINATION"',
|
|
789
|
-
'if [ "${{ matrix.
|
|
790
|
-
` 7z a "dist/release/${pkg.crate}/\${{ matrix.
|
|
787
|
+
'if [ "${{ matrix.os }}" = "win32" ]; then',
|
|
788
|
+
` 7z a "dist/release/${pkg.crate}/\${{ matrix.node }}/binary/${pkg.binary}-\${{ matrix.node }}.zip" "$DESTINATION"`,
|
|
791
789
|
"else",
|
|
792
|
-
` tar -C "dist/release/${pkg.crate}/\${{ matrix.
|
|
790
|
+
` tar -C "dist/release/${pkg.crate}/\${{ matrix.node }}/binary/stage" -czf "dist/release/${pkg.crate}/\${{ matrix.node }}/binary/${pkg.binary}-\${{ matrix.node }}.tar.gz" "${pkg.binary}"`,
|
|
793
791
|
"fi",
|
|
794
|
-
`rm -rf "dist/release/${pkg.crate}/\${{ matrix.
|
|
792
|
+
`rm -rf "dist/release/${pkg.crate}/\${{ matrix.node }}/binary/stage"`,
|
|
795
793
|
]);
|
|
796
|
-
const artifactSteps = [
|
|
794
|
+
const artifactSteps: JobStep[] = [
|
|
797
795
|
...bindings.flatMap((binding) => [
|
|
798
796
|
...(binding.node
|
|
799
797
|
? [
|
|
@@ -801,8 +799,8 @@ export class DBXToolsRustWorkspace {
|
|
|
801
799
|
name: `Upload ${binding.crate} native npm package`,
|
|
802
800
|
uses: "actions/upload-artifact@v7",
|
|
803
801
|
with: {
|
|
804
|
-
name: `${binding.crate}-\${{ matrix.
|
|
805
|
-
path: `dist/release/${binding.crate}/\${{ matrix.
|
|
802
|
+
name: `${binding.crate}-\${{ matrix.node }}-npm`,
|
|
803
|
+
path: `dist/release/${binding.crate}/\${{ matrix.node }}/npm/*.tgz`,
|
|
806
804
|
"retention-days": 7,
|
|
807
805
|
},
|
|
808
806
|
},
|
|
@@ -814,8 +812,8 @@ export class DBXToolsRustWorkspace {
|
|
|
814
812
|
name: `Upload ${binding.crate} Python wheel`,
|
|
815
813
|
uses: "actions/upload-artifact@v7",
|
|
816
814
|
with: {
|
|
817
|
-
name: `${binding.crate}--\${{ matrix.
|
|
818
|
-
path: `dist/release/${binding.crate}/\${{ matrix.
|
|
815
|
+
name: `${binding.crate}--\${{ matrix.python }}--python-wheel`,
|
|
816
|
+
path: `dist/release/${binding.crate}/\${{ matrix.node }}/python/*.whl`,
|
|
819
817
|
"retention-days": 7,
|
|
820
818
|
},
|
|
821
819
|
},
|
|
@@ -826,22 +824,24 @@ export class DBXToolsRustWorkspace {
|
|
|
826
824
|
name: `Upload ${pkg.crate} release binary`,
|
|
827
825
|
uses: "actions/upload-artifact@v7",
|
|
828
826
|
with: {
|
|
829
|
-
name: `${pkg.crate}-\${{ matrix.
|
|
830
|
-
path: `dist/release/${pkg.crate}/\${{ matrix.
|
|
827
|
+
name: `${pkg.crate}-\${{ matrix.node }}-binary`,
|
|
828
|
+
path: `dist/release/${pkg.crate}/\${{ matrix.node }}/binary/*`,
|
|
831
829
|
"retention-days": 7,
|
|
832
830
|
},
|
|
833
831
|
})),
|
|
834
832
|
];
|
|
835
833
|
const buildJob = {
|
|
836
|
-
|
|
834
|
+
if: "${{ github.event_name == 'push' || inputs.stage == 'all' }}",
|
|
835
|
+
name: "${{ matrix.node }}",
|
|
837
836
|
needs: ["verify-context"],
|
|
838
|
-
|
|
837
|
+
runsOn: ["${{ matrix.runner }}"],
|
|
838
|
+
permissions: { contents: JobPermission.READ },
|
|
839
839
|
env: {
|
|
840
840
|
...RUST_CACHE_ENV,
|
|
841
|
-
SCCACHE_GHA_VERSION: `release-\${{ matrix.
|
|
841
|
+
SCCACHE_GHA_VERSION: `release-\${{ matrix.cargo }}-rust-${releaseRustVersion}`,
|
|
842
842
|
},
|
|
843
843
|
strategy: {
|
|
844
|
-
|
|
844
|
+
failFast: false,
|
|
845
845
|
matrix: { include: targetMatrix },
|
|
846
846
|
},
|
|
847
847
|
steps: [
|
|
@@ -849,31 +849,31 @@ export class DBXToolsRustWorkspace {
|
|
|
849
849
|
...(hasPythonBindings ? [{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" }] : []),
|
|
850
850
|
{
|
|
851
851
|
name: "Setup Rust",
|
|
852
|
-
...(usePreinstalledWindowsRust ? { if: "${{ matrix.
|
|
852
|
+
...(usePreinstalledWindowsRust ? { if: "${{ matrix.os != 'win32' }}" } : {}),
|
|
853
853
|
uses: `dtolnay/rust-toolchain@${releaseRustVersion}`,
|
|
854
|
-
with: { targets: "${{ matrix.
|
|
854
|
+
with: { targets: "${{ matrix.cargo }}" },
|
|
855
855
|
},
|
|
856
856
|
...(usePreinstalledWindowsRust
|
|
857
857
|
? [
|
|
858
858
|
{
|
|
859
859
|
name: "Verify preinstalled Windows Rust",
|
|
860
|
-
if: "${{ matrix.
|
|
860
|
+
if: "${{ matrix.os == 'win32' }}",
|
|
861
861
|
shell: "bash",
|
|
862
862
|
run: [
|
|
863
863
|
"rustc --version --verbose",
|
|
864
864
|
"cargo --version",
|
|
865
|
-
'rustup target list --installed | grep -Fx "${{ matrix.
|
|
866
|
-
'test -f "$(rustc --print sysroot)/lib/rustlib/${{ matrix.
|
|
865
|
+
'rustup target list --installed | grep -Fx "${{ matrix.cargo }}"',
|
|
866
|
+
'test -f "$(rustc --print sysroot)/lib/rustlib/${{ matrix.cargo }}/bin/rust-lld.exe"',
|
|
867
867
|
].join("\n"),
|
|
868
868
|
},
|
|
869
869
|
]
|
|
870
870
|
: []),
|
|
871
|
-
...rustCacheSteps(`release-\${{ matrix.
|
|
871
|
+
...rustCacheSteps(`release-\${{ matrix.cargo }}-rust-${releaseRustVersion}`),
|
|
872
872
|
{
|
|
873
873
|
name: "Log cache configuration",
|
|
874
874
|
shell: "bash",
|
|
875
875
|
run: [
|
|
876
|
-
`echo "cargo_cache_namespace=release-\${{ matrix.
|
|
876
|
+
`echo "cargo_cache_namespace=release-\${{ matrix.cargo }}-rust-${releaseRustVersion}"`,
|
|
877
877
|
'echo "cargo_cache_hit=${{ steps.cargo_cache.outputs.cache-hit }}"',
|
|
878
878
|
'echo "sccache_scope=${{ github.ref }}"',
|
|
879
879
|
'echo "sccache_namespace=${SCCACHE_GHA_VERSION}"',
|
|
@@ -881,7 +881,7 @@ export class DBXToolsRustWorkspace {
|
|
|
881
881
|
},
|
|
882
882
|
{
|
|
883
883
|
name: "Install Linux native dependencies",
|
|
884
|
-
if: "${{ matrix.
|
|
884
|
+
if: "${{ matrix.os == 'linux' }}",
|
|
885
885
|
run: "sudo apt-get update && sudo apt-get install --yes libdbus-1-dev pkg-config",
|
|
886
886
|
},
|
|
887
887
|
{
|
|
@@ -889,11 +889,11 @@ export class DBXToolsRustWorkspace {
|
|
|
889
889
|
shell: "bash",
|
|
890
890
|
env: {
|
|
891
891
|
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER:
|
|
892
|
-
"${{ matrix.
|
|
892
|
+
"${{ matrix.os == 'win32' && 'rust-lld' || '' }}",
|
|
893
893
|
},
|
|
894
894
|
run: timedBash(
|
|
895
895
|
"rust_workspace",
|
|
896
|
-
'cargo build --release --workspace --target "${{ matrix.
|
|
896
|
+
'cargo build --release --workspace --target "${{ matrix.cargo }}"',
|
|
897
897
|
),
|
|
898
898
|
},
|
|
899
899
|
...(bindingCommands.length
|
|
@@ -901,7 +901,7 @@ export class DBXToolsRustWorkspace {
|
|
|
901
901
|
{
|
|
902
902
|
name: "Package UniFFI outputs",
|
|
903
903
|
shell: "bash",
|
|
904
|
-
env: { VERSION:
|
|
904
|
+
env: { VERSION: RELEASE_VERSION },
|
|
905
905
|
run: timedBash("uniffi_packaging", bindingCommands.join("\n")),
|
|
906
906
|
},
|
|
907
907
|
]
|
|
@@ -924,194 +924,160 @@ export class DBXToolsRustWorkspace {
|
|
|
924
924
|
},
|
|
925
925
|
],
|
|
926
926
|
};
|
|
927
|
-
const
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
"
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
927
|
+
const workflow = releaseWorkflow(project);
|
|
928
|
+
if (hasTargetOutputs && targetMatrix.length) {
|
|
929
|
+
workflow.addJob("rust-build", buildJob);
|
|
930
|
+
}
|
|
931
|
+
if (publicCrates.length) {
|
|
932
|
+
workflow.addJob("publish-cargo", {
|
|
933
|
+
if: "${{ github.event_name == 'push' }}",
|
|
934
|
+
needs: ["verify-context", "rust-build"],
|
|
935
|
+
runsOn: ["ubuntu-latest"],
|
|
936
|
+
permissions: { contents: JobPermission.READ },
|
|
937
|
+
steps: [
|
|
938
|
+
...releaseSourceSteps(),
|
|
939
|
+
{
|
|
940
|
+
name: "Setup Rust",
|
|
941
|
+
uses: `dtolnay/rust-toolchain@${releaseRustVersion}`,
|
|
939
942
|
},
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
943
|
+
{
|
|
944
|
+
name: "Publish public crates",
|
|
945
|
+
env: { CARGO_REGISTRY_TOKEN: "${{ secrets.CARGO_REGISTRY_TOKEN }}" },
|
|
946
|
+
run: publicCrates
|
|
947
|
+
.map((crate) => `cargo publish --package "${crate}" --registry crates-io --no-verify`)
|
|
948
|
+
.join("\n"),
|
|
949
|
+
},
|
|
950
|
+
],
|
|
951
|
+
});
|
|
952
|
+
workflow.addJob("publish-local-cargo", {
|
|
953
|
+
if: "${{ github.event_name == 'push' && vars.LOCAL_REPOSITORIES == 'true' }}",
|
|
954
|
+
needs: ["verify-context", "rust-build"],
|
|
955
|
+
runsOn: ["self-hosted"],
|
|
956
|
+
permissions: { contents: JobPermission.READ },
|
|
957
|
+
steps: [
|
|
958
|
+
...releaseSourceSteps(),
|
|
959
|
+
{
|
|
960
|
+
name: "Setup Rust",
|
|
961
|
+
uses: `dtolnay/rust-toolchain@${releaseRustVersion}`,
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
name: "Publish Cargo crates locally",
|
|
965
|
+
env: { CARGO_REGISTRY_TOKEN: "${{ secrets.LOCAL_CARGO_TOKEN }}" },
|
|
966
|
+
run: publicCrates
|
|
967
|
+
.map(
|
|
968
|
+
(crate) =>
|
|
969
|
+
`cargo publish --package "${crate}" --registry "\${{ vars.LOCAL_CARGO_REGISTRY }}" --no-verify`,
|
|
970
|
+
)
|
|
971
|
+
.join("\n"),
|
|
972
|
+
},
|
|
973
|
+
],
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
if (releaseBinaries.length) {
|
|
977
|
+
workflow.addJob("publish-github-release", {
|
|
978
|
+
if: "${{ github.event_name == 'push' }}",
|
|
979
|
+
needs: ["verify-context", "rust-build"],
|
|
980
|
+
runsOn: ["ubuntu-latest"],
|
|
981
|
+
permissions: { contents: JobPermission.WRITE },
|
|
982
|
+
steps: [
|
|
983
|
+
{
|
|
984
|
+
name: "Download release binaries",
|
|
985
|
+
uses: "actions/download-artifact@v8",
|
|
986
|
+
with: {
|
|
987
|
+
pattern: "*-binary",
|
|
988
|
+
path: "dist/rust-release",
|
|
989
|
+
"merge-multiple": true,
|
|
952
990
|
},
|
|
953
991
|
},
|
|
992
|
+
{
|
|
993
|
+
name: "Publish GitHub release assets",
|
|
994
|
+
uses: "softprops/action-gh-release@v2",
|
|
995
|
+
with: {
|
|
996
|
+
files: "dist/rust-release/*",
|
|
997
|
+
"generate-release-notes": true,
|
|
998
|
+
tag_name: RELEASE_TAG,
|
|
999
|
+
target_commitish: RELEASE_SHA,
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
],
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
const nodeBindings = bindings.filter((binding) => Boolean(binding.node && binding.nodePackage));
|
|
1007
|
+
if (nodeBindings.length && hasNodeRelease(project)) {
|
|
1008
|
+
workflow.addJob("publish-native-npm", {
|
|
1009
|
+
if: "${{ 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 == 'node') }}",
|
|
1010
|
+
needs: ["verify-context", "rust-build"],
|
|
1011
|
+
runsOn: ["ubuntu-latest"],
|
|
1012
|
+
permissions: {
|
|
1013
|
+
actions: JobPermission.READ,
|
|
1014
|
+
contents: JobPermission.READ,
|
|
1015
|
+
idToken: JobPermission.WRITE,
|
|
954
1016
|
},
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
},
|
|
970
|
-
run: 'test "$GITHUB_REF_NAME" = "$RELEASE_BRANCH"',
|
|
971
|
-
},
|
|
972
|
-
{
|
|
973
|
-
name: "Write release metadata",
|
|
974
|
-
shell: "bash",
|
|
975
|
-
env: {
|
|
976
|
-
RELEASE_TAG,
|
|
977
|
-
EXPECTED_SHA: RELEASE_SHA,
|
|
978
|
-
},
|
|
979
|
-
run: [
|
|
980
|
-
"mkdir -p .release",
|
|
981
|
-
'printf "%s\\n" "$RELEASE_TAG" > .release/tag',
|
|
982
|
-
'printf "%s\\n" "$EXPECTED_SHA" > .release/sha',
|
|
983
|
-
].join("\n"),
|
|
984
|
-
},
|
|
985
|
-
{
|
|
986
|
-
name: "Upload release metadata",
|
|
987
|
-
uses: "actions/upload-artifact@v7",
|
|
988
|
-
with: {
|
|
989
|
-
name: "release-metadata",
|
|
990
|
-
path: ".release",
|
|
991
|
-
},
|
|
992
|
-
},
|
|
993
|
-
],
|
|
1017
|
+
timeoutMinutes: 15,
|
|
1018
|
+
env: { BUN_VERSION, CI: "true" },
|
|
1019
|
+
steps: [
|
|
1020
|
+
...nodeReleaseSetupSteps(project),
|
|
1021
|
+
...releaseArtifactSteps({
|
|
1022
|
+
currentName: "Download native npm packages",
|
|
1023
|
+
recoveredName: "Download recovered native npm packages",
|
|
1024
|
+
pattern: "*-npm",
|
|
1025
|
+
path: "dist/uniffi/native",
|
|
1026
|
+
}),
|
|
1027
|
+
{
|
|
1028
|
+
name: "Publish native npm packages",
|
|
1029
|
+
env: { RELEASE_VERSION, ...npmPublishEnvironment() },
|
|
1030
|
+
run: 'bun node_modules/@dbx-tools/projen/tasks/publish-npm.ts --directory dist/uniffi/native --version "$RELEASE_VERSION" $DRY_RUN',
|
|
994
1031
|
},
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
"publish-local-cargo": {
|
|
1026
|
-
if: "${{ github.event_name == 'repository_dispatch' && vars.LOCAL_REPOSITORIES == 'true' }}",
|
|
1027
|
-
needs: ["build"],
|
|
1028
|
-
"runs-on": ["self-hosted"],
|
|
1029
|
-
permissions: { contents: "read" },
|
|
1030
|
-
steps: [
|
|
1031
|
-
...releaseSourceSteps(),
|
|
1032
|
-
{
|
|
1033
|
-
name: "Setup Rust",
|
|
1034
|
-
uses: `dtolnay/rust-toolchain@${releaseRustVersion}`,
|
|
1035
|
-
},
|
|
1036
|
-
{
|
|
1037
|
-
name: "Publish Cargo crates locally",
|
|
1038
|
-
env: {
|
|
1039
|
-
CARGO_REGISTRY_TOKEN: "${{ secrets.LOCAL_CARGO_TOKEN }}",
|
|
1040
|
-
},
|
|
1041
|
-
run: publicCrates
|
|
1042
|
-
.map(
|
|
1043
|
-
(crate) =>
|
|
1044
|
-
`cargo publish --package "${crate}" --registry "\${{ vars.LOCAL_CARGO_REGISTRY }}" --no-verify`,
|
|
1045
|
-
)
|
|
1046
|
-
.join("\n"),
|
|
1047
|
-
},
|
|
1048
|
-
],
|
|
1049
|
-
},
|
|
1050
|
-
}
|
|
1051
|
-
: {}),
|
|
1052
|
-
...(releaseBinaries.length
|
|
1053
|
-
? {
|
|
1054
|
-
"publish-github-release": {
|
|
1055
|
-
if: "${{ github.event_name == 'repository_dispatch' }}",
|
|
1056
|
-
needs: ["build"],
|
|
1057
|
-
"runs-on": "ubuntu-latest",
|
|
1058
|
-
permissions: { contents: "write" },
|
|
1059
|
-
steps: [
|
|
1060
|
-
{
|
|
1061
|
-
name: "Download release binaries",
|
|
1062
|
-
uses: "actions/download-artifact@v8",
|
|
1063
|
-
with: {
|
|
1064
|
-
pattern: "*-binary",
|
|
1065
|
-
path: "dist/rust-release",
|
|
1066
|
-
"merge-multiple": true,
|
|
1067
|
-
},
|
|
1068
|
-
},
|
|
1069
|
-
{
|
|
1070
|
-
name: "Publish GitHub release assets",
|
|
1071
|
-
uses: "softprops/action-gh-release@v2",
|
|
1072
|
-
with: {
|
|
1073
|
-
files: "dist/rust-release/*",
|
|
1074
|
-
"generate-release-notes": true,
|
|
1075
|
-
tag_name: RELEASE_TAG,
|
|
1076
|
-
target_commitish: RELEASE_SHA,
|
|
1077
|
-
},
|
|
1078
|
-
},
|
|
1079
|
-
],
|
|
1080
|
-
},
|
|
1081
|
-
}
|
|
1082
|
-
: {}),
|
|
1083
|
-
"dispatch-downstream": {
|
|
1084
|
-
if: "${{ github.event_name == 'repository_dispatch' }}",
|
|
1085
|
-
needs: releaseCompletionJobs,
|
|
1086
|
-
"runs-on": "ubuntu-latest",
|
|
1087
|
-
permissions: { contents: "write" },
|
|
1088
|
-
steps: [
|
|
1089
|
-
{
|
|
1090
|
-
name: "Dispatch downstream releases",
|
|
1091
|
-
shell: "bash",
|
|
1092
|
-
env: {
|
|
1093
|
-
GH_TOKEN: "${{ github.token }}",
|
|
1094
|
-
RELEASE_TAG,
|
|
1095
|
-
EXPECTED_SHA: RELEASE_SHA,
|
|
1096
|
-
RELEASE_EVENT: DOWNSTREAM_RELEASE_EVENT,
|
|
1097
|
-
RUST_RUN_ID: "${{ github.run_id }}",
|
|
1098
|
-
RUST_RUN_ATTEMPT: "${{ github.run_attempt }}",
|
|
1099
|
-
},
|
|
1100
|
-
run: [
|
|
1101
|
-
[
|
|
1102
|
-
'gh api --method POST "repos/$GITHUB_REPOSITORY/dispatches"',
|
|
1103
|
-
'--raw-field event_type="$RELEASE_EVENT"',
|
|
1104
|
-
'--raw-field "client_payload[release_tag]=$RELEASE_TAG"',
|
|
1105
|
-
'--raw-field "client_payload[expected_sha]=$EXPECTED_SHA"',
|
|
1106
|
-
'--raw-field "client_payload[rust_run_id]=$RUST_RUN_ID"',
|
|
1107
|
-
'--raw-field "client_payload[rust_run_attempt]=$RUST_RUN_ATTEMPT"',
|
|
1108
|
-
].join(" \\\n "),
|
|
1109
|
-
].join("\n"),
|
|
1110
|
-
},
|
|
1111
|
-
],
|
|
1032
|
+
],
|
|
1033
|
+
});
|
|
1034
|
+
const nodeJob = workflow.getJob("publish-node");
|
|
1035
|
+
if ("uses" in nodeJob) throw new Error("publish-node must be a workflow job");
|
|
1036
|
+
workflow.updateJob("publish-node", {
|
|
1037
|
+
...nodeJob,
|
|
1038
|
+
if: "${{ always() && needs.verify-context.result == 'success' && needs.publish-native-npm.result == 'success' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'node') }}",
|
|
1039
|
+
needs: ["verify-context", "publish-native-npm"],
|
|
1040
|
+
});
|
|
1041
|
+
workflow.addJob("publish-node-facades", {
|
|
1042
|
+
if: releaseStageCondition("node"),
|
|
1043
|
+
needs: ["verify-context", "publish-node"],
|
|
1044
|
+
runsOn: ["ubuntu-latest"],
|
|
1045
|
+
permissions: { contents: JobPermission.READ, idToken: JobPermission.WRITE },
|
|
1046
|
+
timeoutMinutes: 30,
|
|
1047
|
+
env: { BUN_VERSION, CI: "true" },
|
|
1048
|
+
steps: [
|
|
1049
|
+
...nodeReleaseSetupSteps(project),
|
|
1050
|
+
{
|
|
1051
|
+
name: "Build and publish UniFFI npm facades",
|
|
1052
|
+
env: { RELEASE_VERSION, ...npmPublishEnvironment() },
|
|
1053
|
+
run: nodeBindings
|
|
1054
|
+
.flatMap((binding) => {
|
|
1055
|
+
const output = `dist/uniffi/facades/${binding.crate}`;
|
|
1056
|
+
return [
|
|
1057
|
+
`node .projen/uniffi-release.mjs facade --node "${binding.node}" --node-package "${binding.nodePackage}" --node-triple "linux-x64-gnu" --version "$RELEASE_VERSION" --output "${output}"`,
|
|
1058
|
+
`bun node_modules/@dbx-tools/projen/tasks/publish-npm.ts --directory "${output}/npm-facade" --version "$RELEASE_VERSION" $DRY_RUN`,
|
|
1059
|
+
];
|
|
1060
|
+
})
|
|
1061
|
+
.join("\n"),
|
|
1112
1062
|
},
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1063
|
+
{
|
|
1064
|
+
name: "Smoke test published UniFFI npm facades",
|
|
1065
|
+
if: "${{ github.event_name == 'push' && vars.UNIFFI_FACADE_SMOKE == 'true' }}",
|
|
1066
|
+
continueOnError: true,
|
|
1067
|
+
env: { RELEASE_VERSION },
|
|
1068
|
+
run: [
|
|
1069
|
+
'SMOKE_DIR="$(mktemp -d)"',
|
|
1070
|
+
"trap 'rm -rf \"$SMOKE_DIR\"' EXIT",
|
|
1071
|
+
'cd "$SMOKE_DIR"',
|
|
1072
|
+
"npm init --yes >/dev/null",
|
|
1073
|
+
...nodeBindings.flatMap((binding) => [
|
|
1074
|
+
`npm install --ignore-scripts --no-audit --no-fund --package-lock=false "${binding.nodePackage}@$RELEASE_VERSION"`,
|
|
1075
|
+
`node -e 'import("${binding.nodePackage}")'`,
|
|
1076
|
+
]),
|
|
1077
|
+
].join("\n"),
|
|
1078
|
+
},
|
|
1079
|
+
],
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1116
1082
|
}
|
|
1117
1083
|
}
|
package/src/release-dispatch.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
export const RUST_RELEASE_EVENT = "rust-release";
|
|
4
|
-
export const RELEASE_TAG =
|
|
5
|
-
"${{ github.event_name == 'repository_dispatch' && github.event.client_payload.release_tag || inputs.release_tag }}";
|
|
6
|
-
export const RELEASE_SHA =
|
|
7
|
-
"${{ github.event_name == 'repository_dispatch' && github.event.client_payload.expected_sha || inputs.expected_sha }}";
|
|
1
|
+
/** Verified release context shared by every job in the unified workflow. */
|
|
2
|
+
import type { JobStep } from "projen/lib/github/workflows-model";
|
|
8
3
|
|
|
9
|
-
|
|
10
|
-
export
|
|
4
|
+
export const RELEASE_TAG = "${{ needs.verify-context.outputs.release_tag }}";
|
|
5
|
+
export const RELEASE_SHA = "${{ needs.verify-context.outputs.expected_sha }}";
|
|
6
|
+
export const RELEASE_VERSION = "${{ needs.verify-context.outputs.release_version }}";
|
|
7
|
+
|
|
8
|
+
/** Check out and verify the immutable commit selected by the release tag. */
|
|
9
|
+
export function releaseSourceSteps(): readonly JobStep[] {
|
|
11
10
|
return [
|
|
12
11
|
{
|
|
13
12
|
name: "Checkout release commit",
|
|
@@ -25,9 +24,8 @@ export function releaseSourceSteps(): readonly Record<string, unknown>[] {
|
|
|
25
24
|
EXPECTED_SHA: RELEASE_SHA,
|
|
26
25
|
},
|
|
27
26
|
run: [
|
|
28
|
-
'test -n "$RELEASE_TAG"',
|
|
29
|
-
'test -n "$EXPECTED_SHA"',
|
|
30
27
|
'git fetch --force origin "+refs/tags/$RELEASE_TAG:refs/tags/$RELEASE_TAG"',
|
|
28
|
+
'test "$(git cat-file -t "$RELEASE_TAG")" = "tag"',
|
|
31
29
|
'test "$(git rev-parse "$RELEASE_TAG^{commit}")" = "$EXPECTED_SHA"',
|
|
32
30
|
'test "$(git rev-parse HEAD)" = "$EXPECTED_SHA"',
|
|
33
31
|
].join("\n"),
|