@theholocron/astromech 5.0.0-alpha.10 → 5.0.0-alpha.12

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/dist/index.d.mts CHANGED
@@ -221,6 +221,12 @@ declare function normalizeWorkflowWith(raw: Record<string, unknown>): Record<str
221
221
  */
222
222
  declare function deriveDeployPaths(raw: Record<string, unknown>): string[];
223
223
  //#endregion
224
+ //#region src/turbo.d.ts
225
+ interface EnsureRootWorkspaceMemberResult {
226
+ content: string;
227
+ changed: boolean;
228
+ }
229
+ //#endregion
224
230
  //#region src/astromech.d.ts
225
231
  interface AstromechOptions {
226
232
  /** Repo root. */
@@ -315,6 +321,17 @@ interface Astromech {
315
321
  * config (nothing to write). See {@link TurboTaskConfig} in `registry.ts`.
316
322
  */
317
323
  turboConfig(): string | null;
324
+ /**
325
+ * Fixes #692: whenever {@link turboConfig} isn't `null`, this repo's root
326
+ * package needs to actually be a workspace member for the tasks it fans
327
+ * out — otherwise a root that's genuinely a directly-buildable package
328
+ * (not just an orchestrator) silently vanishes from `turbo run <task>`.
329
+ * Pass `pnpm-workspace.yaml`'s current content (or `""` if none exists —
330
+ * a no-op either way, since no `packages:` key means single-package mode
331
+ * already) and root `package.json`'s own `scripts` keys. `changed: false`
332
+ * means don't write anything — the file is already correct.
333
+ */
334
+ ensureRootWorkspaceMember(workspaceYaml: string, rootScripts: readonly string[]): EnsureRootWorkspaceMemberResult;
318
335
  }
319
336
  declare function createAstromech(options: AstromechOptions): Astromech;
320
337
  //#endregion
package/dist/index.mjs CHANGED
@@ -823,7 +823,7 @@ const WORKFLOW_TEMPLATES = {
823
823
  "platform.repoValidation": "name: Platform\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\npermissions:\n contents: read\n\njobs:\n repo-validation:\n name: Repo Validation\n uses: theholocron/.github/.github/workflows/platform.repoValidation.yml@main\n secrets: inherit\n",
824
824
  "knowledge.wiki": "name: Knowledge\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\nconcurrency:\n group: ${{ github.event_name == 'pull_request' && format('wiki-preview-{0}', github.event.pull_request.number) || 'wiki' }}\n cancel-in-progress: ${{ github.event_name == 'pull_request' }}\n\npermissions:\n contents: read\n deployments: write\n\njobs:\n publish:\n name: Publish\n if: ${{ github.event_name != 'pull_request' }}\n uses: theholocron/.github/.github/workflows/knowledge.wiki.yml@main\n secrets: inherit\n\n preview:\n name: Preview\n if: ${{ github.event_name == 'pull_request' }}\n uses: theholocron/.github/.github/workflows/knowledge.wiki.yml@main\n with:\n preview: true\n preview-id: pr-${{ github.event.pull_request.number }}\n secrets: inherit\n",
825
825
  preview: "name: Preview\n\non: # yamllint disable-line rule:truthy\n pull_request:\n branches: [main]\n\nconcurrency:\n group: preview-${{ github.event.pull_request.number }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n deployments: write\n pull-requests: write\n\njobs:\n preview:\n name: Preview\n uses: theholocron/.github/.github/workflows/preview.yml@main\n secrets: inherit\n",
826
- review: "name: Review\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\nconcurrency:\n group: review-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n checks: write\n pull-requests: write\n\njobs:\n review:\n name: Lint Annotations\n uses: theholocron/.github/.github/workflows/review.yml@main\n secrets: inherit\n",
826
+ review: "name: Source Quality\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\nconcurrency:\n group: review-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n checks: write\n pull-requests: write\n\njobs:\n review:\n name: Annotations\n uses: theholocron/.github/.github/workflows/review.yml@main\n secrets: inherit\n",
827
827
  stale: "name: Stale\n\non: # yamllint disable-line rule:truthy\n schedule:\n - cron: \"30 1 * * *\"\n\npermissions:\n contents: write\n issues: write\n pull-requests: write\n\njobs:\n stale:\n uses: theholocron/.github/.github/workflows/stale.yml@main\n with:\n exempt-issue-labels: \"in-progress,wip\"\n exempt-all-issue-milestones: true\n exempt-all-issue-projects: true\n exempt-all-pr-projects: true\n secrets: inherit\n",
828
828
  greetings: "name: Platform\n\non: # yamllint disable-line rule:truthy\n pull_request:\n issues:\n\npermissions:\n issues: write\n pull-requests: write\n\njobs:\n greetings:\n name: Greetings\n uses: theholocron/.github/.github/workflows/greetings.yml@main\n secrets: inherit\n",
829
829
  dependencies: "name: Platform\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n dependencies:\n name: Dependencies\n uses: theholocron/.github/.github/workflows/dependencies.yml@main\n secrets: inherit\n",
@@ -1444,6 +1444,72 @@ function turboConfig(config) {
1444
1444
  tasks
1445
1445
  }, null, 2)}\n`;
1446
1446
  }
1447
+ /**
1448
+ * Fixes #692: `turboConfig()` writes a `turbo.json` the moment *any* task in
1449
+ * the manifest has fan-out config — with no check for whether the repo's own
1450
+ * root package is actually covered by `pnpm-workspace.yaml`'s `packages:`
1451
+ * list. A repo shaped like `observability` (the library lives at repo root;
1452
+ * `packages:` lists only an unrelated `docs` site) silently breaks the
1453
+ * instant `turbo.json` exists: `holocron run <task>` switches from running
1454
+ * root's own script directly to `turbo run <task>`, which only sees declared
1455
+ * workspace members — root vanishes, the task "succeeds" with zero real work
1456
+ * done (confirmed empirically: `Packages in scope: docs`, root never
1457
+ * mentioned, exit 0).
1458
+ *
1459
+ * Detection is narrow and specific: root only needs to be an explicit
1460
+ * workspace member if its *own* `package.json` has a script literally named
1461
+ * after one of the tasks turbo.json is about to fan out — a plain
1462
+ * orchestrator root (`holocron`'s own `"build": "turbo run delivery.build"`,
1463
+ * which has no `delivery.build` script itself) never trips this; only a root
1464
+ * that's genuinely a directly-buildable package does. Confirmed the fix
1465
+ * empirically too — adding `.` to `packages:` makes turbo pick root back up
1466
+ * (`Packages in scope: docs, root-lib`) without disturbing the sibling
1467
+ * package's own caching.
1468
+ *
1469
+ * A targeted line-based edit, not a full YAML parse/reserialize — same
1470
+ * pattern `codecov.ts`'s `mergeCodecovComponents()` already uses for editing
1471
+ * an existing generated file. `pnpm-workspace.yaml` routinely carries a
1472
+ * `catalog:`/`catalogs:`/`overrides:` block after `packages:`; a real parser
1473
+ * round-trip risks reformatting or reordering content nobody asked to touch.
1474
+ * Only ever *adds* a line — never rewrites or reorders anything already
1475
+ * there — and is a no-op (`changed: false`) whenever root doesn't need it,
1476
+ * root is already listed, or `packages:` isn't in the plain block-list form
1477
+ * every repo checked actually uses.
1478
+ */
1479
+ function ensureRootWorkspaceMember(workspaceYaml, rootScripts, taskNames) {
1480
+ if (!taskNames.some((t) => rootScripts.includes(t))) return {
1481
+ content: workspaceYaml,
1482
+ changed: false
1483
+ };
1484
+ const lines = workspaceYaml.split("\n");
1485
+ const packagesLineIdx = lines.findIndex((l) => /^packages:\s*$/.test(l));
1486
+ if (packagesLineIdx === -1) return {
1487
+ content: workspaceYaml,
1488
+ changed: false
1489
+ };
1490
+ const items = [];
1491
+ let cursor = packagesLineIdx + 1;
1492
+ while (cursor < lines.length && /^\s*-\s*/.test(lines[cursor])) {
1493
+ items.push(lines[cursor]);
1494
+ cursor++;
1495
+ }
1496
+ if (items.some((item) => {
1497
+ const value = item.replace(/^\s*-\s*/, "").replace(/^["']|["']$/g, "").trim();
1498
+ return value === "." || value === "";
1499
+ })) return {
1500
+ content: workspaceYaml,
1501
+ changed: false
1502
+ };
1503
+ const newLine = `${items[0]?.match(/^(\s*-\s*)/)?.[1] ?? " - "}"."`;
1504
+ return {
1505
+ content: [
1506
+ ...lines.slice(0, packagesLineIdx + 1),
1507
+ newLine,
1508
+ ...lines.slice(packagesLineIdx + 1)
1509
+ ].join("\n"),
1510
+ changed: true
1511
+ };
1512
+ }
1447
1513
  //#endregion
1448
1514
  //#region src/astromech.ts
1449
1515
  /**
@@ -1546,7 +1612,10 @@ function createAstromech(options) {
1546
1612
  reusableTemplates: () => reusableTemplates(),
1547
1613
  requiredChecks: () => requiredChecks(options.config ?? {}),
1548
1614
  codecovConfig: (existing) => codecovConfig(options.cwd, existing),
1549
- turboConfig: () => turboConfig(options.config ?? {})
1615
+ turboConfig: () => turboConfig(options.config ?? {}),
1616
+ ensureRootWorkspaceMember: (workspaceYaml, rootScripts) => {
1617
+ return ensureRootWorkspaceMember(workspaceYaml, rootScripts, (options.config?.tasks ?? []).map(normalizeTaskEntry).filter((e) => e.local !== false).map((e) => e.name));
1618
+ }
1550
1619
  };
1551
1620
  }
1552
1621
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/astromech",
3
- "version": "5.0.0-alpha.10",
3
+ "version": "5.0.0-alpha.12",
4
4
  "description": "The Holocron task runner — one task manifest drives `holocron run`, `holocron ci`, the CI workflows, package.json scripts, linters, and required checks.",
5
5
  "keywords": [
6
6
  "ci",
@@ -37,7 +37,7 @@
37
37
  "dist"
38
38
  ],
39
39
  "dependencies": {
40
- "@theholocron/datapad": "5.0.0-alpha.10"
40
+ "@theholocron/datapad": "5.0.0-alpha.12"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@theholocron/eslint-config": "^8.0.0",
@@ -53,7 +53,7 @@
53
53
  "tsdown": "^0.22.14",
54
54
  "typescript": "^5.9.3",
55
55
  "vitest": "^4.1.11",
56
- "@theholocron/rollup-plugin-transform-template": "5.0.0-alpha.10"
56
+ "@theholocron/rollup-plugin-transform-template": "5.0.0-alpha.12"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">=22"