@dbx-tools/projen 0.6.163 → 0.6.174
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 +56 -41
- package/index.ts +2 -1
- package/package.json +4 -5
- package/src/barrels.ts +134 -34
- package/src/project-js.ts +19 -22
- package/src/project-py.ts +83 -21
- package/src/project-rs.ts +175 -309
- package/src/release.ts +109 -4
- package/src/uniffi.ts +45 -0
- package/tasks/bump.ts +12 -2
- package/tasks/publish-uniffi-local.ts +3 -4
- package/tasks/publish.ts +22 -13
- package/tasks/rust.ts +17 -3
- package/tasks/uniffi-release.mjs +242 -29
- package/tasks/uniffi.ts +101 -55
package/src/project-rs.ts
CHANGED
|
@@ -5,14 +5,14 @@ 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
7
|
import { Project, TextFile, YamlFile, javascript } from "projen";
|
|
8
|
-
import { BUN_VERSION, bunCacheRestoreSteps, bunCacheSaveStep } from "./bun-workflow.ts";
|
|
9
|
-
import type { DBXToolsProject } from "./project.ts";
|
|
10
8
|
import {
|
|
11
9
|
DBXToolsTypeScriptProject,
|
|
12
10
|
projectReleaseBranch,
|
|
13
11
|
projectRepositoryUrl,
|
|
14
12
|
} from "./project-js.ts";
|
|
13
|
+
import { isDBXToolsJavaScriptProject } from "./project-predicate.ts";
|
|
15
14
|
import { pythonModuleName, type PythonPackageOptions } from "./project-py.ts";
|
|
15
|
+
import type { DBXToolsProject } from "./project.ts";
|
|
16
16
|
import {
|
|
17
17
|
DOWNSTREAM_RELEASE_EVENT,
|
|
18
18
|
RELEASE_SHA,
|
|
@@ -21,13 +21,13 @@ import {
|
|
|
21
21
|
releaseSourceSteps,
|
|
22
22
|
} from "./release-dispatch.ts";
|
|
23
23
|
import { readWorkspaceVersion } from "./workspace-version.ts";
|
|
24
|
-
import { isDBXToolsJavaScriptProject } from "./project-predicate.ts";
|
|
25
24
|
|
|
26
25
|
export interface CargoDependencyOptions {
|
|
27
26
|
readonly version?: string;
|
|
28
27
|
readonly workspace?: boolean;
|
|
29
28
|
readonly path?: string;
|
|
30
29
|
readonly optional?: boolean;
|
|
30
|
+
readonly package?: string;
|
|
31
31
|
readonly defaultFeatures?: boolean;
|
|
32
32
|
readonly features?: readonly string[];
|
|
33
33
|
}
|
|
@@ -61,8 +61,6 @@ export interface DBXToolsRustWorkspaceOptions {
|
|
|
61
61
|
readonly rustVersion?: string;
|
|
62
62
|
/** Rust toolchain used by release builds. Defaults to `stable`. */
|
|
63
63
|
readonly releaseRustVersion?: string;
|
|
64
|
-
/** Rust toolchain used to compile the host-side UBRN generator. Defaults to releaseRustVersion. */
|
|
65
|
-
readonly ubrnRustVersion?: string;
|
|
66
64
|
readonly license?: string;
|
|
67
65
|
readonly repository?: string;
|
|
68
66
|
readonly workspaceDependencies?: Readonly<Record<string, CargoDependency>>;
|
|
@@ -79,6 +77,8 @@ export interface DBXToolsRustWorkspaceOptions {
|
|
|
79
77
|
readonly releasePlatforms?: readonly RustReleasePlatform[];
|
|
80
78
|
/** Workflow name used by downstream release stages. Defaults to `rust-release`. */
|
|
81
79
|
readonly releaseWorkflowName?: string;
|
|
80
|
+
/** Workflow that publishes generated Python wheels. Defaults to `python-release`. */
|
|
81
|
+
readonly pythonReleaseWorkflowName?: string;
|
|
82
82
|
/** Tag prefix dispatched into the branch-scoped release workflow. Defaults to `v`. */
|
|
83
83
|
readonly releaseTagPrefix?: string;
|
|
84
84
|
}
|
|
@@ -156,6 +156,8 @@ export const UNIFFI_RELEASE_TARGETS: readonly UniFFIReleaseTarget[] = [
|
|
|
156
156
|
] as const;
|
|
157
157
|
|
|
158
158
|
const RUST_CACHE_ENV = {
|
|
159
|
+
CARGO_INCREMENTAL: "0",
|
|
160
|
+
CARGO_TERM_COLOR: "always",
|
|
159
161
|
RUSTC_WRAPPER: "sccache",
|
|
160
162
|
SCCACHE_GHA_ENABLED: "true",
|
|
161
163
|
} as const;
|
|
@@ -203,8 +205,9 @@ function releaseTargets(options: DBXToolsRustWorkspaceOptions): readonly UniFFIR
|
|
|
203
205
|
const target = UNIFFI_RELEASE_TARGETS.find(
|
|
204
206
|
(candidate) => candidate.os === platform.os && candidate.cpu === platform.cpu,
|
|
205
207
|
);
|
|
206
|
-
if (!target)
|
|
208
|
+
if (!target) {
|
|
207
209
|
throw new Error(`Unsupported Rust release platform: ${platform.os}-${platform.cpu}`);
|
|
210
|
+
}
|
|
208
211
|
return target;
|
|
209
212
|
});
|
|
210
213
|
}
|
|
@@ -247,6 +250,7 @@ export interface RustBindingMapping {
|
|
|
247
250
|
readonly pythonPackage?: string;
|
|
248
251
|
readonly pythonModule?: string;
|
|
249
252
|
readonly facadeTarget?: boolean;
|
|
253
|
+
readonly dependencies?: readonly string[];
|
|
250
254
|
}
|
|
251
255
|
|
|
252
256
|
/** Persisted Rust workspace state consumed by `sync --watch`. */
|
|
@@ -257,6 +261,29 @@ export interface RustWorkspaceMapping {
|
|
|
257
261
|
readonly releaseWorkflow?: string;
|
|
258
262
|
}
|
|
259
263
|
|
|
264
|
+
export function orderRustBindings(bindings: readonly RustBindingMapping[]): RustBindingMapping[] {
|
|
265
|
+
const ordered: RustBindingMapping[] = [];
|
|
266
|
+
const visiting = new Set<string>();
|
|
267
|
+
const completed = new Set<string>();
|
|
268
|
+
const visit = (binding: RustBindingMapping): void => {
|
|
269
|
+
if (completed.has(binding.crate)) return;
|
|
270
|
+
if (visiting.has(binding.crate)) {
|
|
271
|
+
throw new Error(`Cyclic Rust binding dependency: ${binding.crate}`);
|
|
272
|
+
}
|
|
273
|
+
visiting.add(binding.crate);
|
|
274
|
+
for (const name of binding.dependencies ?? []) {
|
|
275
|
+
const dependency = bindings.find((candidate) => candidate.crate === name);
|
|
276
|
+
if (!dependency) throw new Error(`Missing Rust binding dependency: ${name}`);
|
|
277
|
+
visit(dependency);
|
|
278
|
+
}
|
|
279
|
+
visiting.delete(binding.crate);
|
|
280
|
+
completed.add(binding.crate);
|
|
281
|
+
ordered.push(binding);
|
|
282
|
+
};
|
|
283
|
+
for (const binding of bindings) visit(binding);
|
|
284
|
+
return ordered;
|
|
285
|
+
}
|
|
286
|
+
|
|
260
287
|
function rustSources(directory: string): string[] {
|
|
261
288
|
if (!existsSync(directory)) return [];
|
|
262
289
|
const files: string[] = [];
|
|
@@ -294,6 +321,7 @@ function cargoDependency(
|
|
|
294
321
|
...(!value.version && value.path && workspaceVersion ? { version: workspaceVersion } : {}),
|
|
295
322
|
...(value.workspace ? { workspace: true } : {}),
|
|
296
323
|
...(value.path ? { path: value.path } : {}),
|
|
324
|
+
...(value.package ? { package: value.package } : {}),
|
|
297
325
|
...(value.optional ? { optional: true } : {}),
|
|
298
326
|
...(value.defaultFeatures === false ? { "default-features": false } : {}),
|
|
299
327
|
...(value.features?.length ? { features: [...value.features] } : {}),
|
|
@@ -366,7 +394,7 @@ export class DBXToolsRustProject extends Project implements DBXToolsProject {
|
|
|
366
394
|
...(this.uniffi || binary
|
|
367
395
|
? {
|
|
368
396
|
bin: this.uniffi
|
|
369
|
-
? { name:
|
|
397
|
+
? { name: `${crateName}-uniffi-bindgen`, path: "uniffi-bindgen.rs" }
|
|
370
398
|
: { name: binaryName, path: "src/main.rs" },
|
|
371
399
|
}
|
|
372
400
|
: {}),
|
|
@@ -418,7 +446,7 @@ export class DBXToolsRustProject extends Project implements DBXToolsProject {
|
|
|
418
446
|
}
|
|
419
447
|
}
|
|
420
448
|
|
|
421
|
-
/** Generated Rust workspace plus convention-derived
|
|
449
|
+
/** Generated Rust workspace plus convention-derived UniFFI facade packages. */
|
|
422
450
|
export class DBXToolsRustWorkspace {
|
|
423
451
|
readonly packages: readonly DBXToolsRustProject[];
|
|
424
452
|
readonly nodePackages: readonly DBXToolsTypeScriptProject[];
|
|
@@ -447,27 +475,75 @@ export class DBXToolsRustWorkspace {
|
|
|
447
475
|
);
|
|
448
476
|
|
|
449
477
|
const bindings = this.packages.filter((pkg) => pkg.uniffi);
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
478
|
+
const bindingDependencies = (pkg: DBXToolsRustProject, language: "node" | "python") =>
|
|
479
|
+
bindings.filter(
|
|
480
|
+
(dependency) =>
|
|
481
|
+
dependency !== pkg &&
|
|
482
|
+
(dependency.packageOptions.bindings ?? ["node", "python"]).includes(language) &&
|
|
483
|
+
Object.entries(pkg.packageOptions.dependencies ?? {}).some(([name, value]) => {
|
|
484
|
+
const resolved =
|
|
485
|
+
typeof value === "object" && value.workspace
|
|
486
|
+
? (options.workspaceDependencies?.[name] ?? value)
|
|
487
|
+
: value;
|
|
488
|
+
return (
|
|
489
|
+
name === dependency.crateName ||
|
|
490
|
+
(typeof resolved === "object" &&
|
|
491
|
+
(resolved.package === dependency.crateName ||
|
|
492
|
+
(resolved.path !== undefined &&
|
|
493
|
+
resolve(
|
|
494
|
+
typeof value === "object" && value.workspace ? project.outdir : pkg.outdir,
|
|
495
|
+
resolved.path,
|
|
496
|
+
) === dependency.outdir)))
|
|
497
|
+
);
|
|
498
|
+
}),
|
|
499
|
+
);
|
|
500
|
+
this.bindingMappings = orderRustBindings(
|
|
501
|
+
bindings.map((pkg) => {
|
|
502
|
+
const targets = pkg.packageOptions.bindings ?? ["node", "python"];
|
|
503
|
+
const packageName = pkg.packageOptions.directory.toLowerCase().replace(/[^a-z0-9-]+/g, "-");
|
|
504
|
+
const dependencies = [
|
|
505
|
+
...new Set([...bindingDependencies(pkg, "node"), ...bindingDependencies(pkg, "python")]),
|
|
506
|
+
].map((dependency) => dependency.crateName);
|
|
507
|
+
return {
|
|
508
|
+
crate: pkg.crateName,
|
|
509
|
+
...(dependencies.length ? { dependencies } : {}),
|
|
510
|
+
rust: `${root}/${pkg.packageOptions.directory}`,
|
|
511
|
+
...(targets.includes("node")
|
|
512
|
+
? {
|
|
513
|
+
node: `${nodeRoot}/${pkg.packageOptions.directory}`,
|
|
514
|
+
nodePackage: `@${scope}/${packageName}`,
|
|
515
|
+
}
|
|
516
|
+
: {}),
|
|
517
|
+
...(targets.includes("python")
|
|
518
|
+
? {
|
|
519
|
+
python: `${options.pythonRoot ?? "packages/py"}/${pkg.packageOptions.directory}`,
|
|
520
|
+
pythonPackage: pkg.crateName,
|
|
521
|
+
pythonModule: pythonModuleName(pythonModulePrefix, pkg.packageOptions.directory),
|
|
522
|
+
}
|
|
523
|
+
: {}),
|
|
524
|
+
};
|
|
525
|
+
}),
|
|
526
|
+
);
|
|
527
|
+
for (const pkg of bindings) {
|
|
528
|
+
const dependencies = bindingDependencies(pkg, "python");
|
|
529
|
+
if (dependencies.length === 0) continue;
|
|
530
|
+
pkg.tryRemoveFile("uniffi.toml");
|
|
531
|
+
new TextFile(pkg, "uniffi.toml", {
|
|
532
|
+
lines: renderToml({
|
|
533
|
+
"bindings.python": { cdylib_name: pkg.crateName.replaceAll("-", "_") },
|
|
534
|
+
"bindings.typescript": { strictTypeChecking: true },
|
|
535
|
+
...pkg.packageOptions.uniffiConfig,
|
|
536
|
+
"bindings.python.external_packages": Object.fromEntries(
|
|
537
|
+
dependencies.map((dependency) => [
|
|
538
|
+
dependency.crateName.replaceAll("-", "_"),
|
|
539
|
+
`${pythonModuleName(pythonModulePrefix, dependency.packageOptions.directory)}.bindings`,
|
|
540
|
+
]),
|
|
541
|
+
),
|
|
542
|
+
})
|
|
543
|
+
.trimEnd()
|
|
544
|
+
.split("\n"),
|
|
545
|
+
});
|
|
546
|
+
}
|
|
471
547
|
const releaseEnabled =
|
|
472
548
|
(options.release ?? true) &&
|
|
473
549
|
(this.bindingMappings.length > 0 ||
|
|
@@ -484,13 +560,7 @@ export class DBXToolsRustWorkspace {
|
|
|
484
560
|
project.gitignore.addPatterns(
|
|
485
561
|
"target/",
|
|
486
562
|
...this.bindingMappings.flatMap((binding) => [
|
|
487
|
-
...(binding.node
|
|
488
|
-
? [
|
|
489
|
-
`${binding.node}/src/bindings.ts`,
|
|
490
|
-
`${binding.node}/src/_bindings*.ts`,
|
|
491
|
-
`${binding.node}/src/*${binding.crate.replaceAll("-", "_")}.*`,
|
|
492
|
-
]
|
|
493
|
-
: []),
|
|
563
|
+
...(binding.node ? [`${binding.node}/src/*${binding.crate.replaceAll("-", "_")}.*`] : []),
|
|
494
564
|
...(binding.python && binding.pythonModule
|
|
495
565
|
? [
|
|
496
566
|
`${binding.python}/src/${binding.pythonModule.replaceAll(".", "/")}/bindings.py`,
|
|
@@ -499,6 +569,13 @@ export class DBXToolsRustWorkspace {
|
|
|
499
569
|
: []),
|
|
500
570
|
]),
|
|
501
571
|
);
|
|
572
|
+
for (const binding of this.bindingMappings) {
|
|
573
|
+
if (!binding.node) {
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
project.prettier?.addIgnorePattern(`${binding.node}/src/bindings.ts`);
|
|
577
|
+
project.prettier?.addIgnorePattern(`${binding.node}/src/_bindings*.ts`);
|
|
578
|
+
}
|
|
502
579
|
this.pythonPackages = bindings
|
|
503
580
|
.filter((pkg) => (pkg.packageOptions.bindings ?? ["node", "python"]).includes("python"))
|
|
504
581
|
.map((pkg) => {
|
|
@@ -508,10 +585,16 @@ export class DBXToolsRustWorkspace {
|
|
|
508
585
|
name: pkg.crateName,
|
|
509
586
|
module,
|
|
510
587
|
description: `Python bindings for ${pkg.crateName}`,
|
|
511
|
-
|
|
512
|
-
|
|
588
|
+
uniffi: true,
|
|
589
|
+
internalDependencies: bindingDependencies(pkg, "python").map(
|
|
590
|
+
(dependency) => dependency.packageOptions.directory,
|
|
591
|
+
),
|
|
592
|
+
generatedSources: [
|
|
593
|
+
`src/${module.replaceAll(".", "/")}/bindings.py`,
|
|
594
|
+
`src/${module.replaceAll(".", "/")}/__init__.py`,
|
|
595
|
+
],
|
|
513
596
|
trustedPublisher: {
|
|
514
|
-
workflowName: options.
|
|
597
|
+
workflowName: options.pythonReleaseWorkflowName ?? "python-release",
|
|
515
598
|
environment: `pypi-${pkg.crateName}`,
|
|
516
599
|
artifacts: `platform-specific wheels for ${releaseTargets(options)
|
|
517
600
|
.map((target) => `${target.os}-${target.cpu}`)
|
|
@@ -530,22 +613,23 @@ export class DBXToolsRustWorkspace {
|
|
|
530
613
|
const directory = binding.packageOptions.directory;
|
|
531
614
|
const memberPath = `${nodeRoot}/${directory}`;
|
|
532
615
|
const found = existing.get(memberPath);
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
616
|
+
const existingNode = found instanceof DBXToolsTypeScriptProject ? found : undefined;
|
|
617
|
+
const node = existingNode
|
|
618
|
+
? existingNode
|
|
619
|
+
: new DBXToolsTypeScriptProject({
|
|
620
|
+
parent: project,
|
|
621
|
+
outdir: memberPath,
|
|
622
|
+
name: `@${scope}/${directory.toLowerCase().replace(/[^a-z0-9-]+/g, "-")}`,
|
|
623
|
+
tags: ["node"],
|
|
624
|
+
});
|
|
542
625
|
node.package.addField(
|
|
543
626
|
"name",
|
|
544
627
|
`@${scope}/${directory.toLowerCase().replace(/[^a-z0-9-]+/g, "-")}`,
|
|
545
628
|
);
|
|
546
|
-
node.
|
|
547
|
-
|
|
548
|
-
|
|
629
|
+
node.dbxToolsConfig.uniffi = true;
|
|
630
|
+
if (!existingNode) {
|
|
631
|
+
node.package.addField("description", `Node bindings for ${binding.crateName}`);
|
|
632
|
+
}
|
|
549
633
|
const nativeTargets = releaseTargets(options);
|
|
550
634
|
if (options.release ?? true) {
|
|
551
635
|
node.package.addField(
|
|
@@ -559,6 +643,11 @@ export class DBXToolsRustWorkspace {
|
|
|
559
643
|
);
|
|
560
644
|
}
|
|
561
645
|
node.addDeps("@ubjs/core@0.31.0-5", "@ubjs/node@0.31.0-5");
|
|
646
|
+
node.addDeps(
|
|
647
|
+
...bindingDependencies(binding, "node").map(
|
|
648
|
+
(dependency) => `@${scope}/${dependency.packageOptions.directory}@workspace:*`,
|
|
649
|
+
),
|
|
650
|
+
);
|
|
562
651
|
if (binding.packageOptions.nodeDependencies?.length) {
|
|
563
652
|
node.addDeps(...binding.packageOptions.nodeDependencies);
|
|
564
653
|
}
|
|
@@ -566,10 +655,6 @@ export class DBXToolsRustWorkspace {
|
|
|
566
655
|
if (binding.packageOptions.nodeDevDependencies?.length) {
|
|
567
656
|
node.addDevDeps(...binding.packageOptions.nodeDevDependencies);
|
|
568
657
|
}
|
|
569
|
-
node.compileTask.reset();
|
|
570
|
-
new TextFile(node, "exports.ts", {
|
|
571
|
-
lines: ['export * from "./src/bindings.ts";', ""],
|
|
572
|
-
});
|
|
573
658
|
nodePackages.push(node);
|
|
574
659
|
}
|
|
575
660
|
this.nodePackages = nodePackages;
|
|
@@ -607,10 +692,13 @@ export class DBXToolsRustWorkspace {
|
|
|
607
692
|
project.addTask("rs:lint", { exec: "cargo clippy --workspace --all-targets --all-features" });
|
|
608
693
|
project.addTask("rs:test", { exec: "cargo test --workspace" });
|
|
609
694
|
project.addTask("rs:build", { exec: "cargo build --workspace" });
|
|
610
|
-
project.addTask("rs:bindings", {
|
|
695
|
+
const bindingsTask = project.addTask("rs:bindings", {
|
|
611
696
|
exec: "bun node_modules/@dbx-tools/projen/tasks/rust.ts",
|
|
612
697
|
description: "Generate language bindings for UniFFI-enabled Rust crates",
|
|
613
698
|
});
|
|
699
|
+
if (this.bindingMappings.some((binding) => binding.node)) {
|
|
700
|
+
project.tasks.tryFind("pre-compile")?.spawn(bindingsTask);
|
|
701
|
+
}
|
|
614
702
|
project.addTask("rs:bindings:demo", {
|
|
615
703
|
description: "Generate and run UniFFI Node and Python example CLIs",
|
|
616
704
|
exec: [
|
|
@@ -637,15 +725,6 @@ export class DBXToolsRustWorkspace {
|
|
|
637
725
|
const workflowName = options.releaseWorkflowName ?? "rust-release";
|
|
638
726
|
const releaseTagPrefix = options.releaseTagPrefix ?? "v";
|
|
639
727
|
const releaseRustVersion = options.releaseRustVersion ?? "stable";
|
|
640
|
-
const ubrnRustVersion = options.ubrnRustVersion ?? releaseRustVersion;
|
|
641
|
-
const ubrnToolchainInstall =
|
|
642
|
-
ubrnRustVersion === releaseRustVersion
|
|
643
|
-
? ""
|
|
644
|
-
: `rustup toolchain install ${ubrnRustVersion} --profile minimal\n`;
|
|
645
|
-
const ubrnExecutable =
|
|
646
|
-
"${{ github.workspace }}/.cache/ubrn/uniffi-bindgen-react-native${{ matrix.target.os == 'win32' && '.exe' || '' }}";
|
|
647
|
-
const builtUbrnExecutable =
|
|
648
|
-
"target/ubrn/debug/uniffi-bindgen-react-native${{ matrix.target.os == 'win32' && '.exe' || '' }}";
|
|
649
728
|
const releaseBranch = projectReleaseBranch(project);
|
|
650
729
|
const bindings = this.bindingMappings.map((binding) => ({
|
|
651
730
|
...binding,
|
|
@@ -662,12 +741,14 @@ export class DBXToolsRustWorkspace {
|
|
|
662
741
|
}));
|
|
663
742
|
const publicCrates = this.packages
|
|
664
743
|
.filter((pkg) => !pkg.packageOptions.private)
|
|
744
|
+
.sort((first, second) => {
|
|
745
|
+
const order = this.bindingMappings.map((binding) => binding.crate);
|
|
746
|
+
return order.indexOf(first.crateName) - order.indexOf(second.crateName);
|
|
747
|
+
})
|
|
665
748
|
.map((pkg) => pkg.crateName);
|
|
666
|
-
const targetMatrix = targets.map((target
|
|
667
|
-
target: { ...target, facade: index === 0 },
|
|
668
|
-
}));
|
|
669
|
-
const hasNodeBindings = bindings.some((binding) => binding.node);
|
|
749
|
+
const targetMatrix = targets.map((target) => ({ target }));
|
|
670
750
|
const hasPythonBindings = bindings.some((binding) => binding.python);
|
|
751
|
+
const usePreinstalledWindowsRust = releaseRustVersion === "stable";
|
|
671
752
|
const hasTargetOutputs =
|
|
672
753
|
bindings.length > 0 || releaseBinaries.length > 0 || publicCrates.length > 0;
|
|
673
754
|
if (hasTargetOutputs && targetMatrix.length === 0) {
|
|
@@ -689,16 +770,12 @@ export class DBXToolsRustWorkspace {
|
|
|
689
770
|
`--python "${binding.python}"`,
|
|
690
771
|
`--node-package "${binding.nodePackage}"`,
|
|
691
772
|
`--python-package "${binding.pythonPackage}"`,
|
|
692
|
-
...(binding.node
|
|
693
|
-
? ['--node-generator "projen/tasks/uniffi.ts"', '--ubrn "$UBRN_EXECUTABLE"']
|
|
694
|
-
: []),
|
|
695
773
|
'--cargo-target "${{ matrix.target.cargo }}"',
|
|
696
774
|
'--node-triple "${{ matrix.target.node }}"',
|
|
697
775
|
'--python-tag "${{ matrix.target.python }}"',
|
|
698
776
|
'--os "${{ matrix.target.os }}"',
|
|
699
777
|
'--cpu "${{ matrix.target.cpu }}"',
|
|
700
778
|
'--libc "${{ matrix.target.libc }}"',
|
|
701
|
-
'--facade "${{ matrix.target.facade }}"',
|
|
702
779
|
`--version "\${VERSION#${releaseTagPrefix}}"`,
|
|
703
780
|
`--output "dist/release/${binding.crate}/\${{ matrix.target.node }}"`,
|
|
704
781
|
"--skip-build",
|
|
@@ -726,15 +803,7 @@ export class DBXToolsRustWorkspace {
|
|
|
726
803
|
with: {
|
|
727
804
|
name: `${binding.crate}-\${{ matrix.target.node }}-npm`,
|
|
728
805
|
path: `dist/release/${binding.crate}/\${{ matrix.target.node }}/npm/*.tgz`,
|
|
729
|
-
|
|
730
|
-
},
|
|
731
|
-
{
|
|
732
|
-
name: `Upload ${binding.crate} npm facade`,
|
|
733
|
-
if: "${{ matrix.target.facade }}",
|
|
734
|
-
uses: "actions/upload-artifact@v7",
|
|
735
|
-
with: {
|
|
736
|
-
name: `${binding.crate}-npm-facade`,
|
|
737
|
-
path: `dist/release/${binding.crate}/\${{ matrix.target.node }}/npm-facade/*.tgz`,
|
|
806
|
+
"retention-days": 7,
|
|
738
807
|
},
|
|
739
808
|
},
|
|
740
809
|
]
|
|
@@ -745,8 +814,9 @@ export class DBXToolsRustWorkspace {
|
|
|
745
814
|
name: `Upload ${binding.crate} Python wheel`,
|
|
746
815
|
uses: "actions/upload-artifact@v7",
|
|
747
816
|
with: {
|
|
748
|
-
name: `${binding.crate}
|
|
817
|
+
name: `${binding.crate}--\${{ matrix.target.python }}--python-wheel`,
|
|
749
818
|
path: `dist/release/${binding.crate}/\${{ matrix.target.node }}/python/*.whl`,
|
|
819
|
+
"retention-days": 7,
|
|
750
820
|
},
|
|
751
821
|
},
|
|
752
822
|
]
|
|
@@ -758,6 +828,7 @@ export class DBXToolsRustWorkspace {
|
|
|
758
828
|
with: {
|
|
759
829
|
name: `${pkg.crate}-\${{ matrix.target.node }}-binary`,
|
|
760
830
|
path: `dist/release/${pkg.crate}/\${{ matrix.target.node }}/binary/*`,
|
|
831
|
+
"retention-days": 7,
|
|
761
832
|
},
|
|
762
833
|
})),
|
|
763
834
|
];
|
|
@@ -767,7 +838,6 @@ export class DBXToolsRustWorkspace {
|
|
|
767
838
|
"runs-on": "${{ matrix.target.runner }}",
|
|
768
839
|
env: {
|
|
769
840
|
...RUST_CACHE_ENV,
|
|
770
|
-
BUN_VERSION,
|
|
771
841
|
SCCACHE_GHA_VERSION: `release-\${{ matrix.target.cargo }}-rust-${releaseRustVersion}`,
|
|
772
842
|
},
|
|
773
843
|
strategy: {
|
|
@@ -779,28 +849,26 @@ export class DBXToolsRustWorkspace {
|
|
|
779
849
|
...(hasPythonBindings ? [{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" }] : []),
|
|
780
850
|
{
|
|
781
851
|
name: "Setup Rust",
|
|
852
|
+
...(usePreinstalledWindowsRust ? { if: "${{ matrix.target.os != 'win32' }}" } : {}),
|
|
782
853
|
uses: `dtolnay/rust-toolchain@${releaseRustVersion}`,
|
|
783
854
|
with: { targets: "${{ matrix.target.cargo }}" },
|
|
784
855
|
},
|
|
785
|
-
...
|
|
786
|
-
...(hasNodeBindings
|
|
856
|
+
...(usePreinstalledWindowsRust
|
|
787
857
|
? [
|
|
788
858
|
{
|
|
789
|
-
name: "
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
859
|
+
name: "Verify preinstalled Windows Rust",
|
|
860
|
+
if: "${{ matrix.target.os == 'win32' }}",
|
|
861
|
+
shell: "bash",
|
|
862
|
+
run: [
|
|
863
|
+
"rustc --version --verbose",
|
|
864
|
+
"cargo --version",
|
|
865
|
+
'rustup target list --installed | grep -Fx "${{ matrix.target.cargo }}"',
|
|
866
|
+
'test -f "$(rustc --print sysroot)/lib/rustlib/${{ matrix.target.cargo }}/bin/rust-lld.exe"',
|
|
867
|
+
].join("\n"),
|
|
796
868
|
},
|
|
797
869
|
]
|
|
798
870
|
: []),
|
|
799
|
-
...(
|
|
800
|
-
? bunCacheRestoreSteps(project, {
|
|
801
|
-
condition: "steps.ubrn_cache.outputs.cache-hit != 'true'",
|
|
802
|
-
})
|
|
803
|
-
: []),
|
|
871
|
+
...rustCacheSteps(`release-\${{ matrix.target.cargo }}-rust-${releaseRustVersion}`),
|
|
804
872
|
{
|
|
805
873
|
name: "Log cache configuration",
|
|
806
874
|
shell: "bash",
|
|
@@ -809,13 +877,6 @@ export class DBXToolsRustWorkspace {
|
|
|
809
877
|
'echo "cargo_cache_hit=${{ steps.cargo_cache.outputs.cache-hit }}"',
|
|
810
878
|
'echo "sccache_scope=${{ github.ref }}"',
|
|
811
879
|
'echo "sccache_namespace=${SCCACHE_GHA_VERSION}"',
|
|
812
|
-
`echo "ubrn_rust_toolchain=${ubrnRustVersion}"`,
|
|
813
|
-
...(hasNodeBindings
|
|
814
|
-
? [
|
|
815
|
-
`echo "ubrn_executable_cache_key=ubrn-executable-\${{ runner.os }}-\${{ runner.arch }}-rust-${ubrnRustVersion}-${UBRN_VERSION}"`,
|
|
816
|
-
'echo "ubrn_executable_cache_hit=${{ steps.ubrn_cache.outputs.cache-hit }}"',
|
|
817
|
-
]
|
|
818
|
-
: []),
|
|
819
880
|
].join("\n"),
|
|
820
881
|
},
|
|
821
882
|
{
|
|
@@ -823,59 +884,13 @@ export class DBXToolsRustWorkspace {
|
|
|
823
884
|
if: "${{ matrix.target.os == 'linux' }}",
|
|
824
885
|
run: "sudo apt-get update && sudo apt-get install --yes libdbus-1-dev pkg-config",
|
|
825
886
|
},
|
|
826
|
-
...(hasNodeBindings
|
|
827
|
-
? [
|
|
828
|
-
{
|
|
829
|
-
name: "Install Node tooling",
|
|
830
|
-
if: "${{ steps.ubrn_cache.outputs.cache-hit != 'true' }}",
|
|
831
|
-
shell: "bash",
|
|
832
|
-
run: timedBash("node_tooling", "bun install"),
|
|
833
|
-
},
|
|
834
|
-
bunCacheSaveStep({
|
|
835
|
-
condition: "steps.ubrn_cache.outputs.cache-hit != 'true'",
|
|
836
|
-
}),
|
|
837
|
-
]
|
|
838
|
-
: []),
|
|
839
|
-
...(hasNodeBindings
|
|
840
|
-
? [
|
|
841
|
-
{
|
|
842
|
-
name: "Prepare UBRN generator",
|
|
843
|
-
if: "${{ steps.ubrn_cache.outputs.cache-hit != 'true' }}",
|
|
844
|
-
env: {
|
|
845
|
-
CARGO_TARGET_DIR: "${{ github.workspace }}/target/ubrn",
|
|
846
|
-
UBRN_EXECUTABLE: ubrnExecutable,
|
|
847
|
-
},
|
|
848
|
-
shell: "bash",
|
|
849
|
-
run: timedBash(
|
|
850
|
-
"ubrn_generator",
|
|
851
|
-
[
|
|
852
|
-
`${ubrnToolchainInstall}cargo +${ubrnRustVersion} build --manifest-path node_modules/uniffi-bindgen-react-native/crates/ubrn_cli/Cargo.toml`,
|
|
853
|
-
'mkdir -p "$(dirname "$UBRN_EXECUTABLE")"',
|
|
854
|
-
`cp "${builtUbrnExecutable}" "$UBRN_EXECUTABLE"`,
|
|
855
|
-
'chmod +x "$UBRN_EXECUTABLE"',
|
|
856
|
-
].join("\n"),
|
|
857
|
-
),
|
|
858
|
-
},
|
|
859
|
-
{
|
|
860
|
-
name: "Verify UBRN executable",
|
|
861
|
-
env: { UBRN_EXECUTABLE: ubrnExecutable },
|
|
862
|
-
shell: "bash",
|
|
863
|
-
run: 'test -f "$UBRN_EXECUTABLE"',
|
|
864
|
-
},
|
|
865
|
-
{
|
|
866
|
-
name: "Save UBRN executable",
|
|
867
|
-
if: "${{ steps.ubrn_cache.outputs.cache-hit != 'true' }}",
|
|
868
|
-
uses: "actions/cache/save@v5",
|
|
869
|
-
with: {
|
|
870
|
-
path: ".cache/ubrn",
|
|
871
|
-
key: "${{ steps.ubrn_cache.outputs.cache-primary-key }}",
|
|
872
|
-
},
|
|
873
|
-
},
|
|
874
|
-
]
|
|
875
|
-
: []),
|
|
876
887
|
{
|
|
877
888
|
name: "Build Rust outputs",
|
|
878
889
|
shell: "bash",
|
|
890
|
+
env: {
|
|
891
|
+
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER:
|
|
892
|
+
"${{ matrix.target.os == 'win32' && 'rust-lld' || '' }}",
|
|
893
|
+
},
|
|
879
894
|
run: timedBash(
|
|
880
895
|
"rust_workspace",
|
|
881
896
|
'cargo build --release --workspace --target "${{ matrix.target.cargo }}"',
|
|
@@ -886,14 +901,7 @@ export class DBXToolsRustWorkspace {
|
|
|
886
901
|
{
|
|
887
902
|
name: "Package UniFFI outputs",
|
|
888
903
|
shell: "bash",
|
|
889
|
-
env: {
|
|
890
|
-
VERSION: RELEASE_TAG,
|
|
891
|
-
...(hasNodeBindings
|
|
892
|
-
? {
|
|
893
|
-
UBRN_EXECUTABLE: ubrnExecutable,
|
|
894
|
-
}
|
|
895
|
-
: {}),
|
|
896
|
-
},
|
|
904
|
+
env: { VERSION: RELEASE_TAG },
|
|
897
905
|
run: timedBash("uniffi_packaging", bindingCommands.join("\n")),
|
|
898
906
|
},
|
|
899
907
|
]
|
|
@@ -916,80 +924,8 @@ export class DBXToolsRustWorkspace {
|
|
|
916
924
|
},
|
|
917
925
|
],
|
|
918
926
|
};
|
|
919
|
-
const bindingPublishJobs = Object.fromEntries(
|
|
920
|
-
bindings.map((binding) => [
|
|
921
|
-
`publish-${binding.crate}`,
|
|
922
|
-
{
|
|
923
|
-
if: "${{ github.event_name == 'repository_dispatch' }}",
|
|
924
|
-
needs: ["build"],
|
|
925
|
-
"runs-on": "ubuntu-latest",
|
|
926
|
-
permissions: {
|
|
927
|
-
contents: "read",
|
|
928
|
-
...(binding.python ? { "id-token": "write" } : {}),
|
|
929
|
-
},
|
|
930
|
-
...(binding.python ? { environment: { name: `pypi-${binding.crate}` } } : {}),
|
|
931
|
-
steps: [
|
|
932
|
-
...(binding.node
|
|
933
|
-
? [
|
|
934
|
-
{
|
|
935
|
-
name: "Setup Node.js",
|
|
936
|
-
uses: "actions/setup-node@v6",
|
|
937
|
-
with: { "registry-url": "https://registry.npmjs.org" },
|
|
938
|
-
},
|
|
939
|
-
{
|
|
940
|
-
name: "Download native npm packages",
|
|
941
|
-
uses: "actions/download-artifact@v8",
|
|
942
|
-
with: {
|
|
943
|
-
pattern: `${binding.crate}-*-npm`,
|
|
944
|
-
path: "dist/npm",
|
|
945
|
-
"merge-multiple": true,
|
|
946
|
-
},
|
|
947
|
-
},
|
|
948
|
-
{
|
|
949
|
-
name: "Download npm facade",
|
|
950
|
-
uses: "actions/download-artifact@v8",
|
|
951
|
-
with: {
|
|
952
|
-
name: `${binding.crate}-npm-facade`,
|
|
953
|
-
path: "dist/npm-facade",
|
|
954
|
-
},
|
|
955
|
-
},
|
|
956
|
-
{
|
|
957
|
-
name: "Publish native npm packages",
|
|
958
|
-
env: { NODE_AUTH_TOKEN: "${{ secrets.NPM_TOKEN }}" },
|
|
959
|
-
run: 'for package in dist/npm/*.tgz; do npm publish "$package" --access public; done',
|
|
960
|
-
},
|
|
961
|
-
{
|
|
962
|
-
name: "Publish npm facade",
|
|
963
|
-
env: { NODE_AUTH_TOKEN: "${{ secrets.NPM_TOKEN }}" },
|
|
964
|
-
run: 'for package in dist/npm-facade/*.tgz; do npm publish "$package" --access public; done',
|
|
965
|
-
},
|
|
966
|
-
]
|
|
967
|
-
: []),
|
|
968
|
-
...(binding.python
|
|
969
|
-
? [
|
|
970
|
-
{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" },
|
|
971
|
-
{
|
|
972
|
-
name: "Download Python wheels",
|
|
973
|
-
uses: "actions/download-artifact@v8",
|
|
974
|
-
with: {
|
|
975
|
-
pattern: `${binding.crate}-*-python-wheel`,
|
|
976
|
-
path: "dist/python",
|
|
977
|
-
"merge-multiple": true,
|
|
978
|
-
},
|
|
979
|
-
},
|
|
980
|
-
{
|
|
981
|
-
name: "Publish Python wheels",
|
|
982
|
-
run: "uv publish --trusted-publishing always dist/python/*.whl",
|
|
983
|
-
},
|
|
984
|
-
]
|
|
985
|
-
: []),
|
|
986
|
-
],
|
|
987
|
-
},
|
|
988
|
-
]),
|
|
989
|
-
);
|
|
990
927
|
const releaseCompletionJobs = [
|
|
991
928
|
"build",
|
|
992
|
-
...bindings.map((binding) => `publish-${binding.crate}`),
|
|
993
929
|
...(publicCrates.length ? ["publish-cargo"] : []),
|
|
994
930
|
...(releaseBinaries.length ? ["publish-github-release"] : []),
|
|
995
931
|
];
|
|
@@ -1057,7 +993,6 @@ export class DBXToolsRustWorkspace {
|
|
|
1057
993
|
],
|
|
1058
994
|
},
|
|
1059
995
|
...(hasTargetOutputs && targetMatrix.length ? { build: buildJob } : {}),
|
|
1060
|
-
...bindingPublishJobs,
|
|
1061
996
|
...(publicCrates.length
|
|
1062
997
|
? {
|
|
1063
998
|
"publish-cargo": {
|
|
@@ -1085,79 +1020,6 @@ export class DBXToolsRustWorkspace {
|
|
|
1085
1020
|
},
|
|
1086
1021
|
}
|
|
1087
1022
|
: {}),
|
|
1088
|
-
...(bindings.length
|
|
1089
|
-
? {
|
|
1090
|
-
"publish-local-bindings": {
|
|
1091
|
-
if: "${{ github.event_name == 'repository_dispatch' && vars.LOCAL_REPOSITORIES == 'true' }}",
|
|
1092
|
-
needs: ["build"],
|
|
1093
|
-
"runs-on": ["self-hosted"],
|
|
1094
|
-
permissions: { contents: "read" },
|
|
1095
|
-
steps: [
|
|
1096
|
-
...(hasNodeBindings
|
|
1097
|
-
? [
|
|
1098
|
-
{
|
|
1099
|
-
name: "Setup Node.js",
|
|
1100
|
-
uses: "actions/setup-node@v6",
|
|
1101
|
-
with: {
|
|
1102
|
-
"registry-url": "${{ vars.LOCAL_NPM_REGISTRY }}",
|
|
1103
|
-
},
|
|
1104
|
-
},
|
|
1105
|
-
{
|
|
1106
|
-
name: "Download native npm packages",
|
|
1107
|
-
uses: "actions/download-artifact@v8",
|
|
1108
|
-
with: {
|
|
1109
|
-
pattern: "*-npm",
|
|
1110
|
-
path: "dist/npm",
|
|
1111
|
-
"merge-multiple": true,
|
|
1112
|
-
},
|
|
1113
|
-
},
|
|
1114
|
-
{
|
|
1115
|
-
name: "Download npm facades",
|
|
1116
|
-
uses: "actions/download-artifact@v8",
|
|
1117
|
-
with: {
|
|
1118
|
-
pattern: "*-npm-facade",
|
|
1119
|
-
path: "dist/npm-facade",
|
|
1120
|
-
"merge-multiple": true,
|
|
1121
|
-
},
|
|
1122
|
-
},
|
|
1123
|
-
{
|
|
1124
|
-
name: "Publish npm packages locally",
|
|
1125
|
-
env: {
|
|
1126
|
-
NODE_AUTH_TOKEN: "${{ secrets.LOCAL_NPM_TOKEN }}",
|
|
1127
|
-
},
|
|
1128
|
-
run: [
|
|
1129
|
-
'for package in dist/npm/*.tgz; do npm publish "$package" --access public; done',
|
|
1130
|
-
'for package in dist/npm-facade/*.tgz; do npm publish "$package" --access public; done',
|
|
1131
|
-
].join("\n"),
|
|
1132
|
-
},
|
|
1133
|
-
]
|
|
1134
|
-
: []),
|
|
1135
|
-
...(hasPythonBindings
|
|
1136
|
-
? [
|
|
1137
|
-
{ name: "Setup uv", uses: "astral-sh/setup-uv@v7" },
|
|
1138
|
-
{
|
|
1139
|
-
name: "Download Python wheels",
|
|
1140
|
-
uses: "actions/download-artifact@v8",
|
|
1141
|
-
with: {
|
|
1142
|
-
pattern: "*-python-wheel",
|
|
1143
|
-
path: "dist/python",
|
|
1144
|
-
"merge-multiple": true,
|
|
1145
|
-
},
|
|
1146
|
-
},
|
|
1147
|
-
{
|
|
1148
|
-
name: "Publish Python wheels locally",
|
|
1149
|
-
env: {
|
|
1150
|
-
UV_PUBLISH_USERNAME: "${{ secrets.LOCAL_PYPI_USERNAME }}",
|
|
1151
|
-
UV_PUBLISH_PASSWORD: "${{ secrets.LOCAL_PYPI_PASSWORD }}",
|
|
1152
|
-
},
|
|
1153
|
-
run: 'uv publish --publish-url "${{ vars.LOCAL_PYPI_PUBLISH_URL }}" dist/python/*.whl',
|
|
1154
|
-
},
|
|
1155
|
-
]
|
|
1156
|
-
: []),
|
|
1157
|
-
],
|
|
1158
|
-
},
|
|
1159
|
-
}
|
|
1160
|
-
: {}),
|
|
1161
1023
|
...(publicCrates.length
|
|
1162
1024
|
? {
|
|
1163
1025
|
"publish-local-cargo": {
|
|
@@ -1232,6 +1094,8 @@ export class DBXToolsRustWorkspace {
|
|
|
1232
1094
|
RELEASE_TAG,
|
|
1233
1095
|
EXPECTED_SHA: RELEASE_SHA,
|
|
1234
1096
|
RELEASE_EVENT: DOWNSTREAM_RELEASE_EVENT,
|
|
1097
|
+
RUST_RUN_ID: "${{ github.run_id }}",
|
|
1098
|
+
RUST_RUN_ATTEMPT: "${{ github.run_attempt }}",
|
|
1235
1099
|
},
|
|
1236
1100
|
run: [
|
|
1237
1101
|
[
|
|
@@ -1239,6 +1103,8 @@ export class DBXToolsRustWorkspace {
|
|
|
1239
1103
|
'--raw-field event_type="$RELEASE_EVENT"',
|
|
1240
1104
|
'--raw-field "client_payload[release_tag]=$RELEASE_TAG"',
|
|
1241
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"',
|
|
1242
1108
|
].join(" \\\n "),
|
|
1243
1109
|
].join("\n"),
|
|
1244
1110
|
},
|