@theholocron/cli 3.24.0 → 3.24.2

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/cli.mjs CHANGED
@@ -2808,6 +2808,65 @@ function generateThinCallerContent(name, withOverrides, additionalPaths) {
2808
2808
  if (injected === result) console.warn(`[generateThinCallerContent] could not inject with: overrides into "${name}" template`);
2809
2809
  return injected;
2810
2810
  }
2811
+ /**
2812
+ * Expand structured with-values to flat GitHub Actions inputs before
2813
+ * generating the thin caller. Handles:
2814
+ * - deploy shorthand: docs/storybook → type + storybook-projects
2815
+ * - run-chromatic object → run-chromatic: true + chromatic-projects
2816
+ * - plain arrays → JSON-stringified for YAML scalar quoting
2817
+ *
2818
+ * Used by both `holocron setup` and `sync-workflow-templates`.
2819
+ */
2820
+ function normalizeWorkflowWith(raw) {
2821
+ const result = { ...raw };
2822
+ const hasDocs = raw["docs"] === true || raw["docs"] !== null && typeof raw["docs"] === "object";
2823
+ const storybookProjects = raw["storybook"];
2824
+ if (hasDocs) {
2825
+ result["type"] = "docs";
2826
+ delete result["docs"];
2827
+ }
2828
+ if (Array.isArray(storybookProjects)) {
2829
+ if (!hasDocs) result["type"] = "storybook";
2830
+ result["storybook-projects"] = JSON.stringify(storybookProjects.map(({ name, path = "." }) => ({
2831
+ name,
2832
+ workingDir: path
2833
+ })));
2834
+ delete result["storybook"];
2835
+ }
2836
+ const runChromatic = raw["run-chromatic"];
2837
+ if (runChromatic !== null && typeof runChromatic === "object" && "projects" in runChromatic) {
2838
+ result["run-chromatic"] = true;
2839
+ const projects = runChromatic.projects.map((p) => ({
2840
+ ...p,
2841
+ ...Array.isArray(p.untraced) ? { untraced: p.untraced.join("\n") } : {}
2842
+ }));
2843
+ result["chromatic-projects"] = JSON.stringify(projects);
2844
+ }
2845
+ for (const [k, v] of Object.entries(result)) if (Array.isArray(v)) result[k] = JSON.stringify(v);
2846
+ return result;
2847
+ }
2848
+ /**
2849
+ * Derive on.push.paths entries from the deploy with: shorthand.
2850
+ * Used by both `holocron setup` and `sync-workflow-templates`.
2851
+ */
2852
+ function deriveDeployPaths(raw) {
2853
+ const paths = [];
2854
+ const docs = raw["docs"];
2855
+ if (docs === true) paths.push("docs/**");
2856
+ else if (docs !== null && typeof docs === "object" && "path" in docs) {
2857
+ const p = docs.path;
2858
+ if (p && p !== ".") paths.push(`${p}/**`);
2859
+ }
2860
+ const storybookProjects = raw["storybook"];
2861
+ if (Array.isArray(storybookProjects)) for (const s of storybookProjects) {
2862
+ const p = s.path || ".";
2863
+ if (p === ".") {
2864
+ paths.push("src/**");
2865
+ paths.push(".storybook/**");
2866
+ } else paths.push(`${p}/**`);
2867
+ }
2868
+ return paths;
2869
+ }
2811
2870
  //#endregion
2812
2871
  //#region src/commands/setup.ts
