@dbx-tools/projen 0.9.18 → 0.9.21
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/._LICENSE +0 -0
- package/._README.md +0 -0
- package/._index.ts +0 -0
- package/._package.json +0 -0
- package/README.md +72 -88
- package/index.ts +2 -7
- package/package.json +9 -5
- package/src/.__lazy-require.ts +0 -0
- package/src/.__release-platform.ts +0 -0
- package/src/.__rust-project.ts +0 -0
- package/src/.__rust-release-workflow.ts +0 -0
- package/src/.__task-command.ts +0 -0
- package/src/._barrels.ts +0 -0
- package/src/._bun-app.ts +0 -0
- package/src/._bun-workflow.ts +0 -0
- package/src/._clean.ts +0 -0
- package/src/._codegen.ts +0 -0
- package/src/._dbx-tools-config.ts +0 -0
- package/src/._engine-root.ts +0 -0
- package/src/._generated.ts +0 -0
- package/src/._mixin.ts +0 -0
- package/src/._module-exports.ts +0 -0
- package/src/._openapi.ts +0 -0
- package/src/._packages.ts +0 -0
- package/src/._pnpm-workspace.ts +0 -0
- package/src/._project-js.ts +0 -0
- package/src/._project-predicate.ts +0 -0
- package/src/._project-py.ts +0 -0
- package/src/._project-rs.ts +0 -0
- package/src/._project.ts +0 -0
- package/src/._projen-version.ts +0 -0
- package/src/._publish.ts +0 -0
- package/src/._release-catalog.ts +0 -0
- package/src/._release-dispatch.ts +0 -0
- package/src/._release-github.ts +0 -0
- package/src/._release.ts +0 -0
- package/src/._scaffold.ts +0 -0
- package/src/._tags.ts +0 -0
- package/src/._tsconfig.ts +0 -0
- package/src/._uniffi.ts +0 -0
- package/src/._vscode.ts +0 -0
- package/src/._watch.ts +0 -0
- package/src/._workspace-lock.ts +0 -0
- package/src/._workspace-version.ts +0 -0
- package/src/_rust-release-workflow.ts +18 -582
- package/src/_task-command.ts +75 -0
- package/src/project-js.ts +2 -42
- package/src/project-py.ts +60 -162
- package/src/project-rs.ts +4 -100
- package/src/release-catalog.ts +37 -203
- package/src/release.ts +96 -775
- package/src/scaffold.ts +2 -6
- package/src/workspace-version.ts +9 -121
- package/tasks/._barrels.ts +0 -0
- package/tasks/._bump.ts +0 -0
- package/tasks/._clean.ts +0 -0
- package/tasks/._compile-workspace.ts +0 -0
- package/tasks/._local-publish.ts +0 -0
- package/tasks/._openapi.ts +0 -0
- package/tasks/._projenrc.ts +0 -0
- package/tasks/._publish-npm.ts +0 -0
- package/tasks/._publish-python.ts +0 -0
- package/tasks/._publish-uniffi-local.ts +0 -0
- package/tasks/._publish.ts +0 -0
- package/tasks/._python-registry.ts +0 -0
- package/tasks/._release-assets.ts +0 -0
- package/tasks/._release-candidate.ts +0 -0
- package/tasks/._release-manifest.ts +0 -0
- package/tasks/._release-pr.ts +0 -0
- package/tasks/._release-summary.ts +0 -0
- package/tasks/._release-version.ts +0 -0
- package/tasks/._rust.ts +0 -0
- package/tasks/._sync.ts +0 -0
- package/tasks/._uniffi-python.d.ts +0 -0
- package/tasks/._uniffi-python.js +0 -0
- package/tasks/._uniffi-release.mjs +0 -0
- package/tasks/._uniffi.ts +0 -0
- package/tasks/._version-check.ts +0 -0
- package/tasks/bump.ts +17 -34
- package/tasks/local-publish.ts +124 -117
- package/tasks/publish-npm.ts +125 -41
- package/tasks/publish-python.ts +79 -106
- package/tasks/publish-uniffi-local.ts +129 -84
- package/tasks/publish.ts +44 -139
- package/tasks/python-registry.ts +2 -9
- package/tasks/release-assets.ts +56 -65
- package/tasks/release-candidate.ts +416 -0
- package/tasks/release-manifest.ts +273 -0
- package/tasks/release-pr.ts +312 -369
- package/tasks/release-summary.ts +8 -10
- package/tasks/release-version.ts +23 -2
- package/tasks/rust.ts +8 -13
- package/tasks/uniffi-python.d.ts +2 -3
- package/tasks/uniffi-python.js +7 -20
- package/tasks/uniffi-release.mjs +19 -13
- package/tasks/uniffi.ts +15 -24
- package/tasks/version-check.ts +24 -56
- package/src/release-plan.ts +0 -269
- package/src/release-please.ts +0 -242
- package/tasks/release-bootstrap.ts +0 -59
- package/tasks/release-plan.ts +0 -89
- package/tasks/release-please.ts +0 -162
- package/tasks/release-request.ts +0 -166
- package/tasks/release-summary-units.ts +0 -75
- package/tasks/stamp-python.ts +0 -13
package/src/_task-command.ts
CHANGED
|
@@ -12,6 +12,13 @@ export interface CaptureTaskCommandOptions extends TaskCommandOptions {
|
|
|
12
12
|
readonly check?: boolean;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
export type ProbeTaskCommandOptions = TaskCommandOptions;
|
|
16
|
+
|
|
17
|
+
export interface LoggedTaskCommandOptions extends TaskCommandOptions {
|
|
18
|
+
/** Receive normalized stdout and stderr lines after the command exits. */
|
|
19
|
+
readonly onLine: (line: string) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
15
22
|
function executable(command: string): string {
|
|
16
23
|
return command === "bun" && process.versions.bun ? process.execPath : command;
|
|
17
24
|
}
|
|
@@ -69,6 +76,47 @@ export function captureTaskCommand(
|
|
|
69
76
|
return result.exitCode === 0 ? (result.stdout?.trim() ?? "") : "";
|
|
70
77
|
}
|
|
71
78
|
|
|
79
|
+
/** Capture trimmed stdout while preserving command failure as `undefined`. */
|
|
80
|
+
export function probeTaskCommand(
|
|
81
|
+
cwd: string,
|
|
82
|
+
command: string,
|
|
83
|
+
args: readonly string[],
|
|
84
|
+
options: ProbeTaskCommandOptions = {},
|
|
85
|
+
): string | undefined {
|
|
86
|
+
const result = exec.spawnSync(executable(command), [...args], {
|
|
87
|
+
cwd,
|
|
88
|
+
env: options.env,
|
|
89
|
+
stdout: "capture",
|
|
90
|
+
stderr: options.stderr ?? "ignore",
|
|
91
|
+
stdin: "ignore",
|
|
92
|
+
check: false,
|
|
93
|
+
});
|
|
94
|
+
return result.exitCode === 0 ? (result.stdout?.trim() ?? "") : undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Run a checked command while routing captured output through one line policy. */
|
|
98
|
+
export function runLoggedTaskCommand(
|
|
99
|
+
cwd: string,
|
|
100
|
+
command: string,
|
|
101
|
+
args: readonly string[],
|
|
102
|
+
options: LoggedTaskCommandOptions,
|
|
103
|
+
): void {
|
|
104
|
+
const result = exec.spawnSync(executable(command), [...args], {
|
|
105
|
+
cwd,
|
|
106
|
+
env: options.env,
|
|
107
|
+
stdout: "capture",
|
|
108
|
+
stderr: "capture",
|
|
109
|
+
stdin: "ignore",
|
|
110
|
+
check: false,
|
|
111
|
+
});
|
|
112
|
+
for (const line of [...result.stdoutLines, ...result.stderrLines]) {
|
|
113
|
+
if (line) options.onLine(line);
|
|
114
|
+
}
|
|
115
|
+
if (result.exitCode !== 0) {
|
|
116
|
+
throw new Error(`${command} exited with ${result.exitCode}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
72
120
|
/** Whether a quiet, non-interactive command exits successfully. */
|
|
73
121
|
export function taskCommandSucceeds(
|
|
74
122
|
cwd: string,
|
|
@@ -87,3 +135,30 @@ export function taskCommandSucceeds(
|
|
|
87
135
|
}).exitCode === 0
|
|
88
136
|
);
|
|
89
137
|
}
|
|
138
|
+
|
|
139
|
+
/** Run Git with the shared non-interactive checked command policy. */
|
|
140
|
+
export function runGitTaskCommand(
|
|
141
|
+
cwd: string,
|
|
142
|
+
args: readonly string[],
|
|
143
|
+
options: TaskCommandOptions = {},
|
|
144
|
+
): void {
|
|
145
|
+
runTaskCommand(cwd, "git", args, options);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Capture Git output, returning an empty string for optional offline probes. */
|
|
149
|
+
export function captureGitTaskCommand(
|
|
150
|
+
cwd: string,
|
|
151
|
+
args: readonly string[],
|
|
152
|
+
options: CaptureTaskCommandOptions = {},
|
|
153
|
+
): string {
|
|
154
|
+
return captureTaskCommand(cwd, "git", args, options);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Whether a quiet Git command succeeds. */
|
|
158
|
+
export function gitTaskCommandSucceeds(
|
|
159
|
+
cwd: string,
|
|
160
|
+
args: readonly string[],
|
|
161
|
+
options: Pick<TaskCommandOptions, "env"> = {},
|
|
162
|
+
): boolean {
|
|
163
|
+
return taskCommandSucceeds(cwd, "git", args, options);
|
|
164
|
+
}
|
package/src/project-js.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { type IConstruct } from "constructs";
|
|
|
15
15
|
import { Component, IgnoreFile, Project, type TaskOptions, javascript, typescript } from "projen";
|
|
16
16
|
import { BuildWorkflow } from "projen/lib/build";
|
|
17
17
|
import { AutoMerge } from "projen/lib/github";
|
|
18
|
-
import { JobPermission, type JobStep
|
|
18
|
+
import { JobPermission, type JobStep } from "projen/lib/github/workflows-model";
|
|
19
19
|
import type { ReleaseProjectOptions } from "projen/lib/release";
|
|
20
20
|
import { mixin } from "..";
|
|
21
21
|
import { generateBarrels } from "./barrels.ts";
|
|
@@ -44,7 +44,6 @@ import { PROJEN_VERSION } from "./projen-version.ts";
|
|
|
44
44
|
import { applyCompiledPublish } from "./publish.ts";
|
|
45
45
|
import {
|
|
46
46
|
DBXToolsReleaseCatalog,
|
|
47
|
-
type DBXToolsVersioningMode,
|
|
48
47
|
type ExternalReleaseProjectRegistration,
|
|
49
48
|
type ReleaseDependencyInput,
|
|
50
49
|
type ReleaseUnitRule,
|
|
@@ -628,18 +627,12 @@ export type DBXToolsJavaScriptProjectOptions = CommonProjectOptions &
|
|
|
628
627
|
readonly releaseValidationTasks?: readonly string[];
|
|
629
628
|
/** Optional AI-generated release summary. Defaults to enabled. */
|
|
630
629
|
readonly releaseSummary?: boolean | ReleaseSummaryOptions;
|
|
631
|
-
/** Existing source branch safely fast-forwarded after an independent release. */
|
|
632
|
-
readonly releaseSyncBranch?: string | false;
|
|
633
630
|
/** Set to `false` to omit normal npm workspace publication. */
|
|
634
631
|
readonly nodeRelease?: boolean;
|
|
635
632
|
/** Unified dbx-tools release workflow, or no release surface. Defaults to `dbx-tools`. */
|
|
636
633
|
readonly releaseMode?: DBXToolsReleaseMode;
|
|
637
|
-
/** Package version ownership mode. Defaults to `fixed`. */
|
|
638
|
-
readonly versioningMode?: DBXToolsVersioningMode;
|
|
639
634
|
/** Explicit stable release-unit grouping rules. */
|
|
640
635
|
readonly releaseUnits?: readonly ReleaseUnitRule[];
|
|
641
|
-
/** Commit before the first independent Release Please history. */
|
|
642
|
-
readonly releaseBootstrapSha?: string;
|
|
643
636
|
/** Publishable workspace members synthesized outside the attached project tree. */
|
|
644
637
|
readonly externalReleaseProjects?: readonly ExternalReleaseProjectRegistration[];
|
|
645
638
|
/** Prefix for generated release tags. Defaults to `v`. */
|
|
@@ -723,10 +716,8 @@ export class DBXToolsNodeProject
|
|
|
723
716
|
// (its build phase installs with pnpm and reads catalog + `allowBuilds`).
|
|
724
717
|
pnpmWorkspace.attachWorkspaceFile(this);
|
|
725
718
|
this.releaseCatalog = new DBXToolsReleaseCatalog(this, {
|
|
726
|
-
mode: options.versioningMode,
|
|
727
719
|
units: options.releaseUnits,
|
|
728
720
|
externalProjects: options.externalReleaseProjects,
|
|
729
|
-
bootstrapSha: options.releaseBootstrapSha,
|
|
730
721
|
});
|
|
731
722
|
registerJavaScriptReleaseProject(this);
|
|
732
723
|
this.package.addField("version", () => this.releaseCatalog.versionFor(this));
|
|
@@ -862,10 +853,8 @@ export class DBXToolsTypeScriptProject
|
|
|
862
853
|
(parent instanceof DBXToolsNodeProject || parent instanceof DBXToolsTypeScriptProject)
|
|
863
854
|
? parent.releaseCatalog
|
|
864
855
|
: new DBXToolsReleaseCatalog(this, {
|
|
865
|
-
mode: options.versioningMode,
|
|
866
856
|
units: options.releaseUnits,
|
|
867
857
|
externalProjects: options.externalReleaseProjects,
|
|
868
|
-
bootstrapSha: options.releaseBootstrapSha,
|
|
869
858
|
});
|
|
870
859
|
// Pairs with `jsx` in SHARED_COMPILER_OPTIONS: projen's default `include` is
|
|
871
860
|
// `src/**/*.ts` only, which silently omits a `.tsx` file from the program
|
|
@@ -937,35 +926,7 @@ function configureBuildWorkflow(
|
|
|
937
926
|
});
|
|
938
927
|
validation.exec("bunx projen default");
|
|
939
928
|
validation.exec("bun run compile");
|
|
940
|
-
const configured = {
|
|
941
|
-
...options.buildWorkflowOptions,
|
|
942
|
-
...(!options.buildWorkflowOptions?.workflowTriggers &&
|
|
943
|
-
project.releaseCatalog.mode === "independent"
|
|
944
|
-
? {
|
|
945
|
-
workflowTriggers: {
|
|
946
|
-
pullRequest: {
|
|
947
|
-
types: ["opened", "synchronize", "reopened", "closed"],
|
|
948
|
-
paths: [
|
|
949
|
-
"**",
|
|
950
|
-
"!.projen/release-units.json",
|
|
951
|
-
"!.release-please-manifest.json",
|
|
952
|
-
"!.release-units/**",
|
|
953
|
-
"!.release-notes/**",
|
|
954
|
-
"!docs/releases/**",
|
|
955
|
-
"!Cargo.lock",
|
|
956
|
-
"!**/Cargo.toml",
|
|
957
|
-
"!**/package.json",
|
|
958
|
-
"!**/pyproject.toml",
|
|
959
|
-
"!**/index.ts",
|
|
960
|
-
"!packages/js/node/rust-binary/src/_release-binaries.ts",
|
|
961
|
-
"!packages/js/node/appkit-graphiti/src/_python-runtime.ts",
|
|
962
|
-
],
|
|
963
|
-
},
|
|
964
|
-
workflowDispatch: {},
|
|
965
|
-
} satisfies Triggers,
|
|
966
|
-
}
|
|
967
|
-
: {}),
|
|
968
|
-
};
|
|
929
|
+
const configured = { ...options.buildWorkflowOptions };
|
|
969
930
|
const compatibility = nodeWorkflowCompatibility(project);
|
|
970
931
|
const configuredRunner = configured.runsOn !== undefined || configured.runsOnGroup !== undefined;
|
|
971
932
|
const workflow = new BuildWorkflow(project, {
|
|
@@ -1620,7 +1581,6 @@ function initProject(
|
|
|
1620
1581
|
pythonRoot: options.releasePythonRoot,
|
|
1621
1582
|
validationTasks: options.releaseValidationTasks,
|
|
1622
1583
|
summary: options.releaseSummary,
|
|
1623
|
-
syncBranch: options.releaseSyncBranch,
|
|
1624
1584
|
});
|
|
1625
1585
|
}
|
|
1626
1586
|
}
|
package/src/project-py.ts
CHANGED
|
@@ -4,14 +4,17 @@ 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 { RELEASE_TAG, RELEASE_VERSION, releaseSourceSteps } from "./release-dispatch.ts";
|
|
11
10
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
RELEASE_SHA,
|
|
12
|
+
RELEASE_TAG,
|
|
13
|
+
RELEASE_VERSION,
|
|
14
|
+
releaseSourceSteps,
|
|
15
|
+
} from "./release-dispatch.ts";
|
|
16
|
+
import {
|
|
17
|
+
releaseTagPattern,
|
|
15
18
|
releasePublishCondition,
|
|
16
19
|
releaseStageCondition,
|
|
17
20
|
tryReleaseWorkflow,
|
|
@@ -109,8 +112,6 @@ const DEFAULT_DEV_DEPENDENCIES = [
|
|
|
109
112
|
"ruff>=0.12,<1",
|
|
110
113
|
] as const;
|
|
111
114
|
|
|
112
|
-
const quote = (value: string): string => JSON.stringify(value);
|
|
113
|
-
|
|
114
115
|
/** Repository-relative path for a Python package directory. */
|
|
115
116
|
export function pythonPackagePath(repository: PythonRepositoryOptions, directory: string): string {
|
|
116
117
|
return `${repository.root ?? "packages/py"}/${directory}`;
|
|
@@ -274,10 +275,7 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
274
275
|
}));
|
|
275
276
|
const resolvedOptions = { ...options, packages };
|
|
276
277
|
this.requiresPython = options.requiresPython ?? ">=3.10";
|
|
277
|
-
this.version =
|
|
278
|
-
isDBXToolsJavaScriptProject()(project) && project.releaseCatalog.mode === "independent"
|
|
279
|
-
? "0.0.0"
|
|
280
|
-
: readWorkspaceVersion(project.outdir);
|
|
278
|
+
this.version = readWorkspaceVersion(project.outdir);
|
|
281
279
|
this.file = this.emitWorkspace(project, resolvedOptions, scope);
|
|
282
280
|
this.packages = packages.map(
|
|
283
281
|
(pkg) =>
|
|
@@ -457,100 +455,15 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
457
455
|
const uniffiPublications = this.uniffiPublications(options);
|
|
458
456
|
const allPublications = [...publications, ...uniffiPublications];
|
|
459
457
|
if (allPublications.length === 0) return;
|
|
460
|
-
const usesRustArtifacts = uniffiPublications.length > 0;
|
|
461
458
|
const workflow = tryReleaseWorkflow(project);
|
|
462
459
|
if (!workflow) {
|
|
463
460
|
throw new Error("Python release requires the root dbx-tools release mode");
|
|
464
461
|
}
|
|
465
|
-
if (project.releaseCatalog.mode === "independent") {
|
|
466
|
-
workflow.addJob("build-python", {
|
|
467
|
-
if: usesRustArtifacts
|
|
468
|
-
? "${{ always() && needs.release-plan.outputs.python == 'true' && needs.rust-build.result != 'failure' && needs.rust-build.result != 'cancelled' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'python') }}"
|
|
469
|
-
: "${{ needs.release-plan.outputs.python == 'true' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'python') }}",
|
|
470
|
-
needs: ["release-plan", ...(usesRustArtifacts ? ["rust-build"] : [])],
|
|
471
|
-
runsOn: ["ubuntu-latest"],
|
|
472
|
-
permissions: { actions: JobPermission.READ, contents: JobPermission.READ },
|
|
473
|
-
timeoutMinutes: 20,
|
|
474
|
-
env: { BUN_VERSION },
|
|
475
|
-
steps: [
|
|
476
|
-
...independentReleaseSetupSteps(project),
|
|
477
|
-
{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" },
|
|
478
|
-
...uniffiPublications.map((publication) => ({
|
|
479
|
-
name: `Download ${publication.distribution} native wheels`,
|
|
480
|
-
uses: "actions/download-artifact@v8",
|
|
481
|
-
with: {
|
|
482
|
-
pattern: `${publication.distribution}--*--python-wheel`,
|
|
483
|
-
path: `dist/${publication.directory}`,
|
|
484
|
-
"merge-multiple": true,
|
|
485
|
-
},
|
|
486
|
-
})),
|
|
487
|
-
{
|
|
488
|
-
name: "Build affected distributions",
|
|
489
|
-
shell: "bash",
|
|
490
|
-
run: publications
|
|
491
|
-
.map(
|
|
492
|
-
(publication) =>
|
|
493
|
-
`if jq -e --arg package ${quote(publication.distribution)} '.pythonPackages[] | select(.identity == $package)' dist/release-plan.json >/dev/null; then uv build --package ${quote(publication.distribution)} --out-dir dist/${publication.directory}; fi`,
|
|
494
|
-
)
|
|
495
|
-
.join("\n"),
|
|
496
|
-
},
|
|
497
|
-
{
|
|
498
|
-
name: "Validate affected distributions",
|
|
499
|
-
run: "find dist -type f \\( -name '*.whl' -o -name '*.tar.gz' \\) -print0 | xargs -0 uvx twine check",
|
|
500
|
-
},
|
|
501
|
-
{
|
|
502
|
-
name: "Upload distributions",
|
|
503
|
-
uses: "actions/upload-artifact@v7",
|
|
504
|
-
with: { name: "python-distributions", path: "dist", "retention-days": 7 },
|
|
505
|
-
},
|
|
506
|
-
],
|
|
507
|
-
});
|
|
508
|
-
for (const publication of allPublications) {
|
|
509
|
-
const dependencyJobs = (publication.dependencies ?? []).map(
|
|
510
|
-
(dependency) => `publish-pypi-${dependency}`,
|
|
511
|
-
);
|
|
512
|
-
const dependencyCondition = dependencyJobs
|
|
513
|
-
.map((job) => `needs.${job}.result != 'failure' && needs.${job}.result != 'cancelled'`)
|
|
514
|
-
.join(" && ");
|
|
515
|
-
workflow.addJob(`publish-pypi-${publication.directory}`, {
|
|
516
|
-
if: `\${{ always() && needs.build-python.result == 'success' && contains(needs.release-plan.outputs.python_packages, '"identity":"${publication.distribution}"') && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'python')${dependencyCondition ? ` && ${dependencyCondition}` : ""} }}`,
|
|
517
|
-
needs: ["release-plan", "build-python", ...dependencyJobs],
|
|
518
|
-
environment: {
|
|
519
|
-
name: publication.environment,
|
|
520
|
-
url:
|
|
521
|
-
options.environmentUrl ??
|
|
522
|
-
`https://pypi.org/project/${publication.distribution.replaceAll("_", "-")}/`,
|
|
523
|
-
},
|
|
524
|
-
runsOn: ["ubuntu-latest"],
|
|
525
|
-
permissions: { idToken: JobPermission.WRITE },
|
|
526
|
-
timeoutMinutes: 10,
|
|
527
|
-
steps: [
|
|
528
|
-
{
|
|
529
|
-
name: "Download distributions",
|
|
530
|
-
uses: "actions/download-artifact@v8",
|
|
531
|
-
with: { name: "python-distributions", path: "dist" },
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
name: `Publish ${publication.distribution} to PyPI`,
|
|
535
|
-
uses: "pypa/gh-action-pypi-publish@release/v1",
|
|
536
|
-
with: {
|
|
537
|
-
"packages-dir": `dist/${publication.directory}`,
|
|
538
|
-
"skip-existing": true,
|
|
539
|
-
},
|
|
540
|
-
},
|
|
541
|
-
],
|
|
542
|
-
});
|
|
543
|
-
registerIndependentPublicationJob(workflow, `publish-pypi-${publication.directory}`);
|
|
544
|
-
}
|
|
545
|
-
return;
|
|
546
|
-
}
|
|
547
462
|
workflow.addJob("build-python", {
|
|
548
|
-
if:
|
|
549
|
-
|
|
550
|
-
: releaseStageCondition("python"),
|
|
551
|
-
needs: ["verify-context", ...(usesRustArtifacts ? ["rust-assets"] : [])],
|
|
463
|
+
if: releaseStageCondition("python", ["needs.verify-context.result == 'success'"]),
|
|
464
|
+
needs: ["verify-context"],
|
|
552
465
|
runsOn: ["ubuntu-latest"],
|
|
553
|
-
permissions: {
|
|
466
|
+
permissions: { contents: JobPermission.READ },
|
|
554
467
|
timeoutMinutes: 20,
|
|
555
468
|
env: { BUN_VERSION },
|
|
556
469
|
steps: [
|
|
@@ -561,76 +474,60 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
561
474
|
{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" },
|
|
562
475
|
{ name: "Install release helpers", run: "bun install" },
|
|
563
476
|
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
|
-
{
|
|
592
|
-
name: "Stamp workspace versions",
|
|
593
|
-
env: { VERSION: RELEASE_VERSION },
|
|
594
|
-
run: `bun node_modules/@dbx-tools/projen/tasks/stamp-python.ts "$VERSION" --root ${quote(this.repository.root)}`,
|
|
595
|
-
},
|
|
596
477
|
{
|
|
597
|
-
name: "
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
478
|
+
name: "Download approved Python distributions",
|
|
479
|
+
env: { GH_TOKEN: "${{ github.token }}", RELEASE_TAG },
|
|
480
|
+
run: [
|
|
481
|
+
"rm -rf dist/release-download",
|
|
482
|
+
"mkdir -p dist/release-download",
|
|
483
|
+
'gh release download "$RELEASE_TAG" --pattern release-manifest.json --pattern SHA256SUMS --pattern "*.whl" --pattern "*.tar.gz" --dir dist/release-download',
|
|
484
|
+
].join("\n"),
|
|
604
485
|
},
|
|
605
|
-
{
|
|
606
|
-
name:
|
|
486
|
+
...allPublications.map((publication) => ({
|
|
487
|
+
name: `Select ${publication.distribution} distributions`,
|
|
488
|
+
env: {
|
|
489
|
+
PACKAGE_NAME: publication.distribution.replaceAll("_", "-").toLowerCase(),
|
|
490
|
+
RELEASE_SHA,
|
|
491
|
+
RELEASE_TAG,
|
|
492
|
+
RELEASE_VERSION,
|
|
493
|
+
},
|
|
607
494
|
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",
|
|
495
|
+
"bun node_modules/@dbx-tools/projen/tasks/release-manifest.ts verify \\",
|
|
496
|
+
" --directory dist/release-download \\",
|
|
497
|
+
' --tag "$RELEASE_TAG" \\',
|
|
498
|
+
' --sha "$RELEASE_SHA" \\',
|
|
499
|
+
' --version "$RELEASE_VERSION" \\',
|
|
500
|
+
" --kind pypi \\",
|
|
501
|
+
' --package "$PACKAGE_NAME" \\',
|
|
502
|
+
` --output dist/${publication.directory}`,
|
|
617
503
|
].join("\n"),
|
|
504
|
+
})),
|
|
505
|
+
{
|
|
506
|
+
name: "Validate approved distributions",
|
|
507
|
+
run: `find ${allPublications.map((publication) => `dist/${publication.directory}`).join(" ")} -type f \\( -name '*.whl' -o -name '*.tar.gz' \\) -print0 | xargs -0 uvx twine check`,
|
|
618
508
|
},
|
|
619
509
|
{
|
|
620
510
|
name: "Upload distributions",
|
|
621
511
|
uses: "actions/upload-artifact@v7",
|
|
622
|
-
with: {
|
|
512
|
+
with: {
|
|
513
|
+
name: "python-distributions",
|
|
514
|
+
path: allPublications.map((publication) => `dist/${publication.directory}`).join("\n"),
|
|
515
|
+
"retention-days": 7,
|
|
516
|
+
},
|
|
623
517
|
},
|
|
624
518
|
],
|
|
625
519
|
});
|
|
626
520
|
for (const publication of allPublications) {
|
|
521
|
+
const dependencyJobs = (publication.dependencies ?? []).map(
|
|
522
|
+
(dependency) => `publish-pypi-${dependency}`,
|
|
523
|
+
);
|
|
627
524
|
workflow.addJob(`publish-pypi-${publication.directory}`, {
|
|
628
|
-
if: releasePublishCondition("python"
|
|
629
|
-
|
|
630
|
-
"
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
],
|
|
525
|
+
if: releasePublishCondition("python", [
|
|
526
|
+
"needs.verify-context.result == 'success'",
|
|
527
|
+
"needs.build-python.result == 'success'",
|
|
528
|
+
...dependencyJobs.map((job) => `needs['${job}'].result == 'success'`),
|
|
529
|
+
]),
|
|
530
|
+
needs: ["verify-context", "build-python", ...dependencyJobs],
|
|
634
531
|
environment: {
|
|
635
532
|
name: publication.environment,
|
|
636
533
|
url:
|
|
@@ -710,15 +607,16 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
710
607
|
): void {
|
|
711
608
|
const repository = this.githubRepository();
|
|
712
609
|
const publications = this.trustedPublisherPublications(options);
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
610
|
+
const releaseTag =
|
|
611
|
+
isDBXToolsJavaScriptProject()(project) && tryReleaseWorkflow(project)
|
|
612
|
+
? releaseTagPattern(project)
|
|
613
|
+
: "v*";
|
|
716
614
|
const linesBeforeAuthentication = [
|
|
717
615
|
"# PyPI Trusted Publisher Setup Instructions",
|
|
718
616
|
"",
|
|
719
617
|
"Use the system browser to audit and configure the PyPI trusted publishers below.",
|
|
720
618
|
"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
|
|
619
|
+
"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
620
|
"Use only PyPI pages for this task.",
|
|
723
621
|
"",
|
|
724
622
|
"## Audit and confirmation",
|
|
@@ -736,7 +634,7 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
736
634
|
"",
|
|
737
635
|
"## GitHub environment policy",
|
|
738
636
|
"",
|
|
739
|
-
`- The supplied
|
|
637
|
+
`- The supplied deployment tag policy value is ${releaseTag}.`,
|
|
740
638
|
"- Do not inspect or configure GitHub environments during this task.",
|
|
741
639
|
"- GitHub environment administration is a separate task; use the supplied values only when comparing PyPI publisher entries.",
|
|
742
640
|
"",
|
|
@@ -777,7 +675,7 @@ export class DBXToolsPythonWorkspace extends Component {
|
|
|
777
675
|
`- Repository name: ${repository.name}`,
|
|
778
676
|
"- Workflow name: release.yml",
|
|
779
677
|
`- Environment name: ${publication.environment}`,
|
|
780
|
-
`- GitHub environment
|
|
678
|
+
`- GitHub environment tag: ${releaseTag}`,
|
|
781
679
|
...(publication.artifacts ? [`- Artifacts: ${publication.artifacts}`] : []),
|
|
782
680
|
"",
|
|
783
681
|
];
|
package/src/project-rs.ts
CHANGED
|
@@ -19,19 +19,10 @@ import {
|
|
|
19
19
|
type RustOpenApiOptions as RustOpenApiConfiguration,
|
|
20
20
|
} from "./_rust-project.ts";
|
|
21
21
|
import {
|
|
22
|
-
rustAssetsJob,
|
|
23
22
|
configureRustReleaseTask,
|
|
24
|
-
independentRustCargoPublishJob,
|
|
25
|
-
independentRustGitHubReleaseJob,
|
|
26
|
-
independentRustNativeNpmPublishJob,
|
|
27
|
-
independentRustNodeFacadePublishJob,
|
|
28
23
|
orderRustBindings,
|
|
29
24
|
planRustRelease,
|
|
30
|
-
rustBuildJob,
|
|
31
25
|
rustCargoPublishJob,
|
|
32
|
-
rustGitHubReleaseJob,
|
|
33
|
-
rustNativeNpmPublishJob,
|
|
34
|
-
rustNodeFacadePublishJob,
|
|
35
26
|
} from "./_rust-release-workflow.ts";
|
|
36
27
|
import { toPosix } from "./packages.ts";
|
|
37
28
|
import {
|
|
@@ -43,12 +34,7 @@ import {
|
|
|
43
34
|
import { isDBXToolsJavaScriptProject } from "./project-predicate.ts";
|
|
44
35
|
import { pythonModuleName, type PythonPackageOptions } from "./project-py.ts";
|
|
45
36
|
import { defaultReleaseUnitId, type ReleaseDependencyInput } from "./release-catalog.ts";
|
|
46
|
-
import {
|
|
47
|
-
hasNodeRelease,
|
|
48
|
-
independentReleaseSetupSteps,
|
|
49
|
-
registerIndependentPublicationJob,
|
|
50
|
-
tryReleaseWorkflow,
|
|
51
|
-
} from "./release.ts";
|
|
37
|
+
import { tryReleaseWorkflow } from "./release.ts";
|
|
52
38
|
import { readWorkspaceVersion } from "./workspace-version.ts";
|
|
53
39
|
export { discoverRustCrates, hasUniFFIBindings } from "./_rust-project.ts";
|
|
54
40
|
export { orderRustBindings } from "./_rust-release-workflow.ts";
|
|
@@ -458,10 +444,7 @@ function planRustReleaseBinaries(
|
|
|
458
444
|
component: defaultReleaseUnitId("rust", pkg.crateName),
|
|
459
445
|
version: readWorkspaceVersion(project.outdir),
|
|
460
446
|
};
|
|
461
|
-
const tagPrefix =
|
|
462
|
-
isDBXToolsJavaScriptProject()(project) && project.releaseCatalog.mode === "independent"
|
|
463
|
-
? `${identity.component}-v`
|
|
464
|
-
: "v";
|
|
447
|
+
const tagPrefix = "v";
|
|
465
448
|
return {
|
|
466
449
|
command,
|
|
467
450
|
description,
|
|
@@ -670,14 +653,6 @@ function createRustPackages(
|
|
|
670
653
|
...resolved.packageOptions[directory],
|
|
671
654
|
};
|
|
672
655
|
const name = `${resolved.scope}-${directory.toLowerCase().replace(/[^a-z0-9-]+/g, "-")}`;
|
|
673
|
-
const version =
|
|
674
|
-
isDBXToolsJavaScriptProject()(project) && project.releaseCatalog.mode === "independent"
|
|
675
|
-
? project.releaseCatalog.versionForRegistration(
|
|
676
|
-
"rust",
|
|
677
|
-
name,
|
|
678
|
-
`${resolved.root}/${directory}`,
|
|
679
|
-
)
|
|
680
|
-
: undefined;
|
|
681
656
|
return new DBXToolsRustProject({
|
|
682
657
|
parent: project,
|
|
683
658
|
outdir: `${resolved.root}/${directory}`,
|
|
@@ -686,7 +661,6 @@ function createRustPackages(
|
|
|
686
661
|
workspaceRoot: resolved.root,
|
|
687
662
|
workspace: true,
|
|
688
663
|
scope: resolved.scope,
|
|
689
|
-
...(version ? { version } : {}),
|
|
690
664
|
...configured,
|
|
691
665
|
});
|
|
692
666
|
});
|
|
@@ -832,9 +806,7 @@ function configureRustWorkspaceFiles(
|
|
|
832
806
|
.map((pkg) => `${resolved.root}/${pkg.packageOptions.directory}`),
|
|
833
807
|
resolver: "2",
|
|
834
808
|
package: {
|
|
835
|
-
|
|
836
|
-
? { version: readWorkspaceVersion(project.outdir) }
|
|
837
|
-
: {}),
|
|
809
|
+
version: readWorkspaceVersion(project.outdir),
|
|
838
810
|
edition: options.edition ?? "2021",
|
|
839
811
|
"rust-version": options.rustVersion ?? "1.82",
|
|
840
812
|
license: options.license ?? DBX_TOOLS_LICENSE,
|
|
@@ -919,29 +891,6 @@ function rustReleaseDependencies(
|
|
|
919
891
|
});
|
|
920
892
|
}
|
|
921
893
|
|
|
922
|
-
function configureIndependentRustVersions(
|
|
923
|
-
project: DBXToolsJavaScriptProject,
|
|
924
|
-
packages: readonly DBXToolsRustProject[],
|
|
925
|
-
): void {
|
|
926
|
-
for (const pkg of packages) {
|
|
927
|
-
for (const [section, dependencies] of [
|
|
928
|
-
["dependencies", pkg.packageOptions.dependencies],
|
|
929
|
-
["dev-dependencies", pkg.packageOptions.devDependencies],
|
|
930
|
-
] as const) {
|
|
931
|
-
for (const [name, dependency] of Object.entries(dependencies ?? {})) {
|
|
932
|
-
if (typeof dependency === "string" || !dependency.path) continue;
|
|
933
|
-
const dependencyPath = resolve(pkg.outdir, dependency.path);
|
|
934
|
-
const target = packages.find((candidate) => resolve(candidate.outdir) === dependencyPath);
|
|
935
|
-
if (!target) continue;
|
|
936
|
-
pkg.manifestFile.addOverride(
|
|
937
|
-
`${section}.${name}.version`,
|
|
938
|
-
project.releaseCatalog.versionFor(target),
|
|
939
|
-
);
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
|
|
945
894
|
/** Generated Rust workspace plus convention-derived UniFFI binding packages. */
|
|
946
895
|
export class DBXToolsRustWorkspace extends Component {
|
|
947
896
|
readonly packages: readonly DBXToolsRustProject[];
|
|
@@ -989,9 +938,6 @@ export class DBXToolsRustWorkspace extends Component {
|
|
|
989
938
|
],
|
|
990
939
|
});
|
|
991
940
|
}
|
|
992
|
-
if (project.releaseCatalog.mode === "independent") {
|
|
993
|
-
configureIndependentRustVersions(project, this.packages);
|
|
994
|
-
}
|
|
995
941
|
}
|
|
996
942
|
this.releaseBinaries = planRustReleaseBinaries(project, this.packages, resolved);
|
|
997
943
|
configureRustCliRegistry(project, options.cliRegistryPath, this.releaseBinaries);
|
|
@@ -1101,50 +1047,8 @@ export class DBXToolsRustWorkspace extends Component {
|
|
|
1101
1047
|
throw new Error("Rust release requires the root dbx-tools release mode");
|
|
1102
1048
|
}
|
|
1103
1049
|
configureRustReleaseTask(project, plan);
|
|
1104
|
-
if (project.releaseCatalog.mode === "independent") {
|
|
1105
|
-
if (plan.targets.length) {
|
|
1106
|
-
workflow.addJob("rust-build", rustBuildJob(plan, independentReleaseSetupSteps(project)));
|
|
1107
|
-
}
|
|
1108
|
-
if (plan.publicCrates.length) {
|
|
1109
|
-
workflow.addJob("publish-cargo", independentRustCargoPublishJob(project, plan));
|
|
1110
|
-
registerIndependentPublicationJob(workflow, "publish-cargo");
|
|
1111
|
-
}
|
|
1112
|
-
if (plan.releaseBinaries.length) {
|
|
1113
|
-
workflow.addJob("publish-github-release", independentRustGitHubReleaseJob(project, plan));
|
|
1114
|
-
registerIndependentPublicationJob(workflow, "publish-github-release");
|
|
1115
|
-
}
|
|
1116
|
-
if (plan.nodeBindings.length && hasNodeRelease(project)) {
|
|
1117
|
-
workflow.addJob("publish-native-npm", independentRustNativeNpmPublishJob(project));
|
|
1118
|
-
registerIndependentPublicationJob(workflow, "publish-native-npm");
|
|
1119
|
-
workflow.addJob(
|
|
1120
|
-
"publish-node-facades",
|
|
1121
|
-
independentRustNodeFacadePublishJob(project, plan.nodeBindings),
|
|
1122
|
-
);
|
|
1123
|
-
registerIndependentPublicationJob(workflow, "publish-node-facades");
|
|
1124
|
-
}
|
|
1125
|
-
return;
|
|
1126
|
-
}
|
|
1127
|
-
if (plan.targets.length) {
|
|
1128
|
-
workflow.addJob("rust-build", rustBuildJob(plan));
|
|
1129
|
-
workflow.addJob("rust-assets", rustAssetsJob());
|
|
1130
|
-
}
|
|
1131
1050
|
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));
|
|
1051
|
+
workflow.addJob("publish-cargo", rustCargoPublishJob(plan));
|
|
1148
1052
|
}
|
|
1149
1053
|
}
|
|
1150
1054
|
}
|