@theholocron/cli 2.0.0-alpha.63 → 2.0.0-alpha.65

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.
Files changed (2) hide show
  1. package/dist/cli.mjs +215 -1149
  2. package/package.json +2 -2
package/dist/cli.mjs CHANGED
@@ -3,11 +3,13 @@ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSy
3
3
  import path, { basename, dirname, join } from "node:path";
4
4
  import yargs from "yargs";
5
5
  import { hideBin } from "yargs/helpers";
6
+ import { createInterface } from "node:readline";
7
+ import { stdin, stdout } from "node:process";
6
8
  import { ProviderApiError, ProviderApiError as ProviderApiError$1 } from "@theholocron/http-client";
7
9
  import { Entry, findCredentials } from "@napi-rs/keyring";
8
10
  import { createHash } from "node:crypto";
9
11
  import { createGitHubClient } from "@theholocron/github-client";
10
- import { execFile, spawnSync } from "node:child_process";
12
+ import { execFile, execFileSync, spawnSync } from "node:child_process";
11
13
  import { access, readFile, readdir, stat, writeFile } from "node:fs/promises";
12
14
  import { pathToFileURL } from "node:url";
13
15
  import { promisify } from "node:util";
@@ -834,879 +836,132 @@ async function runUpgradeNode(input) {
834
836
  };
835
837
  }
836
838
  //#endregion
