@theholocron/cli 3.7.0 → 3.8.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/dist/cli.mjs +84 -4
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -889,7 +889,21 @@ function generateHolocronConfig(opts) {
|
|
|
889
889
|
if (opts.homepage) lines.push(`\thomepage: ${JSON.stringify(opts.homepage)},`);
|
|
890
890
|
const topics = opts.topics?.length ? opts.topics : [];
|
|
891
891
|
const hasRuntimeOverride = opts.runtimeEnvironment != null && opts.runtimeEnvironment !== "node";
|
|
892
|
-
if (
|
|
892
|
+
if (opts.org != null) {
|
|
893
|
+
const repoName = `${opts.org}/${opts.name}`;
|
|
894
|
+
lines.push(`\trepo: {`);
|
|
895
|
+
lines.push(`\t\tname: ${JSON.stringify(repoName)},`);
|
|
896
|
+
lines.push(`\t\tteams: [{ slug: "gatekeepers", permission: "maintain" }],`);
|
|
897
|
+
lines.push(`\t\ttopics: ${JSON.stringify(topics)},`);
|
|
898
|
+
lines.push(`\t\t...repo,`);
|
|
899
|
+
if (opts.protection && opts.protection !== "strict") lines.push(`\t\tprotection: ${JSON.stringify(opts.protection)},`);
|
|
900
|
+
const propParts = [];
|
|
901
|
+
if (hasRuntimeOverride) propParts.push(`runtime_environment: ${JSON.stringify(opts.runtimeEnvironment)}`);
|
|
902
|
+
if (opts.openSource === false) propParts.push(`open_source: false`);
|
|
903
|
+
if (opts.usesExternalPackages === false) propParts.push(`uses_external_packages: false`);
|
|
904
|
+
if (propParts.length > 0) lines.push(`\t\tproperties: { ...repo.properties, ${propParts.join(", ")} },`);
|
|
905
|
+
lines.push(`\t},`);
|
|
906
|
+
} else if (topics.length > 0 || hasRuntimeOverride) {
|
|
893
907
|
lines.push(`\trepo: {`);
|
|
894
908
|
if (topics.length > 0) lines.push(`\t\ttopics: ${JSON.stringify(topics)},`);
|
|
895
909
|
lines.push(`\t\t...repo,`);
|
|
@@ -917,6 +931,7 @@ function generateHolocronConfig(opts) {
|
|
|
917
931
|
lines.push(`\t},`);
|
|
918
932
|
} else lines.push(`\tproviders,`);
|
|
919
933
|
if (opts.agent && opts.agent !== "none") lines.push(`\tagent: ${JSON.stringify(opts.agent)},`);
|
|
934
|
+
if (opts.skills?.length) lines.push(`\tskills: ${JSON.stringify(opts.skills)},`);
|
|
920
935
|
lines.push(`});`);
|
|
921
936
|
lines.push(``);
|
|
922
937
|
return lines.join("\n");
|
|
@@ -1029,11 +1044,14 @@ async function runNew(input) {
|
|
|
1029
1044
|
} catch {}
|
|
1030
1045
|
print(` Detected template slug: ${templateSlug}`);
|
|
1031
1046
|
print(` Patching files…`);
|
|
1032
|
-
const
|
|
1047
|
+
const variants = deriveVariants(templateSlug, input.name);
|
|
1048
|
+
variants.unshift([`theholocron/${templateSlug}`, `${org}/${input.name}`]);
|
|
1049
|
+
const filesPatched = patchFiles(repoDir, variants, input.description, input.homepage, input.runtimeEnvironment, print, readFn, writeFn, walkFn);
|
|
1033
1050
|
print(` ${filesPatched.length} file${filesPatched.length === 1 ? "" : "s"} patched`);
|
|
1034
1051
|
const configContent = generateHolocronConfig({
|
|
1035
1052
|
name: input.name,
|
|
1036
1053
|
type: input.type,
|
|
1054
|
+
org,
|
|
1037
1055
|
description: input.description,
|
|
1038
1056
|
homepage: input.homepage,
|
|
1039
1057
|
vaultProvider: input.vaultProvider,
|
|
@@ -1042,7 +1060,11 @@ async function runNew(input) {
|
|
|
1042
1060
|
deploymentProvider: input.deploymentProvider,
|
|
1043
1061
|
agent: input.agent,
|
|
1044
1062
|
runtimeEnvironment: input.runtimeEnvironment,
|
|
1045
|
-
|
|
1063
|
+
protection: input.protection,
|
|
1064
|
+
openSource: input.openSource,
|
|
1065
|
+
usesExternalPackages: input.usesExternalPackages,
|
|
1066
|
+
topics: input.topics,
|
|
1067
|
+
skills: input.skills
|
|
1046
1068
|
});
|
|
1047
1069
|
writeFn(path.join(repoDir, "holocron.config.ts"), configContent);
|
|
1048
1070
|
print(` Generated holocron.config.ts`);
|
|
@@ -4024,7 +4046,7 @@ var setup_node_default = "name: Setup Node\ndescription: Install pnpm and Node.j
|
|
|
4024
4046
|
var audit_default = "name: Audit\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n build-script:\n description: Script to build and upload bundle stats to Codecov\n type: string\n required: false\n default: pnpm build\n run-knip:\n description: Run Knip to detect unused files, exports, and dependencies\n type: boolean\n required: false\n default: false\n knip-script:\n description: Script that invokes Knip (must exit non-zero on findings)\n type: string\n required: false\n default: pnpm run audit\n secrets:\n CODECOV_TOKEN:\n required: false\n TURBO_TOKEN:\n required: false\n\njobs:\n bundle-size:\n name: Audit the bundle size\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n concurrency:\n group: audit-${{ github.ref }}\n cancel-in-progress: true\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$BUILD_SCRIPT\"\n name: Build and upload bundle stats\n env:\n BUILD_SCRIPT: ${{ inputs.build-script }}\n CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n\n knip:\n name: Knip\n if: ${{ inputs.run-knip }}\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\n concurrency:\n group: knip-${{ github.ref }}\n cancel-in-progress: true\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n persist-credentials: false\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: eval \"$KNIP_SCRIPT\"\n name: Run Knip\n env:\n KNIP_SCRIPT: ${{ inputs.knip-script }}\n";
|
|
4025
4047
|
//#endregion
|
|
4026
4048
|
//#region src/templates/workflows/bookkeeping.yml
|
|
4027
|
-
var bookkeeping_default = "name: Bookkeeping\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n configuration-path:\n description: Path to the labeler configuration file in the calling repo\n type: string\n required: false\n default: .github/labeler.yml\n\njobs:\n label:\n name: Apply Labels\n permissions:\n contents: read\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n concurrency:\n group: bookkeeping-${{ github.event.pull_request.number || github.event.issue.number }}\n cancel-in-progress: true\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n sparse-checkout: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n sparse-checkout-cone-mode: false\n\n - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4\n if: ${{ github.event_name == 'pull_request' && hashFiles(inputs.configuration-path || '.github/labeler.yml') != '' }}\n # v3.4 bundles Node 20; allow it to run under Actions' current default.\n env:\n ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true\n with:\n # Fall back to default path when triggered directly (not via workflow_call)\n # because inputs.* defaults only apply on workflow_call events.\n configuration-path: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n include-title: 1\n include-body: 0\n sync-labels: 1\n enable-versioned-regex: 0\n repo-token: ${{ github.token }}\n";
|
|
4049
|
+
var bookkeeping_default = "name: Bookkeeping\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n configuration-path:\n description: Path to the labeler configuration file in the calling repo\n type: string\n required: false\n default: .github/labeler.yml\n\njobs:\n label:\n name: Apply Labels\n permissions:\n contents: read\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n concurrency:\n group: bookkeeping-${{ github.event.pull_request.number || github.event.issue.number }}\n cancel-in-progress: true\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n sparse-checkout: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n sparse-checkout-cone-mode: false\n\n - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4\n if: ${{ github.event_name == 'pull_request' && hashFiles(inputs.configuration-path || '.github/labeler.yml') != '' }}\n # v3.4 bundles Node 20; allow it to run under Actions' current default.\n env:\n ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true\n with:\n # Fall back to default path when triggered directly (not via workflow_call)\n # because inputs.* defaults only apply on workflow_call events.\n configuration-path: ${{ inputs.configuration-path || '.github/labeler.yml' }}\n include-title: 1\n include-body: 0\n sync-labels: 1\n enable-versioned-regex: 0\n repo-token: ${{ github.token }}\n";
|
|
4028
4050
|
//#endregion
|
|
4029
4051
|
//#region src/templates/workflows/codeql.yml
|
|
4030
4052
|
var codeql_default = "name: CodeQL\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n language:\n description: CodeQL language to analyze\n type: string\n required: false\n default: javascript-typescript\n\njobs:\n analyze:\n name: Analyze (${{ inputs.language }})\n permissions:\n actions: read\n contents: read\n security-events: write\n runs-on: ubuntu-latest\n timeout-minutes: 45\n # Do not cancel in-progress security scans.\n concurrency:\n group: codeql-${{ github.ref }}\n cancel-in-progress: false\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n\n - uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Initialize CodeQL\n with:\n languages: ${{ inputs.language }}\n\n - uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Autobuild\n\n - uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0\n name: Analyze\n with:\n category: /language:${{ inputs.language }}\n";
|
|
@@ -5205,6 +5227,18 @@ try {
|
|
|
5205
5227
|
}).option("topics", {
|
|
5206
5228
|
type: "string",
|
|
5207
5229
|
describe: "Comma-separated repo topics (e.g. typescript,nodejs)"
|
|
5230
|
+
}).option("protection", {
|
|
5231
|
+
type: "string",
|
|
5232
|
+
describe: "Branch protection level: strict, balanced, minimal"
|
|
5233
|
+
}).option("open-source", {
|
|
5234
|
+
type: "boolean",
|
|
5235
|
+
describe: "Whether the repo is open source (default: true)"
|
|
5236
|
+
}).option("uses-external-packages", {
|
|
5237
|
+
type: "boolean",
|
|
5238
|
+
describe: "Whether the repo calls external APIs or services (default: true)"
|
|
5239
|
+
}).option("skills", {
|
|
5240
|
+
type: "string",
|
|
5241
|
+
describe: "Comma-separated agent skill names (e.g. git-safety,pr-workflow)"
|
|
5208
5242
|
}).option("org", {
|
|
5209
5243
|
type: "string",
|
|
5210
5244
|
default: "theholocron",
|
|
@@ -5226,6 +5260,10 @@ try {
|
|
|
5226
5260
|
let agent = argv.agent;
|
|
5227
5261
|
let runtimeEnvironment = argv.runtimeEnvironment;
|
|
5228
5262
|
let topics = parseTopics(argv.topics);
|
|
5263
|
+
let protection = argv.protection;
|
|
5264
|
+
let openSource = argv.openSource;
|
|
5265
|
+
let usesExternalPackages = argv.usesExternalPackages;
|
|
5266
|
+
let skills = parseTopics(argv.skills);
|
|
5229
5267
|
if (!type) type = await select({
|
|
5230
5268
|
message: "Template type:",
|
|
5231
5269
|
choices: [
|
|
@@ -5341,6 +5379,44 @@ try {
|
|
|
5341
5379
|
}]
|
|
5342
5380
|
});
|
|
5343
5381
|
if (topics.length === 0) topics = parseTopics(await input({ message: "Topics (comma-separated, optional):" }));
|
|
5382
|
+
if (!protection) protection = await select({
|
|
5383
|
+
message: "Branch protection:",
|
|
5384
|
+
choices: [
|
|
5385
|
+
{
|
|
5386
|
+
name: "strict — required reviews + passing checks",
|
|
5387
|
+
value: "strict"
|
|
5388
|
+
},
|
|
5389
|
+
{
|
|
5390
|
+
name: "balanced — required reviews, flexible checks",
|
|
5391
|
+
value: "balanced"
|
|
5392
|
+
},
|
|
5393
|
+
{
|
|
5394
|
+
name: "minimal — branch protection only",
|
|
5395
|
+
value: "minimal"
|
|
5396
|
+
}
|
|
5397
|
+
]
|
|
5398
|
+
});
|
|
5399
|
+
if (openSource === void 0) openSource = await select({
|
|
5400
|
+
message: "Open source?",
|
|
5401
|
+
choices: [{
|
|
5402
|
+
name: "Yes",
|
|
5403
|
+
value: "yes"
|
|
5404
|
+
}, {
|
|
5405
|
+
name: "No",
|
|
5406
|
+
value: "no"
|
|
5407
|
+
}]
|
|
5408
|
+
}) === "yes";
|
|
5409
|
+
if (usesExternalPackages === void 0) usesExternalPackages = await select({
|
|
5410
|
+
message: "Uses external APIs or services?",
|
|
5411
|
+
choices: [{
|
|
5412
|
+
name: "Yes",
|
|
5413
|
+
value: "yes"
|
|
5414
|
+
}, {
|
|
5415
|
+
name: "No",
|
|
5416
|
+
value: "no"
|
|
5417
|
+
}]
|
|
5418
|
+
}) === "yes";
|
|
5419
|
+
if (skills.length === 0) skills = parseTopics(await input({ message: "Agent skills (comma-separated, optional):" }));
|
|
5344
5420
|
if (!type) {
|
|
5345
5421
|
console.error("new: template type is required");
|
|
5346
5422
|
process.exitCode = 1;
|
|
@@ -5362,7 +5438,11 @@ try {
|
|
|
5362
5438
|
deploymentProvider: deploymentProvider ?? "none",
|
|
5363
5439
|
agent: agent ?? "claude",
|
|
5364
5440
|
runtimeEnvironment: runtimeEnvironment ?? "node",
|
|
5441
|
+
protection: protection ?? "strict",
|
|
5442
|
+
openSource: openSource ?? true,
|
|
5443
|
+
usesExternalPackages: usesExternalPackages ?? true,
|
|
5365
5444
|
topics,
|
|
5445
|
+
skills,
|
|
5366
5446
|
org: argv.org,
|
|
5367
5447
|
dryRun: argv.dryRun,
|
|
5368
5448
|
noVerify: !argv.verify,
|