@dbx-tools/projen 0.9.105 → 0.9.108
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 +32 -25
- package/index.ts +1 -1
- package/package.json +6 -5
- package/src/project-py.ts +3 -1
- package/tasks/barrels.ts +19 -13
- package/tasks/bump.ts +33 -28
- package/tasks/clean.ts +20 -2
- package/tasks/cli.ts +80 -0
- package/tasks/compile-workspace.ts +2 -1
- package/tasks/dev-watch.ts +35 -50
- package/tasks/options.ts +59 -0
- package/tasks/projenrc.ts +2 -1
- package/tasks/publish-npm.ts +25 -14
- package/tasks/publish-python.ts +50 -52
- package/tasks/publish.ts +37 -25
- package/tasks/python-node-bindings-watch.ts +2 -1
- package/tasks/python-node-bindings.ts +29 -16
- package/tasks/python-node-runtime-watch.ts +9 -8
- package/tasks/python-sync.ts +20 -9
- package/tasks/release-options.ts +17 -8
- package/tasks/release-version.ts +22 -15
- package/tasks/release.ts +103 -96
- package/tasks/shared-core-usage.ts +6 -1
- package/tasks/sync.ts +16 -2
- package/tasks/test-workspace.ts +27 -12
- package/tasks/ui-bundle-sizes.ts +17 -12
- package/tasks/version-check.ts +2 -1
package/tasks/release.ts
CHANGED
|
@@ -4,8 +4,11 @@ import { readFileSync } from "node:fs";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import * as projectUtils from "@dbx-tools/core/project-utils";
|
|
6
6
|
import { log } from "@dbx-tools/shared-core";
|
|
7
|
-
import { Command
|
|
7
|
+
import type { Command } from "commander";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { parsedTaskOptions, runTaskMain, taskCommand } from "./cli.ts";
|
|
8
10
|
import { publishLocalRelease } from "./local-publish.ts";
|
|
11
|
+
import { TaskDirectoriesOptionSchema, TaskRootOptionSchema } from "./options.ts";
|
|
9
12
|
import { writeReleaseNotes } from "./release-notes.ts";
|
|
10
13
|
import { assertReleaseVersion } from "./release-version.ts";
|
|
11
14
|
import { captureTaskCommand, runTaskCommand, taskCommandSucceeds } from "../src/_task-command.ts";
|
|
@@ -368,101 +371,105 @@ export async function runRelease(
|
|
|
368
371
|
return tag;
|
|
369
372
|
}
|
|
370
373
|
|
|
371
|
-
|
|
374
|
+
export const ReleaseOptionsSchema = z.object({
|
|
375
|
+
root: TaskRootOptionSchema,
|
|
376
|
+
branch: z.string().trim().min(1).default("main").describe("Release branch"),
|
|
377
|
+
prefix: z.string().default("v").describe("Release tag prefix"),
|
|
378
|
+
remote: z.string().trim().min(1).default("origin").describe("Git remote"),
|
|
379
|
+
pythonRoot: z
|
|
380
|
+
.string()
|
|
381
|
+
.trim()
|
|
382
|
+
.min(1)
|
|
383
|
+
.default("packages/py")
|
|
384
|
+
.describe("Python package root for local publish"),
|
|
385
|
+
validate: TaskDirectoriesOptionSchema.describe("Repeatable task to run before pushing"),
|
|
386
|
+
bump: z.boolean().default(true).describe("Create and synchronize a patch version bump"),
|
|
387
|
+
publish: z.enum(RELEASE_PUBLISH_TARGETS).default("auto").describe("Publication scope"),
|
|
388
|
+
install: z
|
|
389
|
+
.enum(RELEASE_INSTALL_MODES)
|
|
390
|
+
.default("auto")
|
|
391
|
+
.describe("Local workspace dependency installation"),
|
|
392
|
+
npm: z.boolean().default(true).describe("Build and publish npm packages"),
|
|
393
|
+
pypi: z.boolean().default(true).describe("Build and publish Python packages"),
|
|
394
|
+
docs: z.boolean().optional().describe("Build and deploy documentation"),
|
|
395
|
+
validation: z
|
|
396
|
+
.boolean()
|
|
397
|
+
.default(true)
|
|
398
|
+
.describe("Run optional release validation tasks before publishing"),
|
|
399
|
+
releaseNotes: z.boolean().default(true).describe("Write release notes before tagging"),
|
|
400
|
+
releaseNotesText: z
|
|
401
|
+
.string()
|
|
402
|
+
.optional()
|
|
403
|
+
.describe("Write supplied release-note Markdown without invoking Genie"),
|
|
404
|
+
releaseNotesFile: z
|
|
405
|
+
.string()
|
|
406
|
+
.trim()
|
|
407
|
+
.min(1)
|
|
408
|
+
.optional()
|
|
409
|
+
.describe("Copy release-note Markdown from this file without invoking Genie"),
|
|
410
|
+
releaseNotesInstructions: z
|
|
411
|
+
.string()
|
|
412
|
+
.optional()
|
|
413
|
+
.describe("Append instructions to the Genie release-note prompt"),
|
|
414
|
+
demoDeploy: z
|
|
415
|
+
.boolean()
|
|
416
|
+
.optional()
|
|
417
|
+
.describe("Deploy the AppKit demo after tagging and local publication"),
|
|
418
|
+
profile: z
|
|
419
|
+
.string()
|
|
420
|
+
.trim()
|
|
421
|
+
.min(1)
|
|
422
|
+
.optional()
|
|
423
|
+
.describe("Explicit Databricks CLI profile for demo deployment")
|
|
424
|
+
.meta({ env: [], helpDefault: false }),
|
|
425
|
+
localPublish: z.boolean().default(true).describe("Publish to configured local registries"),
|
|
426
|
+
localRegistry: z
|
|
427
|
+
.string()
|
|
428
|
+
.trim()
|
|
429
|
+
.min(1)
|
|
430
|
+
.default("auto")
|
|
431
|
+
.describe("Local npm registry selection: auto, false, or URL"),
|
|
432
|
+
localPypi: z
|
|
433
|
+
.string()
|
|
434
|
+
.trim()
|
|
435
|
+
.min(1)
|
|
436
|
+
.default("auto")
|
|
437
|
+
.describe("Local devpi registry selection: auto, false, or URL"),
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
/** Build the release task's schema-driven parser without executing release operations. */
|
|
372
441
|
export function createReleaseCommand(): Command {
|
|
373
|
-
return
|
|
374
|
-
.
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
"skip optional release validation tasks; workspace version checks remain mandatory",
|
|
405
|
-
)
|
|
406
|
-
.option("--no-release-notes", "skip writing docs/releases notes (Genie and git-log fallback)")
|
|
407
|
-
.option("--release-notes-text <markdown>", "write supplied markdown without invoking Genie")
|
|
408
|
-
.option("--release-notes-file <path>", "copy supplied markdown without invoking Genie")
|
|
409
|
-
.option(
|
|
410
|
-
"--release-notes-instructions <text>",
|
|
411
|
-
"append custom instructions to the Genie release-notes prompt",
|
|
412
|
-
)
|
|
413
|
-
.option("--demo-deploy", "after tagging, stage and deploy the AppKit demo app (off by default)")
|
|
414
|
-
.option("--profile <name>", "Databricks CLI profile for --demo-deploy")
|
|
415
|
-
.option("--no-local-publish", "skip publishing to configured local registries")
|
|
416
|
-
.option("--local-registry <auto|false|url>", "local npm registry selection", "auto")
|
|
417
|
-
.option("--local-pypi <auto|false|url>", "local devpi registry selection", "auto")
|
|
418
|
-
.action(
|
|
419
|
-
async (
|
|
420
|
-
options: ReleaseSelectionOptions & {
|
|
421
|
-
root?: string;
|
|
422
|
-
branch: string;
|
|
423
|
-
bump: boolean;
|
|
424
|
-
prefix: string;
|
|
425
|
-
remote: string;
|
|
426
|
-
pythonRoot: string;
|
|
427
|
-
localPublish: boolean;
|
|
428
|
-
localRegistry: string;
|
|
429
|
-
localPypi: string;
|
|
430
|
-
install: ReleaseInstallMode;
|
|
431
|
-
validate: string[];
|
|
432
|
-
demoDeploy?: boolean;
|
|
433
|
-
profile?: string;
|
|
434
|
-
releaseNotes?: boolean;
|
|
435
|
-
releaseNotesInstructions?: string;
|
|
436
|
-
releaseNotesText?: string;
|
|
437
|
-
releaseNotesFile?: string;
|
|
438
|
-
},
|
|
439
|
-
) => {
|
|
440
|
-
await runRelease({
|
|
441
|
-
root: options.root ?? projectUtils.root() ?? process.cwd(),
|
|
442
|
-
branch: options.branch,
|
|
443
|
-
bump: options.bump,
|
|
444
|
-
prefix: options.prefix,
|
|
445
|
-
remote: options.remote,
|
|
446
|
-
pythonRoot: options.pythonRoot,
|
|
447
|
-
localPublish: options.localPublish,
|
|
448
|
-
localRegistry: options.localRegistry,
|
|
449
|
-
localPypi: options.localPypi,
|
|
450
|
-
install: options.install,
|
|
451
|
-
publish: options.publish,
|
|
452
|
-
npm: options.npm,
|
|
453
|
-
pypi: options.pypi,
|
|
454
|
-
docs: options.docs,
|
|
455
|
-
validation: options.validation,
|
|
456
|
-
validationTasks: options.validate,
|
|
457
|
-
demoDeploy: options.demoDeploy,
|
|
458
|
-
demoProfile: options.profile,
|
|
459
|
-
releaseNotes: options.releaseNotes,
|
|
460
|
-
releaseNotesInstructions: options.releaseNotesInstructions,
|
|
461
|
-
releaseNotesText: options.releaseNotesText,
|
|
462
|
-
releaseNotesFile: options.releaseNotesFile,
|
|
463
|
-
});
|
|
464
|
-
},
|
|
465
|
-
);
|
|
442
|
+
return taskCommand(
|
|
443
|
+
import.meta.url,
|
|
444
|
+
"Prepare an annotated release and select its build and publication steps",
|
|
445
|
+
ReleaseOptionsSchema,
|
|
446
|
+
).action(async (_options: unknown, command: Command) => {
|
|
447
|
+
const options = parsedTaskOptions(command, ReleaseOptionsSchema);
|
|
448
|
+
await runRelease({
|
|
449
|
+
root: options.root ?? projectUtils.root() ?? process.cwd(),
|
|
450
|
+
branch: options.branch,
|
|
451
|
+
bump: options.bump,
|
|
452
|
+
prefix: options.prefix,
|
|
453
|
+
remote: options.remote,
|
|
454
|
+
pythonRoot: options.pythonRoot,
|
|
455
|
+
localPublish: options.localPublish,
|
|
456
|
+
localRegistry: options.localRegistry,
|
|
457
|
+
localPypi: options.localPypi,
|
|
458
|
+
install: options.install,
|
|
459
|
+
publish: options.publish,
|
|
460
|
+
npm: options.npm,
|
|
461
|
+
pypi: options.pypi,
|
|
462
|
+
docs: options.docs,
|
|
463
|
+
validation: options.validation,
|
|
464
|
+
validationTasks: options.validate,
|
|
465
|
+
demoDeploy: options.demoDeploy,
|
|
466
|
+
demoProfile: options.profile,
|
|
467
|
+
releaseNotes: options.releaseNotes,
|
|
468
|
+
releaseNotesInstructions: options.releaseNotesInstructions,
|
|
469
|
+
releaseNotesText: options.releaseNotesText,
|
|
470
|
+
releaseNotesFile: options.releaseNotesFile,
|
|
471
|
+
});
|
|
472
|
+
});
|
|
466
473
|
}
|
|
467
474
|
|
|
468
475
|
/** Execute the native release task parser. */
|
|
@@ -470,4 +477,4 @@ export async function main(): Promise<void> {
|
|
|
470
477
|
await createReleaseCommand().parseAsync();
|
|
471
478
|
}
|
|
472
479
|
|
|
473
|
-
|
|
480
|
+
await runTaskMain(import.meta, main);
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env -S bun
|
|
2
2
|
/** Print shared-core runtime-export usage by caller kind. */
|
|
3
|
+
import { runTaskMain } from "./cli.ts";
|
|
3
4
|
import { formatSharedCoreUsage, sharedCoreExportUsage } from "../src/shared-core-usage.ts";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
export function main(): void {
|
|
7
|
+
process.stdout.write(formatSharedCoreUsage(sharedCoreExportUsage()));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
await runTaskMain(import.meta, main);
|
package/tasks/sync.ts
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { log } from "@dbx-tools/shared-core";
|
|
5
5
|
import concurrently from "concurrently";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { runTaskMain, taskCommand, taskOptions } from "./cli.ts";
|
|
8
|
+
import { TaskWatchOptionSchema } from "./options.ts";
|
|
6
9
|
import { repoRoot, syncWatchTasks } from "../src/packages.ts";
|
|
7
10
|
import { runSynth } from "../src/scaffold.ts";
|
|
8
11
|
import { withWorkspaceMutationLock } from "../src/workspace-lock.ts";
|
|
@@ -45,8 +48,19 @@ function taskWatcher(task: string) {
|
|
|
45
48
|
};
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
export const SyncOptionsSchema = z.object({ watch: TaskWatchOptionSchema });
|
|
52
|
+
|
|
48
53
|
export async function main(args: string[] = process.argv.slice(2)): Promise<void> {
|
|
49
|
-
|
|
54
|
+
const { watch } = await taskOptions(
|
|
55
|
+
taskCommand(
|
|
56
|
+
import.meta.url,
|
|
57
|
+
"Synthesize once or supervise focused generators",
|
|
58
|
+
SyncOptionsSchema,
|
|
59
|
+
),
|
|
60
|
+
SyncOptionsSchema,
|
|
61
|
+
args,
|
|
62
|
+
);
|
|
63
|
+
if (!watch) {
|
|
50
64
|
// One-shot: full synth (+install + barrels via the post-synth component). This is
|
|
51
65
|
// the scriptable path, so a failed synth stays a failed exit code.
|
|
52
66
|
logger.start("synthesizing");
|
|
@@ -123,4 +137,4 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
139
|
|
|
126
|
-
|
|
140
|
+
await runTaskMain(import.meta, main);
|
package/tasks/test-workspace.ts
CHANGED
|
@@ -2,6 +2,9 @@ import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { basename, join, relative, resolve, sep } from "node:path";
|
|
3
3
|
import * as exec from "@dbx-tools/core/exec";
|
|
4
4
|
import { log, object } from "@dbx-tools/shared-core";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { runTaskMain, taskCommand, taskOptions, taskPositionals, taskRoot } from "./cli.ts";
|
|
7
|
+
import { TaskRootOptionSchema } from "./options.ts";
|
|
5
8
|
|
|
6
9
|
const logger = log.logger("projen:test");
|
|
7
10
|
|
|
@@ -26,6 +29,12 @@ export interface WorkspaceGraph {
|
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
type TestMode = "focused" | "changed" | "unit" | "integration" | "all" | "graph";
|
|
32
|
+
const TEST_MODES = ["focused", "changed", "unit", "integration", "all", "graph"] as const;
|
|
33
|
+
|
|
34
|
+
export const TestWorkspaceOptionsSchema = z.object({
|
|
35
|
+
root: TaskRootOptionSchema,
|
|
36
|
+
base: z.string().trim().min(1).optional().describe("Git base used for changed-test selection"),
|
|
37
|
+
});
|
|
29
38
|
|
|
30
39
|
const PROJEN_INTEGRATION_TEST =
|
|
31
40
|
/(?:local-publish|npm-release|packed-consumer|project-py|publish|python-sync|release|root-install|sdk-boundary).*\.test\.ts$/;
|
|
@@ -155,7 +164,8 @@ function selectedTests(
|
|
|
155
164
|
root: string,
|
|
156
165
|
graph: WorkspaceGraph,
|
|
157
166
|
mode: TestMode,
|
|
158
|
-
|
|
167
|
+
selections: readonly string[],
|
|
168
|
+
base?: string,
|
|
159
169
|
): string[] {
|
|
160
170
|
const all = [
|
|
161
171
|
...graph.packages.flatMap((pkg) => testFiles(join(root, pkg.path, "test"))),
|
|
@@ -167,14 +177,13 @@ function selectedTests(
|
|
|
167
177
|
|
|
168
178
|
let names: Set<string>;
|
|
169
179
|
if (mode === "changed") {
|
|
170
|
-
const
|
|
171
|
-
const changed = changedFiles(root, baseIndex >= 0 ? args[baseIndex + 1] : undefined);
|
|
180
|
+
const changed = changedFiles(root, base);
|
|
172
181
|
if (changed.length === 0) return [];
|
|
173
182
|
names = affectedPackages(graph, changed);
|
|
174
183
|
} else {
|
|
175
|
-
if (
|
|
184
|
+
if (selections.length === 0) throw new Error("test:focused requires a package name or path");
|
|
176
185
|
names = new Set<string>();
|
|
177
|
-
for (const value of
|
|
186
|
+
for (const value of selections) {
|
|
178
187
|
const direct = graph.packages.find((pkg) => pkg.name === value);
|
|
179
188
|
const byPath = direct ?? packageForPath(graph, toPosix(relative(root, resolve(root, value))));
|
|
180
189
|
if (!byPath) throw new Error(`Unknown workspace package or path: ${value}`);
|
|
@@ -239,15 +248,21 @@ async function runTests(root: string, files: readonly string[]): Promise<void> {
|
|
|
239
248
|
}
|
|
240
249
|
|
|
241
250
|
export async function main(argv: readonly string[] = process.argv.slice(2)): Promise<void> {
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
251
|
+
const command = taskCommand(
|
|
252
|
+
import.meta.url,
|
|
253
|
+
"Select and run workspace tests by dependency graph",
|
|
254
|
+
TestWorkspaceOptionsSchema,
|
|
255
|
+
)
|
|
256
|
+
.argument(`[mode]`, `Test mode: ${TEST_MODES.join(", ")}`, "all")
|
|
257
|
+
.argument("[selection...]", "Workspace package names or paths for focused mode");
|
|
258
|
+
const options = await taskOptions(command, TestWorkspaceOptionsSchema, argv);
|
|
259
|
+
const [modeValue = "all", selections = []] = taskPositionals(command) as [string?, string[]?];
|
|
260
|
+
const mode = z.enum(TEST_MODES).parse(modeValue);
|
|
261
|
+
const root = taskRoot(options.root);
|
|
247
262
|
const graph = workspaceGraph(root);
|
|
248
263
|
writeGraph(root, graph);
|
|
249
264
|
if (mode === "graph") return;
|
|
250
|
-
await runTests(root, selectedTests(root, graph, mode,
|
|
265
|
+
await runTests(root, selectedTests(root, graph, mode, selections, options.base));
|
|
251
266
|
}
|
|
252
267
|
|
|
253
|
-
|
|
268
|
+
await runTaskMain(import.meta, main);
|
package/tasks/ui-bundle-sizes.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
+
import { runTaskMain } from "./cli.ts";
|
|
2
3
|
|
|
3
4
|
const entries = {
|
|
4
5
|
auth: "packages/js/ui/appkit/src/auth/react/index.ts",
|
|
@@ -6,17 +7,21 @@ const entries = {
|
|
|
6
7
|
search: "packages/js/ui/appkit/src/search/react/index.ts",
|
|
7
8
|
} as const;
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
export async function main(): Promise<void> {
|
|
11
|
+
for (const [name, entry] of Object.entries(entries)) {
|
|
12
|
+
const result = await Bun.build({
|
|
13
|
+
entrypoints: [resolve(entry)],
|
|
14
|
+
target: "browser",
|
|
15
|
+
minify: true,
|
|
16
|
+
sourcemap: "none",
|
|
17
|
+
external: ["react", "react-dom", "@databricks/*", "@dbx-tools/shared-*", "lucide-react"],
|
|
18
|
+
});
|
|
19
|
+
if (!result.success) {
|
|
20
|
+
throw new AggregateError(result.logs, `Could not build the ${name} UI subpath`);
|
|
21
|
+
}
|
|
22
|
+
const bytes = result.outputs.reduce((total, output) => total + output.size, 0);
|
|
23
|
+
console.log(`${name}: ${bytes} bytes`);
|
|
19
24
|
}
|
|
20
|
-
const bytes = result.outputs.reduce((total, output) => total + output.size, 0);
|
|
21
|
-
console.log(`${name}: ${bytes} bytes`);
|
|
22
25
|
}
|
|
26
|
+
|
|
27
|
+
await runTaskMain(import.meta, main);
|
package/tasks/version-check.ts
CHANGED
|
@@ -6,6 +6,7 @@ import * as projectUtils from "@dbx-tools/core/project-utils";
|
|
|
6
6
|
import { find } from "@dbx-tools/path";
|
|
7
7
|
import { json, log } from "@dbx-tools/shared-core";
|
|
8
8
|
import { parse } from "smol-toml";
|
|
9
|
+
import { runTaskMain } from "./cli.ts";
|
|
9
10
|
import { recordedPackages } from "../src/packages.ts";
|
|
10
11
|
import { readWorkspaceVersion } from "../src/workspace-version.ts";
|
|
11
12
|
|
|
@@ -45,4 +46,4 @@ export function main(): void {
|
|
|
45
46
|
logger.success(`all workspace package versions match ${version}`);
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
await runTaskMain(import.meta, main);
|