839
+ //#region src/templates/actions/setup.yml
840
+ var setup_default = "name: Setup\ndescription: Prepare the environment and install project dependencies.\n\ninputs:\n node-version:\n description: Node.js version\n required: false\n default: \"22.x\"\n\nruns:\n using: composite\n\n steps:\n - uses: theholocron/.github/.github/actions/setup-node@main\n with:\n node-version: ${{ inputs.node-version }}\n\n - uses: theholocron/.github/.github/actions/install@main\n";
841
+ //#endregion
842
+ //#region src/templates/actions/install.yml
843
+ var install_default = "name: Install dependencies\ndescription: Install project dependencies with pnpm frozen lockfile.\n\nruns:\n using: composite\n\n steps:\n - name: Install dependencies\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n shell: bash\n run: pnpm install --frozen-lockfile\n";
844
+ //#endregion
845
+ //#region src/templates/actions/setup-node.yml
846
+ var setup_node_default = "name: Setup Node\ndescription: Install pnpm and Node.js with pnpm dependency caching.\n\ninputs:\n node-version:\n description: Node.js version\n required: false\n default: \"22.x\"\n\nruns:\n using: composite\n\n steps:\n - name: Setup pnpm\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4\n\n - name: Setup Node.js\n uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4\n with:\n node-version: ${{ hashFiles('.node-version') != '' && '' || inputs.node-version }}\n node-version-file: ${{ hashFiles('.node-version') != '' && '.node-version' || '' }}\n cache: ${{ hashFiles('pnpm-lock.yaml') != '' && 'pnpm' || '' }}\n\n - name: Add node_modules/.bin to PATH\n shell: bash\n run: echo \"$GITHUB_WORKSPACE/node_modules/.bin\" >> $GITHUB_PATH\n";
847
+ //#endregion
848
+ //#region src/templates/workflows/audit.yml
849
+ var audit_default$1 = "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 secrets:\n CODECOV_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 steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\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";
850
+ //#endregion
851
+ //#region src/templates/workflows/bookkeeping.yml
852
+ var bookkeeping_default$1 = "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: ${{ 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";
853
+ //#endregion
854
+ //#region src/templates/workflows/codeql.yml
855
+ var codeql_default$1 = "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";
856
+ //#endregion
857
+ //#region src/templates/workflows/dependencies.yml
858
+ var dependencies_default$1 = "name: Dependencies\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n merge-token:\n description: >\n Optional privileged token for auto-merge. Falls back to GITHUB_TOKEN.\n Required when branch protection enforces required reviews — GITHUB_TOKEN\n cannot approve its own PRs.\n required: false\n\njobs:\n dependabot:\n name: Update the dependencies\n permissions:\n contents: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n concurrency:\n group: dependencies-${{ github.event.pull_request.number }}\n cancel-in-progress: true\n if: github.event.pull_request.user.login == 'dependabot[bot]'\n steps:\n - uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0\n name: Fetch Dependabot metadata\n id: metadata\n\n - run: gh pr merge --auto --squash \"$PR_URL\"\n # --squash is intentional: repo protection sets allow_merge_commit: false,\n # so --merge would fail on any repo using the standard preset.\n name: Enable auto-merge for Dependabot PRs\n if: steps.metadata.outputs.update-type == 'version-update:semver-patch'\n env:\n PR_URL: ${{ github.event.pull_request.html_url }}\n GH_TOKEN: ${{ secrets.merge-token || github.token }}\n";
859
+ //#endregion
860
+ //#region src/templates/workflows/greetings.yml
861
+ var greetings_default$1 = "name: Greetings\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n\njobs:\n greeting:\n name: Greet first-time contributors\n permissions:\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 5\n # Group by the issue/PR number so duplicate events don't race each other.\n concurrency:\n group: greetings-${{ github.event.issue.number || github.event.pull_request.number }}\n cancel-in-progress: false\n steps:\n - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0\n name: Greet on first contribution\n with:\n script: |\n // Only greet on the initial open — ignore synchronize, reopened, etc.\n if (context.payload.action !== 'opened') return;\n\n const actor = context.actor;\n const { owner, repo } = context.repo;\n\n // Payload inspection is more reliable than context.eventName for detecting\n // whether this is an issue vs. PR event — works regardless of how GitHub\n // propagates event names through workflow_call chains.\n const isIssue = !!context.payload.issue && !context.payload.pull_request;\n // listForRepo returns both issues and PRs (GitHub treats PRs as issues),\n // sorted newest-first. Filter by type to track first-issue and first-PR\n // independently, and avoid search-index eventual-consistency lag.\n const { data: recent } = await github.rest.issues.listForRepo({\n owner, repo,\n creator: actor,\n state: 'all',\n per_page: 100\n });\n\n const sameType = recent.filter(item =>\n isIssue ? !item.pull_request : !!item.pull_request\n );\n\n if (sameType.length !== 1) return;\n const body = isIssue\n ? `Hey @${actor}!\\n\\nWe really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.`\n : `Hey @${actor}!\\n\\nWe really appreciate you taking the time to help out with this PR. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.`;\n\n await github.rest.issues.createComment({\n owner,\n repo,\n issue_number: context.issue.number,\n body\n });\n";
862
+ //#endregion
863
+ //#region src/templates/workflows/lint.yml
864
+ var lint_default$1 = "name: Lint\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n prettier-config:\n type: string\n required: false\n default: prettier.config.js\n yaml-config:\n type: string\n required: false\n default: yamllint.config.yml\n enable-auto-commit:\n description: Auto-commit super-linter fixes via GPG-signed commit\n type: boolean\n required: false\n default: false\n secrets:\n SUPER_LINTER_GPG_PRIVATE_KEY:\n required: false\n SUPER_LINTER_GPG_PASSPHRASE:\n required: false\n\njobs:\n super-lint:\n name: Lint entire codebase\n permissions:\n contents: write\n statuses: write\n runs-on: ubuntu-latest\n timeout-minutes: 30\n env:\n GPG_KEY_SET: ${{ secrets.SUPER_LINTER_GPG_PRIVATE_KEY != '' }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n token: ${{ github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n\n - uses: super-linter/super-linter/slim@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0\n name: Run Super Linter\n env:\n GITHUB_TOKEN: ${{ github.token }}\n DEFAULT_BRANCH: ${{ github.event.pull_request.base.ref || github.event.repository.default_branch }}\n ANNOTATE_ONLY: true\n DISABLE_COMMENTS: false\n IGNORE_GITIGNORED_FILES: true\n LINTER_RULES_PATH: /\n EDITORCONFIG_FILE_NAME: \".editorconfig-checker.json\"\n FIX_ENV: true\n FIX_GRAPHQL_PRETTIER: true\n FIX_HTML_PRETTIER: true\n FIX_JAVASCRIPT_PRETTIER: true\n FIX_JSX_PRETTIER: true\n FIX_MARKDOWN_PRETTIER: true\n FIX_TSX: true\n FIX_TYPESCRIPT_PRETTIER: true\n PRETTIER_CONFIG: ${{ inputs.prettier-config }}\n VALIDATE_DOCKERFILE: true\n VALIDATE_EDITORCONFIG: true\n VALIDATE_ENV: true\n VALIDATE_GIT_COMMITLINT: true\n VALIDATE_GIT_MERGE_CONFLICT_MARKERS: true\n VALIDATE_GITHUB_ACTIONS: true\n VALIDATE_GITLEAKS: true\n VALIDATE_GRAPHQL_PRETTIER: true\n VALIDATE_HTML_PRETTIER: true\n VALIDATE_JAVASCRIPT_PRETTIER: true\n VALIDATE_JSX_PRETTIER: true\n VALIDATE_MARKDOWN_PRETTIER: true\n VALIDATE_TSX: true\n VALIDATE_TYPESCRIPT_PRETTIER: true\n VALIDATE_YAML: true\n YAML_CONFIG_FILE: ${{ inputs.yaml-config }}\n\n - uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0\n name: Import GPG Key\n # Conditions mirror auto-commit exactly — no point importing GPG if the\n # commit step will be skipped (fork PR, default branch, or secret unset).\n if: >\n inputs.enable-auto-commit == true &&\n github.event.pull_request != null &&\n github.event.pull_request.head.repo.full_name == github.repository &&\n github.ref_name != github.event.repository.default_branch &&\n env.GPG_KEY_SET == 'true'\n with:\n git_user_signingkey: true\n git_commit_gpgsign: true\n GPG_PRIVATE_KEY: ${{ secrets.SUPER_LINTER_GPG_PRIVATE_KEY }}\n PASSPHRASE: ${{ secrets.SUPER_LINTER_GPG_PASSPHRASE }}\n\n - uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0\n name: Commit and push linting fixes\n if: >\n inputs.enable-auto-commit == true &&\n github.event.pull_request != null &&\n github.event.pull_request.head.repo.full_name == github.repository &&\n github.ref_name != github.event.repository.default_branch &&\n env.GPG_KEY_SET == 'true'\n with:\n branch: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref }}\n commit_message: \"chore: fix linting issues\\n\\nSigned-off-by: super-linter <super-linter@super-linter.dev>\"\n commit_options: \"--no-verify\"\n commit_user_name: super-linter\n commit_user_email: super-linter@super-linter.dev\n";
865
+ //#endregion
866
+ //#region src/templates/workflows/release.yml
867
+ var release_default$1 = "name: Release\n\n# Semantic-release with OIDC Trusted Publishing — no NPM_TOKEN required.\n# The calling repo must have a .releaserc.json that configures branches,\n# plugins, and any publish options. npm@11+ is installed to support OIDC.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n run-build:\n description: Run `pnpm build` before releasing\n type: boolean\n required: false\n default: true\n secrets:\n SYNC_TOKEN:\n description: >\n Optional PAT with Contents write access. Required when the default\n branch is protected by a ruleset — github.token cannot push through\n rulesets, but a PAT with admin bypass can. Falls back to github.token.\n required: false\n\njobs:\n release:\n name: Semantic release\n permissions:\n contents: write\n id-token: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 30\n # Do not cancel in-progress releases — a partial release is worse than a slow one.\n concurrency:\n group: release-${{ github.ref }}\n cancel-in-progress: false\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n # Use SYNC_TOKEN when available — git push (tags, release commits)\n # uses the checkout credential, not GITHUB_TOKEN env var. The\n # built-in github.token cannot push through branch protection rulesets.\n token: ${{ secrets.SYNC_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Configure git identity\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n git config --global user.name \"$GIT_NAME\"\n git config --global user.email \"$GIT_EMAIL\"\n git config --global format.signoff true\n env:\n GH_TOKEN: ${{ secrets.SYNC_TOKEN || github.token }}\n\n - run: npm install -g npm@11 sigstore\n name: Upgrade npm for OIDC support\n # sigstore is required by libnpmpublish/provenance.js at module parse\n # time — before any config takes effect. Some npm 11.x builds stopped\n # bundling it; installing it globally into the same prefix ensures it\n # resolves regardless of npm version. (Discovered 2026-07-09.)\n\n - run: pnpm build\n name: Build\n if: ${{ inputs.run-build == true }}\n\n - run: npx semantic-release\n name: Release\n env:\n # Prefer SYNC_TOKEN (a PAT with Contents write) when available —\n # the built-in github.token cannot push to protected default branches\n # because rulesets block non-PAT pushes. Falls back to github.token\n # for repos without branch protection.\n GITHUB_TOKEN: ${{ secrets.SYNC_TOKEN || github.token }}\n NPM_CONFIG_PROVENANCE: true\n";
868
+ //#endregion
869
+ //#region src/templates/workflows/review.yml
870
+ var review_default$1 = "name: Review\n\n# ReviewDog is the annotation layer — posts inline PR diff annotations.\n# Runs on pull_request only: inline annotations require PR context,\n# and branch protection ensures all changes go through PRs anyway.\n# super-linter (lint.yml) is the CI gate covering push + PR events.\n# Gitleaks and YAML are intentionally duplicated: super-linter gates\n# merges; ReviewDog surfaces exact line annotations in the PR diff.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n\nconcurrency:\n group: review-${{ github.workflow }}-${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n reviewdog:\n name: Review PRs\n runs-on: ubuntu-latest\n timeout-minutes: 20\n permissions:\n contents: read\n checks: write\n pull-requests: write\n\n steps:\n - name: Checkout repository\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n\n - name: Setup\n if: ${{ hashFiles('pnpm-lock.yaml') != '' }}\n uses: theholocron/.github/.github/actions/setup@main\n\n - name: Install ReviewDog\n uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1\n with:\n reviewdog_version: latest\n\n # Detect which tools are relevant for this repo, excluding node_modules.\n # hashFiles('**/*') recurses into node_modules/.pnpm and produces false\n # positives for repos that don't own those file types.\n # -print -quit stops find after the first match without a pipe, avoiding\n # the SIGPIPE/pipefail exit-141 that find|head-1 triggers under\n # GitHub Actions' default bash --noprofile --norc -e -o pipefail mode.\n - name: Detect project features\n id: detect\n shell: bash\n run: |\n has() { find . -not -path '*/node_modules/*' -name \"$1\" -print -quit 2>/dev/null | grep -q .; }\n has_ext() { find . -not -path '*/node_modules/*' -name \"$1\" -print -quit 2>/dev/null | grep -q .; }\n { { has 'eslint.config.js' || has 'eslint.config.mjs' || has 'eslint.config.cjs' || \\\n has 'eslint.config.ts' || has '.eslintrc' || has '.eslintrc.js' || \\\n has '.eslintrc.cjs' || has '.eslintrc.json' || has '.eslintrc.yaml' || \\\n has '.eslintrc.yml'; } && grep -qF '\"eslint\":' package.json 2>/dev/null; } && echo \"eslint=true\" >> \"$GITHUB_OUTPUT\" || echo \"eslint=false\" >> \"$GITHUB_OUTPUT\"\n { has 'tsconfig.json' && grep -qF '\"typescript\":' package.json 2>/dev/null; } && echo \"tsconfig=true\" >> \"$GITHUB_OUTPUT\" || echo \"tsconfig=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '*.sh' && echo \"shell=true\" >> \"$GITHUB_OUTPUT\" || echo \"shell=false\" >> \"$GITHUB_OUTPUT\"\n has 'Dockerfile' || has_ext '*.Dockerfile' || has 'Containerfile' && \\\n echo \"docker=true\" >> \"$GITHUB_OUTPUT\" || echo \"docker=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '.env*' && echo \"dotenv=true\" >> \"$GITHUB_OUTPUT\" || echo \"dotenv=false\" >> \"$GITHUB_OUTPUT\"\n has_ext '*.md' && echo \"markdown=true\" >> \"$GITHUB_OUTPUT\" || echo \"markdown=false\" >> \"$GITHUB_OUTPUT\"\n\n #\n # Always applicable\n #\n\n - name: Gitleaks (secrets)\n uses: reviewdog/action-gitleaks@2b7b5685e3e3eecddab5d30cfa04f18123031421 # v1\n with:\n reporter: github-pr-check\n gitleaks_flags: --log-opts=${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}\n\n - name: YamlLint\n if: ${{ hashFiles('yamllint.config.yml') != '' }}\n uses: reviewdog/action-yamllint@b5f7217d8c815ae374d1d55840d5e569d82f01f0 # v1\n with:\n reporter: github-pr-check\n yamllint_flags: -c ${{ github.workspace }}/yamllint.config.yml ${{ github.workspace }}\n\n - name: ActionLint (GitHub Actions)\n if: ${{ hashFiles('.github/workflows/*.yml', '.github/workflows/*.yaml') != '' }}\n uses: reviewdog/action-actionlint@6fb7acc99f4a1008869fa8a0f09cfca740837d9d # v1\n with:\n reporter: github-pr-check\n\n #\n # TypeScript / JavaScript\n #\n\n - name: ESLint\n if: steps.detect.outputs.eslint == 'true'\n uses: reviewdog/action-eslint@556a3fdaf8b4201d4d74d406013386aa4f7dab96 # v1.34.0\n with:\n reporter: github-pr-check\n eslint_flags: .\n\n - name: TypeScript\n if: steps.detect.outputs.tsconfig == 'true'\n uses: EPMatt/reviewdog-action-tsc@63d923a3c5b4497671940b8874f58a404e2351b5 # v1\n with:\n reporter: github-pr-check\n\n #\n # Shell\n #\n\n - name: ShellCheck\n if: steps.detect.outputs.shell == 'true'\n uses: reviewdog/action-shellcheck@4c07458293ac342d477251099501a718ae5ef86e # v1\n with:\n reporter: github-pr-check\n fail_level: none\n\n #\n # Docker\n #\n\n - name: Hadolint\n if: steps.detect.outputs.docker == 'true'\n uses: reviewdog/action-hadolint@1b2cfa6ba72072ad35158d7ff3aa49bbdc03506d # v1\n with:\n reporter: github-pr-check\n fail_level: none\n\n #\n # Environment files\n #\n\n - name: dotenv-linter\n if: steps.detect.outputs.dotenv == 'true'\n uses: dotenv-linter/action-dotenv-linter@afde61cfda2ecffe7bea35837b6f20b956c88689 # v3.0.0\n with:\n reporter: github-code-suggestions\n\n #\n # Documentation\n #\n\n - name: Alex (inclusive language)\n if: steps.detect.outputs.markdown == 'true'\n uses: reviewdog/action-alex@347481655add010a2ae302df34b57c9bcfa0d6e4 # v1\n with:\n reporter: github-pr-check\n";
871
+ //#endregion
872
+ //#region src/templates/workflows/stale.yml
873
+ var stale_default$1 = "name: Stale\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n days-before-stale:\n description: Days of inactivity before an issue is marked stale\n type: number\n required: false\n default: 30\n days-before-close:\n description: Days of inactivity after stale label before closing\n type: number\n required: false\n default: 5\n\njobs:\n stale:\n name: Mark stale issues and pull requests\n permissions:\n contents: write\n issues: write\n pull-requests: write\n runs-on: ubuntu-latest\n timeout-minutes: 10\n steps:\n - uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0\n name: Run Stale\n with:\n close-issue-message: >\n This issue was closed because it has been stalled for\n ${{ inputs.days-before-close }} days with no activity.\n days-before-close: ${{ inputs.days-before-close }}\n days-before-stale: ${{ inputs.days-before-stale }}\n exempt-all-pr-milestones: true\n stale-issue-label: wontfix\n stale-issue-message: >\n This issue is stale because it has been open ${{ inputs.days-before-stale }}\n days with no activity. Remove the stale label or comment, or this will be\n closed in ${{ inputs.days-before-close }} days.\n stale-pr-label: wontfix\n stale-pr-message: >\n This PR is stale because it has been open ${{ inputs.days-before-stale }}\n days with no activity. Remove the stale label or comment, or this will be\n closed in ${{ inputs.days-before-close }} days.\n";
874
+ //#endregion
875
+ //#region src/templates/workflows/sync-github.yml
876
+ var sync_github_default$1 = "name: Sync GitHub Templates\n\n# Builds the holocron CLI from source and pushes updated workflow templates\n# and composite actions to downstream .github repos. Runs whenever the\n# template source files change on main or alpha.\n#\n# Secrets required:\n# SYNC_TOKEN — fine-grained PAT (resource owner: org) with:\n# Contents: Read and write (git trees, blobs, refs)\n# Pull requests: Read and write (open sync PR)\n# Workflows: Read and write (write .github/workflows/*.yml)\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n primary-repo:\n description: >\n Primary .github repo — receives composite actions, reusable workflows,\n and thin-caller templates. Requires a PR (branch protection assumed).\n type: string\n required: false\n default: theholocron/.github\n secondary-repos:\n description: >\n Space-separated list of secondary repos (reusable workflows + thin\n callers only, no composite actions). Changes are delivered via pull\n request, same as the primary repo.\n type: string\n required: false\n default: \"\"\n sync-branch:\n description: Branch name used for the primary and secondary repo PRs\n type: string\n required: false\n default: chore/sync-templates\n secrets:\n SYNC_TOKEN:\n required: true\n\njobs:\n sync:\n name: Sync templates\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\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: pnpm build\n name: Build CLI\n\n - name: Validate generated workflows\n run: |\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --output-dir /tmp/sync-validate\n curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz \\\n | tar -xz -C /tmp actionlint\n /tmp/actionlint /tmp/sync-validate/.github/workflows/*.yml\n env:\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n\n - name: Sync primary repo (PR)\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$PRIMARY_REPO\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n env:\n GITHUB_TOKEN: ${{ secrets.SYNC_TOKEN }}\n GH_TOKEN: ${{ secrets.SYNC_TOKEN }}\n PRIMARY_REPO: ${{ inputs.primary-repo }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n\n - name: Sync secondary repos (PR)\n if: ${{ inputs.secondary-repos != '' }}\n run: |\n GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo \"github-actions[bot]\")\n GIT_EMAIL=$(gh api user --jq '\"\\(.id)+\\(.login)@users.noreply.github.com\"' 2>/dev/null || echo \"41898282+github-actions[bot]@users.noreply.github.com\")\n COMMIT_MSG=\"chore: sync from theholocron/holocron\"$'\\n\\n'\"Signed-off-by: $GIT_NAME <$GIT_EMAIL>\"\n for repo in $SECONDARY_REPOS; do\n node packages/cli/dist/cli.mjs sync-github \\\n --repo \"$repo\" \\\n --branch \"$SYNC_BRANCH\" \\\n --pr \\\n --message \"$COMMIT_MSG\"\n done\n env:\n GITHUB_TOKEN: ${{ secrets.SYNC_TOKEN }}\n GH_TOKEN: ${{ secrets.SYNC_TOKEN }}\n SECONDARY_REPOS: ${{ inputs.secondary-repos }}\n SYNC_BRANCH: ${{ inputs.sync-branch }}\n";
877
+ //#endregion
878
+ //#region src/templates/workflows/test.yml
879
+ var test_default$1 = "name: Test\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n CODECOV_TOKEN:\n required: false\n\njobs:\n unit:\n name: Run tests and collect coverage\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 15\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n fetch-depth: 0\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - run: pnpm test -- --coverage\n name: Run tests with coverage\n\n - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0\n name: Upload coverage to Codecov\n with:\n token: ${{ secrets.CODECOV_TOKEN }}\n\n - uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1\n name: Upload test results to Codecov\n if: ${{ !cancelled() }}\n with:\n token: ${{ secrets.CODECOV_TOKEN }}\n files: '**/test-report.junit.xml'\n";
880
+ //#endregion
881
+ //#region src/templates/workflows/typecheck.yml
882
+ var typecheck_default$1 = "name: Typecheck\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n\njobs:\n typecheck:\n name: tsc --noEmit\n permissions:\n contents: read\n runs-on: ubuntu-latest\n timeout-minutes: 10\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: pnpm typecheck\n name: Type check\n";
883
+ //#endregion
837
884
  //#region src/templates/index.ts
