@theholocron/cli 5.0.0-alpha.128 → 5.0.0-alpha.129

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
@@ -54,11 +54,11 @@ entirely, straight to the real run, for when you already know what you want.
54
54
 
55
55
  Every command is tagged with how much of a repo it needs:
56
56
 
57
- | Context | Needs | Examples |
58
- | ------------ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
59
- | `global` | the CLI binary alone | `version`, `clone`, `new`, `upgrade node`, `auth set` / `check`, `plugin create`, `skills …` |
60
- | `repo-aware` | `./holocron.config`, walking up from cwd, no plugins | `run`, `ci`, `config show`, `sync-readme` |
61
- | `workspace` | the `@theholocron/holocron-plugin-*` packages resolvable | `doctor`, `setup`, `sync`, `secrets sync`, `deploy` |
57
+ | Context | Needs | Examples |
58
+ | ------------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
59
+ | `global` | the CLI binary alone | `version`, `clone`, `new`, `upgrade node`, `auth set` / `check`, `plugin create`, `run lint commit-msg`, `skills …` |
60
+ | `repo-aware` | `./holocron.config`, walking up from cwd, no plugins | `run`, `run ci`, `config show`, `sync-readme` |
61
+ | `workspace` | the `@theholocron/holocron-plugin-*` packages resolvable | `doctor`, `setup`, `sync`, `secrets sync`, `deploy` |
62
62
 
63
63
  A `workspace` command run from a bare global install (no plugins next to the
64
64
  CLI) fails with one actionable line — install the plugins as devDependencies or
@@ -252,7 +252,7 @@ export default defineConfig({
252
252
  });
253
253
  ```
254
254
 
255
- `holocron setup` writes `.husky/pre-push` (runs `holocron ci` before every
255
+ `holocron setup` writes `.husky/pre-push` (runs `holocron run ci` before every
256
256
  push) and `.husky/pre-commit` (runs `gitleaks protect --staged` + `lint-staged`
257
257
  before every commit — scoped to staged changes, not the whole history, so a
258
258
  past false positive can't permanently block future commits) and sets
@@ -298,7 +298,7 @@ export default defineConfig({
298
298
  `@theholocron/astromech`'s `loadTasksConfig` merges it over
299
299
  `holocron.config`'s `tasks` — **task arrays concatenate**
300
300
  (`holocron.config` first), the dedicated file **wins on scalars**,
301
- `extraRequiredChecks` concatenate. `holocron run` / `holocron ci` /
301
+ `extraRequiredChecks` concatenate. `holocron run` / `holocron run ci` /
302
302
  `holocron setup` / `holocron sync` all read the merged result, so the
303
303
  split is transparent. Useful for keeping the capability/provider config
304
304
  and the "what this repo runs" manifest in separate files (this repo does).
@@ -343,10 +343,10 @@ delivery.deploy`. A package that doesn't apply is skipped; a failed deploy
343
343
  exits non-zero. The shared `delivery.publish` workflow runs it as its own
344
344
  `deploy` job after the release job (opt in with `deploy-on-release: true`).
345
345
 
346
- ### `holocron ci`
346
+ ### `holocron run ci`
347
347
 
348
348
  ```bash
349
- holocron ci [--all] [--filter <pkg>] [--dry-run]
349
+ holocron run ci [--all] [--filter <pkg>] [--dry-run]
350
350
  ```
351
351
 
352
352
  Runs the merge-gating checks locally, in CI order, exiting non-zero on the
@@ -466,7 +466,7 @@ export default acmeConfig;
466
466
  shape (`const { repo, workflows } = node()` + `repo.requiredChecks` +
467
467
  `workflows:`) to the current composed-preset API (`const preset = node()` +
468
468
  `...preset` + `tasks:` + `extraRequiredChecks:`). Mechanical transforms only —
469
- review the result, then `pnpm install && holocron ci`. `--pins-only` skips
469
+ review the result, then `pnpm install && holocron run ci`. `--pins-only` skips
470
470
  the config migration; `--dry-run` prints without writing.
