@dbx-tools/projen 0.9.21 → 0.9.29

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.
Files changed (111) hide show
  1. package/README.md +77 -207
  2. package/index.ts +10 -14
  3. package/package.json +4 -4
  4. package/src/barrels.ts +1 -74
  5. package/src/module-exports.ts +175 -1
  6. package/src/openapi.ts +5 -72
  7. package/src/packages.ts +45 -0
  8. package/src/project-js.ts +3 -6
  9. package/src/project-predicate.ts +1 -2
  10. package/src/project-py.ts +82 -103
  11. package/src/project.ts +2 -2
  12. package/src/python-node-bindings.ts +138 -0
  13. package/src/python-node-bundle.ts +92 -0
  14. package/src/release-catalog.ts +3 -5
  15. package/src/{release-dispatch.ts → release-context.ts} +0 -11
  16. package/src/release.ts +70 -152
  17. package/tasks/bump.ts +12 -21
  18. package/tasks/databricks-cli-assets.ts +129 -0
  19. package/tasks/local-publish.ts +23 -107
  20. package/tasks/publish-npm.ts +10 -1
  21. package/tasks/publish-python.ts +26 -11
  22. package/tasks/publish.ts +12 -48
  23. package/tasks/python-node-bindings-watch.ts +47 -0
  24. package/tasks/python-node-bindings.ts +1017 -0
  25. package/tasks/python-release.ts +74 -0
  26. package/tasks/release.ts +99 -0
  27. package/tasks/sync.ts +13 -18
  28. package/tasks/version-check.ts +1 -28
  29. package/._LICENSE +0 -0
  30. package/._README.md +0 -0
  31. package/._index.ts +0 -0
  32. package/._package.json +0 -0
  33. package/src/.__lazy-require.ts +0 -0
  34. package/src/.__release-platform.ts +0 -0
  35. package/src/.__rust-project.ts +0 -0
  36. package/src/.__rust-release-workflow.ts +0 -0
  37. package/src/.__task-command.ts +0 -0
  38. package/src/._barrels.ts +0 -0
  39. package/src/._bun-app.ts +0 -0
  40. package/src/._bun-workflow.ts +0 -0
  41. package/src/._clean.ts +0 -0
  42. package/src/._codegen.ts +0 -0
  43. package/src/._dbx-tools-config.ts +0 -0
  44. package/src/._engine-root.ts +0 -0
  45. package/src/._generated.ts +0 -0
  46. package/src/._mixin.ts +0 -0
  47. package/src/._module-exports.ts +0 -0
  48. package/src/._openapi.ts +0 -0
  49. package/src/._packages.ts +0 -0
  50. package/src/._pnpm-workspace.ts +0 -0
  51. package/src/._project-js.ts +0 -0
  52. package/src/._project-predicate.ts +0 -0
  53. package/src/._project-py.ts +0 -0
  54. package/src/._project-rs.ts +0 -0
  55. package/src/._project.ts +0 -0
  56. package/src/._projen-version.ts +0 -0
  57. package/src/._publish.ts +0 -0
  58. package/src/._release-catalog.ts +0 -0
  59. package/src/._release-dispatch.ts +0 -0
  60. package/src/._release-github.ts +0 -0
  61. package/src/._release.ts +0 -0
  62. package/src/._scaffold.ts +0 -0
  63. package/src/._tags.ts +0 -0
  64. package/src/._tsconfig.ts +0 -0
  65. package/src/._uniffi.ts +0 -0
  66. package/src/._vscode.ts +0 -0
  67. package/src/._watch.ts +0 -0
  68. package/src/._workspace-lock.ts +0 -0
  69. package/src/._workspace-version.ts +0 -0
  70. package/src/_release-platform.ts +0 -78
  71. package/src/_rust-project.ts +0 -429
  72. package/src/_rust-release-workflow.ts +0 -311
  73. package/src/project-rs.ts +0 -1054
  74. package/src/release-github.ts +0 -109
  75. package/src/uniffi.ts +0 -65
  76. package/tasks/._barrels.ts +0 -0
  77. package/tasks/._bump.ts +0 -0
  78. package/tasks/._clean.ts +0 -0
  79. package/tasks/._compile-workspace.ts +0 -0
  80. package/tasks/._local-publish.ts +0 -0
  81. package/tasks/._openapi.ts +0 -0
  82. package/tasks/._projenrc.ts +0 -0
  83. package/tasks/._publish-npm.ts +0 -0
  84. package/tasks/._publish-python.ts +0 -0
  85. package/tasks/._publish-uniffi-local.ts +0 -0
  86. package/tasks/._publish.ts +0 -0
  87. package/tasks/._python-registry.ts +0 -0
  88. package/tasks/._release-assets.ts +0 -0
  89. package/tasks/._release-candidate.ts +0 -0
  90. package/tasks/._release-manifest.ts +0 -0
  91. package/tasks/._release-pr.ts +0 -0
  92. package/tasks/._release-summary.ts +0 -0
  93. package/tasks/._release-version.ts +0 -0
  94. package/tasks/._rust.ts +0 -0
  95. package/tasks/._sync.ts +0 -0
  96. package/tasks/._uniffi-python.d.ts +0 -0
  97. package/tasks/._uniffi-python.js +0 -0
  98. package/tasks/._uniffi-release.mjs +0 -0
  99. package/tasks/._uniffi.ts +0 -0
  100. package/tasks/._version-check.ts +0 -0
  101. package/tasks/publish-uniffi-local.ts +0 -359
  102. package/tasks/release-assets.ts +0 -467
  103. package/tasks/release-candidate.ts +0 -416
  104. package/tasks/release-manifest.ts +0 -273
  105. package/tasks/release-pr.ts +0 -589
  106. package/tasks/release-summary.ts +0 -379
  107. package/tasks/rust.ts +0 -173
  108. package/tasks/uniffi-python.d.ts +0 -60
  109. package/tasks/uniffi-python.js +0 -178
  110. package/tasks/uniffi-release.mjs +0 -579
  111. package/tasks/uniffi.ts +0 -262
