@dbx-tools/projen 0.9.17 → 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/src/project-js.ts CHANGED
@@ -1064,18 +1064,14 @@ class GeneratedSource extends Component {
1064
1064
  *
1065
1065
  * projen gives a monorepo root empty `compile`/`test` tasks - a child's tasks
1066
1066
  * are the child's business - so `bun run build` at the root type-checked nothing
1067
- * and ran no package tests. The fan-out is delegated to bun's own workspace
1068
- * filter rather than one `exec` per member, which matters three ways: bun runs
1069
- * the members in PARALLEL (measured ~2.5x faster across this repo than the
1070
- * sequential per-`cwd` form), a member that does not define the script is
1071
- * skipped instead of needing a guard, and the filter reads the workspace from
1072
- * `package.json` - so it stays correct when a package is added without a
1073
- * re-synth. A non-zero member exit still fails the run.
1067
+ * and ran no package tests. Compilation groups ordinary `tsc --build` members
1068
+ * into a few TypeScript processes and runs custom compile tasks alongside them. Tests
1069
+ * still use Bun's filtered workspace fan-out. Both read the current workspace
1070
+ * list from `package.json`, so a newly added member needs no re-synth.
1074
1071
  *
1075
- * `*` matches every workspace MEMBER and never the root itself, so the root
1072
+ * `*` matches every workspace MEMBER and never the root itself, so the test
1076
1073
  * task delegating to it cannot recurse. Members declared outside the scanned
1077
- * package roots (`extraWorkspaceMembers`) are workspace members too, so they are
1078
- * covered by the same filter.
1074
+ * package roots (`extraWorkspaceMembers`) are covered by both tasks.
1079
1075
  */
1080
1076
  class WorkspaceValidationTasks extends Component {
1081
1077
  private configured = false;
@@ -1087,9 +1083,8 @@ class WorkspaceValidationTasks extends Component {
1087
1083
  if (project.subprojects.length === 0 && project.extraWorkspaceMembers.length === 0) {
1088
1084
  return;
1089
1085
  }
1090
- for (const task of [project.compileTask, project.testTask]) {
1091
- task.exec(`bun run --filter '*' ${task.name}`);
1092
- }
1086
+ project.compileTask.exec(taskScript(project, "compile-workspace.ts"));
1087
+ project.testTask.exec("bun run --filter '*' test");
1093
1088
  }
1094
1089
  }
1095
1090
 
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, projectReleaseBranch, projectRepositoryUrl } from "./project-js.ts";
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_VERSION, releaseSourceSteps } from "./release-dispatch.ts";
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
- releaseArtifactSteps,
19
+ releaseTagPattern,
15
20
  releasePublishCondition,
16
21
  releaseStageCondition,
17
22
  tryReleaseWorkflow,
