@theholocron/astromech 4.19.0 → 5.0.0-alpha.4
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 +93 -83
- package/dist/config/index.d.mts +1 -1
- package/dist/index.d.mts +83 -101
- package/dist/index.mjs +333 -248
- package/dist/{schema-BegK4MsY.d.mts → schema-D01VYg43.d.mts} +11 -7
- package/package.json +7 -8
package/README.md
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
The Holocron task runner. One **task manifest** per repo, and every
|
|
4
4
|
derived surface comes from it: `holocron run` (local), `holocron ci` (the
|
|
5
5
|
CI suite run locally), the generated GitHub Actions workflows, the
|
|
6
|
-
`package.json` scripts,
|
|
7
|
-
required-checks list.
|
|
6
|
+
`package.json` scripts, and the branch-protection required-checks list.
|
|
8
7
|
|
|
9
8
|
> An astromech droid runs a starfighter's maintenance, diagnostics and
|
|
10
9
|
> system wiring while the pilot flies. This does that for a repo.
|
|
@@ -25,27 +24,75 @@ import { createAstromech } from "@theholocron/astromech";
|
|
|
25
24
|
|
|
26
25
|
const astromech = createAstromech({ cwd });
|
|
27
26
|
|
|
28
|
-
const report = astromech.run("
|
|
27
|
+
const report = astromech.run("verification.unitTests", { passthrough: ["--watch"] });
|
|
29
28
|
// → { status: "ok" | "fail" | "skip" | "dry-run" | "unknown", command?, message? }
|
|
30
29
|
```
|
|
31
30
|
|
|
32
31
|
### `holocron run <task>` resolution
|
|
33
32
|
|
|
34
|
-
`holocron run
|
|
35
|
-
npm, or which runner:
|
|
33
|
+
`holocron run verification.unitTests` runs your tests — you don't tell it
|
|
34
|
+
turbo vs pnpm vs npm, or which runner:
|
|
36
35
|
|
|
37
36
|
```
|
|
38
37
|
1. turbo.json defines the task → turbo run <task>
|
|
39
38
|
2. package.json has a <task> script → <detected pm> run <task>
|
|
40
39
|
(a "holocron run …" thin caller is skipped — no recursion)
|
|
41
40
|
3. the registry has a local runner → <tool> <args> <org-flags> (e.g. --coverage)
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
3b. the task is a linterGroup → each resolved linter, run natively
|
|
42
|
+
4. the task is a container of jobs → each job, in declared order
|
|
43
|
+
5. known task, nothing to run → "no <task> task", exit 0 (exit 1 with --required)
|
|
44
|
+
6. unknown task → error, exit 1
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
## Intent → technology
|
|
48
|
+
|
|
49
|
+
Tasks are named by **intent**, not by tool — a repo declares
|
|
50
|
+
`verification.unitTests`, not `vitest`. The table below is the full
|
|
51
|
+
registry (`TASKS` in `src/registry.ts`): every task name astromech knows,
|
|
52
|
+
what it actually runs, and why. Tool names never appear in
|
|
53
|
+
`holocron.config.ts` — they're an implementation detail this table
|
|
54
|
+
documents, not a naming convention repos need to follow.
|
|
55
|
+
|
|
56
|
+
| Task | Runs | Notes |
|
|
57
|
+
| ---------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `verification.unitTests` | vitest | carries the `--coverage` org default |
|
|
59
|
+
| `verification.typeSafety` | tsc | `tsc --noEmit` |
|
|
60
|
+
| `verification.performance` | Lighthouse CI | only runs with a `lighthouse.config.*` present |
|
|
61
|
+
| `sourceQuality.staticAnalysis` | eslint, actionlint, git-merge-conflict-markers | a `linterGroup` — see below |
|
|
62
|
+
| `sourceQuality.formatting` | prettier, editorconfig-checker, markdownlint-cli2 | a `linterGroup` |
|
|
63
|
+
| `sourceQuality.structuredDataValidation` | yamllint | |
|
|
64
|
+
| `sourceQuality.deadCodeAnalysis` | knip | |
|
|
65
|
+
| `security.secretDetection` | gitleaks | |
|
|
66
|
+
| `security.codeScanning` | CodeQL | no local equivalent — CI only |
|
|
67
|
+
| `security.dependencyReview` | GitHub's native Dependabot alerts/graph | a capability-model method (`Source.enableVulnerabilityAlerts()`), not a task |
|
|
68
|
+
| `delivery.build` | tsdown / vite / rollup / tsc, detected from the repo's own config file | |
|
|
69
|
+
| `delivery.publish` | semantic-release | no local equivalent — CI only; carries `preview` (npm dist-tags) |
|
|
70
|
+
| `delivery.deploy` | Cloudflare Pages / Vercel | no local equivalent — CI only; carries `preview` |
|
|
71
|
+
| `delivery.bundleSize` | bundle-size upload to Codecov | no local equivalent — CI only |
|
|
72
|
+
| `platform.repoSync` | `holocron sync` | keeps generated files current |
|
|
73
|
+
| `platform.commitStandards` | commitlint | no local equivalent — enforced by the `commit-msg` hook locally, over the PR's commit range in CI |
|
|
74
|
+
| `platform.repoValidation` | `scripts/validate-adrs.mjs`, `scripts/validate-registry.mjs`, `scripts/validate-docs-presence.mjs` | a job-bearing task — spec/ADR frontmatter, registry-doc completeness, and docs-presence, not linters |
|
|
75
|
+
| `knowledge.wiki` | Fern | publishes `docs/wiki/*.md` — not a sync, a publish; carries `preview` |
|
|
76
|
+
| `knowledge.docs` | Astro build | the docs site itself; carries `preview` (defaults on) |
|
|
77
|
+
| `knowledge.components` | Storybook build | a browsable component catalog — "Storybook" is the tool, not the intent; carries `preview` (defaults on) |
|
|
78
|
+
|
|
79
|
+
**`preview` is a cross-cutting feature, not a namespace.** npm has staging
|
|
80
|
+
dist-tags, Cloudflare/Vercel do per-PR preview deploys, Fern previews
|
|
81
|
+
docs — none of these earn their own task or verb; it's one capability any
|
|
82
|
+
publish/deploy-shaped task can carry, toggled via that task's `with:`.
|
|
83
|
+
|
|
84
|
+
**`linterGroup` tasks** (`sourceQuality.staticAnalysis`,
|
|
85
|
+
`sourceQuality.formatting`) bundle more than one tool under a single
|
|
86
|
+
required check. Each tool is still gated by its own detection rule (e.g.
|
|
87
|
+
`eslint` only runs if `eslint.config.*` is present) — the
|
|
88
|
+
`tool name → detection rule → local binary` mapping lives in one place,
|
|
89
|
+
`src/linters.ts`. A repo's choice of which of these run is just which
|
|
90
|
+
tasks it includes in `tasks: [...]`, same as any other task.
|
|
91
|
+
|
|
92
|
+
**No super-linter.** Each task above runs its own tool directly, through
|
|
93
|
+
the same `holocron` composite action that resolves it locally — CI runs
|
|
94
|
+
the identical command a developer runs, not a third-party action bundling
|
|
95
|
+
a tool version this org doesn't control.
|
|
49
96
|
|
|
50
97
|
## Config — `@theholocron/astromech/config`
|
|
51
98
|
|
|
@@ -59,9 +106,9 @@ import { defineConfig } from "@theholocron/astromech/config";
|
|
|
59
106
|
|
|
60
107
|
export default defineConfig({
|
|
61
108
|
tasks: [
|
|
62
|
-
"
|
|
63
|
-
{ name: "
|
|
64
|
-
{ name: "
|
|
109
|
+
"verification.typeSafety",
|
|
110
|
+
{ name: "verification.unitTests", required: true, with: { "run-coverage": true } },
|
|
111
|
+
{ name: "security.codeScanning", ci: true, local: false }, // CI-only
|
|
65
112
|
],
|
|
66
113
|
});
|
|
67
114
|
```
|
|
@@ -77,7 +124,6 @@ export default defineConfig({
|
|
|
77
124
|
| `local: false` | `holocron run <name>` → "CI-only task", exit 0 |
|
|
78
125
|
| `required` | the task's check context is a required status check |
|
|
79
126
|
| `with` | per-repo overrides on the reusable-workflow channel |
|
|
80
|
-
| `linters` (`lint` only) | explicit linter list; omitted → auto-detect |
|
|
81
127
|
|
|
82
128
|
Top-level keys: `syncScripts: false` disables the `package.json` script
|
|
83
129
|
writes entirely; `holocronScript` sets the command the synced `"holocron"`
|
|
@@ -89,39 +135,43 @@ script runs (default `"holocron"`).
|
|
|
89
135
|
const astromech = createAstromech({ cwd, config, orgContext: { org, domain } });
|
|
90
136
|
|
|
91
137
|
astromech.thinCallers(); // Map<"<name>.yml", yaml> — one per templated, ci-enabled task
|
|
92
|
-
astromech.packageScripts(); // { holocron: "holocron",
|
|
93
|
-
astromech.requiredChecks(); // ["
|
|
138
|
+
astromech.packageScripts(); // { holocron: "holocron", "verification.unitTests": "holocron run verification.unitTests", … }
|
|
139
|
+
astromech.requiredChecks(); // ["Typecheck / tsc --noEmit", "codecov/patch", …] — branch-protection contexts
|
|
94
140
|
astromech.codecovConfig(existing); // codecov.yml content — merges into `existing`, or scaffolds fresh when null
|
|
95
141
|
astromech.ci({ scope: "required" }); // CiReport — run the gating checks locally, in CI order
|
|
96
142
|
```
|
|
97
143
|
|
|
98
|
-
`ci()` runs every `required: true` task (else every `ci: true` task) through
|
|
99
|
-
same resolution as `run()`, in `CI_ORDER`, and returns `{ status, jobs }`.
|
|
100
|
-
`required` task whose local runner can't run is a failure
|
|
101
|
-
|
|
144
|
+
`ci()` runs every `required: true` task (else every `ci: true` task) through
|
|
145
|
+
the same resolution as `run()`, in `CI_ORDER`, and returns `{ status, jobs }`.
|
|
146
|
+
A `required` task whose local runner can't run is a failure — **except** a
|
|
147
|
+
task that's genuinely CI-only (`local: null`, or a `linterGroup` whose every
|
|
148
|
+
member lacks a local binary entirely, like `platform.commitStandards`),
|
|
149
|
+
which is reported skipped even when required. `holocron ci` sets the
|
|
102
150
|
process exit code from `status`.
|
|
103
151
|
|
|
104
152
|
`thinCallers()` returns the raw `.github/workflows/*.yml` content (no
|
|
105
|
-
generated-by header — the caller prefixes its own). `deploy`
|
|
106
|
-
`
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
153
|
+
generated-by header — the caller prefixes its own). `delivery.deploy` /
|
|
154
|
+
`knowledge.docs` / `knowledge.components` with `preview:` produce the
|
|
155
|
+
combined push-to-Pages / PR-to-preview workflow —
|
|
156
|
+
`knowledge.docs`/`knowledge.components` default `preview` on, since
|
|
157
|
+
neither has a plain-production-only fallback template.
|
|
158
|
+
`packageScripts()` emits the `holocron` entry (`holocronScript ?? "holocron"`)
|
|
159
|
+
plus one `"<task>": "holocron run <task>"` per runnable task; it skips
|
|
160
|
+
`local: false` entries and tasks with no local runner at all, and returns
|
|
161
|
+
`{}` when `syncScripts: false` or there is no config.
|
|
112
162
|
|
|
113
163
|
### Required checks
|
|
114
164
|
|
|
115
165
|
`requiredChecks()` derives the branch-protection required-status-check list
|
|
116
|
-
from the manifest: every `{ required: true }` task's check context
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
166
|
+
from the manifest: every `{ required: true }` task's check context, ordered
|
|
167
|
+
by `CI_ORDER`, then `config.extraRequiredChecks` (codecov gates, …),
|
|
168
|
+
de-duplicated. Most tasks are single always-run jobs now, so their context
|
|
169
|
+
names that job directly (`"Typecheck / tsc --noEmit"`) — the `… /
|
|
170
|
+
Conclusion` fan-in aggregate is only used where a task genuinely has
|
|
171
|
+
several conditionally-run jobs feeding one check
|
|
172
|
+
(`verification.unitTests`, `platform.repoValidation`). `holocron setup`
|
|
173
|
+
prepends `"DCO"` and applies the list for `protection: "strict"` repos.
|
|
174
|
+
Policy-free — manifest only.
|
|
125
175
|
|
|
126
176
|
### `codecov.yml`
|
|
127
177
|
|
|
@@ -135,56 +185,16 @@ current file's content (or `null`) and it either merges the
|
|
|
135
185
|
thresholds, flags, custom rules) or scaffolds a fresh file from the base
|
|
136
186
|
template. `holocron setup` writes the result via the `source` capability;
|
|
137
187
|
this method never touches the filesystem beyond reading `packages/*` and
|
|
138
|
-
`apps/*` under `cwd`.
|
|
139
|
-
coverage setup tracks the `test` task, the same way required checks track
|
|
140
|
-
`tasks`.
|
|
141
|
-
|
|
142
|
-
## Lint parity
|
|
143
|
-
|
|
144
|
-
One linter list drives both CI and local — no asymmetry. Source: the
|
|
145
|
-
`lint` task's `linters` array, or auto-detection from the config files
|
|
146
|
-
present. The `linter name → super-linter VALIDATE_* keys` mapping lives in
|
|
147
|
-
one place, `src/linters.ts`.
|
|
148
|
-
|
|
149
|
-
| linter | `VALIDATE_*` | always-on | local binary |
|
|
150
|
-
| ---------------------------- | ----------------------------------------- | ----------------------------------- | ---------------------------------------- |
|
|
151
|
-
| `eslint` | `JAVASCRIPT_ES`, `TYPESCRIPT_ES` | on `eslint.config.*` / `.eslintrc*` | `eslint .` |
|
|
152
|
-
| `prettier` | `*_PRETTIER` (JS/JSX/TS/TSX/MD) + `FIX_*` | yes | `prettier --check .` |
|
|
153
|
-
| `yamllint` | `YAML` | yes | `yamllint .` (usually CI-only) |
|
|
154
|
-
| `actionlint` | `GITHUB_ACTIONS` | yes | `actionlint` (usually CI-only) |
|
|
155
|
-
| `gitleaks` | `GITLEAKS` | yes | `gitleaks dir` (usually CI-only) |
|
|
156
|
-
| `editorconfig` | `EDITORCONFIG` | yes | `editorconfig-checker` (usually CI-only) |
|
|
157
|
-
| `commitlint` | `GIT_COMMITLINT` | yes | — (commit-msg hook + CI) |
|
|
158
|
-
| `git-merge-conflict-markers` | `GIT_MERGE_CONFLICT_MARKERS` | yes | — (CI only) |
|
|
159
|
-
| `markdownlint` | `MARKDOWN` | on `.markdownlint*` | `markdownlint-cli2` |
|
|
160
|
-
|
|
161
|
-
```ts
|
|
162
|
-
import { superLinterConfig, resolveLinters } from "@theholocron/astromech";
|
|
163
|
-
|
|
164
|
-
superLinterConfig({ explicit: ["eslint", "prettier"], rootFiles: fs.readdirSync(cwd) });
|
|
165
|
-
// → { env: { VALIDATE_JAVASCRIPT_ES: "true", … }, linters: ["eslint","prettier"], configInputs: { … } }
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
`superLinterConfig().env` is the exact `VALIDATE_*`/`FIX_*` map the CI
|
|
169
|
-
`lint` job needs — the CLI serializes it as the `super-linter-env` input on
|
|
170
|
-
each repo's generated `lint` thin caller. Setting any `VALIDATE_*` puts
|
|
171
|
-
super-linter in allow-list mode, so emitting only the enabled keys makes it
|
|
172
|
-
run exactly the resolved set.
|
|
173
|
-
|
|
174
|
-
`holocron run lint` (later phase) runs the same set natively: `turbo run
|
|
175
|
-
lint` for the eslint portion (cached), then each other linter whose binary
|
|
176
|
-
resolves; linters with a binary that is not on `PATH` are flagged with an
|
|
177
|
-
install hint; the rest print "CI only".
|
|
188
|
+
`apps/*` under `cwd`.
|
|
178
189
|
|
|
179
190
|
## Development
|
|
180
191
|
|
|
181
|
-
| Script
|
|
182
|
-
|
|
|
183
|
-
| `pnpm build`
|
|
184
|
-
| `pnpm
|
|
185
|
-
| `pnpm
|
|
186
|
-
| `pnpm
|
|
187
|
-
| `pnpm lint` | ESLint |
|
|
192
|
+
| Script | Description |
|
|
193
|
+
| --------------------------------------- | ------------------------------------------- |
|
|
194
|
+
| `pnpm run delivery.build` | Bundle with tsdown |
|
|
195
|
+
| `pnpm run verification.unitTests` | Run the vitest suite (always with coverage) |
|
|
196
|
+
| `pnpm run verification.typeSafety` | `tsc --noEmit` |
|
|
197
|
+
| `pnpm run sourceQuality.staticAnalysis` | ESLint |
|
|
188
198
|
|
|
189
199
|
## Releases
|
|
190
200
|
|
package/dist/config/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as normalizeTaskEntry, n as TaskEntry, r as TasksConfig, t as TaskConfigItem } from "../schema-
|
|
1
|
+
import { i as normalizeTaskEntry, n as TaskEntry, r as TasksConfig, t as TaskConfigItem } from "../schema-D01VYg43.mjs";
|
|
2
2
|
//#region src/config/define.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Typed identity helper for `astromech.config.ts`:
|
package/dist/index.d.mts
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
import { r as TasksConfig } from "./schema-
|
|
1
|
+
import { r as TasksConfig } from "./schema-D01VYg43.mjs";
|
|
2
2
|
//#region src/run.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* `holocron run <task> [job] [-- <passthrough>]` — run a registry task (or one
|
|
5
5
|
* of its sub-jobs) locally.
|
|
6
6
|
*
|
|
7
|
-
* A `job` argument only applies to tasks that declare `jobs
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* audit` runs every job in declared order.
|
|
7
|
+
* A `job` argument only applies to tasks that declare `jobs`; for any other
|
|
8
|
+
* task it is folded back into the passthrough (`holocron run delivery.build
|
|
9
|
+
* src/`).
|
|
11
10
|
*
|
|
12
11
|
* Resolution:
|
|
13
12
|
*
|
|
14
|
-
* 0. task === "lint" (no job) → the linter aggregate (see below)
|
|
15
13
|
* J. job given → TASKS[task].jobs[job].local (unknown job → exit 1)
|
|
16
14
|
* 1. turbo.json defines the task → `turbo run <task>`
|
|
17
15
|
* 2. package.json has a `<task>` script → `<pm> run <task>`
|
|
18
16
|
* (unless it's the `holocron run …` thin caller — that recurses)
|
|
19
17
|
* 3. TASKS[task].local resolves → `<tool> <args> <org-flags> <passthrough>`
|
|
18
|
+
* 3b. TASKS[task].linterGroup → run each resolved linter natively (see below)
|
|
20
19
|
* 4. TASKS[task].jobs has entries → run each job in declared order
|
|
21
20
|
* 5. TASKS[task].local === null → "enforced in CI" (skip, even with --required)
|
|
22
21
|
* 5b. known task, nothing resolved → "no <task> task" (exit 0, or 1 with --required)
|
|
23
22
|
* 6. unknown task → "unknown task" (exit 1)
|
|
24
23
|
*
|
|
25
|
-
* `
|
|
26
|
-
*
|
|
27
|
-
* `
|
|
28
|
-
*
|
|
29
|
-
*
|
|
24
|
+
* A `linterGroup` task (`sourceQuality.staticAnalysis`, etc.) runs its fixed
|
|
25
|
+
* set of `linters.ts` entries, each still gated by that linter's own
|
|
26
|
+
* `detect`/`always` rule — every entry runs its `localBin` natively when
|
|
27
|
+
* found on PATH. Missing tools are flagged; the exit code is the worst of
|
|
28
|
+
* the lot. Unlike the old single `lint` task, this check runs *after*
|
|
29
|
+
* turbo/`package.json` resolution (step 3b, not step 0) — a `linterGroup`
|
|
30
|
+
* task is a normal turbo-delegatable task like any other.
|
|
30
31
|
*/
|
|
31
32
|
/** Minimal structural logger — `@theholocron/observability`'s `Logger` satisfies it. */
|
|
32
33
|
interface RunLogger {
|
|
@@ -70,8 +71,6 @@ interface RunTaskInput extends RunDeps {
|
|
|
70
71
|
dryRun?: boolean;
|
|
71
72
|
/** Turn "no such task for this repo" (normally exit 0) into a failure. */
|
|
72
73
|
required?: boolean;
|
|
73
|
-
/** The `lint` task's explicit linter list from `config.tasks`, if any. */
|
|
74
|
-
linters?: string[];
|
|
75
74
|
/** `turbo --filter=<pkg>` passthrough (monorepo). Ignored when the repo has no `turbo.json`. */
|
|
76
75
|
filter?: string;
|
|
77
76
|
}
|
|
@@ -107,68 +106,9 @@ interface CiReport {
|
|
|
107
106
|
interface CiInput extends RunDeps, CiOptions {
|
|
108
107
|
cwd: string;
|
|
109
108
|
config: TasksConfig;
|
|
110
|
-
/** Explicit linter list for the `lint` task (the config's lint entry `linters`). */
|
|
111
|
-
linters?: string[];
|
|
112
109
|
}
|
|
113
110
|
declare function runCi(input: CiInput): CiReport;
|
|
114
111
|
//#endregion
|
|
115
|
-
//#region src/super-linter.d.ts
|
|
116
|
-
/**
|
|
117
|
-
* `superLinterConfig()` — turn the resolved linter set into the exact
|
|
118
|
-
* super-linter `VALIDATE_*` / `FIX_*` env the CI `lint` job needs. The CLI
|
|
119
|
-
* serializes {@link SuperLinterConfig.env} as the `super-linter-env` input
|
|
120
|
-
* on each repo's generated `lint` thin caller; the reusable workflow
|
|
121
|
-
* expands it verbatim. This is the CI half of "lint parity" — the local
|
|
122
|
-
* half is the `holocron run lint` aggregate, driven by the same
|
|
123
|
-
* {@link resolveLinters}.
|
|
124
|
-
*/
|
|
125
|
-
interface SuperLinterConfig {
|
|
126
|
-
/**
|
|
127
|
-
* Enabled `VALIDATE_*` / `FIX_*` keys → `"true"`. Only enabled keys are
|
|
128
|
-
* present (super-linter allow-list mode). Ready for `JSON.stringify`.
|
|
129
|
-
*/
|
|
130
|
-
env: Record<string, string>;
|
|
131
|
-
/** Resolved linter names in execution order — for the human-readable comment. */
|
|
132
|
-
linters: string[];
|
|
133
|
-
/** Config-file inputs the resolved set honors (`eslint-config`, …). */
|
|
134
|
-
configInputs: Partial<Record<"eslint-config" | "prettier-config" | "yaml-config", true>>;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Resolve the super-linter env for a repo's `lint` task.
|
|
138
|
-
*
|
|
139
|
-
* @param opts.explicit the task's `linters` list, if any (else auto-detect)
|
|
140
|
-
* @param opts.rootFiles repo-root filenames (from `listDir(cwd)`)
|
|
141
|
-
* @param opts.includeFix emit `FIX_*` keys too (default `true`)
|
|
142
|
-
*/
|
|
143
|
-
declare function superLinterConfig(opts: {
|
|
144
|
-
explicit?: string[];
|
|
145
|
-
rootFiles: string[];
|
|
146
|
-
includeFix?: boolean;
|
|
147
|
-
}): SuperLinterConfig;
|
|
148
|
-
/**
|
|
149
|
-
* The always-on baseline env — every `always` linter, no detection. This is
|
|
150
|
-
* what the reusable `lint.yml`'s `super-linter-env` input defaults to, so a
|
|
151
|
-
* repo whose thin caller has not been re-synced yet behaves exactly as before.
|
|
152
|
-
*/
|
|
153
|
-
declare function baselineSuperLinterEnv(): Record<string, string>;
|
|
154
|
-
/**
|
|
155
|
-
* The `lint` thin caller's `with:` overrides + the `# linters: …` comment,
|
|
156
|
-
* from the resolved linter set. Shared by `createAstromech().thinCallers()`
|
|
157
|
-
* and the CLI's `sync` / `setup` workflow writers so the three stay in step.
|
|
158
|
-
*
|
|
159
|
-
* @param opts.explicit the `lint` task's `linters` list, if any
|
|
160
|
-
* @param opts.rootFiles repo-root filenames (auto-detect fallback)
|
|
161
|
-
* @param opts.extra per-repo `with:` overrides that win over the defaults
|
|
162
|
-
*/
|
|
163
|
-
declare function lintThinCallerWith(opts: {
|
|
164
|
-
explicit?: string[];
|
|
165
|
-
rootFiles: string[];
|
|
166
|
-
extra?: Record<string, unknown>;
|
|
167
|
-
}): {
|
|
168
|
-
withOverrides: Record<string, unknown>;
|
|
169
|
-
comments: Record<string, string>;
|
|
170
|
-
};
|
|
171
|
-
//#endregion
|
|
172
112
|
//#region src/thin-callers.d.ts
|
|
173
113
|
/**
|
|
174
114
|
* Workflow templates + thin-caller generation.
|
|
@@ -183,10 +123,17 @@ declare const KNOWN_WORKFLOWS: Set<string>;
|
|
|
183
123
|
* The GitHub status-check context a `required` task contributes to branch
|
|
184
124
|
* protection. Format: `"{workflow name} / {job name}"`.
|
|
185
125
|
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
126
|
+
* Most of these are single-job workflows now (D3's decomposition split what
|
|
127
|
+
* used to be multi-job `lint`/`audit` into one task per concern) — the
|
|
128
|
+
* context names that job directly, no `Conclusion` aggregator needed; a
|
|
129
|
+
* single job's own conclusion already *is* the workflow's conclusion.
|
|
130
|
+
* `Conclusion` fan-in jobs are kept only where a task genuinely has several
|
|
131
|
+
* conditionally-run jobs feeding one required check:
|
|
132
|
+
* `verification.unitTests` (unit / Storybook / Chromatic / interaction /
|
|
133
|
+
* user-flow, each gated by its own `run-*` input) and
|
|
134
|
+
* `platform.repoValidation` (its three script jobs all must pass). Only
|
|
135
|
+
* merge-gating workflows are listed. `astromech.requiredChecks()` reads this
|
|
136
|
+
* for every `required` task.
|
|
190
137
|
*/
|
|
191
138
|
declare const WORKFLOW_CHECK_CONTEXTS: Partial<Record<string, string>>;
|
|
192
139
|
/**
|
|
@@ -348,14 +295,6 @@ interface Astromech {
|
|
|
348
295
|
* when there is no config or `syncScripts: false`.
|
|
349
296
|
*/
|
|
350
297
|
packageScripts(): Record<string, string>;
|
|
351
|
-
/**
|
|
352
|
-
* The resolved super-linter env for this repo's `lint` task — the CI half
|
|
353
|
-
* of lint parity. `thinCallers()` already bakes `env` into the `lint` thin
|
|
354
|
-
* caller's `super-linter-env` input; this method exposes the full result
|
|
355
|
-
* for `holocron doctor` / diagnostics. Driven by the `lint` entry's
|
|
356
|
-
* `linters` list, else auto-detection from the repo's config files.
|
|
357
|
-
*/
|
|
358
|
-
superLinterConfig(): SuperLinterConfig;
|
|
359
298
|
/**
|
|
360
299
|
* The branch-protection required-status-check contexts for this repo —
|
|
361
300
|
* every `required: true` task's check context plus `extraRequiredChecks`,
|
|
@@ -370,6 +309,12 @@ interface Astromech {
|
|
|
370
309
|
* as {@link requiredChecks} — `holocron setup` owns writing the result.
|
|
371
310
|
*/
|
|
372
311
|
codecovConfig(existing: string | null): string;
|
|
312
|
+
/**
|
|
313
|
+
* The generated `turbo.json` for this repo's manifest, pretty-printed —
|
|
314
|
+
* write directly, no merge. `null` when no manifest task has turbo fan-out
|
|
315
|
+
* config (nothing to write). See {@link TurboTaskConfig} in `registry.ts`.
|
|
316
|
+
*/
|
|
317
|
+
turboConfig(): string | null;
|
|
373
318
|
}
|
|
374
319
|
declare function createAstromech(options: AstromechOptions): Astromech;
|
|
375
320
|
//#endregion
|
|
@@ -495,7 +440,19 @@ declare function resolveLinters(opts: {
|
|
|
495
440
|
* Actions. `holocron run <task>` and `holocron ci` resolve against this;
|
|
496
441
|
* adding a task here gives every repo that task.
|
|
497
442
|
*
|
|
498
|
-
* Keyed identically to the workflow templates — a task IS a workflow.
|
|
443
|
+
* Keyed identically to the workflow templates — a task IS a workflow. This
|
|
444
|
+
* is the canonical vocabulary table (epic #672, D11): every other artifact
|
|
445
|
+
* (`KNOWN_TASKS`, `thin-callers.ts`'s `KNOWN_WORKFLOWS`/`WORKFLOW_CHECK_CONTEXTS`,
|
|
446
|
+
* `CI_ORDER`) derives from these keys rather than hand-duplicating them —
|
|
447
|
+
* including the future GitHub App (#679), which imports this same table for
|
|
448
|
+
* config-schema validation instead of reimplementing its own copy.
|
|
449
|
+
*
|
|
450
|
+
* Task names are an intent-facing vocabulary (`verification.*`,
|
|
451
|
+
* `sourceQuality.*`, `security.*`, `delivery.*`, `platform.*`,
|
|
452
|
+
* `knowledge.*`), not tool names — `eslint`/`vitest`/`tsdown`/… stay
|
|
453
|
+
* internal to this file and `theholocron/configs`. See
|
|
454
|
+
* `.notes/tech-vocabulary-rename.spec.md` (#675) for the full mapping and
|
|
455
|
+
* the reasoning behind each namespace and decomposition.
|
|
499
456
|
*
|
|
500
457
|
* Spec: `docs/wiki/specifications/tech-astromech-task-runner.spec.md` (epic #581).
|
|
501
458
|
*/
|
|
@@ -514,40 +471,65 @@ interface LocalRunner {
|
|
|
514
471
|
/** The task is already a holocron subcommand (`sync`, `sync-wiki`). */
|
|
515
472
|
command?: string;
|
|
516
473
|
}
|
|
474
|
+
/**
|
|
475
|
+
* How a task fans out across every workspace via Turborepo — content-hash
|
|
476
|
+
* caching + `^`-prefixed cross-package ordering, epic #672 D9 (#681).
|
|
477
|
+
* Present only on tasks that genuinely run *per workspace* (a real build/
|
|
478
|
+
* compile/test step); whole-repo single-run tools (prettier, gitleaks,
|
|
479
|
+
* commitlint, yamllint, …) have no entry here — they stay off turbo.json
|
|
480
|
+
* entirely and run once, un-fanned-out, the way they already do.
|
|
481
|
+
*/
|
|
482
|
+
interface TurboTaskConfig {
|
|
483
|
+
/** Glob patterns turbo hashes to decide whether a cached run is still valid. */
|
|
484
|
+
inputs: string[];
|
|
485
|
+
/** Glob patterns turbo caches/restores after a run. Empty array for a task with no build artifact (lint, typecheck). */
|
|
486
|
+
outputs: string[];
|
|
487
|
+
/** Task names this depends on — a bare name runs in this package first; `^name` waits on every upstream workspace's task. */
|
|
488
|
+
dependsOn: string[];
|
|
489
|
+
}
|
|
517
490
|
/** One sub-job of a task — `performance` in `holocron run audit performance`. */
|
|
518
491
|
interface JobDef {
|
|
519
492
|
/** How the job runs locally; `null` → no local equivalent (enforced in CI). */
|
|
520
493
|
local: LocalRunner | null;
|
|
521
494
|
/**
|
|
522
|
-
* The CI status-check context this job reports as (
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
* `
|
|
495
|
+
* The CI status-check context this job reports as (e.g.
|
|
496
|
+
* `platform.repoValidation / Validate registry consistency`) — every sub-job is a CI job.
|
|
497
|
+
* `holocron run <task>` and `holocron ci` label each job line with it;
|
|
498
|
+
* the task-level `… / Conclusion` context (only for tasks with several
|
|
499
|
+
* jobs) lives in `WORKFLOW_CHECK_CONTEXTS`.
|
|
526
500
|
*/
|
|
527
501
|
checkContext: string;
|
|
528
502
|
}
|
|
529
503
|
interface TaskDef {
|
|
530
504
|
/**
|
|
531
|
-
* `null` — the registry has no built-in runner (CodeQL, deploys,
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
505
|
+
* `null` — the registry has no built-in runner (CodeQL, deploys, the
|
|
506
|
+
* bundle-size job). An explicit turbo task or `package.json` script still
|
|
507
|
+
* runs (resolution steps 1–2); with neither, `holocron run` does nothing
|
|
508
|
+
* and `holocron ci` skips it — never a failure, even when the task is
|
|
509
|
+
* `required` (a CI-only check isn't a local one).
|
|
536
510
|
*/
|
|
537
511
|
local: LocalRunner | null;
|
|
538
512
|
/**
|
|
539
|
-
* Sub-jobs, keyed by slug
|
|
540
|
-
*
|
|
513
|
+
* Sub-jobs, keyed by slug. Declared order is run order: `holocron run
|
|
514
|
+
* <task>` (no job) runs each in turn.
|
|
541
515
|
*/
|
|
542
516
|
jobs?: Record<string, JobDef>;
|
|
543
517
|
/** Org-default flags injected by tool name. Removed by a repo override. */
|
|
544
518
|
flags?: Record<string, string[]>;
|
|
545
519
|
/**
|
|
546
|
-
* This task is
|
|
547
|
-
*
|
|
548
|
-
*
|
|
520
|
+
* This task is a linter-group aggregate: `holocron run <task>` resolves
|
|
521
|
+
* this fixed set of `linters.ts` entries (still gated by each linter's
|
|
522
|
+
* own `detect`/`always` rule) and runs each natively, instead of using
|
|
523
|
+
* `local`. Replaces the old single `lint` task's auto-detected linter
|
|
524
|
+
* list (`config.tasks[].linters`) — a repo's choice of which of these
|
|
525
|
+
* run is now just whether it includes this task in `tasks: [...]`, same
|
|
526
|
+
* as any other task. See `linters.ts` / `run.ts`.
|
|
549
527
|
*/
|
|
550
|
-
|
|
528
|
+
linterGroup?: string[];
|
|
529
|
+
/** Carries a `preview` mode (Cloudflare/Vercel deploy, npm dist-tag, Fern preview docs, …). Cross-cutting, not its own task. */
|
|
530
|
+
preview?: boolean;
|
|
531
|
+
/** Turborepo fan-out config for this task — see {@link TurboTaskConfig}. Omitted for whole-repo, non-fan-out tasks. */
|
|
532
|
+
turbo?: TurboTaskConfig;
|
|
551
533
|
}
|
|
552
534
|
declare const TASKS: Record<string, TaskDef>;
|
|
553
535
|
/** Every task name the registry knows. */
|
|
@@ -591,4 +573,4 @@ declare const WORKFLOW_TEMPLATE_PROPERTIES: Record<string, string>;
|
|
|
591
573
|
*/
|
|
592
574
|
declare function reusableTemplates(): Map<string, string>;
|
|
593
575
|
//#endregion
|
|
594
|
-
export { type Astromech, type AstromechOptions, CI_ORDER, type CiJobReport, type CiOptions, type CiReport, type ExecFn, type JobDef, KNOWN_TASKS, KNOWN_WORKFLOWS, LINTERS, LINTER_NAMES, type LinterDef, type LocalRunner, type OrgContext, type PreviewConfig, REUSABLE_ACTIONS, REUSABLE_WORKFLOWS, type RunLogger, type RunOptions, type RunTaskInput, type RunTaskReport,
|
|
576
|
+
export { type Astromech, type AstromechOptions, CI_ORDER, type CiJobReport, type CiOptions, type CiReport, type ExecFn, type JobDef, KNOWN_TASKS, KNOWN_WORKFLOWS, LINTERS, LINTER_NAMES, type LinterDef, type LocalRunner, type OrgContext, type PreviewConfig, REUSABLE_ACTIONS, REUSABLE_WORKFLOWS, type RunLogger, type RunOptions, type RunTaskInput, type RunTaskReport, TASKS, type TaskDef, WORKFLOW_CHECK_CONTEXTS, WORKFLOW_TEMPLATES, WORKFLOW_TEMPLATE_PROPERTIES, type WorkspacePackage, codecovComponentBlock, codecovConfig, createAstromech, createCodecovConfig, deriveDeployPaths, ensureIfNotFound, extractPreviewConfig, generateCombinedDeployContent, generateThinCallerContent, mergeCodecovComponents, normalizeWorkflowWith, readWorkspacePackages, requiredChecks, resolveLinters, reusableTemplates, runCi, runTask };
|