838
885
  /**
839
886
  * All reusable workflow and composite action content bundled as string
840
887
  * constants so the CLI can push them to theholocron/.github without
841
888
  * needing filesystem access at runtime.
842
889
  *
843
- * These are the sources of truth the YAML files in this directory
844
- * have been removed in favour of these constants.
890
+ * Content lives in standalone .yml files; the rawYml rollup plugin
891
+ * inlines them as string exports at build time.
845
892
  */
846
893
  const ACTIONS = {
847
- "setup/action": `\
848
- name: Setup
849
- description: Prepare the environment and install project dependencies.
850
-
851
- inputs:
852
- node-version:
853
- description: Node.js version
854
- required: false
855
- default: "22.x"
856
-
857
- runs:
858
- using: composite
859
-
860
- steps:
861
- - uses: theholocron/.github/.github/actions/setup-node@main
862
- with:
863
- node-version: \${{ inputs.node-version }}
864
-
865
- - uses: theholocron/.github/.github/actions/install@main
866
- `,
867
- "install/action": `\
868
- name: Install dependencies
869
- description: Install project dependencies with pnpm frozen lockfile.
870
-
871
- runs:
872
- using: composite
873
-
874
- steps:
875
- - name: Install dependencies
876
- if: \${{ hashFiles('pnpm-lock.yaml') != '' }}
877
- shell: bash
878
- run: pnpm install --frozen-lockfile
879
- `,
880
- "setup-node/action": `\
881
- name: Setup Node
882
- description: Install pnpm and Node.js with pnpm dependency caching.
883
-
884
- inputs:
885
- node-version:
886
- description: Node.js version
887
- required: false
888
- default: "22.x"
889
-
890
- runs:
891
- using: composite
892
-
893
- steps:
894
- - name: Setup pnpm
895
- if: \${{ hashFiles('pnpm-lock.yaml') != '' }}
896
- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
897
-
898
- - name: Setup Node.js
899
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
900
- with:
901
- node-version: \${{ hashFiles('.node-version') != '' && '' || inputs.node-version }}
902
- node-version-file: \${{ hashFiles('.node-version') != '' && '.node-version' || '' }}
903
- cache: \${{ hashFiles('pnpm-lock.yaml') != '' && 'pnpm' || '' }}
904
-
905
- - name: Add node_modules/.bin to PATH
906
- shell: bash
907
- run: echo "$GITHUB_WORKSPACE/node_modules/.bin" >> $GITHUB_PATH
908
- `
894
+ "setup/action": setup_default,
895
+ "install/action": install_default,
896
+ "setup-node/action": setup_node_default
909
897
  };
