@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 +15 -0
- package/dist/cli.mjs +42 -13
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +2 -0
- package/package.json +5 -5
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
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
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
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
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,
|