@theholocron/cli 4.4.0 → 4.6.0

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 CHANGED
@@ -93,6 +93,21 @@ Writes `"holocron": "<holocronScript ?? 'holocron'>"` plus one
93
93
  `"<task>": "holocron run <task>"` per runnable task. `syncScripts: false`
94
94
  opts out entirely.
95
95
 
96
+ ### Lint parity
97
+
98
+ The `lint` task takes an optional `linters` array — one list that drives
99
+ **both** the CI `lint` job (super-linter's `VALIDATE_*` env, baked into the
100
+ generated `.github/workflows/lint.yml` thin caller as a `super-linter-env`
101
+ input) **and** `holocron run lint` locally. Omitted → auto-detected from the
102
+ config files present plus the org always-on set.
103
+
104
+ ```ts
105
+ export default defineConfig({
106
+ tasks: [{ name: "lint", linters: ["eslint", "prettier", "yamllint", "actionlint", "gitleaks"] }],
107
+ providers: { source: "github" },
108
+ });
109
+ ```
110
+
96
111
  ### Skills installer
97
112
 
98
113
  `holocron setup` can install shared skills from `@theholocron/skills` into the local repo:
package/dist/cli.mjs CHANGED
@@ -3,7 +3,8 @@ import { createRequire } from "node:module";
3
3
  import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
4
4
  import path, { basename, dirname, join, relative, resolve } from "node:path";
5
5
  import { checkbox, input, select } from "@inquirer/prompts";
6
- import { KNOWN_WORKFLOWS, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, createAstromech, deriveDeployPaths, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, normalizeWorkflowWith } from "@theholocron/astromech";
6
+ import { KNOWN_WORKFLOWS, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, createAstromech, deriveDeployPaths, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, lintThinCallerWith, normalizeWorkflowWith } from "@theholocron/astromech";
7
+ import { loadTasksConfig } from "@theholocron/astromech/config";
7
8
  import yargs from "yargs";
8
9
  import { hideBin } from "yargs/helpers";
9
10
  import { AuthError, ProviderApiError, ProviderApiError as ProviderApiError$1, createRestClient } from "@theholocron/http-client";
@@ -4371,10 +4372,21 @@ async function runSetup(input) {
4371
4372
  const name = typeof entry === "string" ? entry : entry.name;
4372
4373
  const rawWith = typeof entry === "object" ? entry.with : void 0;
4373
4374
  const normalized = rawWith ? normalizeWorkflowWith(rawWith) : void 0;
4374
- const withOverrides = name === "lint" ? {
4375
- "enable-auto-commit": true,
4376
- ...normalized ?? {}
4377
- } : normalized;
4375
+ let withOverrides = normalized;
4376
+ let comments;
4377
+ if (name === "lint") {
4378
+ let rootFiles = [];
4379
+ try {
4380
+ rootFiles = readdirSync(input.context.repoRoot);
4381
+ } catch {}
4382
+ const lint = lintThinCallerWith({
4383
+ explicit: typeof entry === "object" ? entry.linters : void 0,
4384
+ rootFiles,
4385
+ extra: normalized
4386
+ });
4387
+ withOverrides = lint.withOverrides;
4388
+ comments = lint.comments;
4389
+ }
4378
4390
  const additionalPaths = (typeof entry === "object" ? entry.paths : void 0) ?? (name === "deploy" && rawWith ? deriveDeployPaths(rawWith) : void 0);
4379
4391
  if (name === "test" && withOverrides) {
4380
4392
  const runUnit = withOverrides["run-unit"];
@@ -4406,7 +4418,7 @@ async function runSetup(input) {
4406
4418
  }
4407
4419
  }
4408
4420
  steps.push(await runStep("source", `write workflow ${name}`, dryRun, async () => {
4409
- await source.writeWorkflowFile(`${name}.yml`, `${workflowHeader$2()}${generateThinCallerContent(name, withOverrides, additionalPaths)}`);
4421
+ await source.writeWorkflowFile(`${name}.yml`, `${workflowHeader$2()}${generateThinCallerContent(name, withOverrides, additionalPaths, void 0, comments)}`);
4410
4422
  }));
4411
4423
  print(formatStep(steps[steps.length - 1]));
4412
4424
  }
@@ -5580,10 +5592,17 @@ async function runSync(input) {
5580
5592
  const name = typeof entry === "string" ? entry : entry.name;
5581
5593
  const rawWith = typeof entry === "object" ? entry.with : void 0;
5582
5594
  const normalized = rawWith ? normalizeWorkflowWith(rawWith) : void 0;
5583
- const withOverrides = name === "lint" ? {
5584
- "enable-auto-commit": true,
5585
- ...normalized ?? {}
5586
- } : normalized;
5595
+ let withOverrides = normalized;
5596
+ let comments;
5597
+ if (name === "lint") {
5598
+ const lint = lintThinCallerWith({
5599
+ explicit: typeof entry === "object" ? entry.linters : void 0,
5600
+ rootFiles: safeReaddir(input.context.repoRoot),
5601
+ extra: normalized
5602
+ });
5603
+ withOverrides = lint.withOverrides;
5604
+ comments = lint.comments;
5605
+ }
5587
5606
  const additionalPaths = (typeof entry === "object" ? entry.paths : void 0) ?? (name === "deploy" && rawWith ? deriveDeployPaths(rawWith) : void 0);
5588
5607
  if (!KNOWN_WORKFLOWS.has(name)) {
5589
5608
  steps.push({
@@ -5610,7 +5629,7 @@ async function runSync(input) {
5610
5629
  }
5611
5630
  }
5612
5631
  steps.push(await runSyncStep("local", `sync workflow ${name}`, dryRun, async () => {
5613
- const content = `${workflowHeader$1()}${generateThinCallerContent(name, withOverrides, additionalPaths)}`;
5632
+ const content = `${workflowHeader$1()}${generateThinCallerContent(name, withOverrides, additionalPaths, void 0, comments)}`;
5614
5633
  await writeWorkflowFile(input.context.repoRoot, `${name}.yml`, content);
5615
5634
  }));
5616
5635
  print(formatSyncStep(steps[steps.length - 1]));
@@ -5703,6 +5722,14 @@ function formatSyncStep(step) {
5703
5722
  const detail = step.message ? ` (${step.message})` : "";
5704
5723
  return ` ${icon} ${step.step}${detail}`;
5705
5724
  }
5725
+ /** Repo-root filenames for linter auto-detection; `[]` when the dir is unreadable. */
5726
+ function safeReaddir(dir) {
5727
+ try {
5728
+ return readdirSync(dir);
5729
+ } catch {
5730
+ return [];
5731
+ }
5732
+ }
5706
5733
  async function writePackageJsonField(repoRoot, field, value) {
5707
5734
  const pkgPath = join(repoRoot, "package.json");
5708
5735
  let content;
@@ -7038,11 +7065,13 @@ try {
7038
7065
  type: "boolean",
7039
7066
  default: false,
7040
7067
  describe: "Fail (exit 1) if this repo has no such task, instead of skipping."
7041
- }), (argv) => {
7068
+ }), async (argv) => {
7042
7069
  const { logger } = buildCliLogger(argv, { command: "run" });
7070
+ const config = await loadTasksConfig(argv.cwd).catch(() => void 0);
7043
7071
  const report = createAstromech({
7044
7072
  cwd: argv.cwd,
7045
- logger
7073
+ logger,
7074
+ config
7046
7075
  }).run(argv.task, {
7047
7076
  passthrough: argv.passthrough ?? [],
7048
7077
  dryRun: argv.dryRun,