2813
2872
  /**
@@ -3264,52 +3323,6 @@ async function runSetup(input) {
3264
3323
  print(formatStep(steps[steps.length - 1]));
3265
3324
  }
3266
3325
  }
3267
- function normalizeWorkflowWith(raw) {
3268
- const result = { ...raw };
3269
- const hasDocs = raw["docs"] === true || raw["docs"] !== null && typeof raw["docs"] === "object";
3270
- const storybookProjects = raw["storybook"];
3271
- if (hasDocs) {
3272
- result["type"] = "docs";
3273
- delete result["docs"];
3274
- }
3275
- if (Array.isArray(storybookProjects)) {
3276
- if (!hasDocs) result["type"] = "storybook";
3277
- result["storybook-projects"] = JSON.stringify(storybookProjects.map(({ name, path = "." }) => ({
3278
- name,
3279
- workingDir: path
3280
- })));
3281
- delete result["storybook"];
3282
- }
3283
- const runChromatic = raw["run-chromatic"];
3284
- if (runChromatic !== null && typeof runChromatic === "object" && "projects" in runChromatic) {
3285
- result["run-chromatic"] = true;
3286
- const projects = runChromatic.projects.map((p) => ({
3287
- ...p,
3288
- ...Array.isArray(p.untraced) ? { untraced: p.untraced.join("\n") } : {}
3289
- }));
3290
- result["chromatic-projects"] = JSON.stringify(projects);
3291
- }
3292
- for (const [k, v] of Object.entries(result)) if (Array.isArray(v)) result[k] = JSON.stringify(v);
3293
- return result;
3294
- }
3295
- function deriveDeployPaths(raw) {
3296
- const paths = [];
3297
- const docs = raw["docs"];
3298
- if (docs === true) paths.push("docs/**");
3299
- else if (docs !== null && typeof docs === "object" && "path" in docs) {
3300
- const p = docs.path;
3301
- if (p && p !== ".") paths.push(`${p}/**`);
3302
- }
3303
- const storybookProjects = raw["storybook"];
3304
- if (Array.isArray(storybookProjects)) for (const s of storybookProjects) {
3305
- const p = s.path || ".";
3306
- if (p === ".") {
3307
- paths.push("src/**");
3308
- paths.push(".storybook/**");
3309
- } else paths.push(`${p}/**`);
3310
- }
3311
- return paths;
3312
- }
3313
3326
  const workflows = config.workflows;
3314
3327
  if (loader.has("source") && workflows && workflows.length > 0) {
3315
3328
  const source = loader.get("source");
@@ -4233,7 +4246,7 @@ var setup_default = "name: Setup\ndescription: Prepare the environment and insta
4233
4246
  var setup_node_default = "name: Setup Node\ndescription: Install pnpm and Node.js with pnpm dependency caching.\n\ninputs:\n node-version:\n description: Node.js version\n required: false\n default: \"22.x\"\nruns:\n using: composite\n\n steps:\n - name: Setup pnpm\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4\n\n - name: Setup Node.js\n uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0\n with:\n node-version: ${{ hashFiles('.node-version') != '' && '' || inputs.node-version }}\n node-version-file: ${{ hashFiles('.node-version') != '' && '.node-version' || '' }}\n cache: ${{ hashFiles('pnpm-lock.yaml') != '' && 'pnpm' || '' }}\n # Do NOT add registry-url here. setup-node writes .npmrc with\n # _authToken=${NODE_AUTH_TOKEN} and sets NPM_CONFIG_USERCONFIG to it.\n # pnpm reads that file, fails env-var substitution when the token is\n # empty, and loses auth entirely. Without registry-url, pnpm 10.15+\n # handles Trusted Publishing via its own native OIDC exchange.\n\n - name: Add node_modules/.bin to PATH\n shell: bash\n run: echo \"$GITHUB_WORKSPACE/node_modules/.bin\" >> $GITHUB_PATH\n";
4234
4247
  //#endregion
4235
4248
  //#region src/templates/workflows/audit.yml
4236
- var audit_default = "name: Audit\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n build-script:\n description: Script to build and upload bundle stats to Codecov\n type: string\n required: false\n default: pnpm build\n run-knip:\n description: Run Knip to detect unused files, exports, and dependencies\n type: boolean\n required: false\n default: false\n run-performance:\n description: Run Lighthouse CI performance audit (requires a lighthouse config file)\n type: boolean\n required: false\n default: false\n lighthouse-config:\n description: >\n Path to the Lighthouse CI config file passed as --config to lhci autorun.\n Defaults to lighthouse.config.js (the org standard).\n type: string\n required: false\n default: lighthouse.config.js\n knip-script:\n description: Script that invokes Knip (must exit non-zero on findings)\n type: string\n required: false\n default: pnpm run audit\n secrets:\n CODECOV_TOKEN:\n required: false\n LHCI_GITHUB_APP_TOKEN:\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n bundle-size:\n name: Audit the bundle size\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$BUILD_SCRIPT\"\n name: Build and upload bundle stats\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n\n knip:\n name: Knip\n if: ${{ inputs.run-knip }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n persist-credentials: false\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$KNIP_SCRIPT\"\n name: Run Knip\n env:\n KNIP_SCRIPT: ${{ inputs.knip-script }}\n\n performance:\n name: Audit the performance\n if: ${{ inputs.run-performance }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: npm install -g @lhci/cli@0.14.x\n name: Install Lighthouse CLI\n\n - run: lhci autorun --config=\"$LIGHTHOUSE_CONFIG\"\n name: Run Lighthouse CI\n env:\n LIGHTHOUSE_CONFIG: ${{ inputs.lighthouse-config }}\n LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}\n";
4249
+ var audit_default = "name: Audit\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n build-script:\n description: Script to build and upload bundle stats to Codecov\n type: string\n required: false\n default: pnpm build\n run-knip:\n description: Run Knip to detect unused files, exports, and dependencies\n type: boolean\n required: false\n default: false\n run-performance:\n description: Run Lighthouse CI performance audit (requires a lighthouse config file)\n type: boolean\n required: false\n default: false\n lighthouse-config:\n description: >\n Path to the Lighthouse CI config file passed as --config to lhci autorun.\n Defaults to lighthouse.config.cjs (the org standard).\n type: string\n required: false\n default: lighthouse.config.cjs\n knip-script:\n description: Script that invokes Knip (must exit non-zero on findings)\n type: string\n required: false\n default: pnpm run audit\n secrets:\n CODECOV_TOKEN:\n required: false\n LHCI_GITHUB_APP_TOKEN:\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n bundle-size:\n name: Audit the bundle size\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$BUILD_SCRIPT\"\n name: Build and upload bundle stats\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n\n knip:\n name: Knip\n if: ${{ inputs.run-knip }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n persist-credentials: false\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$KNIP_SCRIPT\"\n name: Run Knip\n env:\n KNIP_SCRIPT: ${{ inputs.knip-script }}\n\n performance:\n name: Audit the performance\n if: ${{ inputs.run-performance }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: npm install -g @lhci/cli@0.14.x\n name: Install Lighthouse CLI\n\n - run: lhci autorun --config=\"$LIGHTHOUSE_CONFIG\"\n name: Run Lighthouse CI\n env:\n LIGHTHOUSE_CONFIG: ${{ inputs.lighthouse-config }}\n LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}\n";
4237
4250
  //#endregion
4238
4251
  //#region src/templates/workflows/bookkeeping.yml
4239
4252
  var bookkeeping_default = "name: Bookkeeping\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n configuration-path:\n description: Path to the labeler configuration file in the calling repo\n type: string\n required: false\n default: .github/labeler.yml\n\njobs:\n label:\n name: Apply Labels\n permissions:\n contents: read\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n sparse-checkout: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n sparse-checkout-cone-mode: false\n\n - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4\n if: ${{ github.event_name == 'pull_request' && hashFiles(inputs.configuration-path || '.github/labeler.yml') != '' }}\n # v3.4 bundles Node 20; allow it to run under Actions' current default.\n env:\n ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true\n with:\n # Fall back to default path when triggered directly (not via workflow_call)\n # because inputs.* defaults only apply on workflow_call events.\n configuration-path: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n include-title: 1\n include-body: 0\n sync-labels: 1\n enable-versioned-regex: 0\n repo-token: ${{ github.token }}\n";
@@ -4327,13 +4340,14 @@ function parseWorkflowsFromTs(source) {
4327
4340
  const body = source.slice(start, i - 1);
4328
4341
  const entries = [];
4329
4342
  const objSpans = [];
4330
- const objRe = /\{\s*name\s*:\s*"([^"]+)"(?:\s*,\s*with\s*:\s*(\{[^}]*\}))?\s*\}/g;
4343
+ const objRe = /\{\s*name\s*:\s*"([^"]+)"(?:\s*,\s*with\s*:\s*(\{[^}]*\}))?\s*,?\s*\}/g;
4331
4344
  let m;
4332
4345
  while ((m = objRe.exec(body)) !== null) {
4333
4346
  objSpans.push([m.index, m.index + m[0].length]);
4334
4347
  let withObj;
4335
4348
  if (m[2]) try {
4336
- withObj = JSON.parse(m[2]);
4349
+ const jsonSafe = m[2].replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g, "$1\"$2\":");
4350
+ withObj = JSON.parse(jsonSafe);
4337
4351
  } catch {}
4338
4352
  entries.push({
4339
4353
  pos: m.index,
@@ -4395,7 +4409,8 @@ function buildBatch(repo, allowedWorkflows, withOverrides) {
4395
4409
  }
4396
4410
  } else for (const name of Object.keys(REUSABLE_WORKFLOWS)) {
4397
4411
  if (allowedWorkflows && !allowedWorkflows.has(name)) continue;
4398
- const content = generateThinCallerContent(name, withOverrides?.get(name));
4412
+ const rawWith = withOverrides?.get(name);
4413
+ const content = generateThinCallerContent(name, rawWith ? normalizeWorkflowWith(rawWith) : void 0, name === "deploy" && rawWith ? deriveDeployPaths(rawWith) : void 0);
4399
4414
  if (!content) continue;
4400
4415
  files.push({
4401
4416
  path: `.github/workflows/${name}.yml`,