910
898
  const REUSABLE_WORKFLOWS = {
911
- audit: `\
912
- name: Audit
913
-
914
- on: # yamllint disable-line rule:truthy
915
- workflow_call:
916
- inputs:
917
- build-script:
918
- description: Script to build and upload bundle stats to Codecov
919
- type: string
920
- required: false
921
- default: pnpm build
922
- secrets:
923
- CODECOV_TOKEN:
924
- required: false
925
-
926
- jobs:
927
- bundle-size:
928
- name: Audit the bundle size
929
- permissions:
930
- contents: read
931
- runs-on: ubuntu-latest
932
- timeout-minutes: 15
933
- concurrency:
934
- group: audit-\${{ github.ref }}
935
- cancel-in-progress: true
936
- steps:
937
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
938
- name: Checkout repository
939
- with:
940
- fetch-depth: 0
941
-
942
- - uses: theholocron/.github/.github/actions/setup@main
943
- name: Setup
944
-
945
- - run: eval "$BUILD_SCRIPT"
946
- name: Build and upload bundle stats
947
- env:
948
- BUILD_SCRIPT: \${{ inputs.build-script }}
949
- CODECOV_TOKEN: \${{ secrets.CODECOV_TOKEN }}
950
- `,
951
- bookkeeping: `\
952
- name: Bookkeeping
953
-
954
- on: # yamllint disable-line rule:truthy
955
- workflow_call:
956
- inputs:
957
- configuration-path:
958
- description: Path to the labeler configuration file in the calling repo
959
- type: string
960
- required: false
961
- default: .github/labeler.yml
962
-
963
- jobs:
964
- label:
965
- name: Apply Labels
966
- permissions:
967
- contents: read
968
- issues: write
969
- pull-requests: write
970
- runs-on: ubuntu-latest
971
- timeout-minutes: 5
972
- concurrency:
973
- group: bookkeeping-\${{ github.event.pull_request.number || github.event.issue.number }}
974
- cancel-in-progress: true
975
- steps:
976
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
977
- with:
978
- sparse-checkout: \${{ inputs.configuration-path || '.github/labeler.yml' }}
979
- sparse-checkout-cone-mode: false
980
-
981
- - uses: github/issue-labeler@c1b0f9f52a63158c4adc09425e858e87b32e9685 # v3.4
982
- if: \${{ hashFiles(inputs.configuration-path || '.github/labeler.yml') != '' }}
983
- # v3.4 bundles Node 20; allow it to run under Actions' current default.
984
- env:
985
- ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
986
- with:
987
- # Fall back to default path when triggered directly (not via workflow_call)
988
- # because inputs.* defaults only apply on workflow_call events.
989
- configuration-path: \${{ inputs.configuration-path || '.github/labeler.yml' }}
990
- include-title: 1
991
- include-body: 0
992
- sync-labels: 1
993
- enable-versioned-regex: 0
994
- repo-token: \${{ github.token }}
995
- `,
996
- codeql: `\
997
- name: CodeQL
998
-
999
- on: # yamllint disable-line rule:truthy
1000
- workflow_call:
1001
- inputs:
1002
- language:
1003
- description: CodeQL language to analyze
1004
- type: string
1005
- required: false
1006
- default: javascript-typescript
1007
-
1008
- jobs:
1009
- analyze:
1010
- name: Analyze (\${{ inputs.language }})
1011
- permissions:
1012
- actions: read
1013
- contents: read
1014
- security-events: write
1015
- runs-on: ubuntu-latest
1016
- timeout-minutes: 45
1017
- # Do not cancel in-progress security scans.
1018
- concurrency:
1019
- group: codeql-\${{ github.ref }}
1020
- cancel-in-progress: false
1021
- steps:
1022
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1023
- name: Checkout repository
1024
-
1025
- - uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
1026
- name: Initialize CodeQL
1027
- with:
1028
- languages: \${{ inputs.language }}
1029
-
1030
- - uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
1031
- name: Autobuild
1032
-
1033
- - uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
1034
- name: Analyze
1035
- with:
1036
- category: /language:\${{ inputs.language }}
1037
- `,
1038
- dependencies: `\
1039
- name: Dependencies
1040
-
1041
- on: # yamllint disable-line rule:truthy
1042
- workflow_call:
1043
- secrets:
1044
- merge-token:
1045
- description: >
1046
- Optional privileged token for auto-merge. Falls back to GITHUB_TOKEN.
1047
- Required when branch protection enforces required reviews — GITHUB_TOKEN
1048
- cannot approve its own PRs.
1049
- required: false
1050
-
1051
- jobs:
1052
- dependabot:
1053
- name: Update the dependencies
1054
- permissions:
1055
- contents: write
1056
- pull-requests: write
1057
- runs-on: ubuntu-latest
1058
- timeout-minutes: 5
1059
- concurrency:
1060
- group: dependencies-\${{ github.event.pull_request.number }}
1061
- cancel-in-progress: true
1062
- if: github.event.pull_request.user.login == 'dependabot[bot]'
1063
- steps:
1064
- - uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
1065
- name: Fetch Dependabot metadata
1066
- id: metadata
1067
-
1068
- - run: gh pr merge --auto --squash "$PR_URL"
1069
- # --squash is intentional: repo protection sets allow_merge_commit: false,
1070
- # so --merge would fail on any repo using the standard preset.
1071
- name: Enable auto-merge for Dependabot PRs
1072
- if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
1073
- env:
1074
- PR_URL: \${{ github.event.pull_request.html_url }}
1075
- GH_TOKEN: \${{ secrets.merge-token || github.token }}
1076
- `,
1077
- greetings: `\
1078
- name: Greetings
1079
-
1080
- on: # yamllint disable-line rule:truthy
1081
- workflow_call:
1082
-
1083
- jobs:
1084
- greeting:
1085
- name: Greet first-time contributors
1086
- permissions:
1087
- issues: write
1088
- pull-requests: write
1089
- runs-on: ubuntu-latest
1090
- timeout-minutes: 5
1091
- # Group by the issue/PR number so duplicate events don't race each other.
1092
- concurrency:
1093
- group: greetings-\${{ github.event.issue.number || github.event.pull_request.number }}
1094
- cancel-in-progress: false
1095
- steps:
1096
- - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
1097
- name: Greet on first contribution
1098
- with:
1099
- script: |
1100
- // Only greet on the initial open — ignore synchronize, reopened, etc.
1101
- if (context.payload.action !== 'opened') return;
1102
-
1103
- const actor = context.actor;
1104
- const { owner, repo } = context.repo;
1105
-
1106
- // Payload inspection is more reliable than context.eventName for detecting
1107
- // whether this is an issue vs. PR event — works regardless of how GitHub
1108
- // propagates event names through workflow_call chains.
1109
- const isIssue = !!context.payload.issue && !context.payload.pull_request;
1110
- // listForRepo returns both issues and PRs (GitHub treats PRs as issues),
1111
- // sorted newest-first. Filter by type to track first-issue and first-PR
1112
- // independently, and avoid search-index eventual-consistency lag.
1113
- const { data: recent } = await github.rest.issues.listForRepo({
1114
- owner, repo,
1115
- creator: actor,
1116
- state: 'all',
1117
- per_page: 100
1118
- });
1119
-
1120
- const sameType = recent.filter(item =>
1121
- isIssue ? !item.pull_request : !!item.pull_request
1122
- );
1123
-
1124
- if (sameType.length !== 1) return;
1125
- const body = isIssue
1126
- ? \`Hey @\${actor}!\\n\\nWe really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.\`
1127
- : \`Hey @\${actor}!\\n\\nWe really appreciate you taking the time to help out with this PR. The collaborators on this project attempt to help as many people as possible, but we are a limited number of volunteers, so it is possible that this will not be addressed as swiftly.\\n\\nYour patience is much appreciated and we will get back to you as quickly as possible.\`;
1128
-
1129
- await github.rest.issues.createComment({
1130
- owner,
1131
- repo,
1132
- issue_number: context.issue.number,
1133
- body
1134
- });
1135
- `,
1136
- lint: `\
1137
- name: Lint
1138
-
1139
- on: # yamllint disable-line rule:truthy
1140
- workflow_call:
1141
- inputs:
1142
- prettier-config:
1143
- type: string
1144
- required: false
1145
- default: prettier.config.js
1146
- yaml-config:
1147
- type: string
1148
- required: false
1149
- default: yamllint.config.yml
1150
- enable-auto-commit:
1151
- description: Auto-commit super-linter fixes via GPG-signed commit
1152
- type: boolean
1153
- required: false
1154
- default: false
1155
- secrets:
1156
- SUPER_LINTER_GPG_PRIVATE_KEY:
1157
- required: false
1158
- SUPER_LINTER_GPG_PASSPHRASE:
1159
- required: false
1160
-
1161
- jobs:
1162
- super-lint:
1163
- name: Lint entire codebase
1164
- permissions:
1165
- contents: write
1166
- statuses: write
1167
- runs-on: ubuntu-latest
1168
- timeout-minutes: 30
1169
- env:
1170
- GPG_KEY_SET: \${{ secrets.SUPER_LINTER_GPG_PRIVATE_KEY != '' }}
1171
- steps:
1172
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1173
- name: Checkout repository
1174
- with:
1175
- fetch-depth: 0
1176
- token: \${{ github.token }}
1177
-
1178
- - uses: theholocron/.github/.github/actions/setup@main
1179
- name: Setup
1180
- if: \${{ hashFiles('pnpm-lock.yaml') != '' }}
1181
-
1182
- - uses: super-linter/super-linter/slim@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0
1183
- name: Run Super Linter
1184
- env:
1185
- GITHUB_TOKEN: \${{ github.token }}
1186
- DEFAULT_BRANCH: \${{ github.event.pull_request.base.ref || github.event.repository.default_branch }}
1187
- ANNOTATE_ONLY: true
1188
- DISABLE_COMMENTS: false
1189
- IGNORE_GITIGNORED_FILES: true
1190
- LINTER_RULES_PATH: /
1191
- EDITORCONFIG_FILE_NAME: ".editorconfig-checker.json"
1192
- FIX_ENV: true
1193
- FIX_GRAPHQL_PRETTIER: true
1194
- FIX_HTML_PRETTIER: true
1195
- FIX_JAVASCRIPT_PRETTIER: true
1196
- FIX_JSX_PRETTIER: true
1197
- FIX_MARKDOWN_PRETTIER: true
1198
- FIX_TSX: true
1199
- FIX_TYPESCRIPT_PRETTIER: true
1200
- PRETTIER_CONFIG: \${{ inputs.prettier-config }}
1201
- VALIDATE_DOCKERFILE: true
1202
- VALIDATE_EDITORCONFIG: true
1203
- VALIDATE_ENV: true
1204
- VALIDATE_GIT_COMMITLINT: true
1205
- VALIDATE_GIT_MERGE_CONFLICT_MARKERS: true
1206
- VALIDATE_GITHUB_ACTIONS: true
1207
- VALIDATE_GITLEAKS: true
1208
- VALIDATE_GRAPHQL_PRETTIER: true
1209
- VALIDATE_HTML_PRETTIER: true
1210
- VALIDATE_JAVASCRIPT_PRETTIER: true
1211
- VALIDATE_JSX_PRETTIER: true
1212
- VALIDATE_MARKDOWN_PRETTIER: true
1213
- VALIDATE_TSX: true
1214
- VALIDATE_TYPESCRIPT_PRETTIER: true
1215
- VALIDATE_YAML: true
1216
- YAML_CONFIG_FILE: \${{ inputs.yaml-config }}
1217
-
1218
- - uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd # v7.0.0
1219
- name: Import GPG Key
1220
- # Conditions mirror auto-commit exactly — no point importing GPG if the
1221
- # commit step will be skipped (fork PR, default branch, or secret unset).
1222
- if: >
1223
- inputs.enable-auto-commit == true &&
1224
- github.event.pull_request != null &&
1225
- github.event.pull_request.head.repo.full_name == github.repository &&
1226
- github.ref_name != github.event.repository.default_branch &&
1227
- env.GPG_KEY_SET == 'true'
1228
- with:
1229
- git_user_signingkey: true
1230
- git_commit_gpgsign: true
1231
- GPG_PRIVATE_KEY: \${{ secrets.SUPER_LINTER_GPG_PRIVATE_KEY }}
1232
- PASSPHRASE: \${{ secrets.SUPER_LINTER_GPG_PASSPHRASE }}
1233
-
1234
- - uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0
1235
- name: Commit and push linting fixes
1236
- if: >
1237
- inputs.enable-auto-commit == true &&
1238
- github.event.pull_request != null &&
1239
- github.event.pull_request.head.repo.full_name == github.repository &&
1240
- github.ref_name != github.event.repository.default_branch &&
1241
- env.GPG_KEY_SET == 'true'
1242
- with:
1243
- branch: \${{ github.event.pull_request.head.ref || github.head_ref || github.ref }}
1244
- commit_message: "chore: fix linting issues\\n\\nSigned-off-by: super-linter <super-linter@super-linter.dev>"
1245
- commit_options: "--no-verify"
1246
- commit_user_name: super-linter
1247
- commit_user_email: super-linter@super-linter.dev
1248
- `,
1249
- release: `\
1250
- name: Release
1251
-
1252
- # Semantic-release with OIDC Trusted Publishing — no NPM_TOKEN required.
1253
- # The calling repo must have a .releaserc.json that configures branches,
1254
- # plugins, and any publish options. npm@11+ is installed to support OIDC.
1255
-
1256
- on: # yamllint disable-line rule:truthy
1257
- workflow_call:
1258
- inputs:
1259
- run-build:
1260
- description: Run \`pnpm build\` before releasing
1261
- type: boolean
1262
- required: false
1263
- default: true
1264
- secrets:
1265
- SYNC_TOKEN:
1266
- description: >
1267
- Optional PAT with Contents write access. Required when the default
1268
- branch is protected by a ruleset — github.token cannot push through
1269
- rulesets, but a PAT with admin bypass can. Falls back to github.token.
1270
- required: false
1271
-
1272
- jobs:
1273
- release:
1274
- name: Semantic release
1275
- permissions:
1276
- contents: write
1277
- id-token: write
1278
- issues: write
1279
- pull-requests: write
1280
- runs-on: ubuntu-latest
1281
- timeout-minutes: 30
1282
- # Do not cancel in-progress releases — a partial release is worse than a slow one.
1283
- concurrency:
1284
- group: release-\${{ github.ref }}
1285
- cancel-in-progress: false
1286
- steps:
1287
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1288
- name: Checkout repository
1289
- with:
1290
- fetch-depth: 0
1291
- # Use SYNC_TOKEN when available — git push (tags, release commits)
1292
- # uses the checkout credential, not GITHUB_TOKEN env var. The
1293
- # built-in github.token cannot push through branch protection rulesets.
1294
- token: \${{ secrets.SYNC_TOKEN || github.token }}
1295
-
1296
- - uses: theholocron/.github/.github/actions/setup@main
1297
- name: Setup
1298
-
1299
- - name: Configure git identity
1300
- run: |
1301
- GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo "github-actions[bot]")
1302
- GIT_EMAIL=$(gh api user --jq '"\\(.id)+\\(.login)@users.noreply.github.com"' 2>/dev/null || echo "41898282+github-actions[bot]@users.noreply.github.com")
1303
- git config --global user.name "$GIT_NAME"
1304
- git config --global user.email "$GIT_EMAIL"
1305
- git config --global format.signoff true
1306
- env:
1307
- GH_TOKEN: \${{ secrets.SYNC_TOKEN || github.token }}
1308
-
1309
- - run: npm install -g npm@11 sigstore
1310
- name: Upgrade npm for OIDC support
1311
- # sigstore is required by libnpmpublish/provenance.js at module parse
1312
- # time — before any config takes effect. Some npm 11.x builds stopped
1313
- # bundling it; installing it globally into the same prefix ensures it
1314
- # resolves regardless of npm version. (Discovered 2026-07-09.)
1315
-
1316
- - run: pnpm build
1317
- name: Build
1318
- if: \${{ inputs.run-build == true }}
1319
-
1320
- - run: npx semantic-release
1321
- name: Release
1322
- env:
1323
- # Prefer SYNC_TOKEN (a PAT with Contents write) when available —
1324
- # the built-in github.token cannot push to protected default branches
1325
- # because rulesets block non-PAT pushes. Falls back to github.token
1326
- # for repos without branch protection.
1327
- GITHUB_TOKEN: \${{ secrets.SYNC_TOKEN || github.token }}
1328
- NPM_CONFIG_PROVENANCE: true
1329
- `,
1330
- review: `\
1331
- name: Review
1332
-
1333
- # ReviewDog is the annotation layer — posts inline PR diff annotations.
1334
- # Runs on pull_request only: inline annotations require PR context,
1335
- # and branch protection ensures all changes go through PRs anyway.
1336
- # super-linter (lint.yml) is the CI gate covering push + PR events.
1337
- # Gitleaks and YAML are intentionally duplicated: super-linter gates
1338
- # merges; ReviewDog surfaces exact line annotations in the PR diff.
1339
-
1340
- on: # yamllint disable-line rule:truthy
1341
- workflow_call:
1342
-
1343
- concurrency:
1344
- group: review-\${{ github.workflow }}-\${{ github.ref }}
1345
- cancel-in-progress: true
1346
-
1347
- jobs:
1348
- reviewdog:
1349
- name: Review PRs
1350
- runs-on: ubuntu-latest
1351
- timeout-minutes: 20
1352
- permissions:
1353
- contents: read
1354
- checks: write
1355
- pull-requests: write
1356
-
1357
- steps:
1358
- - name: Checkout repository
1359
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1360
- with:
1361
- fetch-depth: 0
1362
-
1363
- - name: Setup
1364
- if: \${{ hashFiles('pnpm-lock.yaml') != '' }}
1365
- uses: theholocron/.github/.github/actions/setup@main
1366
-
1367
- - name: Install ReviewDog
1368
- uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1
1369
- with:
1370
- reviewdog_version: latest
1371
-
1372
- # Detect which tools are relevant for this repo, excluding node_modules.
1373
- # hashFiles('**/*') recurses into node_modules/.pnpm and produces false
1374
- # positives for repos that don't own those file types.
1375
- # -print -quit stops find after the first match without a pipe, avoiding
1376
- # the SIGPIPE/pipefail exit-141 that find|head-1 triggers under
1377
- # GitHub Actions' default bash --noprofile --norc -e -o pipefail mode.
1378
- - name: Detect project features
1379
- id: detect
1380
- shell: bash
1381
- run: |
1382
- has() { find . -not -path '*/node_modules/*' -name "$1" -print -quit 2>/dev/null | grep -q .; }
1383
- has_ext() { find . -not -path '*/node_modules/*' -name "$1" -print -quit 2>/dev/null | grep -q .; }
1384
- { { has 'eslint.config.js' || has 'eslint.config.mjs' || has 'eslint.config.cjs' || \\
1385
- has 'eslint.config.ts' || has '.eslintrc' || has '.eslintrc.js' || \\
1386
- has '.eslintrc.cjs' || has '.eslintrc.json' || has '.eslintrc.yaml' || \\
1387
- has '.eslintrc.yml'; } && grep -qF '"eslint":' package.json 2>/dev/null; } && echo "eslint=true" >> "$GITHUB_OUTPUT" || echo "eslint=false" >> "$GITHUB_OUTPUT"
1388
- { has 'tsconfig.json' && grep -qF '"typescript":' package.json 2>/dev/null; } && echo "tsconfig=true" >> "$GITHUB_OUTPUT" || echo "tsconfig=false" >> "$GITHUB_OUTPUT"
1389
- has_ext '*.sh' && echo "shell=true" >> "$GITHUB_OUTPUT" || echo "shell=false" >> "$GITHUB_OUTPUT"
1390
- has 'Dockerfile' || has_ext '*.Dockerfile' || has 'Containerfile' && \\
1391
- echo "docker=true" >> "$GITHUB_OUTPUT" || echo "docker=false" >> "$GITHUB_OUTPUT"
1392
- has_ext '.env*' && echo "dotenv=true" >> "$GITHUB_OUTPUT" || echo "dotenv=false" >> "$GITHUB_OUTPUT"
1393
- has_ext '*.md' && echo "markdown=true" >> "$GITHUB_OUTPUT" || echo "markdown=false" >> "$GITHUB_OUTPUT"
1394
-
1395
- #
1396
- # Always applicable
1397
- #
1398
-
1399
- - name: Gitleaks (secrets)
1400
- uses: reviewdog/action-gitleaks@2b7b5685e3e3eecddab5d30cfa04f18123031421 # v1
1401
- with:
1402
- reporter: github-pr-check
1403
- gitleaks_flags: --log-opts=\${{ github.event.pull_request.base.sha }}..\${{ github.event.pull_request.head.sha }}
1404
-
1405
- - name: YamlLint
1406
- if: \${{ hashFiles('yamllint.config.yml') != '' }}
1407
- uses: reviewdog/action-yamllint@b5f7217d8c815ae374d1d55840d5e569d82f01f0 # v1
1408
- with:
1409
- reporter: github-pr-check
1410
- yamllint_flags: -c \${{ github.workspace }}/yamllint.config.yml \${{ github.workspace }}
1411
-
1412
- - name: ActionLint (GitHub Actions)
1413
- if: \${{ hashFiles('.github/workflows/*.yml', '.github/workflows/*.yaml') != '' }}
1414
- uses: reviewdog/action-actionlint@6fb7acc99f4a1008869fa8a0f09cfca740837d9d # v1
1415
- with:
1416
- reporter: github-pr-check
1417
-
1418
- #
1419
- # TypeScript / JavaScript
1420
- #
1421
-
1422
- - name: ESLint
1423
- if: steps.detect.outputs.eslint == 'true'
1424
- uses: reviewdog/action-eslint@556a3fdaf8b4201d4d74d406013386aa4f7dab96 # v1.34.0
1425
- with:
1426
- reporter: github-pr-check
1427
- eslint_flags: .
1428
-
1429
- - name: TypeScript
1430
- if: steps.detect.outputs.tsconfig == 'true'
1431
- uses: EPMatt/reviewdog-action-tsc@63d923a3c5b4497671940b8874f58a404e2351b5 # v1
1432
- with:
1433
- reporter: github-pr-check
1434
-
1435
- #
1436
- # Shell
1437
- #
1438
-
1439
- - name: ShellCheck
1440
- if: steps.detect.outputs.shell == 'true'
1441
- uses: reviewdog/action-shellcheck@4c07458293ac342d477251099501a718ae5ef86e # v1
1442
- with:
1443
- reporter: github-pr-check
1444
- fail_level: none
1445
-
1446
- #
1447
- # Docker
1448
- #
1449
-
1450
- - name: Hadolint
1451
- if: steps.detect.outputs.docker == 'true'
1452
- uses: reviewdog/action-hadolint@1b2cfa6ba72072ad35158d7ff3aa49bbdc03506d # v1
1453
- with:
1454
- reporter: github-pr-check
1455
- fail_level: none
1456
-
1457
- #
1458
- # Environment files
1459
- #
1460
-
1461
- - name: dotenv-linter
1462
- if: steps.detect.outputs.dotenv == 'true'
1463
- uses: dotenv-linter/action-dotenv-linter@afde61cfda2ecffe7bea35837b6f20b956c88689 # v3.0.0
1464
- with:
1465
- reporter: github-code-suggestions
1466
-
1467
- #
1468
- # Documentation
1469
- #
1470
-
1471
- - name: Alex (inclusive language)
1472
- if: steps.detect.outputs.markdown == 'true'
1473
- uses: reviewdog/action-alex@347481655add010a2ae302df34b57c9bcfa0d6e4 # v1
1474
- with:
1475
- reporter: github-pr-check
1476
- `,
1477
- stale: `\
1478
- name: Stale
1479
-
1480
- on: # yamllint disable-line rule:truthy
1481
- workflow_call:
1482
- inputs:
1483
- days-before-stale:
1484
- description: Days of inactivity before an issue is marked stale
1485
- type: number
1486
- required: false
1487
- default: 30
1488
- days-before-close:
1489
- description: Days of inactivity after stale label before closing
1490
- type: number
1491
- required: false
1492
- default: 5
1493
-
1494
- jobs:
1495
- stale:
1496
- name: Mark stale issues and pull requests
1497
- permissions:
1498
- contents: write
1499
- issues: write
1500
- pull-requests: write
1501
- runs-on: ubuntu-latest
1502
- timeout-minutes: 10
1503
- steps:
1504
- - uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10.4.0
1505
- name: Run Stale
1506
- with:
1507
- close-issue-message: >
1508
- This issue was closed because it has been stalled for
1509
- \${{ inputs.days-before-close }} days with no activity.
1510
- days-before-close: \${{ inputs.days-before-close }}
1511
- days-before-stale: \${{ inputs.days-before-stale }}
1512
- exempt-all-pr-milestones: true
1513
- stale-issue-label: wontfix
1514
- stale-issue-message: >
1515
- This issue is stale because it has been open \${{ inputs.days-before-stale }}
1516
- days with no activity. Remove the stale label or comment, or this will be
1517
- closed in \${{ inputs.days-before-close }} days.
1518
- stale-pr-label: wontfix
1519
- stale-pr-message: >
1520
- This PR is stale because it has been open \${{ inputs.days-before-stale }}
1521
- days with no activity. Remove the stale label or comment, or this will be
1522
- closed in \${{ inputs.days-before-close }} days.
1523
- `,
1524
- test: `\
1525
- name: Test
1526
-
1527
- on: # yamllint disable-line rule:truthy
1528
- workflow_call:
1529
- secrets:
1530
- CODECOV_TOKEN:
1531
- required: false
1532
-
1533
- jobs:
1534
- unit:
1535
- name: Run tests and collect coverage
1536
- permissions:
1537
- contents: read
1538
- runs-on: ubuntu-latest
1539
- timeout-minutes: 15
1540
- steps:
1541
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1542
- name: Checkout repository
1543
- with:
1544
- fetch-depth: 0
1545
-
1546
- - uses: theholocron/.github/.github/actions/setup@main
1547
- name: Setup
1548
-
1549
- - run: pnpm test -- --coverage
1550
- name: Run tests with coverage
1551
-
1552
- - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
1553
- name: Upload coverage to Codecov
1554
- with:
1555
- token: \${{ secrets.CODECOV_TOKEN }}
1556
-
1557
- - uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3 # v1
1558
- name: Upload test results to Codecov
1559
- if: \${{ !cancelled() }}
1560
- with:
1561
- token: \${{ secrets.CODECOV_TOKEN }}
1562
- files: '**/test-report.junit.xml'
1563
- `,
1564
- "sync-github": `\
1565
- name: Sync GitHub Templates
1566
-
1567
- # Builds the holocron CLI from source and pushes updated workflow templates
1568
- # and composite actions to downstream .github repos. Runs whenever the
1569
- # template source files change on main or alpha.
1570
- #
1571
- # Secrets required:
1572
- # SYNC_TOKEN — fine-grained PAT (resource owner: org) with:
1573
- # Contents: Read and write (git trees, blobs, refs)
1574
- # Pull requests: Read and write (open sync PR)
1575
- # Workflows: Read and write (write .github/workflows/*.yml)
1576
-
1577
- on: # yamllint disable-line rule:truthy
1578
- workflow_call:
1579
- inputs:
1580
- primary-repo:
1581
- description: >
1582
- Primary .github repo — receives composite actions, reusable workflows,
1583
- and thin-caller templates. Requires a PR (branch protection assumed).
1584
- type: string
1585
- required: false
1586
- default: theholocron/.github
1587
- secondary-repos:
1588
- description: >
1589
- Space-separated list of secondary repos (reusable workflows + thin
1590
- callers only, no composite actions). Changes are delivered via pull
1591
- request, same as the primary repo.
1592
- type: string
1593
- required: false
1594
- default: ""
1595
- sync-branch:
1596
- description: Branch name used for the primary and secondary repo PRs
1597
- type: string
1598
- required: false
1599
- default: chore/sync-templates
1600
- secrets:
1601
- SYNC_TOKEN:
1602
- required: true
1603
-
1604
- jobs:
1605
- sync:
1606
- name: Sync templates
1607
- runs-on: ubuntu-latest
1608
- timeout-minutes: 15
1609
- permissions:
1610
- contents: read
1611
- steps:
1612
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1613
- name: Checkout repository
1614
-
1615
- - uses: theholocron/.github/.github/actions/setup@main
1616
- name: Setup
1617
-
1618
- - run: pnpm build
1619
- name: Build CLI
1620
-
1621
- - name: Validate generated workflows
1622
- run: |
1623
- node packages/cli/dist/cli.mjs sync-github \\
1624
- --repo "$PRIMARY_REPO" \\
1625
- --output-dir /tmp/sync-validate
1626
- curl -fsSL https://github.com/rhysd/actionlint/releases/download/v1.7.7/actionlint_1.7.7_linux_amd64.tar.gz \\
1627
- | tar -xz -C /tmp actionlint
1628
- /tmp/actionlint /tmp/sync-validate/.github/workflows/*.yml
1629
- env:
1630
- PRIMARY_REPO: \${{ inputs.primary-repo }}
1631
-
1632
- - name: Sync primary repo (PR)
1633
- run: |
1634
- GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo "github-actions[bot]")
1635
- GIT_EMAIL=$(gh api user --jq '"\\(.id)+\\(.login)@users.noreply.github.com"' 2>/dev/null || echo "41898282+github-actions[bot]@users.noreply.github.com")
1636
- COMMIT_MSG="chore: sync from theholocron/holocron"$'\\n\\n'"Signed-off-by: $GIT_NAME <$GIT_EMAIL>"
1637
- node packages/cli/dist/cli.mjs sync-github \\
1638
- --repo "$PRIMARY_REPO" \\
1639
- --branch "$SYNC_BRANCH" \\
1640
- --pr \\
1641
- --message "$COMMIT_MSG"
1642
- env:
1643
- GITHUB_TOKEN: \${{ secrets.SYNC_TOKEN }}
1644
- GH_TOKEN: \${{ secrets.SYNC_TOKEN }}
1645
- PRIMARY_REPO: \${{ inputs.primary-repo }}
1646
- SYNC_BRANCH: \${{ inputs.sync-branch }}
1647
-
1648
- - name: Sync secondary repos (PR)
1649
- if: \${{ inputs.secondary-repos != '' }}
1650
- run: |
1651
- GIT_NAME=$(gh api user --jq .name 2>/dev/null || echo "github-actions[bot]")
1652
- GIT_EMAIL=$(gh api user --jq '"\\(.id)+\\(.login)@users.noreply.github.com"' 2>/dev/null || echo "41898282+github-actions[bot]@users.noreply.github.com")
1653
- COMMIT_MSG="chore: sync from theholocron/holocron"$'\\n\\n'"Signed-off-by: $GIT_NAME <$GIT_EMAIL>"
1654
- for repo in $SECONDARY_REPOS; do
1655
- node packages/cli/dist/cli.mjs sync-github \\
1656
- --repo "$repo" \\
1657
- --branch "$SYNC_BRANCH" \\
1658
- --pr \\
1659
- --message "$COMMIT_MSG"
1660
- done
1661
- env:
1662
- GITHUB_TOKEN: \${{ secrets.SYNC_TOKEN }}
1663
- GH_TOKEN: \${{ secrets.SYNC_TOKEN }}
1664
- SECONDARY_REPOS: \${{ inputs.secondary-repos }}
1665
- SYNC_BRANCH: \${{ inputs.sync-branch }}
1666
- `,
1667
- typecheck: `\
1668
- name: Typecheck
1669
-
1670
- on: # yamllint disable-line rule:truthy
1671
- workflow_call:
1672
-
1673
- jobs:
1674
- typecheck:
1675
- name: tsc --noEmit
1676
- permissions:
1677
- contents: read
1678
- runs-on: ubuntu-latest
1679
- timeout-minutes: 10
1680
- steps:
1681
- - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1682
- name: Checkout repository
1683
-
1684
- - uses: theholocron/.github/.github/actions/setup@main
1685
- name: Setup
1686
-
1687
- - run: pnpm typecheck
1688
- name: Type check
1689
- `
899
+ audit: audit_default$1,
900
+ bookkeeping: bookkeeping_default$1,
901
+ codeql: codeql_default$1,
902
+ dependencies: dependencies_default$1,
903
+ greetings: greetings_default$1,
904
+ lint: lint_default$1,
905
+ release: release_default$1,
906
+ review: review_default$1,
907
+ stale: stale_default$1,
908
+ "sync-github": sync_github_default$1,
909
+ test: test_default$1,
910
+ typecheck: typecheck_default$1
911
+ };
912
+ const WORKFLOW_TEMPLATE_PROPERTIES = {
913
+ bookkeeping: JSON.stringify({
914
+ name: "Bookkeeping",
915
+ description: "Label and track issues and pull requests.",
916
+ iconName: "octicon tag"
917
+ }, null, 2),
918
+ "sync-github": JSON.stringify({
919
+ name: "Sync GitHub Templates",
920
+ description: "Sync workflow templates and composite actions from the holocron CLI.",
921
+ iconName: "octicon sync"
922
+ }, null, 2)
1690
923
  };
