@theholocron/cli 2.0.0-alpha.43 → 2.0.0-alpha.45
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 +4 -3
- package/dist/capabilities/index.d.mts +10 -0
- package/dist/cli.mjs +207 -10
- package/dist/index.d.mts +24 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,13 +101,14 @@ export default acmeConfig;
|
|
|
101
101
|
- `src/loader.ts` — `PluginLoader` — dynamic-imports plugins, resolves
|
|
102
102
|
capability config packages, builds the capability registry
|
|
103
103
|
- `src/cli.ts` — yargs entry, dispatches subcommands
|
|
104
|
-
- `src/commands/` — `setup`, `doctor`, `deploy`, `secret set`,
|
|
105
|
-
`secrets sync`, `npm publish-initial`
|
|
104
|
+
- `src/commands/` — `setup`, `sync`, `doctor`, `deploy`, `secret set`,
|
|
105
|
+
`secrets sync`, `npm publish-initial`, `sync-github`, `upgrade node`,
|
|
106
|
+
`plugin create`, `auth`
|
|
106
107
|
|
|
107
108
|
## Status
|
|
108
109
|
|
|
109
110
|
**`v2.0.0-alpha.0`** — published on npm under the `alpha` dist-tag.
|
|
110
111
|
[Release notes](https://github.com/theholocron/holocron/releases/tag/v2.0.0-alpha.0).
|
|
111
112
|
Design in
|
|
112
|
-
[`.notes/tech-architecture.spec.md`](../../.notes/tech-architecture.spec.md).
|
|
113
|
+
[`.notes/archive/tech-architecture.spec.md`](../../.notes/archive/tech-architecture.spec.md).
|
|
113
114
|
APIs may still shift before stable v2.0.0.
|
|
@@ -127,6 +127,16 @@ interface Source extends ProviderIdentity {
|
|
|
127
127
|
* Optional — providers that have no label concept omit this.
|
|
128
128
|
*/
|
|
129
129
|
syncLabels?(canonical: ReadonlyArray<LabelDef>, stale: ReadonlyArray<string>): Promise<string>;
|
|
130
|
+
/**
|
|
131
|
+
* Set org-level custom property values on the repo.
|
|
132
|
+
* Optional — providers that don't support custom properties omit this.
|
|
133
|
+
*/
|
|
134
|
+
syncProperties?(values: Record<string, string>): Promise<string>;
|
|
135
|
+
/**
|
|
136
|
+
* Replace the repo's topic set with the supplied list.
|
|
137
|
+
* Optional — providers that don't support topics omit this.
|
|
138
|
+
*/
|
|
139
|
+
syncTopics?(topics: string[]): Promise<string>;
|
|
130
140
|
}
|
|
131
141
|
type CiRunStatus = "queued" | "in_progress" | "completed" | "cancelled" | "failure" | "success" | "skipped";
|
|
132
142
|
interface CiRun {
|
package/dist/cli.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { ProviderApiError } from "@theholocron/http-client";
|
|
|
7
7
|
import { Entry, findCredentials } from "@napi-rs/keyring";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import { spawnSync } from "node:child_process";
|
|
10
|
-
import { readFile, stat } from "node:fs/promises";
|
|
10
|
+
import { access, readFile, stat } from "node:fs/promises";
|
|
11
11
|
import { pathToFileURL } from "node:url";
|
|
12
12
|
//#region src/capabilities/index.ts
|
|
13
13
|
const CARDINALITY = {
|
|
@@ -464,7 +464,7 @@ var PluginLoader = class {
|
|
|
464
464
|
*/
|
|
465
465
|
projectDefaults() {
|
|
466
466
|
const defaults = {};
|
|
467
|
-
if (this.config.project.repo) defaults.repo = this.config.project.repo;
|
|
467
|
+
if (this.config.project.repo) defaults.repo = this.config.project.repo.name;
|
|
468
468
|
return defaults;
|
|
469
469
|
}
|
|
470
470
|
};
|
|
@@ -1058,7 +1058,7 @@ jobs:
|
|
|
1058
1058
|
id: metadata
|
|
1059
1059
|
|
|
1060
1060
|
- run: gh pr merge --auto --squash "$PR_URL"
|
|
1061
|
-
# --squash is intentional:
|
|
1061
|
+
# --squash is intentional: repo protection sets allow_merge_commit: false,
|
|
1062
1062
|
# so --merge would fail on any repo using the standard preset.
|
|
1063
1063
|
name: Enable auto-merge for Dependabot PRs
|
|
1064
1064
|
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
|
|
@@ -3682,6 +3682,25 @@ function vaultProviderName(loader) {
|
|
|
3682
3682
|
}
|
|
3683
3683
|
//#endregion
|
|
3684
3684
|
//#region src/commands/setup.ts
|
|
3685
|
+
/**
|
|
3686
|
+
* `holocron setup` — orchestrates per-capability setup actions across
|
|
3687
|
+
* every plugin loaded from `holocron.config.json`.
|
|
3688
|
+
*
|
|
3689
|
+
* Per CLAUDE.md soft-skip: each step is wrapped in a try/catch and
|
|
3690
|
+
* failures don't abort subsequent capabilities. The summary at the end
|
|
3691
|
+
* reports counts so the operator can see what worked + what didn't.
|
|
3692
|
+
*
|
|
3693
|
+
* Per the Standards: when `ctx.dryRun` is true, mutating calls are
|
|
3694
|
+
* replaced with "would" log lines. Read-only probes (e.g.,
|
|
3695
|
+
* `vault.list`) still run so the operator sees real state.
|
|
3696
|
+
*
|
|
3697
|
+
* The orchestrator knows about specific capability methods by name
|
|
3698
|
+
* (e.g., `source.enableVulnerabilityAlerts`). This deliberate coupling
|
|
3699
|
+
* makes the "what does setup do" contract explicit and concrete —
|
|
3700
|
+
* decoupling via a per-capability `setupSteps()` method would be more
|
|
3701
|
+
* extensible but pushes the same knowledge into N plugins instead of
|
|
3702
|
+
* one central place.
|
|
3703
|
+
*/
|
|
3685
3704
|
function editorconfigContent() {
|
|
3686
3705
|
return [
|
|
3687
3706
|
`# AUTO-GENERATED — do not edit directly.`,
|
|
@@ -4038,6 +4057,8 @@ async function runSetup(input) {
|
|
|
4038
4057
|
const config = input.loaded.resolved;
|
|
4039
4058
|
const dryRun = input.context.dryRun ?? false;
|
|
4040
4059
|
const steps = [];
|
|
4060
|
+
const repo = config.project.repo;
|
|
4061
|
+
const effectivePreset = repo?.protection;
|
|
4041
4062
|
print(`Holocron setup — ${config.project.name}${dryRun ? " (dry-run)" : ""}`);
|
|
4042
4063
|
print(` config: ${input.loaded.filepath}`);
|
|
4043
4064
|
print("");
|
|
@@ -4062,21 +4083,19 @@ async function runSetup(input) {
|
|
|
4062
4083
|
else return await source.enableCodeScanning();
|
|
4063
4084
|
}));
|
|
4064
4085
|
print(formatStep(steps[steps.length - 1]));
|
|
4065
|
-
|
|
4066
|
-
if (policy && policy.preset !== "none") {
|
|
4067
|
-
const preset = policy.preset ?? "balanced";
|
|
4086
|
+
if (effectivePreset && effectivePreset !== "none") {
|
|
4068
4087
|
steps.push(await runStep("source", "updateRepoSettings", dryRun, async () => {
|
|
4069
4088
|
await source.updateRepoSettings(BALANCED_REPO_SETTINGS);
|
|
4070
4089
|
}));
|
|
4071
4090
|
print(formatStep(steps[steps.length - 1]));
|
|
4072
4091
|
const configuredWorkflowNames = (config.project.workflows ?? []).map((entry) => typeof entry === "string" ? entry : entry.name);
|
|
4073
|
-
const requiredChecks =
|
|
4092
|
+
const requiredChecks = effectivePreset === "strict" ? [
|
|
4074
4093
|
"DCO",
|
|
4075
4094
|
...configuredWorkflowNames.flatMap((name) => {
|
|
4076
4095
|
const ctx = WORKFLOW_CHECK_CONTEXTS[name];
|
|
4077
4096
|
return ctx ? [ctx] : [];
|
|
4078
4097
|
}),
|
|
4079
|
-
...
|
|
4098
|
+
...repo?.requiredChecks ?? []
|
|
4080
4099
|
] : [];
|
|
4081
4100
|
steps.push(await upsertBranchProtection(source, dryRun, requiredChecks));
|
|
4082
4101
|
print(formatStep(steps[steps.length - 1]));
|
|
@@ -4112,7 +4131,7 @@ async function runSetup(input) {
|
|
|
4112
4131
|
}));
|
|
4113
4132
|
print(formatStep(steps[steps.length - 1]));
|
|
4114
4133
|
}
|
|
4115
|
-
if (loader.has("source") &&
|
|
4134
|
+
if (loader.has("source") && effectivePreset !== "none") {
|
|
4116
4135
|
const source = loader.get("source");
|
|
4117
4136
|
steps.push(await runStep("source", "write .github/dependabot.yml", dryRun, async () => {
|
|
4118
4137
|
await source.writeRepoFile(".github/dependabot.yml", DEPENDABOT_CONFIG);
|
|
@@ -4139,6 +4158,24 @@ async function runSetup(input) {
|
|
|
4139
4158
|
}));
|
|
4140
4159
|
print(formatStep(steps[steps.length - 1]));
|
|
4141
4160
|
}
|
|
4161
|
+
const properties = {};
|
|
4162
|
+
if (effectivePreset && effectivePreset !== "none") properties["branch_protection_level"] = effectivePreset;
|
|
4163
|
+
const isMonorepo = await access(join(input.context.repoRoot, "pnpm-workspace.yaml")).then(() => true).catch(() => false);
|
|
4164
|
+
properties["monorepo"] = String(isMonorepo);
|
|
4165
|
+
const manual = repo?.properties ?? {};
|
|
4166
|
+
if (manual.lifecycle) properties["lifecycle"] = manual.lifecycle;
|
|
4167
|
+
if (manual.open_source !== void 0) properties["open_source"] = String(manual.open_source);
|
|
4168
|
+
if (manual.runtime_environment) properties["runtime_environment"] = manual.runtime_environment;
|
|
4169
|
+
if (manual.uses_external_packages !== void 0) properties["uses_external_packages"] = String(manual.uses_external_packages);
|
|
4170
|
+
if (source.syncProperties) {
|
|
4171
|
+
steps.push(await runStep("source", "sync properties", dryRun, () => source.syncProperties(properties)));
|
|
4172
|
+
print(formatStep(steps[steps.length - 1]));
|
|
4173
|
+
}
|
|
4174
|
+
const topics = repo?.topics ?? [];
|
|
4175
|
+
if (topics.length > 0 && source.syncTopics) {
|
|
4176
|
+
steps.push(await runStep("source", "sync topics", dryRun, () => source.syncTopics(topics)));
|
|
4177
|
+
print(formatStep(steps[steps.length - 1]));
|
|
4178
|
+
}
|
|
4142
4179
|
}
|
|
4143
4180
|
if (loader.has("environments")) {
|
|
4144
4181
|
const envs = loader.get("environments");
|
|
@@ -4272,6 +4309,148 @@ function formatStep(step) {
|
|
|
4272
4309
|
return ` ${icon} ${step.step}${detail}`;
|
|
4273
4310
|
}
|
|
4274
4311
|
//#endregion
|
|
4312
|
+
//#region src/commands/sync.ts
|
|
4313
|
+
const SYNC_STEPS = [
|
|
4314
|
+
"labels",
|
|
4315
|
+
"properties",
|
|
4316
|
+
"topics"
|
|
4317
|
+
];
|
|
4318
|
+
async function runSync(input) {
|
|
4319
|
+
const print = input.print ?? ((line) => console.log(line));
|
|
4320
|
+
const loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);
|
|
4321
|
+
await loader.load();
|
|
4322
|
+
const config = input.loaded.resolved;
|
|
4323
|
+
const dryRun = input.context.dryRun ?? false;
|
|
4324
|
+
const requestedSteps = input.steps;
|
|
4325
|
+
const steps = [];
|
|
4326
|
+
print(`Holocron sync — ${config.project.name}${dryRun ? " (dry-run)" : ""}`);
|
|
4327
|
+
print(` config: ${input.loaded.filepath}`);
|
|
4328
|
+
print("");
|
|
4329
|
+
if (loader.has("source")) {
|
|
4330
|
+
const source = loader.get("source");
|
|
4331
|
+
print(" → source");
|
|
4332
|
+
for (const stepName of SYNC_STEPS) {
|
|
4333
|
+
if (requestedSteps !== void 0 && !requestedSteps.includes(stepName)) continue;
|
|
4334
|
+
if (stepName === "labels") if (source.syncLabels) {
|
|
4335
|
+
steps.push(await runSyncStep("source", "sync labels", dryRun, () => source.syncLabels(CANONICAL_LABELS, STALE_LABELS)));
|
|
4336
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
4337
|
+
} else {
|
|
4338
|
+
steps.push({
|
|
4339
|
+
capability: "source",
|
|
4340
|
+
step: "sync labels",
|
|
4341
|
+
status: "skip",
|
|
4342
|
+
message: "provider does not implement syncLabels"
|
|
4343
|
+
});
|
|
4344
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
4345
|
+
}
|
|
4346
|
+
if (stepName === "properties") if (source.syncProperties) {
|
|
4347
|
+
const repo = config.project.repo;
|
|
4348
|
+
const properties = {};
|
|
4349
|
+
const effectivePreset = repo?.protection;
|
|
4350
|
+
if (effectivePreset && effectivePreset !== "none") properties["branch_protection_level"] = effectivePreset;
|
|
4351
|
+
const isMonorepo = await access(join(input.context.repoRoot, "pnpm-workspace.yaml")).then(() => true).catch(() => false);
|
|
4352
|
+
properties["monorepo"] = String(isMonorepo);
|
|
4353
|
+
const manual = repo?.properties ?? {};
|
|
4354
|
+
if (manual.lifecycle) properties["lifecycle"] = manual.lifecycle;
|
|
4355
|
+
if (manual.open_source !== void 0) properties["open_source"] = String(manual.open_source);
|
|
4356
|
+
if (manual.runtime_environment) properties["runtime_environment"] = manual.runtime_environment;
|
|
4357
|
+
if (manual.uses_external_packages !== void 0) properties["uses_external_packages"] = String(manual.uses_external_packages);
|
|
4358
|
+
steps.push(await runSyncStep("source", "sync properties", dryRun, () => source.syncProperties(properties)));
|
|
4359
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
4360
|
+
} else {
|
|
4361
|
+
steps.push({
|
|
4362
|
+
capability: "source",
|
|
4363
|
+
step: "sync properties",
|
|
4364
|
+
status: "skip",
|
|
4365
|
+
message: "provider does not implement syncProperties"
|
|
4366
|
+
});
|
|
4367
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
4368
|
+
}
|
|
4369
|
+
if (stepName === "topics") {
|
|
4370
|
+
const topics = config.project.repo?.topics ?? [];
|
|
4371
|
+
if (topics.length === 0) {
|
|
4372
|
+
steps.push({
|
|
4373
|
+
capability: "source",
|
|
4374
|
+
step: "sync topics",
|
|
4375
|
+
status: "skip",
|
|
4376
|
+
message: "no topics configured"
|
|
4377
|
+
});
|
|
4378
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
4379
|
+
} else if (source.syncTopics) {
|
|
4380
|
+
steps.push(await runSyncStep("source", "sync topics", dryRun, () => source.syncTopics(topics)));
|
|
4381
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
4382
|
+
} else {
|
|
4383
|
+
steps.push({
|
|
4384
|
+
capability: "source",
|
|
4385
|
+
step: "sync topics",
|
|
4386
|
+
status: "skip",
|
|
4387
|
+
message: "provider does not implement syncTopics"
|
|
4388
|
+
});
|
|
4389
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
4390
|
+
}
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
if (requestedSteps) {
|
|
4394
|
+
for (const name of requestedSteps) if (!SYNC_STEPS.includes(name)) {
|
|
4395
|
+
steps.push({
|
|
4396
|
+
capability: "source",
|
|
4397
|
+
step: `sync ${name}`,
|
|
4398
|
+
status: "skip",
|
|
4399
|
+
message: `unknown step "${name}"`
|
|
4400
|
+
});
|
|
4401
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
const summary = steps.reduce((acc, s) => {
|
|
4406
|
+
if (s.status === "ok") acc.ok += 1;
|
|
4407
|
+
else if (s.status === "fail") acc.fail += 1;
|
|
4408
|
+
else if (s.status === "skip") acc.skip += 1;
|
|
4409
|
+
else if (s.status === "dry-run") acc.dryRun += 1;
|
|
4410
|
+
return acc;
|
|
4411
|
+
}, {
|
|
4412
|
+
ok: 0,
|
|
4413
|
+
fail: 0,
|
|
4414
|
+
skip: 0,
|
|
4415
|
+
dryRun: 0
|
|
4416
|
+
});
|
|
4417
|
+
print("");
|
|
4418
|
+
print(` ${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped${dryRun ? `, ${summary.dryRun} would-do` : ""}`);
|
|
4419
|
+
return {
|
|
4420
|
+
steps,
|
|
4421
|
+
summary
|
|
4422
|
+
};
|
|
4423
|
+
}
|
|
4424
|
+
async function runSyncStep(capability, step, dryRun, body) {
|
|
4425
|
+
if (dryRun) return {
|
|
4426
|
+
capability,
|
|
4427
|
+
step,
|
|
4428
|
+
status: "dry-run"
|
|
4429
|
+
};
|
|
4430
|
+
try {
|
|
4431
|
+
const note = await body();
|
|
4432
|
+
const result = {
|
|
4433
|
+
capability,
|
|
4434
|
+
step,
|
|
4435
|
+
status: "ok"
|
|
4436
|
+
};
|
|
4437
|
+
if (typeof note === "string") result.message = note;
|
|
4438
|
+
return result;
|
|
4439
|
+
} catch (err) {
|
|
4440
|
+
return {
|
|
4441
|
+
capability,
|
|
4442
|
+
step,
|
|
4443
|
+
status: "fail",
|
|
4444
|
+
message: err instanceof Error ? err.message : String(err)
|
|
4445
|
+
};
|
|
4446
|
+
}
|
|
4447
|
+
}
|
|
4448
|
+
function formatSyncStep(step) {
|
|
4449
|
+
const icon = step.status === "ok" ? "✓" : step.status === "fail" ? "✗" : step.status === "dry-run" ? "…" : "·";
|
|
4450
|
+
const detail = step.message ? ` (${step.message})` : "";
|
|
4451
|
+
return ` ${icon} ${step.step}${detail}`;
|
|
4452
|
+
}
|
|
4453
|
+
//#endregion
|
|
4275
4454
|
//#region src/load-config.ts
|
|
4276
4455
|
/**
|
|
4277
4456
|
* `holocron.config.{json,js,ts}` file loader.
|
|
@@ -4494,7 +4673,25 @@ await yargs(hideBin(process.argv)).scriptName("holocron").usage("$0 <command> [o
|
|
|
4494
4673
|
dryRun: argv.dryRun,
|
|
4495
4674
|
...argv.otp ? { otp: argv.otp } : {}
|
|
4496
4675
|
})).status === "fail") process.exitCode = 1;
|
|
4497
|
-
}).demandCommand(1, "Run `holocron npm --help` to see available npm subcommands."), () => {}).command("sync
|
|
4676
|
+
}).demandCommand(1, "Run `holocron npm --help` to see available npm subcommands."), () => {}).command("sync [steps..]", "Sync source-level state (labels, properties, topics) from config to the provider", (y) => y.positional("steps", {
|
|
4677
|
+
type: "string",
|
|
4678
|
+
array: true,
|
|
4679
|
+
describe: "Steps to run: labels, properties, topics (default: all)"
|
|
4680
|
+
}).option("repo", {
|
|
4681
|
+
type: "string",
|
|
4682
|
+
describe: "Repo coords (\"owner/name\"). Defaults to plugin-specific resolution."
|
|
4683
|
+
}), async (argv) => {
|
|
4684
|
+
if ((await runSync({
|
|
4685
|
+
loaded: await loadConfig(argv.cwd),
|
|
4686
|
+
context: {
|
|
4687
|
+
repoRoot: argv.cwd,
|
|
4688
|
+
dryRun: argv.dryRun,
|
|
4689
|
+
...argv.repo ? { repo: argv.repo } : {},
|
|
4690
|
+
...argv.token ? { cliToken: argv.token } : {}
|
|
4691
|
+
},
|
|
4692
|
+
...argv.steps && argv.steps.length > 0 ? { steps: argv.steps } : {}
|
|
4693
|
+
})).summary.fail > 0) process.exitCode = 1;
|
|
4694
|
+
}).command("sync-github", "Sync workflow templates and composite actions to theholocron/.github via the GitHub API", (y) => y.option("repo", {
|
|
4498
4695
|
type: "string",
|
|
4499
4696
|
default: "theholocron/.github",
|
|
4500
4697
|
describe: "Target org/repo (default: theholocron/.github)"
|
package/dist/index.d.mts
CHANGED
|
@@ -30,21 +30,27 @@ type SingleEntry = string | [provider: string, options: ProviderOptions];
|
|
|
30
30
|
type MultiEntry = Array<string | [provider: string, options: ProviderOptions]>;
|
|
31
31
|
type RawProviderEntry = SingleEntry | MultiEntry;
|
|
32
32
|
type RawProvidersConfig = Partial<Record<CapabilityKey, RawProviderEntry>>;
|
|
33
|
-
|
|
33
|
+
type RepoProtection = "balanced" | "strict" | "none";
|
|
34
|
+
interface RepoProperties {
|
|
35
|
+
lifecycle?: "active" | "experimental" | "deprecated";
|
|
36
|
+
open_source?: boolean;
|
|
37
|
+
runtime_environment?: "node" | "browser" | "universal" | "none";
|
|
38
|
+
uses_external_packages?: boolean;
|
|
39
|
+
}
|
|
40
|
+
interface RepoConfig {
|
|
41
|
+
/** "owner/name" — the GitHub repository coordinate. */
|
|
42
|
+
name: string;
|
|
34
43
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* plus a ruleset that blocks force-push + deletion and requires a pull request (0 reviews).
|
|
38
|
-
*
|
|
39
|
-
* "strict" — everything in "balanced" plus required status checks from `requiredChecks`.
|
|
40
|
-
*
|
|
41
|
-
* "none" — skips repo settings + ruleset entirely.
|
|
42
|
-
*
|
|
43
|
-
* @default "balanced"
|
|
44
|
+
* Branch protection preset applied by `holocron setup`. When omitted,
|
|
45
|
+
* no protection is applied and no `branch_protection_level` property is set.
|
|
44
46
|
*/
|
|
45
|
-
|
|
46
|
-
/** CI check context names required on the default branch (used
|
|
47
|
+
protection?: RepoProtection;
|
|
48
|
+
/** CI check context names required on the default branch (only used when `protection` is "strict"). */
|
|
47
49
|
requiredChecks?: string[];
|
|
50
|
+
/** GitHub topics set on the repository. */
|
|
51
|
+
topics?: string[];
|
|
52
|
+
/** GitHub custom properties synced to the org dashboard. */
|
|
53
|
+
properties?: RepoProperties;
|
|
48
54
|
}
|
|
49
55
|
interface AppConfig {
|
|
50
56
|
name: string;
|
|
@@ -59,18 +65,12 @@ interface HolocronConfig {
|
|
|
59
65
|
name: string;
|
|
60
66
|
description?: string;
|
|
61
67
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* need a repo (github, etc.) don't require `--repo` on every
|
|
65
|
-
*
|
|
66
|
-
*/
|
|
67
|
-
repo?: string;
|
|
68
|
-
/**
|
|
69
|
-
* Repo-level policy applied by `holocron setup`. Defines merge
|
|
70
|
-
* strategy, branch protection rulesets, and security defaults.
|
|
71
|
-
* Requires `source` capability to be configured.
|
|
68
|
+
* Repository identity and metadata. When set, `PluginLoader` injects
|
|
69
|
+
* `repo.name` into every plugin's `RuntimeContext.repo` so plugins that
|
|
70
|
+
* need a repo (github, etc.) don't require `--repo` on every invocation.
|
|
71
|
+
* `--repo` on the command line still overrides.
|
|
72
72
|
*/
|
|
73
|
-
|
|
73
|
+
repo?: RepoConfig;
|
|
74
74
|
/**
|
|
75
75
|
* CI workflow names to install as thin wrappers during `holocron setup`.
|
|
76
76
|
* Each name maps to a reusable workflow in `theholocron/.github`.
|
|
@@ -190,4 +190,4 @@ interface LoadedConfig {
|
|
|
190
190
|
*/
|
|
191
191
|
declare function loadConfig(cwd: string): Promise<LoadedConfig>;
|
|
192
192
|
//#endregion
|
|
193
|
-
export { Analytics, AppConfig, Auth, AuthDescription, AuthError, AuthEvent, AuthEventType, AuthIdentity, AuthUser, CARDINALITY, CapabilityConfigPackage, CapabilityImpls, CapabilityKey, Cardinality, CardinalityFor, Ci, CiRun, CiRunFilter, CiRunStatus, ConfigError, ConfigFileError, ConnectionStringOptions, CreateAuthUserInput, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, Dns, DnsRecord, DnsRecordType, DoctorConfig, EnsureResult, Environment, EnvironmentReviewer, Environments, HolocronConfig, Issue, IssueSearchFilter, Issues, LabelDef, LifecycleResult, LifecycleSlot, LoadedConfig, MultiEntry, NormalizedAuthUser, Notifications, Observability, ParseWebhookInput, ProviderApiError, ProviderIdentity, ProviderOptions, REQUIRED_CAPABILITIES, RawProviderEntry, RawProvidersConfig,
|
|
193
|
+
export { Analytics, AppConfig, Auth, AuthDescription, AuthError, AuthEvent, AuthEventType, AuthIdentity, AuthUser, CARDINALITY, CapabilityConfigPackage, CapabilityImpls, CapabilityKey, Cardinality, CardinalityFor, Ci, CiRun, CiRunFilter, CiRunStatus, ConfigError, ConfigFileError, ConnectionStringOptions, CreateAuthUserInput, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, Dns, DnsRecord, DnsRecordType, DoctorConfig, EnsureResult, Environment, EnvironmentReviewer, Environments, HolocronConfig, Issue, IssueSearchFilter, Issues, LabelDef, LifecycleResult, LifecycleSlot, LoadedConfig, MultiEntry, NormalizedAuthUser, Notifications, Observability, ParseWebhookInput, ProviderApiError, ProviderIdentity, ProviderOptions, REQUIRED_CAPABILITIES, RawProviderEntry, RawProvidersConfig, RepoConfig, RepoProperties, RepoProtection, RepoRef, RepoSettings, type RequestOptions, ResolveTokenConfig, type ResolveTokenInput, ResolvedCapability, ResolvedHolocronConfig, ResolvedProviderEntry, ResolvedProvidersConfig, ResolvedTuple, type RestClient, type RestClientConfig, Ruleset, SecretScope, Secrets, SingleEntry, Source, StatusCategory, Storage, StorageBranch, Tooling, ToolingDoctorReport, TrackerDoctorReport, TrackerUser, Vault, WebhookDashboardInfo, WebhookVerificationError, createResolveToken, createRestClient, defineConfig, deleteToken, getToken, isMulti, listStoredProviders, loadConfig, resolveConfig, resolveEntry, resolvePluginPackage, setToken };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/cli",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.45",
|
|
4
4
|
"description": "The Holocron CLI — a pluggable, capability-based orchestrator for spinning up and operating software projects.",
|
|
5
5
|
"homepage": "https://github.com/theholocron/holocron/tree/main/packages/cli#readme",
|
|
6
6
|
"bugs": "https://github.com/theholocron/holocron/issues",
|