@theholocron/cli 5.0.0-alpha.54 → 5.0.0-alpha.56
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 +87 -6
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +18 -1
- package/dist/index.mjs +60 -1
- package/package.json +9 -4
package/dist/cli.mjs
CHANGED
|
@@ -24,6 +24,8 @@ import { createGitHubClient } from "@theholocron/github-client";
|
|
|
24
24
|
import { PostHogSink } from "@theholocron/observability/analytics";
|
|
25
25
|
import { NoopAnalyticsSink, NoopErrorSink, redactObject } from "@theholocron/observability/core";
|
|
26
26
|
import { SentrySink } from "@theholocron/observability/errors";
|
|
27
|
+
import load from "@commitlint/load";
|
|
28
|
+
import lint from "@commitlint/lint";
|
|
27
29
|
import { promisify } from "node:util";
|
|
28
30
|
import { ConfigFileError, loadConfigFile } from "@theholocron/datapad";
|
|
29
31
|
import search from "@inquirer/search";
|
|
@@ -1219,6 +1221,7 @@ const COMMAND_CONTEXTS = {
|
|
|
1219
1221
|
"skills install": "global",
|
|
1220
1222
|
"skills remove": "global",
|
|
1221
1223
|
"skills update": "global",
|
|
1224
|
+
"lint commit-msg": "global",
|
|
1222
1225
|
run: "repo-aware",
|
|
1223
1226
|
ci: "repo-aware",
|
|
1224
1227
|
"config show": "repo-aware",
|
|
@@ -4171,12 +4174,21 @@ function createIgnoreConfig$1() {
|
|
|
4171
4174
|
}
|
|
4172
4175
|
//#endregion
|
|
4173
4176
|
//#region src/templates/configs/commit-msg/commit-msg
|
|
4174
|
-
var commit_msg_default = "
|
|
4177
|
+
var commit_msg_default = "__HOLOCRON_SCRIPT__ lint commit-msg \"$1\"\n";
|
|
4175
4178
|
//#endregion
|
|
4176
4179
|
//#region src/templates/configs/commit-msg/create-config.ts
|
|
4177
4180
|
const { workflowHeader: workflowHeader$8 } = createHeader({ source: "packages/cli/src/templates/configs/commit-msg/create-config.ts" });
|
|
4178
|
-
|
|
4179
|
-
|
|
4181
|
+
/**
|
|
4182
|
+
* `.husky/commit-msg` — lints the commit message via `holocron lint
|
|
4183
|
+
* commit-msg` (holocron#789), the real programmatic replacement for
|
|
4184
|
+
* shelling out to `commitlint --edit`. Installed by `holocron setup` when
|
|
4185
|
+
* hooks are enabled. Same `__HOLOCRON_SCRIPT__` substitution as `pre-push`.
|
|
4186
|
+
*
|
|
4187
|
+
* @param holocronScript - the command that invokes the CLI. Defaults to
|
|
4188
|
+
* `pnpm exec holocron`; the source repo passes `node packages/cli/dist/cli.mjs`.
|
|
4189
|
+
*/
|
|
4190
|
+
function createConfig$7(holocronScript = "pnpm exec holocron") {
|
|
4191
|
+
return `${workflowHeader$8("shebang")}${commit_msg_default.replace("__HOLOCRON_SCRIPT__", holocronScript)}`;
|
|
4180
4192
|
}
|
|
4181
4193
|
//#endregion
|
|
4182
4194
|
//#region src/templates/configs/devmoji/create-config.ts
|
|
@@ -5279,7 +5291,7 @@ async function runSetup(input) {
|
|
|
5279
5291
|
}));
|
|
5280
5292
|
print(formatStep(steps[steps.length - 1]));
|
|
5281
5293
|
steps.push(await runStep("source", "write .husky/commit-msg", dryRun, async () => {
|
|
5282
|
-
await source.writeRepoFile(".husky/commit-msg", createConfig$7());
|
|
5294
|
+
await source.writeRepoFile(".husky/commit-msg", createConfig$7(config.holocronScript));
|
|
5283
5295
|
}));
|
|
5284
5296
|
print(formatStep(steps[steps.length - 1]));
|
|
5285
5297
|
if (hooksEnabled) {
|
|
@@ -7651,6 +7663,63 @@ async function runUpgradeNode(input) {
|
|
|
7651
7663
|
};
|
|
7652
7664
|
}
|
|
7653
7665
|
//#endregion
|
|
7666
|
+
//#region src/commit-lint/lint-message.ts
|
|
7667
|
+
/**
|
|
7668
|
+
* Lints one commit message string against an already-loaded commitlint
|
|
7669
|
+
* config. The genuinely environment-independent half of commit-message
|
|
7670
|
+
* linting (holocron#789) — *obtaining* a `QualifiedConfig` differs by
|
|
7671
|
+
* caller (Sentinel isolates itself from any ambient config since it runs
|
|
7672
|
+
* standalone, away from a real repo checkout; `lintCommitMsgFile` below
|
|
7673
|
+
* just lets cosmiconfig discover the invoking repo's own
|
|
7674
|
+
* `commitlint.config.*`, matching `commitlint --edit`'s own contract) —
|
|
7675
|
+
* but linting one message against a loaded config is identical either way.
|
|
7676
|
+
*
|
|
7677
|
+
* Real `@commitlint/lint` — the same programmatic API `@commitlint/cli`
|
|
7678
|
+
* itself uses internally — never a reimplementation of commitlint's rules.
|
|
7679
|
+
*/
|
|
7680
|
+
/** `parserPreset.parserOpts`, if the loaded config sets one — same lookup `@commitlint/cli`'s own `selectParserOpts()` does. */
|
|
7681
|
+
function selectParserOpts(parserPreset) {
|
|
7682
|
+
return parserPreset?.parserOpts;
|
|
7683
|
+
}
|
|
7684
|
+
async function lintCommitMessage(message, loaded) {
|
|
7685
|
+
const opts = {
|
|
7686
|
+
/* istanbul ignore next -- see comment above */
|
|
7687
|
+
parserOpts: selectParserOpts(loaded.parserPreset) ?? {},
|
|
7688
|
+
plugins: loaded.plugins,
|
|
7689
|
+
/* istanbul ignore next -- see comment above */
|
|
7690
|
+
ignores: loaded.ignores ?? [],
|
|
7691
|
+
defaultIgnores: loaded.defaultIgnores !== false
|
|
7692
|
+
};
|
|
7693
|
+
const outcome = await lint(message, loaded.rules, opts);
|
|
7694
|
+
if (outcome.valid) return [];
|
|
7695
|
+
return outcome.errors.map((error) => ({
|
|
7696
|
+
rule: error.name,
|
|
7697
|
+
message: error.message
|
|
7698
|
+
}));
|
|
7699
|
+
}
|
|
7700
|
+
//#endregion
|
|
7701
|
+
//#region src/commit-lint/lint-commit-msg-file.ts
|
|
7702
|
+
/**
|
|
7703
|
+
* `holocron lint commit-msg <file>` — a real programmatic replacement for
|
|
7704
|
+
* shelling out to `commitlint --edit "$1"` from `.husky/commit-msg`
|
|
7705
|
+
* (holocron#789). Matches that CLI's own contract exactly: `file` is a
|
|
7706
|
+
* path to the commit message being written (the arg git's `commit-msg`
|
|
7707
|
+
* hook passes as `$1`), no `--config` override needed — `@commitlint/load`
|
|
7708
|
+
* runs from `cwd` with no seed, so cosmiconfig's own normal upward search
|
|
7709
|
+
* discovers the invoking repo's real `commitlint.config.*` file, exactly
|
|
7710
|
+
* as `commitlint --edit` (no `--config` flag) already does today. Unlike
|
|
7711
|
+
* Sentinel's `loadIsolatedConfig()`, no isolation is needed here — this
|
|
7712
|
+
* runs inside a real repo checkout with a real `node_modules`, not
|
|
7713
|
+
* standalone on a server.
|
|
7714
|
+
*/
|
|
7715
|
+
async function lintCommitMsgFile(filePath, cwd = process.cwd()) {
|
|
7716
|
+
const violations = await lintCommitMessage(await readFile(filePath, "utf8"), await load({}, { cwd }));
|
|
7717
|
+
return {
|
|
7718
|
+
valid: violations.length === 0,
|
|
7719
|
+
violations
|
|
7720
|
+
};
|
|
7721
|
+
}
|
|
7722
|
+
//#endregion
|
|
7654
7723
|
//#region src/config/load-config.ts
|
|
7655
7724
|
/**
|
|
7656
7725
|
* `holocron.config.{ts,js,mjs,cjs,json}` loader.
|
|
@@ -7761,7 +7830,9 @@ const numeric = (value) => /^\d+$/.test(value) ? true : "enter a number";
|
|
|
7761
7830
|
* The full command surface, hand-maintained in parallel with `cli.ts`'s
|
|
7762
7831
|
* yargs registrations (this module does not introspect yargs at runtime).
|
|
7763
7832
|
* `run <task>` is deliberately excluded — it's CI/scripting-oriented, and an
|
|
7764
|
-
* interactive prompt in front of it would work against that.
|
|
7833
|
+
* interactive prompt in front of it would work against that. `lint
|
|
7834
|
+
* commit-msg <file>` is excluded for the same reason: it's invoked
|
|
7835
|
+
* exclusively from `.husky/commit-msg "$1"`, never typed by a human.
|
|
7765
7836
|
*/
|
|
7766
7837
|
const COMMAND_REGISTRY = [
|
|
7767
7838
|
{
|
|
@@ -8670,7 +8741,17 @@ try {
|
|
|
8670
8741
|
scope: argv.all ? "all" : "required",
|
|
8671
8742
|
...argv.filter ? { filter: argv.filter } : {}
|
|
8672
8743
|
}).status === "fail") process.exitCode = 1;
|
|
8673
|
-
}).command("
|
|
8744
|
+
}).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", {
|
|
8745
|
+
type: "string",
|
|
8746
|
+
demandOption: true,
|
|
8747
|
+
describe: "Path to the commit message file (git's commit-msg hook passes this as $1)."
|
|
8748
|
+
}), async (argv) => {
|
|
8749
|
+
const result = await lintCommitMsgFile(argv.file, argv.cwd);
|
|
8750
|
+
if (!result.valid) {
|
|
8751
|
+
for (const violation of result.violations) console.error(`✖ ${violation.rule}: ${violation.message}`);
|
|
8752
|
+
process.exitCode = 1;
|
|
8753
|
+
}
|
|
8754
|
+
}), () => {}).command("sync-github", "Sync workflow templates and composite actions to theholocron/.github", (y) => y.option("repo", {
|
|
8674
8755
|
type: "string",
|
|
8675
8756
|
default: "theholocron/.github",
|
|
8676
8757
|
describe: "Target org/repo (default: theholocron/.github)"
|