1691
- const WORKFLOW_TEMPLATE_PROPERTIES = { "sync-github": JSON.stringify({
1692
- name: "Sync GitHub Templates",
1693
- description: "Sync workflow templates and composite actions from the holocron CLI.",
1694
- iconName: "octicon sync"
1695
- }, null, 2) };
924
+ //#endregion
925
+ //#region src/commands/dependabot.yml
926
+ var dependabot_default = "# AUTO-GENERATED by holocron run `holocron setup` to regenerate.\nversion: 2\nupdates:\n - package-ecosystem: npm\n directory: /\n schedule:\n interval: weekly\n groups:\n security-patches:\n applies-to: security-updates\n patterns:\n - \"*\"\n all-dependencies:\n update-types:\n - minor\n - patch\n\n - package-ecosystem: github-actions\n directory: /\n schedule:\n interval: weekly\n groups:\n all-actions:\n patterns:\n - \"*\"\n";
927
+ //#endregion
928
+ //#region src/commands/workflows/audit.yml
929
+ var audit_default = "name: Audit\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\npermissions:\n contents: read\n\njobs:\n audit:\n uses: theholocron/.github/.github/workflows/audit.yml@main\n secrets: inherit\n";
930
+ //#endregion
931
+ //#region src/commands/workflows/bookkeeping.yml
932
+ var bookkeeping_default = "name: Bookkeeping\n\non: # yamllint disable-line rule:truthy\n pull_request:\n types:\n - opened\n - edited\n issues:\n types:\n - opened\n - edited\n\npermissions:\n contents: read\n issues: write\n pull-requests: write\n\njobs:\n bookkeeping:\n uses: theholocron/.github/.github/workflows/bookkeeping.yml@main\n secrets: inherit\n";
933
+ //#endregion
934
+ //#region src/commands/workflows/codeql.yml
935
+ var codeql_default = "name: CodeQL\n\non: # yamllint disable-line rule:truthy\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n schedule:\n - cron: \"0 0 * * 1\"\n\npermissions:\n actions: read\n contents: read\n security-events: write\n\njobs:\n codeql:\n uses: theholocron/.github/.github/workflows/codeql.yml@main\n secrets: inherit\n";
936
+ //#endregion
937
+ //#region src/commands/workflows/dependencies.yml
938
+ var dependencies_default = "name: Dependencies\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n dependencies:\n uses: theholocron/.github/.github/workflows/dependencies.yml@main\n secrets: inherit\n";
939
+ //#endregion
940
+ //#region src/commands/workflows/greetings.yml
941
+ var greetings_default = "name: Greetings\n\non: # yamllint disable-line rule:truthy\n pull_request:\n issues:\n\npermissions:\n issues: write\n pull-requests: write\n\njobs:\n greetings:\n uses: theholocron/.github/.github/workflows/greetings.yml@main\n secrets: inherit\n";
942
+ //#endregion
943
+ //#region src/commands/workflows/lint.yml
944
+ var lint_default = "name: Lint\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: lint-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: write\n statuses: write\n\njobs:\n lint:\n name: Lint\n uses: theholocron/.github/.github/workflows/lint.yml@main\n secrets: inherit\n with:\n enable-auto-commit: true\n";
945
+ //#endregion
946
+ //#region src/commands/workflows/release.yml
947
+ var release_default = "name: Release\n\non: # yamllint disable-line rule:truthy\n push:\n branches:\n - main\n - alpha\n workflow_dispatch:\n\npermissions:\n contents: write\n id-token: write\n issues: write\n pull-requests: write\n\nconcurrency:\n group: ${{ github.workflow }}-${{ github.ref }}\n cancel-in-progress: false\n\njobs:\n release:\n uses: theholocron/.github/.github/workflows/release.yml@main\n secrets: inherit\n";
948
+ //#endregion
949
+ //#region src/commands/workflows/review.yml
950
+ var review_default = "name: Review\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\nconcurrency:\n group: review-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n checks: write\n pull-requests: write\n\njobs:\n review:\n name: Review\n uses: theholocron/.github/.github/workflows/review.yml@main\n secrets: inherit\n";
951
+ //#endregion
952
+ //#region src/commands/workflows/stale.yml
953
+ var stale_default = "name: Stale\n\non: # yamllint disable-line rule:truthy\n schedule:\n - cron: \"30 1 * * *\"\n\npermissions:\n contents: write\n issues: write\n pull-requests: write\n\njobs:\n stale:\n uses: theholocron/.github/.github/workflows/stale.yml@main\n secrets: inherit\n";
954
+ //#endregion
955
+ //#region src/commands/workflows/sync-github.yml
956
+ var sync_github_default = "name: Sync GitHub Templates\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n paths:\n - packages/cli/src/templates/index.ts\n - packages/cli/src/commands/setup-workflows.ts\n\nconcurrency:\n group: sync-github-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n\njobs:\n sync:\n name: Sync\n uses: theholocron/.github/.github/workflows/sync-github.yml@main\n with:\n secondary-repos: theholocron/.github-private\n secrets:\n SYNC_TOKEN: ${{ secrets.SYNC_TOKEN }}\n";
957
+ //#endregion
958
+ //#region src/commands/workflows/test.yml
959
+ var test_default = "name: Test\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: test-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n\njobs:\n test:\n name: Test\n uses: theholocron/.github/.github/workflows/test.yml@main\n secrets: inherit\n";
960
+ //#endregion
961
+ //#region src/commands/workflows/typecheck.yml
962
+ var typecheck_default = "name: Typecheck\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\nconcurrency:\n group: typecheck-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n\njobs:\n typecheck:\n name: Typecheck\n uses: theholocron/.github/.github/workflows/typecheck.yml@main\n secrets: inherit\n";
1696
963
  //#endregion