@@ -465,9 +470,9 @@ export class DBXToolsPythonWorkspace extends Component {
465
470
  if (project.releaseCatalog.mode === "independent") {
466
471
  workflow.addJob("build-python", {
467
472
  if: usesRustArtifacts
468
- ? "${{ always() && needs.release-plan.outputs.python == 'true' && needs.rust-uniffi.result != 'failure' && needs.rust-uniffi.result != 'cancelled' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'python') }}"
473
+ ? "${{ 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
474
  : "${{ needs.release-plan.outputs.python == 'true' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'python') }}",
470
- needs: ["release-plan", ...(usesRustArtifacts ? ["rust-uniffi"] : [])],
475
+ needs: ["release-plan", ...(usesRustArtifacts ? ["rust-build"] : [])],
471
476
  runsOn: ["ubuntu-latest"],
472
477
  permissions: { actions: JobPermission.READ, contents: JobPermission.READ },
473
478
  timeoutMinutes: 20,
@@ -545,12 +550,10 @@ export class DBXToolsPythonWorkspace extends Component {
545
550
  return;
546
551
  }
547
552
  workflow.addJob("build-python", {
548
- if: usesRustArtifacts
549
- ? "${{ always() && needs.verify-context.result == 'success' && needs.rust-uniffi.result != 'failure' && needs.rust-uniffi.result != 'cancelled' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'python') }}"
550
- : releaseStageCondition("python"),
551
- needs: ["verify-context", ...(usesRustArtifacts ? ["rust-uniffi"] : [])],
553
+ if: releaseStageCondition("python", ["needs.verify-context.result == 'success'"]),
554
+ needs: ["verify-context"],
552
555
  runsOn: ["ubuntu-latest"],
553
- permissions: { actions: JobPermission.READ, contents: JobPermission.READ },
556
+ permissions: { contents: JobPermission.READ },
554
557
  timeoutMinutes: 20,
555
558
  env: { BUN_VERSION },
556
559
  steps: [
@@ -561,57 +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
- }),
571
- ),
572
567
  {
573
- name: "Stamp workspace versions",
574
- env: { VERSION: RELEASE_VERSION },
575
- run: `bun node_modules/@dbx-tools/projen/tasks/stamp-python.ts "$VERSION" --root ${quote(this.repository.root)}`,
576
- },
577
- {
578
- name: "Build distributions",
579
- run: publications
580
- .map(
581
- (publication) =>
582
- `uv build --package ${publication.distribution} --out-dir dist/${publication.directory}`,
583
- )
584
- .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"),
585
575
  },
586
- {
587
- name: "Validate distributions",
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
+ },
588
584
  run: [
589
- ...publications.map(
590
- (publication) =>
591
- `test "$(find dist/${publication.directory} -maxdepth 1 -type f \\( -name '*.whl' -o -name '*.tar.gz' \\) | wc -l | tr -d ' ')" -eq 2`,
592
- ),
593
- ...uniffiPublications.map(
594
- (publication) =>
595
- `find dist/${publication.directory} -maxdepth 1 -name '*.whl' -print -quit | grep -q .`,
596
- ),
597
- "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}`,
598
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`,
599
598
  },
600
599
  {
601
600
  name: "Upload distributions",
602
601
  uses: "actions/upload-artifact@v7",
603
- with: { name: "python-distributions", path: "dist", "retention-days": 7 },
602
+ with: {
603
+ name: "python-distributions",
604
+ path: allPublications.map((publication) => `dist/${publication.directory}`).join("\n"),
605
+ "retention-days": 7,
606
+ },
604
607
  },
605
608
  ],
606
609
  });
607
610
  for (const publication of allPublications) {
611
+ const dependencyJobs = (publication.dependencies ?? []).map(
612
+ (dependency) => `publish-pypi-${dependency}`,
613
+ );
608
614
  workflow.addJob(`publish-pypi-${publication.directory}`, {
609
- if: releasePublishCondition("python"),
610
- needs: [
611
- "verify-context",
612
- "build-python",
613
- ...(publication.dependencies ?? []).map((dependency) => `publish-pypi-${dependency}`),
614
- ],
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],
615
621
  environment: {
616
622
  name: publication.environment,
617
623
  url:
@@ -691,15 +697,17 @@ export class DBXToolsPythonWorkspace extends Component {
691
697
  ): void {
692
698
  const repository = this.githubRepository();
693
699
  const publications = this.trustedPublisherPublications(options);
694
- const releaseBranch = isDBXToolsJavaScriptProject()(project)
695
- ? projectReleaseBranch(project)
696
- : "main";
700
+ const releaseTag = isDBXToolsJavaScriptProject()(project)
701
+ ? project.releaseCatalog.mode === "independent"
702
+ ? "*-v*"
703
+ : releaseTagPattern(project)
704
+ : "v*";
697
705
  const linesBeforeAuthentication = [
698
706
  "# PyPI Trusted Publisher Setup Instructions",
699
707
  "",
700
708
  "Use the system browser to audit and configure the PyPI trusted publishers below.",
701
709
  "Do not use an in-app browser or embedded webview.",
702
- "Do not visit GitHub or use the GitHub API or CLI. Every required GitHub owner, repository, workflow, environment, and branch value is provided below and is authoritative.",
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.",
703
711
  "Use only PyPI pages for this task.",
704
712
  "",
705
713
  "## Audit and confirmation",
@@ -717,7 +725,7 @@ export class DBXToolsPythonWorkspace extends Component {
717
725
  "",
718
726
  "## GitHub environment policy",
719
727
  "",
720
- `- The supplied branch policy value is ${releaseBranch}.`,
728
+ `- The supplied deployment tag policy value is ${releaseTag}.`,
721
729
  "- Do not inspect or configure GitHub environments during this task.",
722
730
  "- GitHub environment administration is a separate task; use the supplied values only when comparing PyPI publisher entries.",
723
731
  "",
@@ -758,7 +766,7 @@ export class DBXToolsPythonWorkspace extends Component {
758
766
  `- Repository name: ${repository.name}`,
759
767
  "- Workflow name: release.yml",
760
768
  `- Environment name: ${publication.environment}`,
761
- `- GitHub environment branch: ${releaseBranch}`,
769
+ `- GitHub environment tag: ${releaseTag}`,
762
770
  ...(publication.artifacts ? [`- Artifacts: ${publication.artifacts}`] : []),
763
771
  "",
764
772
  ];
package/src/project-rs.ts CHANGED
@@ -4,6 +4,7 @@ import { dirname, join, relative, resolve } from "node:path";
4
4
  import * as projectUtils from "@dbx-tools/core/project-utils";
5
5
  import { stringUtils } from "@dbx-tools/shared-core";
6
6
  import { Component, Project, TextFile, TomlFile, javascript } from "projen";
7
+ import { releaseBinaryAssetName } from "./_release-platform.ts";
7
8
  import {
8
9
  RustProject,
9
10
  type CargoExampleOptions as RustCargoExampleOptions,
@@ -25,12 +26,8 @@ import {
25
26
  independentRustNodeFacadePublishJob,
26
27
  orderRustBindings,
27
28
  planRustRelease,
28
- releaseBinaryAssetName,
29
29
  rustBuildJob,
30
30
  rustCargoPublishJob,
31
- rustGitHubReleaseJob,
32
- rustNativeNpmPublishJob,
33
- rustNodeFacadePublishJob,
34
31
  } from "./_rust-release-workflow.ts";
35
32
  import { toPosix } from "./packages.ts";
36
33
  import {
@@ -118,6 +115,7 @@ export interface UniFFIReleaseTarget {
118
115
  readonly os: RustReleaseOs;
119
116
  readonly cpu: RustReleaseCpu;
120
117
  readonly libc?: "glibc";
118
+ readonly glibcVersion?: string;
121
119
  }
122
120
 
123
121
  /** Native targets built on matching GitHub-hosted runners. */
@@ -130,6 +128,7 @@ export const UNIFFI_RELEASE_TARGETS: readonly UniFFIReleaseTarget[] = [
130
128
  os: RustReleaseOs.LINUX,
131
129
  cpu: RustReleaseCpu.X64,
132
130
  libc: "glibc",
131
+ glibcVersion: "2.35",
133
132
  },
134
133
  {
135
134
  runner: "ubuntu-24.04-arm",
@@ -139,6 +138,7 @@ export const UNIFFI_RELEASE_TARGETS: readonly UniFFIReleaseTarget[] = [
139
138
  os: RustReleaseOs.LINUX,
140
139
  cpu: RustReleaseCpu.ARM64,
141
140
  libc: "glibc",
141
+ glibcVersion: "2.39",
142
142
  },
143
143
  {
144
144
  runner: "macos-15-intel",
@@ -1098,17 +1098,8 @@ export class DBXToolsRustWorkspace extends Component {
1098
1098
  }
1099
1099
  configureRustReleaseTask(project, plan);
1100
1100
  if (project.releaseCatalog.mode === "independent") {
1101
- if (plan.uniffiTargets.length) {
1102
- workflow.addJob(
1103
- "rust-uniffi",
1104
- rustBuildJob(plan, "uniffi", independentReleaseSetupSteps(project)),
1105
- );
1106
- }
1107
- if (plan.binaryTargets.length) {
1108
- workflow.addJob(
1109
- "rust-binaries",
1110
- rustBuildJob(plan, "binaries", independentReleaseSetupSteps(project)),
1111
- );
1101
+ if (plan.targets.length) {
1102
+ workflow.addJob("rust-build", rustBuildJob(plan, independentReleaseSetupSteps(project)));
1112
1103
  }
1113
1104
  if (plan.publicCrates.length) {
1114
1105
  workflow.addJob("publish-cargo", independentRustCargoPublishJob(project, plan));
@@ -1129,29 +1120,8 @@ export class DBXToolsRustWorkspace extends Component {
1129
1120
  }
1130
1121
  return;
1131
1122
  }
1132
- if (plan.uniffiTargets.length) {
1133
- workflow.addJob("rust-uniffi", rustBuildJob(plan, "uniffi"));
1134
- }
1135
- if (plan.binaryTargets.length) {
1136
- workflow.addJob("rust-binaries", rustBuildJob(plan, "binaries"));
1137
- }
1138
1123
  if (plan.publicCrates.length) {
1139
- workflow.addJob("publish-cargo", rustCargoPublishJob(plan, false));
1140
- workflow.addJob("publish-local-cargo", rustCargoPublishJob(plan, true));
1141
- }
1142
- if (plan.releaseBinaries.length) {
1143
- workflow.addJob("publish-github-release", rustGitHubReleaseJob(plan));
1144
- }
1145
- if (plan.nodeBindings.length && hasNodeRelease(project)) {
1146
- workflow.addJob("publish-native-npm", rustNativeNpmPublishJob(project));
1147
- const nodeJob = workflow.getJob("publish-node");
1148
- if ("uses" in nodeJob) throw new Error("publish-node must be a workflow job");
1149
- workflow.updateJob("publish-node", {
1150
- ...nodeJob,
1151
- if: "${{ always() && needs.verify-context.result == 'success' && needs.publish-native-npm.result == 'success' && (github.event_name == 'push' || inputs.stage == 'all' || inputs.stage == 'node') }}",
1152
- needs: ["verify-context", "publish-native-npm"],
1153
- });
1154
- workflow.addJob("publish-node-facades", rustNodeFacadePublishJob(project, plan.nodeBindings));
1124
+ workflow.addJob("publish-cargo", rustCargoPublishJob(plan));
1155
1125
  }
1156
1126
  }
1157
1127
  }
@@ -28,6 +28,29 @@ export interface GithubAuthenticatedAccount {
28
28
  scopes: string[];
29
29
  }
30
30
 
31
+ /** Repository capabilities returned for one authenticated actor. */
32
+ export interface GithubRepositoryPermissions {
33
+ readonly push: boolean;
34
+ readonly maintain: boolean;
35
+ readonly admin: boolean;
36
+ }
37
+
38
+ /** Read normalized repository permissions from a GitHub repository response. */
39
+ export function githubRepositoryPermissions(value: unknown): GithubRepositoryPermissions {
40
+ const repository = object.isRecord(value) ? value : undefined;
41
+ const permissions = object.isRecord(repository?.permissions) ? repository.permissions : undefined;
42
+ return {
43
+ push: permissions?.push === true,
44
+ maintain: permissions?.maintain === true,
45
+ admin: permissions?.admin === true,
46
+ };
47
+ }
48
+
49
+ /** Whether the actor can manage releases rather than only push source. */
50
+ export function githubRepositoryCanManage(permissions: GithubRepositoryPermissions): boolean {
51
+ return permissions.maintain || permissions.admin;
52
+ }
53
+
31
54
  /** Parse successful GitHub CLI accounts with the active account first. */
32
55
  export function githubAuthenticatedAccounts(
33
56
  statusOutput: string,
@@ -47,10 +47,10 @@ export interface PlannedRustTarget {
47
47
  readonly runner: string;
48
48
  readonly python: string;
49
49
  readonly libc: string;
50
+ readonly glibcVersion: string;
50
51
  readonly packages: readonly string[];
51
52
  readonly binaries: readonly string[];
52
53
  readonly features: readonly string[];
53
- readonly fingerprintConfig: string;
54
54
  }
55
55
 
56
56
  /** Complete plan persisted as a workflow artifact and used for recovery. */
@@ -62,8 +62,7 @@ export interface ReleasePlan {
62
62
  readonly pythonPackages: readonly PlannedPackage[];
63
63
  readonly rustPackages: readonly PlannedPackage[];
64
64
  readonly artifacts: readonly PlannedArtifact[];
65
- readonly rustUniffiTargets: readonly PlannedRustTarget[];
66
- readonly rustBinaryTargets: readonly PlannedRustTarget[];
65
+ readonly rustTargets: readonly PlannedRustTarget[];
67
66
  readonly stages: {
68
67
  readonly rust: boolean;
69
68
  readonly python: boolean;
@@ -133,53 +132,52 @@ export function buildReleasePlan(
133
132
  ]);
134
133
  }
135
134
  }
136
- const rustTargetsByKind = {
137
- uniffi: new Map<string, PlannedRustTarget>(),
138
- binaries: new Map<string, PlannedRustTarget>(),
139
- };
135
+ const rustTargets = new Map<string, PlannedRustTarget>();
140
136
  for (const artifact of artifacts) {
141
137
  const targets = artifact.data?.targets;
142
138
  if (!Array.isArray(targets)) continue;
143
- const kind = artifact.kind === "github-binary" ? "binaries" : "uniffi";
139
+ const binary = artifact.kind === "github-binary";
144
140
  for (const value of targets) {
145
141
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
146
142
  const target = value as Record<string, unknown>;
147
143
  const required = ["os", "cpu", "node", "cargo", "runner", "python"] as const;
148
144
  if (!required.every((field) => typeof target[field] === "string")) continue;
149
145
  const key = String(target.node);
150
- const targetsByKey = rustTargetsByKind[kind];
151
- const currentTarget = targetsByKey.get(key);
146
+ const currentTarget = rustTargets.get(key);
152
147
  const packages = [
153
148
  ...new Set([
154
149
  ...(currentTarget?.packages ?? []),
155
150
  ...(rustPackagesByUnit.get(artifact.unit) ?? []),
156
151
  ]),
157
152
  ].sort();
158
- const binaries =
159
- kind === "binaries"
160
- ? [
161
- ...new Set([
162
- ...(currentTarget?.binaries ?? []),
163
- ...(typeof artifact.data?.binary === "string" ? [artifact.data.binary] : []),
164
- ]),
165
- ].sort()
166
- : [];
153
+ const binaries = binary
154
+ ? [
155
+ ...new Set([
156
+ ...(currentTarget?.binaries ?? []),
157
+ ...(typeof artifact.data?.binary === "string" ? [artifact.data.binary] : []),
158
+ ]),
159
+ ].sort()
160
+ : (currentTarget?.binaries ?? []);
167
161
  const configuredFeatures = Array.isArray(artifact.data?.features)
168
162
  ? artifact.data.features.filter((feature): feature is string => typeof feature === "string")
169
163
  : [];
170
164
  const crate = typeof artifact.data?.crate === "string" ? artifact.data.crate : undefined;
171
- const features =
172
- kind === "uniffi"
173
- ? packages.map((pkg) => `${pkg}/uniffi-bindgen`)
174
- : [
175
- ...new Set([
176
- ...(currentTarget?.features ?? []),
177
- ...(crate
178
- ? configuredFeatures.map((feature) => `${crate}/${feature}`)
179
- : configuredFeatures),
180
- ]),
181
- ].sort();
182
- targetsByKey.set(key, {
165
+ const features = binary
166
+ ? [
167
+ ...new Set([
168
+ ...(currentTarget?.features ?? []),
169
+ ...(crate
170
+ ? configuredFeatures.map((feature) => `${crate}/${feature}`)
171
+ : configuredFeatures),
172
+ ]),
173
+ ].sort()
174
+ : [
175
+ ...new Set([
176
+ ...(currentTarget?.features ?? []),
177
+ ...packages.map((pkg) => `${pkg}/uniffi-bindgen`),
178
+ ]),
179
+ ].sort();
180
+ rustTargets.set(key, {
183
181
  os: String(target.os),
184
182
  cpu: String(target.cpu),
185
183
  node: String(target.node),
@@ -187,19 +185,14 @@ export function buildReleasePlan(
187
185
  runner: String(target.runner),
188
186
  python: String(target.python),
189
187
  libc: typeof target.libc === "string" ? target.libc : "",
188
+ glibcVersion: typeof target.glibcVersion === "string" ? target.glibcVersion : "",
190
189
  packages,
191
190
  binaries,
192
191
  features,
193
- fingerprintConfig: JSON.stringify({ packages, binaries, features }),
194
192
  });
195
193
  }
196
194
  }
197
- const rustUniffiTargets = [...rustTargetsByKind.uniffi.values()].sort((a, b) =>
198
- a.node.localeCompare(b.node),
199
- );
200
- const rustBinaryTargets = [...rustTargetsByKind.binaries.values()].sort((a, b) =>
201
- a.node.localeCompare(b.node),
202
- );
195
+ const plannedRustTargets = [...rustTargets.values()].sort((a, b) => a.node.localeCompare(b.node));
203
196
  const publishBatches = current.publishBatches
204
197
  .map((batch) => batch.filter((unit) => selected.has(unit)))
205
198
  .filter((batch) => batch.length > 0);
@@ -226,8 +219,7 @@ export function buildReleasePlan(
226
219
  pythonPackages,
227
220
  rustPackages,
228
221
  artifacts,
229
- rustUniffiTargets,
230
- rustBinaryTargets,
222
+ rustTargets: plannedRustTargets,
231
223
  stages,
232
224
  omittedStages,
233
225
  };