471
471
 
472
472
  ## Auth — fine-grained tokens
package/dist/cli.mjs CHANGED
@@ -330,9 +330,9 @@ const COMMAND_CONTEXTS = {
330
330
  "skills install": "global",
331
331
  "skills remove": "global",
332
332
  "skills update": "global",
333
- "lint commit-msg": "global",
333
+ "run lint commit-msg": "global",
334
334
  run: "repo-aware",
335
- ci: "repo-aware",
335
+ "run ci": "repo-aware",
336
336
  "deploy-on-release": "repo-aware",
337
337
  "config show": "repo-aware",
338
338
  "sync-readme": "repo-aware",
@@ -4521,12 +4521,12 @@ function createIgnoreConfig$1() {
4521
4521
  }
4522
4522
  //#endregion
4523
4523
  //#region src/templates/configs/commit-msg/commit-msg
4524
- var commit_msg_default = "__HOLOCRON_SCRIPT__ lint commit-msg \"$1\"\n";
4524
+ var commit_msg_default = "__HOLOCRON_SCRIPT__ run lint commit-msg \"$1\"\n";
4525
4525
  //#endregion
4526
4526
  //#region src/templates/configs/commit-msg/create-config.ts
4527
4527
  const { workflowHeader: workflowHeader$8 } = createHeader({ source: "packages/cli/src/templates/configs/commit-msg/create-config.ts" });
4528
4528
  /**
4529
- * `.husky/commit-msg` — lints the commit message via `holocron lint
4529
+ * `.husky/commit-msg` — lints the commit message via `holocron run lint
4530
4530
  * commit-msg` (holocron#789), the real programmatic replacement for
4531
4531
  * shelling out to `commitlint --edit`. Installed by `holocron setup` when
4532
4532
  * hooks are enabled. Same `__HOLOCRON_SCRIPT__` substitution as `pre-push`.
@@ -4623,12 +4623,12 @@ function createConfig$3() {
4623
4623
  }
4624
4624
  //#endregion
4625
4625
  //#region src/templates/configs/pre-push/pre-push
4626
- var pre_push_default = "# Run the merge-gating checks locally before pushing — the same set CI runs.\n# Bypass once with: git push --no-verify\n\n# CI runners (semantic-release, super-linter auto-commit, bots) push without a\n# built dev environment — the hook has nothing to add there.\n[ -n \"$CI\" ] && exit 0\n\n__HOLOCRON_SCRIPT__ ci\n";
4626
+ var pre_push_default = "# Run the merge-gating checks locally before pushing — the same set CI runs.\n# Bypass once with: git push --no-verify\n\n# CI runners (semantic-release, super-linter auto-commit, bots) push without a\n# built dev environment — the hook has nothing to add there.\n[ -n \"$CI\" ] && exit 0\n\n__HOLOCRON_SCRIPT__ run ci\n";
4627
4627
  //#endregion
4628
4628
  //#region src/templates/configs/pre-push/create-config.ts
4629
4629
  const { workflowHeader: workflowHeader$4 } = createHeader({ source: "packages/cli/src/templates/configs/pre-push/create-config.ts" });
4630
4630
  /**
4631
- * `.husky/pre-push` — runs `holocron ci` (the merge-gating checks, in CI order)
4631
+ * `.husky/pre-push` — runs `holocron run ci` (the merge-gating checks, in CI order)
4632
4632
  * before every push. Installed by `holocron setup` when hooks are enabled
4633
4633
  * (default for `protection: "strict"`). `git push --no-verify` bypasses it.
4634
4634
  *
@@ -5647,7 +5647,7 @@ async function runSetup(input) {
5647
5647
  if (hooksEnabled) {
5648
5648
  steps.push(await runStep("source", "write .husky/pre-push", dryRun, async () => {
5649
5649
  await source.writeRepoFile(".husky/pre-push", createConfig$2(config.holocronScript));
5650
- return "runs `holocron ci` before push — bypass with `git push --no-verify`";
5650
+ return "runs `holocron run ci` before push — bypass with `git push --no-verify`";
5651
5651
  }));
5652
5652
  print(formatStep(steps[steps.length - 1]));
5653
5653
  steps.push(await runStep("source", "write .husky/pre-commit", dryRun, async () => {
@@ -7614,7 +7614,7 @@ async function runSyncGithub(input) {
7614
7614
  * This applies the mechanical transforms and flags anything that needs a
7615
7615
  * human eye.
7616
7616
  *
7617
- * After running, `pnpm install && holocron ci`.
7617
+ * After running, `pnpm install && holocron run ci`.
7618
7618
  */
7619
7619
  const FETCH_TIMEOUT_MS$1 = 4e3;
7620
7620
  /** Resolve a package's `latest` dist-tag from the npm registry. */
@@ -7681,7 +7681,7 @@ function isLegacyConfig(content) {
7681
7681
  }
7682
7682
  /**
7683
7683
  * Apply the mechanical 7.x → 8.x transforms to a `holocron.config.ts`. Best
7684
- * effort — the result should always be reviewed and run through `holocron ci`.
7684
+ * effort — the result should always be reviewed and run through `holocron run ci`.
7685
7685
  */
7686
7686
  function migrateConfig(content) {
7687
7687
  const transforms = [];
@@ -7807,7 +7807,7 @@ async function runUpgradeDeps(input = {}) {
7807
7807
  print("");
7808
7808
  if (bumps.length === 0 && !configMigrated) print("Nothing to do — already up to date.");
7809
7809
  else {
7810
- print(`Next: ${dryRun ? "run without --dry-run, then " : ""}\`pnpm install && holocron ci\``);
7810
+ print(`Next: ${dryRun ? "run without --dry-run, then " : ""}\`pnpm install && holocron run ci\``);
7811
7811
  if (configMigrated) print(" review holocron.config.ts before committing.");
7812
7812
  }
7813
7813
  const status = dryRun ? "dry-run" : "ok";
@@ -8050,7 +8050,7 @@ async function lintCommitMessage(message, loaded) {
8050
8050
  //#endregion
8051
8051
  //#region src/commit-lint/lint-commit-msg-file.ts
8052
8052
  /**
8053
- * `holocron lint commit-msg <file>` — a real programmatic replacement for
8053
+ * `holocron run lint commit-msg <file>` — a real programmatic replacement for
8054
8054
  * shelling out to `commitlint --edit "$1"` from `.husky/commit-msg`
8055
8055
  * (holocron#789). Matches that CLI's own contract exactly: `file` is a
8056
8056
  * path to the commit message being written (the arg git's `commit-msg`
@@ -8194,9 +8194,10 @@ const numeric = (value) => /^\d+$/.test(value) ? true : "enter a number";
8194
8194
  * The full command surface, hand-maintained in parallel with `cli.ts`'s
8195
8195
  * yargs registrations (this module does not introspect yargs at runtime).
8196
8196
  * `run <task>` is deliberately excluded — it's CI/scripting-oriented, and an
8197
- * interactive prompt in front of it would work against that. `lint
8198
- * commit-msg <file>` is excluded for the same reason: it's invoked
8199
- * exclusively from `.husky/commit-msg "$1"`, never typed by a human.
8197
+ * interactive prompt in front of it would work against that. (`run ci` is a
8198
+ * concrete, prompt-free entry, so it stays.) `run lint commit-msg <file>` is
8199
+ * excluded for the same reason: it's invoked exclusively from
8200
+ * `.husky/commit-msg "$1"`, never typed by a human.
8200
8201
  */
8201
8202
  const COMMAND_REGISTRY = [
8202
8203
  {
@@ -8287,7 +8288,7 @@ const COMMAND_REGISTRY = [
8287
8288
  supportsDryRun: true
8288
8289
  },
8289
8290
  {
8290
- name: "ci",
8291
+ name: "run ci",
8291
8292
  description: "Run the merge-gating checks locally, in CI order — 'will CI pass?'",
8292
8293
  positionals: [],
8293
8294
  supportsDryRun: true
@@ -9165,7 +9166,7 @@ try {
9165
9166
  describe: "Repo coords (\"owner/name\"). Defaults to plugin-specific resolution."
9166
9167
  }).option("hooks", {
9167
9168
  type: "boolean",
9168
- describe: "Install git hooks (.husky/pre-push → holocron ci). Default: on for protection:'strict'. --no-hooks to skip."
9169
+ describe: "Install git hooks (.husky/pre-push → holocron run ci). Default: on for protection:'strict'. --no-hooks to skip."
9169
9170
  }), async (argv) => {
9170
9171
  const tokens = tokenContext(argv.token);
9171
9172
  if (!tokens) return;
@@ -9454,13 +9455,13 @@ try {
9454
9455
  },
9455
9456
  ...argv.steps && argv.steps.length > 0 ? { steps: argv.steps } : {}
9456
9457
  })).summary.fail > 0) process.exitCode = 1;
9457
- }).command("run <task> [job] [passthrough..]", "Run a task locally (test, typecheck, lint, build, audit) — figures out turbo / the tool / the package manager", (y) => y.positional("task", {
9458
+ }).command("run <task> [job] [passthrough..]", "Run a task locally (test, typecheck, lint, build, audit) — figures out turbo / the tool / the package manager. `run ci` runs every merge-gating check; `run lint commit-msg <file>` lints a commit message.", (y) => y.positional("task", {
9458
9459
  type: "string",
9459
9460
  demandOption: true,
9460
- describe: "Task name (test, typecheck, lint, build, audit). See `holocron run --help`."
9461
+ describe: "Task name (test, typecheck, lint, build, audit, or `ci` for the merge-gating suite). See `holocron run --help`."
9461
9462
  }).positional("job", {
9462
9463
  type: "string",
9463
- describe: "Sub-job within the task (e.g. `holocron run audit performance`). Omit to run every job. Only `audit` has jobs today."
9464
+ describe: "Sub-job within the task (e.g. `holocron run audit performance`, `holocron run lint commit-msg <file>`). Omit to run every job."
9464
9465
  }).positional("passthrough", {
9465
9466
  type: "string",
9466
9467
  array: true,
@@ -9469,11 +9470,43 @@ try {
9469
9470
  type: "boolean",
9470
9471
  default: false,
9471
9472
  describe: "Fail (exit 1) if this repo has no such task, instead of skipping."
9473
+ }).option("all", {
9474
+ type: "boolean",
9475
+ default: false,
9476
+ describe: "With `run ci`: run every `ci: true` task, not just the required ones."
9472
9477
  }).option("filter", {
9473
9478
  type: "string",
9474
9479
  describe: "turbo --filter=<pkg> passthrough (monorepo)."
9475
9480
  }), async (argv) => {
9476
- const { logger } = buildCliLogger(argv, { command: "run" });
9481
+ const { logger } = buildCliLogger(argv, { command: argv.task === "ci" ? "run ci" : argv.task === "lint" && argv.job === "commit-msg" ? "run lint commit-msg" : "run" });
9482
+ const passthrough = [...argv.passthrough ?? [], ...argv["--"] ?? []];
9483
+ if (argv.task === "lint" && argv.job === "commit-msg") {
9484
+ const file = passthrough[0];
9485
+ if (!file) {
9486
+ reportError("run lint commit-msg: missing <file> (the commit message file git passes as $1).");
9487
+ process.exitCode = 1;
9488
+ return;
9489
+ }
9490
+ const result = await lintCommitMsgFile(file, argv.cwd);
9491
+ if (!result.valid) {
9492
+ for (const violation of result.violations) console.error(`✖ ${violation.rule}: ${violation.message}`);
9493
+ process.exitCode = 1;
9494
+ }
9495
+ return;
9496
+ }
9497
+ if (argv.task === "ci") {
9498
+ const ciConfig = await loadTasksConfig(argv.cwd).catch(() => void 0);
9499
+ if (createAstromech({
9500
+ cwd: argv.cwd,
9501
+ logger,
9502
+ config: ciConfig
9503
+ }).ci({
9504
+ dryRun: argv.dryRun,
9505
+ scope: argv.all ? "all" : "required",
9506
+ ...argv.filter ? { filter: argv.filter } : {}
9507
+ }).status === "fail") process.exitCode = 1;
9508
+ return;
9509
+ }
9477
9510
  const config = await loadTasksConfig(argv.cwd).catch(() => void 0);
9478
9511
  const report = createAstromech({
9479
9512
  cwd: argv.cwd,
@@ -9481,31 +9514,12 @@ try {
9481
9514
  config
9482
9515
  }).run(argv.task, {
9483
9516
  ...argv.job !== void 0 ? { job: argv.job } : {},
9484
- passthrough: [...argv.passthrough ?? [], ...argv["--"] ?? []],
9517
+ passthrough,
9485
9518
  dryRun: argv.dryRun,
9486
9519
  required: argv.required,
9487
9520
  ...argv.filter ? { filter: argv.filter } : {}
9488
9521
  });
9489
9522
  if (report.status === "fail" || report.status === "unknown") process.exitCode = 1;
9490
- }).command("ci", "Run the merge-gating checks locally, in CI order — 'will CI pass?'", (y) => y.option("all", {
9491
- type: "boolean",
9492
- default: false,
9493
- describe: "Run every `ci: true` task, not just the required ones."
9494
- }).option("filter", {
9495
- type: "string",
9496
- describe: "turbo --filter=<pkg> passthrough (monorepo)."
9497
- }), async (argv) => {
9498
- const { logger } = buildCliLogger(argv, { command: "ci" });
9499
- const config = await loadTasksConfig(argv.cwd).catch(() => void 0);
9500
- if (createAstromech({
9501
- cwd: argv.cwd,
9502
- logger,
9503
- config
9504
- }).ci({
9505
- dryRun: argv.dryRun,
9506
- scope: argv.all ? "all" : "required",
9507
- ...argv.filter ? { filter: argv.filter } : {}
9508
- }).status === "fail") process.exitCode = 1;
9509
9523
  }).command("deploy-on-release", "Deploy every workspace package whose delivery.deploy task is `on: release` — run by the delivery.publish workflow's deploy job", (y) => y.option("channel", {
9510
9524
  type: "string",
9511
9525
  default: "",
@@ -9525,17 +9539,7 @@ try {
9525
9539
  dryRun: argv.dryRun,
9526
9540
  print: (line) => console.log(line)
9527
9541
  })).status === "fail") process.exitCode = 1;
9528
- }).command("lint", "Lint content locally against the org's shared rules", (y) => y.command("commit-msg <file>", "Lint a commit message file — matches `commitlint --edit`'s own contract, for use from .husky/commit-msg", (yy) => yy.positional("file", {
9529
- type: "string",
9530
- demandOption: true,
9531
- describe: "Path to the commit message file (git's commit-msg hook passes this as $1)."
9532
- }), async (argv) => {
9533
- const result = await lintCommitMsgFile(argv.file, argv.cwd);
9534
- if (!result.valid) {
9535
- for (const violation of result.violations) console.error(`✖ ${violation.rule}: ${violation.message}`);
9536
- process.exitCode = 1;
9537
- }
9538
- }), () => {}).command("sync-github", "Sync workflow templates and composite actions to theholocron/.github", (y) => y.option("repo", {
9542
+ }).command("sync-github", "Sync workflow templates and composite actions to theholocron/.github", (y) => y.option("repo", {
9539
9543
  type: "string",
9540
9544
  default: "theholocron/.github",
9541
9545
  describe: "Target org/repo (default: theholocron/.github)"