1697
964
  //#region src/commands/setup-workflows.ts
1698
- /**
1699
- * Thin workflow wrapper templates for `holocron setup`.
1700
- *
1701
- * Each entry is a complete `.github/workflows/<name>.yml` that delegates
1702
- * to the corresponding reusable `ci-<name>.yml` in `theholocron/.github`.
1703
- * Files are overwritten on each setup run — they are generated artifacts.
1704
- */
1705
- const WORKFLOW_REPO = "theholocron/.github";
1706
- const WORKFLOW_REF = "main";
1707
- function ref(name) {
1708
- return `${WORKFLOW_REPO}/.github/workflows/${name}.yml@${WORKFLOW_REF}`;
1709
- }
1710
965
  /** Header prepended when holocron setup writes a thin caller to a repo. */
1711
966
  function workflowHeader() {
1712
967
  return [
@@ -1719,254 +974,18 @@ function workflowHeader() {
1719
974
  ].join("\n");
1720
975
  }
1721
976
  const WORKFLOW_TEMPLATES = {
1722
- lint: `\
1723
- name: Lint
1724
-
1725
- on: # yamllint disable-line rule:truthy
1726
- push:
1727
- branches: [main, alpha]
1728
- pull_request:
1729
-
1730
- concurrency:
1731
- group: lint-\${{ github.ref }}
1732
- cancel-in-progress: true
1733
-
1734
- permissions:
1735
- contents: write
1736
- statuses: write
1737
-
1738
- jobs:
1739
- lint:
1740
- name: Lint
1741
- uses: ${ref("lint")}
1742
- secrets: inherit
1743
- with:
1744
- enable-auto-commit: true
1745
- `,
1746
- test: `\
1747
- name: Test
1748
-
1749
- on: # yamllint disable-line rule:truthy
1750
- push:
1751
- branches: [main, alpha]
1752
- pull_request:
1753
-
1754
- concurrency:
1755
- group: test-\${{ github.ref }}
1756
- cancel-in-progress: true
1757
-
1758
- permissions:
1759
- contents: read
1760
-
1761
- jobs:
1762
- test:
1763
- name: Test
1764
- uses: ${ref("test")}
1765
- secrets: inherit
1766
- `,
1767
- typecheck: `\
1768
- name: Typecheck
1769
-
1770
- on: # yamllint disable-line rule:truthy
1771
- push:
1772
- branches: [main, alpha]
1773
- pull_request:
1774
-
1775
- concurrency:
1776
- group: typecheck-\${{ github.ref }}
1777
- cancel-in-progress: true
1778
-
1779
- permissions:
1780
- contents: read
1781
-
1782
- jobs:
1783
- typecheck:
1784
- name: Typecheck
1785
- uses: ${ref("typecheck")}
1786
- secrets: inherit
1787
- `,
1788
- codeql: `\
1789
- name: CodeQL
1790
-
1791
- on: # yamllint disable-line rule:truthy
1792
- push:
1793
- branches:
1794
- - main
1795
- pull_request:
1796
- branches:
1797
- - main
1798
- schedule:
1799
- - cron: "0 0 * * 1"
1800
-
1801
- permissions:
1802
- actions: read
1803
- contents: read
1804
- security-events: write
1805
-
1806
- jobs:
1807
- codeql:
1808
- uses: ${ref("codeql")}
1809
- secrets: inherit
1810
- `,
1811
- review: `\
1812
- name: Review
1813
-
1814
- on: # yamllint disable-line rule:truthy
1815
- pull_request:
1816
-
1817
- concurrency:
1818
- group: review-\${{ github.ref }}
1819
- cancel-in-progress: true
1820
-
1821
- permissions:
1822
- contents: read
1823
- checks: write
1824
- pull-requests: write
1825
-
1826
- jobs:
1827
- review:
1828
- name: Review
1829
- uses: ${ref("review")}
1830
- secrets: inherit
1831
- `,
1832
- release: `\
1833
- name: Release
1834
-
1835
- on: # yamllint disable-line rule:truthy
1836
- push:
1837
- branches:
1838
- - main
1839
- - alpha
1840
- workflow_dispatch:
1841
-
1842
- permissions:
1843
- contents: write
1844
- id-token: write
1845
- issues: write
1846
- pull-requests: write
1847
-
1848
- concurrency:
1849
- group: \${{ github.workflow }}-\${{ github.ref }}
1850
- cancel-in-progress: false
1851
-
1852
- jobs:
1853
- release:
1854
- uses: ${ref("release")}
1855
- secrets: inherit
1856
- `,
1857
- stale: `\
1858
- name: Stale
1859
-
1860
- on: # yamllint disable-line rule:truthy
1861
- schedule:
1862
- - cron: "30 1 * * *"
1863
-
1864
- permissions:
1865
- contents: write
1866
- issues: write
1867
- pull-requests: write
1868
-
1869
- jobs:
1870
- stale:
1871
- uses: ${ref("stale")}
1872
- secrets: inherit
1873
- `,
1874
- greetings: `\
1875
- name: Greetings
1876
-
1877
- on: # yamllint disable-line rule:truthy
1878
- pull_request:
1879
- issues:
1880
-
1881
- permissions:
1882
- issues: write
1883
- pull-requests: write
1884
-
1885
- jobs:
1886
- greetings:
1887
- uses: ${ref("greetings")}
1888
- secrets: inherit
1889
- `,
1890
- dependencies: `\
1891
- name: Dependencies
1892
-
1893
- on: # yamllint disable-line rule:truthy
1894
- pull_request:
1895
-
1896
- permissions:
1897
- contents: write
1898
- pull-requests: write
1899
-
1900
- jobs:
1901
- dependencies:
1902
- uses: ${ref("dependencies")}
1903
- secrets: inherit
1904
- `,
1905
- bookkeeping: `\
1906
- name: Bookkeeping
1907
-
1908
- on: # yamllint disable-line rule:truthy
1909
- pull_request:
1910
- types:
1911
- - opened
1912
- - edited
1913
- issues:
1914
- types:
1915
- - opened
1916
- - edited
1917
-
1918
- permissions:
1919
- contents: read
1920
- issues: write
1921
- pull-requests: write
1922
-
1923
- jobs:
1924
- bookkeeping:
1925
- uses: ${ref("bookkeeping")}
1926
- secrets: inherit
1927
- `,
1928
- audit: `\
1929
- name: Audit
1930
-
1931
- on: # yamllint disable-line rule:truthy
1932
- push:
1933
- branches: [main, alpha]
1934
- pull_request:
1935
-
1936
- permissions:
1937
- contents: read
1938
-
1939
- jobs:
1940
- audit:
1941
- uses: ${ref("audit")}
1942
- secrets: inherit
1943
- `,
1944
- "sync-github": `\
1945
- name: Sync GitHub Templates
1946
-
1947
- on: # yamllint disable-line rule:truthy
1948
- push:
1949
- branches: [main, alpha]
1950
- paths:
1951
- - packages/cli/src/templates/index.ts
1952
- - packages/cli/src/commands/setup-workflows.ts
1953
-
1954
- concurrency:
1955
- group: sync-github-\${{ github.ref }}
1956
- cancel-in-progress: true
1957
-
1958
- permissions:
1959
- contents: read
1960
-
1961
- jobs:
1962
- sync:
1963
- name: Sync
1964
- uses: ${ref("sync-github")}
1965
- with:
1966
- secondary-repos: theholocron/.github-private
1967
- secrets:
1968
- SYNC_TOKEN: \${{ secrets.SYNC_TOKEN }}
1969
- `
977
+ lint: lint_default,
978
+ test: test_default,
979
+ typecheck: typecheck_default,
980
+ codeql: codeql_default,
981
+ review: review_default,
982
+ release: release_default,
983
+ stale: stale_default,
984
+ greetings: greetings_default,
985
+ dependencies: dependencies_default,
986
+ bookkeeping: bookkeeping_default,
987
+ audit: audit_default,
988
+ "sync-github": sync_github_default
1970
989
  };
1971
990
  const KNOWN_WORKFLOWS = new Set(Object.keys(WORKFLOW_TEMPLATES));
1972
991
  /**
@@ -2365,7 +1384,7 @@ async function runNpmPublishInitial(input = {}) {
2365
1384
  const dryRun = input.dryRun ?? false;
2366
1385
  const otp = input.otp;
2367
1386
  const env = input.env ?? process.env;
2368
- const exec = input.exec ?? defaultExec;
1387
+ const exec = input.exec ?? defaultExec$1;
2369
1388
  const publishArgs = [
2370
1389
  "-r",
2371
1390
  "--filter=./packages/*",
@@ -2441,7 +1460,7 @@ function printNextSteps$1(print, env) {
2441
1460
  print(" https://www.npmjs.com/settings/~/tokens");
2442
1461
  }
2443
1462
  }
2444
- const defaultExec = async (cmd, args, opts) => {
1463
+ const defaultExec$1 = async (cmd, args, opts) => {
2445
1464
  const result = spawnSync(cmd, args, {
2446
1465
  cwd: opts.cwd,
2447
1466
  encoding: "utf8",
@@ -3292,13 +2311,11 @@ export default defineConfig({
3292
2311
  * 2. Slug collision — packages/holocron-plugin-<slug>/ must not exist.
3293
2312
  * 3. Capability sanity — must be one of the 14 known keys; warn for
3294
2313
  * many-cardinality caps.
3295
- * 4. Promptfill in any missing flags via cli-utils / inquirer
3296
- * (Phase B; Phase A takes fully-populated input).
3297
- * 5. Generate — for each template, write to
2314
+ * 4. Generatefor each template, write to
3298
2315
  * packages/holocron-plugin-<slug>/<path>.
3299
- * 6. Verify (unless --no-verify) — Phase B; runs pnpm install +
2316
+ * 5. Verify (unless --no-verify) — runs pnpm install +
3300
2317
  * pnpm --filter <pkg> typecheck lint test.
3301
- * 7. Print next steps.
2318
+ * 6. Print next steps.
3302
2319
  */
3303
2320
  var PluginCreateError = class extends Error {
3304
2321
  name = "PluginCreateError";
@@ -3421,6 +2438,51 @@ function runPluginCreate(input) {
3421
2438
  }
3422
2439
  filesWritten.push(resolvedPath);
3423
2440
  }
2441
+ if (!input.dryRun && !input.noVerify) {
2442
+ const execFn = input.exec ?? defaultExec;
2443
+ const pkg = `@theholocron/holocron-plugin-${inputs.slug}`;
2444
+ print("");
2445
+ print(" Verifying scaffold…");
2446
+ try {
2447
+ execFn("pnpm", ["install", "--frozen-lockfile=false"], {
2448
+ cwd,
2449
+ stdio: "inherit"
2450
+ });
2451
+ execFn("pnpm", [
2452
+ "--filter",
2453
+ pkg,
2454
+ "typecheck"
2455
+ ], {
2456
+ cwd,
2457
+ stdio: "inherit"
2458
+ });
2459
+ execFn("pnpm", [
2460
+ "--filter",
2461
+ pkg,
2462
+ "lint"
2463
+ ], {
2464
+ cwd,
2465
+ stdio: "inherit"
2466
+ });
2467
+ execFn("pnpm", [
2468
+ "--filter",
2469
+ pkg,
2470
+ "test"
2471
+ ], {
2472
+ cwd,
2473
+ stdio: "inherit"
2474
+ });
2475
+ print(" ✓ scaffold verified");
2476
+ } catch (err) {
2477
+ print(` ✗ verify failed — ${err instanceof Error ? err.message : String(err)}`);
2478
+ return {
2479
+ status: "fail",
2480
+ packagePath: packageDir,
2481
+ filesWritten,
2482
+ message: "post-scaffold verify failed; inspect output above"
2483
+ };
2484
+ }
2485
+ }
3424
2486
  if (!input.dryRun) printNextSteps(print, inputs);
3425
2487
  return {
3426
2488
  status: "ok",
@@ -3464,6 +2526,12 @@ function defaultWrite(filepath, content) {
3464
2526
  mkdirSync(path.dirname(filepath), { recursive: true });
3465
2527
  writeFileSync(filepath, content, "utf8");
3466
2528
  }
2529
+ function defaultExec(cmd, args, opts) {
2530
+ execFileSync(cmd, args, {
2531
+ cwd: opts.cwd,
2532
+ stdio: opts.stdio
2533
+ });
2534
+ }
3467
2535
  function printNextSteps(print, inputs) {
3468
2536
  print("");
3469
2537
  print(` Scaffolded @theholocron/holocron-plugin-${inputs.slug} (18 files).`);
@@ -3926,33 +2994,6 @@ function labelerConfig() {
3926
2994
  ``
3927
2995
  ].join("\n");
3928
2996
  }
3929
- const DEPENDABOT_CONFIG = `\
3930
- # AUTO-GENERATED by holocron — run \`holocron setup\` to regenerate.
3931
- version: 2
3932
- updates:
3933
- - package-ecosystem: npm
3934
- directory: /
3935
- schedule:
3936
- interval: weekly
3937
- groups:
3938
- security-patches:
3939
- applies-to: security-updates
3940
- patterns:
3941
- - "*"
3942
- all-dependencies:
3943
- update-types:
3944
- - minor
3945
- - patch
3946
-
3947
- - package-ecosystem: github-actions
3948
- directory: /
3949
- schedule:
3950
- interval: weekly
3951
- groups:
3952
- all-actions:
3953
- patterns:
3954
- - "*"
3955
- `;
3956
2997
  const RULESET_NAME = "holocron-default-branch";
3957
2998
  const BALANCED_REPO_SETTINGS = {
3958
2999
  allow_squash_merge: true,
@@ -4162,7 +3203,7 @@ async function runSetup(input) {
4162
3203
  if (loader.has("source") && effectivePreset !== "none") {
4163
3204
  const source = loader.get("source");
4164
3205
  steps.push(await runStep("source", "write .github/dependabot.yml", dryRun, async () => {
4165
- await source.writeRepoFile(".github/dependabot.yml", DEPENDABOT_CONFIG);
3206
+ await source.writeRepoFile(".github/dependabot.yml", dependabot_default);
4166
3207
  }));
4167
3208
  print(formatStep(steps[steps.length - 1]));
4168
3209
  }
@@ -4943,15 +3984,40 @@ await yargs(hideBin(process.argv)).scriptName("holocron").usage("$0 <command> [o
4943
3984
  type: "boolean",
4944
3985
  default: true,
4945
3986
  describe: "Run post-scaffold pnpm install + typecheck + lint + test (default true; --no-verify skips)"
4946
- }), (argv) => {
3987
+ }), async (argv) => {
4947
3988
  try {
4948
- if (!argv.capability || !argv.vendorEnv || !argv.baseUrl) throw new PluginCreateError("Phase A: --capability, --vendor-env, and --base-url are required. Interactive prompts land in Phase B.");
3989
+ const capabilityKeys = Object.keys(CARDINALITY).join(", ");
3990
+ const needsPrompt = !argv.capability || !argv.vendorEnv || !argv.baseUrl;
3991
+ let capability;
3992
+ let vendorEnv;
3993
+ let baseUrl;
3994
+ if (needsPrompt) {
3995
+ const rl = createInterface({
3996
+ input: stdin,
3997
+ output: stdout
3998
+ });
3999
+ const ask = (question) => new Promise((resolve) => rl.question(` ${question} `, (answer) => resolve(answer.trim())));
4000
+ try {
4001
+ if (!argv.capability) {
4002
+ console.log(` Available capabilities: ${capabilityKeys}`);
4003
+ capability = await ask("Capability:");
4004
+ } else capability = argv.capability;
4005
+ vendorEnv = argv.vendorEnv ? argv.vendorEnv : await ask(`Vendor-native env var for the ${argv.vendor} token (e.g. MYVENDOR_API_KEY):`);
4006
+ baseUrl = argv.baseUrl ? argv.baseUrl : await ask(`REST base URL for the ${argv.vendor} API (e.g. https://api.myvendor.com):`);
4007
+ } finally {
4008
+ rl.close();
4009
+ }
4010
+ } else {
4011
+ capability = argv.capability;
4012
+ vendorEnv = argv.vendorEnv;
4013
+ baseUrl = argv.baseUrl;
4014
+ }
4949
4015
  if (runPluginCreate({
4950
4016
  slug: argv.slug,
4951
4017
  vendorName: argv.vendor,
4952
- capability: argv.capability,
4953
- vendorEnv: argv.vendorEnv,
4954
- baseUrl: argv.baseUrl,
4018
+ capability,
4019
+ vendorEnv,
4020
+ baseUrl,
4955
4021
  ...argv.tokenEnv ? { tokenEnv: argv.tokenEnv } : {},
4956
4022
  dryRun: argv.dryRun,
4957
4023
  noVerify: !argv.verify,