@@ -1,467 +0,0 @@
1
- #!/usr/bin/env -S bun
2
- /** Build and optionally upload every native release target from macOS. */
3
-
4
- import { createHash } from "node:crypto";
5
- import {
6
- chmodSync,
7
- existsSync,
8
- mkdirSync,
9
- readFileSync,
10
- readdirSync,
11
- rmSync,
12
- statSync,
13
- writeFileSync,
14
- } from "node:fs";
15
- import { platform } from "node:os";
16
- import { basename, delimiter, dirname, join, relative, resolve } from "node:path";
17
- import * as projectUtils from "@dbx-tools/core/project-utils";
18
- import { json, log } from "@dbx-tools/shared-core";
19
- import { Command } from "commander";
20
- import { releaseBinaryAssetName } from "../src/_release-platform.ts";
21
- import type {
22
- RustReleaseConfiguration,
23
- RustReleaseTargetPlan,
24
- } from "../src/_rust-release-workflow.ts";
25
- import {
26
- captureTaskCommand,
27
- runLoggedTaskCommand,
28
- taskCommandSucceeds,
29
- } from "../src/_task-command.ts";
30
-
31
- const logger = log.logger("projen:release-assets");
32
- const emoji = /[\p{Extended_Pictographic}\uFE0F\u200D]/gu;
33
-
34
- interface CommandInvocation {
35
- readonly command: string;
36
- readonly args: readonly string[];
37
- }
38
-
39
- interface ReleaseAsset {
40
- readonly name: string;
41
- readonly path: string;
42
- readonly sha256: string;
43
- readonly size: number;
44
- }
45
-
46
- function logReleaseOutput(line: string): void {
47
- logger.info(line.replace(emoji, ""));
48
- }
49
-
50
- function releasePath(): string {
51
- const llvm = "/opt/homebrew/opt/llvm/bin";
52
- return [existsSync(llvm) ? llvm : undefined, process.env.PATH].filter(Boolean).join(delimiter);
53
- }
54
-
55
- /** Return missing commands required for a complete local release build. */
56
- export function missingLocalReleaseTools(root: string): string[] {
57
- if (platform() !== "darwin") return ["macOS"];
58
- const checks: Array<readonly [string, string, readonly string[]]> = [
59
- ["cargo", "cargo", ["--version"]],
60
- ["cargo-zigbuild", "cargo", ["zigbuild", "--help"]],
61
- ["cargo-xwin", "cargo", ["xwin", "--help"]],
62
- ["node", "node", ["--version"]],
63
- ["llvm-lib", "llvm-lib", ["--version"]],
64
- ["rustup", "rustup", ["--version"]],
65
- ["uv", "uv", ["--version"]],
66
- ["zig", "zig", ["version"]],
67
- ["zip", "zip", ["-v"]],
68
- ];
69
- return checks
70
- .filter(
71
- ([, command, args]) =>
72
- !taskCommandSucceeds(root, command, args, {
73
- env: { ...process.env, PATH: releasePath() },
74
- }),
75
- )
76
- .map(([name]) => name);
77
- }
78
-
79
- function readConfiguration(root: string): RustReleaseConfiguration {
80
- return json.parse(
81
- readFileSync(join(root, ".projen/rust-release.json"), "utf8"),
82
- ) as RustReleaseConfiguration;
83
- }
84
-
85
- /** Whether the synthesized repository has native release targets. */
86
- export function hasLocalReleaseTargets(root: string): boolean {
87
- const path = join(root, ".projen/rust-release.json");
88
- return existsSync(path) && readConfiguration(root).targets.length > 0;
89
- }
90
-
91
- function buildArguments(
92
- configuration: RustReleaseConfiguration,
93
- target: RustReleaseTargetPlan,
94
- targetName: string,
95
- ): string[] {
96
- return [
97
- "build",
98
- "--release",
99
- "--timings",
100
- ...(configuration.usesCargoLock ? ["--locked"] : []),
101
- ...target.packages.flatMap((pkg) => ["--package", pkg]),
102
- ...target.features.flatMap((feature) => ["--features", feature]),
103
- "--target",
104
- targetName,
105
- ];
106
- }
107
-
108
- /** Resolve the native macOS command used for one release target. */
109
- export function localTargetCommand(
110
- configuration: RustReleaseConfiguration,
111
- target: RustReleaseTargetPlan,
112
- ): CommandInvocation {
113
- const localTarget = {
114
- ...target,
115
- features: [...target.features, ...(target.os === "linux" ? target.localFeatures : [])],
116
- };
117
- if (target.os === "darwin") {
118
- return {
119
- command: "cargo",
120
- args: buildArguments(configuration, localTarget, target.cargo),
121
- };
122
- }
123
- if (target.os === "linux") {
124
- const cargoTarget = target.glibcVersion
125
- ? `${target.cargo}.${target.glibcVersion}`
126
- : target.cargo;
127
- return {
128
- command: "cargo",
129
- args: ["zigbuild", ...buildArguments(configuration, localTarget, cargoTarget).slice(1)],
130
- };
131
- }
132
- if (target.os === "win32") {
133
- return {
134
- command: "cargo",
135
- args: ["xwin", "build", ...buildArguments(configuration, localTarget, target.cargo).slice(1)],
136
- };
137
- }
138
- throw new Error(`Unsupported local release target: ${target.os}-${target.cpu}`);
139
- }
140
-
141
- function targetEnvironment(): NodeJS.ProcessEnv {
142
- return {
143
- ...process.env,
144
- CARGO_INCREMENTAL: "0",
145
- PATH: releasePath(),
146
- RUSTC_WRAPPER: "",
147
- SCCACHE_DISABLE: "1",
148
- };
149
- }
150
-
151
- function targetBuildEnvironment(
152
- root: string,
153
- target: RustReleaseTargetPlan,
154
- env: NodeJS.ProcessEnv,
155
- ): NodeJS.ProcessEnv {
156
- if (target.os !== "win32" || target.cpu !== "arm64") return env;
157
- const tools = join(root, "target/release-tools/windows-arm64");
158
- mkdirSync(tools, { recursive: true });
159
- const clang = join(tools, "clang");
160
- writeFileSync(clang, '#!/bin/sh\nexec /opt/homebrew/opt/llvm/bin/clang --driver-mode=cl "$@"\n');
161
- chmodSync(clang, 0o755);
162
- return {
163
- ...env,
164
- PATH: [tools, env.PATH].filter(Boolean).join(delimiter),
165
- };
166
- }
167
-
168
- function cargoTargetRoot(root: string, env: NodeJS.ProcessEnv): string {
169
- const metadata = json.parseRecord(
170
- captureTaskCommand(root, "cargo", ["metadata", "--format-version", "1", "--no-deps"], {
171
- env,
172
- check: true,
173
- stderr: "inherit",
174
- }),
175
- );
176
- if (typeof metadata?.target_directory !== "string") {
177
- throw new Error("Cargo metadata returned no target directory");
178
- }
179
- return metadata.target_directory;
180
- }
181
-
182
- function rustHostTarget(root: string, env: NodeJS.ProcessEnv): string {
183
- const host = /^host:\s+(.+)$/m.exec(
184
- captureTaskCommand(root, "rustc", ["-vV"], {
185
- env,
186
- check: true,
187
- stderr: "inherit",
188
- }),
189
- )?.[1];
190
- if (!host) throw new Error("rustc did not report a host target");
191
- return host;
192
- }
193
-
194
- function buildBindingGenerators(
195
- root: string,
196
- configuration: RustReleaseConfiguration,
197
- hostTarget: string,
198
- env: NodeJS.ProcessEnv,
199
- ): void {
200
- if (configuration.bindings.length === 0) return;
201
- runLoggedTaskCommand(
202
- root,
203
- "cargo",
204
- [
205
- "build",
206
- "--release",
207
- ...(configuration.usesCargoLock ? ["--locked"] : []),
208
- ...configuration.bindings.flatMap((binding) => ["--package", binding.crate]),
209
- ...configuration.bindings.flatMap((binding) => [
210
- "--features",
211
- `${binding.crate}/uniffi-bindgen`,
212
- ]),
213
- "--target",
214
- hostTarget,
215
- ],
216
- { env, onLine: logReleaseOutput },
217
- );
218
- }
219
-
220
- function generatePythonBindings(
221
- root: string,
222
- configuration: RustReleaseConfiguration,
223
- hostTarget: string,
224
- env: NodeJS.ProcessEnv,
225
- ): Map<string, string> {
226
- const generated = new Map<string, string>();
227
- for (const binding of configuration.bindings) {
228
- if (!binding.python) continue;
229
- const output = join(root, "dist/local-bindings", binding.crate);
230
- runLoggedTaskCommand(
231
- root,
232
- "node",
233
- [
234
- ".projen/uniffi-release.mjs",
235
- "generate-python",
236
- "--crate",
237
- binding.crate,
238
- "--cargo-target",
239
- hostTarget,
240
- "--os",
241
- "darwin",
242
- "--output",
243
- output,
244
- ],
245
- { env, onLine: logReleaseOutput },
246
- );
247
- generated.set(binding.crate, join(output, `${binding.crate.replaceAll("-", "_")}.py`));
248
- }
249
- return generated;
250
- }
251
-
252
- function packageBindings(
253
- root: string,
254
- configuration: RustReleaseConfiguration,
255
- target: RustReleaseTargetPlan,
256
- version: string,
257
- pythonBindings: ReadonlyMap<string, string>,
258
- env: NodeJS.ProcessEnv,
259
- ): void {
260
- for (const binding of configuration.bindings) {
261
- runLoggedTaskCommand(
262
- root,
263
- "node",
264
- [
265
- ".projen/uniffi-release.mjs",
266
- "build",
267
- "--crate",
268
- binding.crate,
269
- "--node",
270
- binding.node,
271
- "--python",
272
- binding.python,
273
- "--node-package",
274
- binding.nodePackage,
275
- "--python-package",
276
- binding.pythonPackage,
277
- "--python-module",
278
- binding.pythonModule ?? "",
279
- "--cargo-target",
280
- target.cargo,
281
- "--node-triple",
282
- target.node,
283
- "--python-tag",
284
- target.python,
285
- "--os",
286
- target.os,
287
- "--cpu",
288
- target.cpu,
289
- "--libc",
290
- target.libc,
291
- "--version",
292
- version,
293
- "--output",
294
- `dist/release/${binding.crate}/${target.node}`,
295
- "--skip-build",
296
- ...(pythonBindings.has(binding.crate)
297
- ? ["--python-bindings", pythonBindings.get(binding.crate)!]
298
- : []),
299
- ],
300
- { env, onLine: logReleaseOutput },
301
- );
302
- }
303
- }
304
-
305
- function packageBinaries(
306
- root: string,
307
- configuration: RustReleaseConfiguration,
308
- target: RustReleaseTargetPlan,
309
- targetRoot: string,
310
- env: NodeJS.ProcessEnv,
311
- ): void {
312
- const selected = configuration.binaries.filter(
313
- (binary) => !binary.excludedOs.includes(target.os),
314
- );
315
- for (const crate of new Set(selected.map((binary) => binary.crate))) {
316
- const output = join(root, "dist/release", crate, target.node, "binary");
317
- rmSync(output, { recursive: true, force: true });
318
- mkdirSync(output, { recursive: true });
319
- }
320
- for (const binary of selected) {
321
- const extension = target.os === "win32" ? ".exe" : "";
322
- const source = resolve(targetRoot, target.cargo, "release", `${binary.binary}${extension}`);
323
- if (!existsSync(source)) throw new Error(`Missing release binary: ${source}`);
324
- const output = join(root, "dist/release", binary.crate, target.node, "binary");
325
- const asset = join(output, releaseBinaryAssetName(binary.binary, target.node, target.os));
326
- if (target.os === "win32") {
327
- runLoggedTaskCommand(root, "zip", ["-j", asset, source], {
328
- env,
329
- onLine: logReleaseOutput,
330
- });
331
- } else {
332
- runLoggedTaskCommand(root, "tar", ["-C", dirname(source), "-czf", asset, basename(source)], {
333
- env,
334
- onLine: logReleaseOutput,
335
- });
336
- }
337
- }
338
- }
339
-
340
- function files(root: string, directory: string): string[] {
341
- const absolute = resolve(root, directory);
342
- if (!existsSync(absolute)) return [];
343
- return readdirSync(absolute, { withFileTypes: true }).flatMap((entry) => {
344
- const child = join(absolute, entry.name);
345
- return entry.isDirectory() ? files(root, child) : [child];
346
- });
347
- }
348
-
349
- function releaseAssets(root: string): ReleaseAsset[] {
350
- const allowed = new Set([".tgz", ".whl", ".zip", ".gz"]);
351
- const found = files(root, "dist/release").filter((path) =>
352
- [...allowed].some((extension) => path.endsWith(extension)),
353
- );
354
- const names = new Set<string>();
355
- return found.map((path) => {
356
- const name = basename(path);
357
- if (names.has(name)) throw new Error(`Duplicate release asset name: ${name}`);
358
- names.add(name);
359
- const content = readFileSync(path);
360
- return {
361
- name,
362
- path,
363
- sha256: createHash("sha256").update(content).digest("hex"),
364
- size: statSync(path).size,
365
- };
366
- });
367
- }
368
-
369
- function writeReleaseManifest(
370
- root: string,
371
- tag: string | undefined,
372
- version: string,
373
- ): { readonly assets: ReleaseAsset[]; readonly manifest: string } {
374
- const assets = releaseAssets(root);
375
- if (assets.length === 0) throw new Error("Local release build produced no assets");
376
- const manifest = join(root, "dist/release/rust-assets.json");
377
- writeFileSync(
378
- manifest,
379
- `${JSON.stringify(
380
- {
381
- schemaVersion: 1,
382
- tag,
383
- version,
384
- assets: assets.map((asset) => ({ ...asset, path: relative(root, asset.path) })),
385
- },
386
- null,
387
- 2,
388
- )}\n`,
389
- );
390
- return { assets, manifest };
391
- }
392
-
393
- function uploadAssets(
394
- root: string,
395
- tag: string,
396
- assets: readonly ReleaseAsset[],
397
- manifest: string,
398
- ): void {
399
- runLoggedTaskCommand(
400
- root,
401
- "gh",
402
- ["release", "upload", tag, ...assets.map((asset) => asset.path), "--clobber"],
403
- { onLine: logReleaseOutput },
404
- );
405
- runLoggedTaskCommand(root, "gh", ["release", "upload", tag, manifest, "--clobber"], {
406
- onLine: logReleaseOutput,
407
- });
408
- }
409
-
410
- /** Build all configured targets sequentially and optionally upload them. */
411
- export function buildReleaseAssets(options: {
412
- readonly root: string;
413
- readonly version: string;
414
- readonly tag?: string;
415
- readonly upload?: boolean;
416
- }): void {
417
- const root = resolve(options.root);
418
- const missing = missingLocalReleaseTools(root);
419
- if (missing.length > 0) {
420
- throw new Error(`Local release build requires: ${missing.join(", ")}`);
421
- }
422
- const configuration = readConfiguration(root);
423
- const env = targetEnvironment();
424
- const targetRoot = cargoTargetRoot(root, env);
425
- const hostTarget = rustHostTarget(root, env);
426
- rmSync(join(root, "dist/release"), { recursive: true, force: true });
427
- rmSync(join(root, "dist/local-bindings"), { recursive: true, force: true });
428
- buildBindingGenerators(root, configuration, hostTarget, env);
429
- const pythonBindings = generatePythonBindings(root, configuration, hostTarget, env);
430
- for (const target of configuration.targets) {
431
- runLoggedTaskCommand(root, "rustup", ["target", "add", target.cargo], {
432
- env,
433
- onLine: logReleaseOutput,
434
- });
435
- const invocation = localTargetCommand(configuration, target);
436
- const buildEnv = targetBuildEnvironment(root, target, env);
437
- logger.info("building Rust release target", { target: target.cargo });
438
- runLoggedTaskCommand(root, invocation.command, invocation.args, {
439
- env: buildEnv,
440
- onLine: logReleaseOutput,
441
- });
442
- packageBindings(root, configuration, target, options.version, pythonBindings, env);
443
- packageBinaries(root, configuration, target, targetRoot, env);
444
- }
445
- const prepared = writeReleaseManifest(root, options.tag, options.version);
446
- if (options.upload) {
447
- if (!options.tag) throw new Error("--tag is required with --upload");
448
- uploadAssets(root, options.tag, prepared.assets, prepared.manifest);
449
- }
450
- }
451
-
452
- if (import.meta.main) {
453
- new Command()
454
- .requiredOption("--version <version>", "release version")
455
- .option("--root <path>", "repository root")
456
- .option("--tag <tag>", "GitHub Release tag")
457
- .option("--upload", "upload assets to the GitHub Release")
458
- .action((options: { version: string; root?: string; tag?: string; upload?: boolean }) => {
459
- buildReleaseAssets({
460
- root: options.root ?? projectUtils.root() ?? process.cwd(),
461
- version: options.version,
462
- tag: options.tag,
463
- upload: options.upload,
464
- });
465
- })
466
- .parse();
467
- }