@theholocron/astromech 5.0.0-alpha.185 → 5.0.0-alpha.187

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -70,6 +70,7 @@ documents, not a naming convention repos need to follow.
70
70
  | `delivery.deploy` | Cloudflare Pages / Vercel | no local equivalent — CI only; carries `preview` |
71
71
  | `delivery.bundleSize` | bundle-size upload to Codecov | no local equivalent — CI only |
72
72
  | `delivery.previewCheck` | `holocron monitoring check <url>` against the PR's own Vercel preview URL | no local equivalent — CI only; triggered by `deployment_status`, not `push`/`pull_request` |
73
+ | `platform.notifyCheck` | _(none — manual workflow)_ | posts a labelled test message to every notification channel; fails per channel that does not work |
73
74
  | `platform.repoSync` | `holocron repo sync` | keeps generated files current |
74
75
  | `platform.commitStandards` | commitlint | no local equivalent — enforced by the `commit-msg` hook locally, over the PR's commit range in CI |
75
76
  | `platform.repoValidation` | `scripts/validate-adrs.mjs`, `scripts/validate-registry.mjs`, `scripts/validate-docs-presence.mjs` | a job-bearing task — spec/ADR frontmatter, registry-doc completeness, and docs-presence, not linters |
package/dist/index.mjs CHANGED
@@ -122,7 +122,7 @@ var holocron_default = "name: Holocron\ndescription: >\n Run the Holocron CLI
122
122
  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";
123
123
  //#endregion
124
124
  //#region src/templates/reusable/actions/notify.yml
125
- var notify_default = "name: Notify\ndescription: >\n Post a message to a chat channel through an incoming webhook. The request\n body is Discord-compatible (`content`, `username`, `allowed_mentions`), so\n the webhook must accept that shape. Does nothing (and never fails the\n calling job) when no webhook is provided, so repos that haven't set one up\n are unaffected.\n\ninputs:\n webhook:\n description: >\n Incoming webhook URL for the target channel.\n A webhook posts to exactly one channel, so pass the secret for the\n channel this message belongs in (for example\n `secrets.HOLOCRON_NOTIFY_WEBHOOK_ALERTS`). Empty = skip.\n required: false\n default: \"\"\n message:\n description: Message text. Truncated to 2000 characters.\n required: true\n mention:\n description: >\n Optional role id (digits only) to ping. Only that one role can\n be mentioned; anything else in the message never pings.\n required: false\n default: \"\"\n username:\n description: Display name for the post.\n required: false\n default: \"Holocron\"\n\nruns:\n using: composite\n steps:\n - name: Post the notification\n shell: bash\n run: |\n if [ -z \"$WEBHOOK\" ]; then\n echo \"::notice::No notification webhook set — skipping notification.\"\n exit 0\n fi\n echo \"::add-mask::$WEBHOOK\"\n # allowed_mentions.parse = [] so message text can never ping @everyone\n # or a role; only the explicit `mention` role id is allowed through. The body is built with jq so quotes/newlines in the\n # message can't break the JSON.\n content=\"$MESSAGE\"\n roles='[]'\n if [[ \"$MENTION\" =~ ^[0-9]+$ ]]; then\n content=\"<@&$MENTION> $MESSAGE\"\n roles=$(jq -cn --arg r \"$MENTION\" '[$r]')\n fi\n body=$(jq -n --arg content \"${content:0:2000}\" --arg username \"$USERNAME\" --argjson roles \"$roles\" \\\n '{content: $content, username: $username, allowed_mentions: {parse: [], roles: $roles}}')\n status=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 15 \\\n -H 'Content-Type: application/json' -d \"$body\" \"$WEBHOOK\" || true)\n case \"${status:-000}\" in\n 2??) echo \"Notification posted.\" ;;\n *) echo \"::warning::Notification failed (HTTP ${status:-000}).\" ;;\n esac\n env:\n WEBHOOK: ${{ inputs.webhook }}\n MESSAGE: ${{ inputs.message }}\n MENTION: ${{ inputs.mention }}\n USERNAME: ${{ inputs.username }}\n";
125
+ var notify_default = "name: Notify\ndescription: >\n Post a message to a chat channel through an incoming webhook. The request\n body is Discord-compatible (`content`, `username`, `allowed_mentions`), so\n the webhook must accept that shape. Does nothing (and never fails the\n calling job) when no webhook is provided, so repos that haven't set one up\n are unaffected. Set `strict` for a check whose only purpose is to prove the\n notification works: it then fails when the webhook is missing or rejects the post.\n\ninputs:\n webhook:\n description: >\n Incoming webhook URL for the target channel.\n A webhook posts to exactly one channel, so pass the secret for the\n channel this message belongs in (for example\n `secrets.HOLOCRON_NOTIFY_WEBHOOK_ALERTS`). Empty = skip.\n required: false\n default: \"\"\n message:\n description: Message text. Truncated to 2000 characters.\n required: true\n mention:\n description: >\n Optional role id (digits only) to ping. Only that one role can\n be mentioned; anything else in the message never pings.\n required: false\n default: \"\"\n username:\n description: Display name for the post.\n required: false\n default: \"Holocron\"\n strict:\n description: >\n \"true\" fails the step when no webhook is set or the post is rejected.\n Off by default: a notification problem must never fail the job it reports on.\n required: false\n default: \"false\"\n\nruns:\n using: composite\n steps:\n - name: Post the notification\n shell: bash\n run: |\n if [ -z \"$WEBHOOK\" ]; then\n if [ \"$STRICT\" = \"true\" ]; then\n echo \"::error::No notification webhook set.\"\n exit 1\n fi\n echo \"::notice::No notification webhook set — skipping notification.\"\n exit 0\n fi\n echo \"::add-mask::$WEBHOOK\"\n # allowed_mentions.parse = [] so message text can never ping @everyone\n # or a role; only the explicit `mention` role id is allowed through. The\n # body is built with jq so quotes/newlines in the message can't break the JSON.\n content=\"$MESSAGE\"\n roles='[]'\n # A mention that is not a role id is dropped, which is right for a real\n # notification but would let a check pass without ever pinging anyone.\n if [ \"$STRICT\" = \"true\" ] && [ -n \"$MENTION\" ] && ! [[ \"$MENTION\" =~ ^[0-9]+$ ]]; then\n echo \"::error::The mention is not a role id (digits only).\"\n exit 1\n fi\n if [[ \"$MENTION\" =~ ^[0-9]+$ ]]; then\n content=\"<@&$MENTION> $MESSAGE\"\n roles=$(jq -cn --arg r \"$MENTION\" '[$r]')\n fi\n body=$(jq -n --arg content \"${content:0:2000}\" --arg username \"$USERNAME\" --argjson roles \"$roles\" \\\n '{content: $content, username: $username, allowed_mentions: {parse: [], roles: $roles}}')\n status=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 15 \\\n -H 'Content-Type: application/json' -d \"$body\" \"$WEBHOOK\" || true)\n case \"${status:-000}\" in\n 2??) echo \"Notification posted.\" ;;\n *)\n if [ \"$STRICT\" = \"true\" ]; then\n echo \"::error::Notification failed (HTTP ${status:-000}).\"\n exit 1\n fi\n echo \"::warning::Notification failed (HTTP ${status:-000}).\"\n ;;\n esac\n env:\n WEBHOOK: ${{ inputs.webhook }}\n MESSAGE: ${{ inputs.message }}\n MENTION: ${{ inputs.mention }}\n USERNAME: ${{ inputs.username }}\n STRICT: ${{ inputs.strict }}\n";
126
126
  //#endregion
127
127
  //#region src/templates/reusable/actions/setup.yml
128
128
  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\n # `@theholocron/cli`'s `dist/cli.mjs` doesn't exist yet at this point, so\n # pnpm's workspace bin-linking can't create `node_modules/.bin/holocron`\n # (silent `WARN ... ENOENT`, not a hard failure). Every package whose\n # scripts delegate via `holocron run <task> --` then fails at run time\n # with `holocron: not found` (#698). Same fix the `holocron` composite\n # action already applies for its own direct invocation (see its \"Build\n # the workspace when the CLI resolves to an unbuilt checkout\" step) —\n # mirrored here so it also covers *nested* `holocron run <task> --`\n # calls from inside package.json scripts, which that action's own guard\n # doesn't reach. `pnpm build` (not a scoped `--filter`) so the CLI's own\n # workspace dependencies (e.g. astromech) build\n # in topological order too — a scoped build skips them and fails.\n # No-op in every consumer repo, where the published tarball already\n # ships `dist/`.\n - name: Build the Holocron CLI\n shell: bash\n run: |\n if [ ! -f node_modules/@theholocron/cli/dist/cli.mjs ]; then\n echo \"→ @theholocron/cli dist/ missing — building the workspace from source\" >&2\n pnpm build\n echo \"→ re-linking node_modules/.bin — pnpm skipped it pre-build\" >&2\n pnpm install --frozen-lockfile\n fi\n\n - name: Cache Turbo artifacts\n if: ${{ hashFiles('turbo.json') != '' }}\n uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0\n with:\n path: .turbo\n key: turbo-${{ runner.os }}-${{ github.sha }}\n restore-keys: |\n turbo-${{ runner.os }}-\n";
@@ -166,8 +166,11 @@ var platform_commitStandards_default$1 = "name: Commit Standards\n\non: # yamlli
166
166
  //#region src/templates/reusable/platform.dispatchedCheck.yml
167
167
  var platform_dispatchedCheck_default = "name: Dispatched Check\n\non: # yamllint disable-line rule:truthy\n workflow_dispatch:\n inputs:\n repo:\n description: Target repo, \"owner/name\", to check out and run the task against.\n type: string\n required: true\n ref:\n description: Git ref (branch or commit SHA) to check out.\n type: string\n required: true\n task:\n description: The holocron task name to run (e.g. \"verification.typeSafety\").\n type: string\n required: true\n check-run-id:\n description: >\n ID of the check run already posted as \"queued\" on the target repo —\n patched to \"completed\" once the task finishes.\n type: string\n required: true\n\npermissions:\n contents: read\n\njobs:\n run-task:\n name: Run a Sentinel-dispatched task against another repo\n runs-on: ubuntu-latest\n timeout-minutes: 20\n env:\n TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n TURBO_TEAM: ${{ vars.TURBO_TEAM }}\n steps:\n # actions/create-github-app-token defaults to scoping its token to the\n # *current* repo (.github, where this workflow runs) when owner/\n # repositories are omitted — useless here, since every real use of this\n # token targets inputs.repo instead. Split \"owner/name\" up front so the\n # token step below can scope explicitly to the actual target.\n - name: Parse target repo\n id: target\n run: |\n echo \"owner=${INPUT_REPO%%/*}\" >> \"$GITHUB_OUTPUT\"\n echo \"name=${INPUT_REPO##*/}\" >> \"$GITHUB_OUTPUT\"\n env:\n INPUT_REPO: ${{ inputs.repo }}\n\n # Sentinel's own dispatch call only carries plain, non-secret inputs\n # (repo/ref/task/check-run-id — all visible in the Actions UI/logs).\n # This step mints a fresh, short-lived installation token here instead,\n # scoped by the same App's stored credentials — never a raw token\n # passed through a dispatch input.\n - name: Generate installation token\n id: app-token\n uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0\n with:\n app-id: ${{ secrets.SENTINEL_APP_ID }}\n private-key: ${{ secrets.SENTINEL_APP_PRIVATE_KEY }}\n owner: ${{ steps.target.outputs.owner }}\n repositories: ${{ steps.target.outputs.name }}\n\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout target repository\n with:\n repository: ${{ inputs.repo }}\n ref: ${{ inputs.ref }}\n token: ${{ steps.app-token.outputs.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Run the task\n id: run-task\n continue-on-error: true\n uses: theholocron/.github/.github/actions/holocron@main\n with:\n task: ${{ inputs.task }}\n\n # A bare .../actions/runs/<id> link lands on the run summary, one click\n # short of the actual step-by-step log a normal check's details_url\n # points at. This job is always alone in its run, so the first (only)\n # job in the run's own job list is unambiguously this one.\n - name: Resolve this job's numeric ID\n id: job-info\n if: always()\n run: |\n job_id=$(gh api \"repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs\" --jq '.jobs[0].id')\n echo \"job_id=$job_id\" >> \"$GITHUB_OUTPUT\"\n env:\n GH_TOKEN: ${{ steps.app-token.outputs.token }}\n\n # Ships the task's real captured output (tsc/vitest/etc — whatever\n # `holocron run` actually printed) to the same Axiom dataset Sentinel's\n # own structured logs already flow into, tagged so it's queryable by\n # this exact run. Reuses the existing dataset rather than provisioning\n # a new one — a prototype-stage call, revisit if CI-log volume ever\n # warrants a dedicated dataset. Builds a permalink filtered to this\n # run's own logs (Axiom's own \"copy query link\" URL shape:\n # /<org>/query?initForm={\"apl\":\"...\"} ) so a viewer lands directly on\n # the relevant lines, not a bare dataset view.\n - name: Ship task output to Axiom\n id: axiom\n if: always()\n run: |\n message=$(tail -c 40000 \"$LOG_FILE\" 2>/dev/null || echo \"(no output captured)\")\n # \"level\" is one of the field names Axiom's Stream/Query tabs\n # recognize for severity-color highlighting (docs: level, @level,\n # severity, @severity, status.code) -- conclusion alone isn't.\n level=$([ \"$CONCLUSION\" = \"success\" ] && echo \"info\" || echo \"error\")\n event=$(jq -cn \\\n --arg time \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" \\\n --arg repo \"$REPO\" --arg task \"$TASK\" --arg run_id \"$GITHUB_RUN_ID\" \\\n --arg job_id \"$JOB_ID\" --arg check_run_id \"$CHECK_RUN_ID\" \\\n --arg conclusion \"$CONCLUSION\" --arg level \"$level\" --arg message \"$message\" \\\n '{_time: $time, source: \"dispatched-check\", repo: $repo, task: $task,\n run_id: $run_id, job_id: $job_id, check_run_id: $check_run_id,\n conclusion: $conclusion, level: $level, message: $message}')\n curl -sf -X POST \"https://api.axiom.co/v1/datasets/${AXIOM_DATASET}/ingest\" \\\n -H \"Authorization: Bearer ${AXIOM_TOKEN}\" \\\n -H \"Content-Type: application/json\" \\\n -d \"[${event}]\" || echo \"::warning::Axiom ingest failed — continuing, the check itself still reports the real result\"\n\n # The ['...'] is Axiom's own APL array-dataset-reference syntax, not\n # a shell quote boundary — $AXIOM_DATASET/$CHECK_RUN_ID both expand\n # fine here; shellcheck's single-quote heuristic just can't tell.\n # shellcheck disable=SC2016\n apl=\"['${AXIOM_DATASET}'] | where check_run_id == \\\"${CHECK_RUN_ID}\\\"\"\n init_form=$(jq -cn --arg apl \"$apl\" '{apl: $apl}')\n encoded=$(jq -rn --arg s \"$init_form\" '$s | @uri')\n echo \"query-url=https://app.axiom.co/${AXIOM_ORG}/query?initForm=${encoded}\" >> \"$GITHUB_OUTPUT\"\n env:\n LOG_FILE: ${{ steps.run-task.outputs.log-file }}\n REPO: ${{ inputs.repo }}\n TASK: ${{ inputs.task }}\n JOB_ID: ${{ steps.job-info.outputs.job_id }}\n CHECK_RUN_ID: ${{ inputs.check-run-id }}\n CONCLUSION: ${{ steps.run-task.outcome == 'success' && 'success' || 'failure' }}\n AXIOM_ORG: the-holocron-7bbe\n AXIOM_DATASET: holocron-sentinel\n AXIOM_TOKEN: ${{ secrets.SENTINEL_AXIOM_INGEST_TOKEN }}\n\n # Always runs, success or failure — the queued check run on the target\n # repo must be resolved either way, not left hanging. Full JSON body via\n # jq + --input, not -f flags: output.text needs real nesting (gh api -f\n # has no dot-notation for that), and the captured task output can\n # contain characters (quotes, $, backticks) that would break a\n # hand-built -f string.\n - name: Report result to the target repo's check run\n if: always()\n run: |\n excerpt=$(tail -c 3000 \"$LOG_FILE\" 2>/dev/null || echo \"(no output captured)\")\n # The single-quoted format string is intentional — every %s fills\n # via printf's own args below, not shell expansion; nothing in it\n # needs to expand.\n # shellcheck disable=SC2016\n text=$(printf '**Task:** `%s`\\n\\n**Result:** %s\\n\\n[Full logs on Axiom](%s)\\n\\n### Last output\\n\\n```\\n%s\\n```\\n' \\\n \"$TASK\" \"$CONCLUSION\" \"$QUERY_URL\" \"$excerpt\")\n body=$(jq -n \\\n --arg conclusion \"$CONCLUSION\" \\\n --arg details_url \"$RUN_URL\" \\\n --arg title \"$TASK ($CONCLUSION)\" \\\n --arg summary \"Dispatched via theholocron/.github — see the log excerpt below, or the full run/Axiom links.\" \\\n --arg text \"$text\" \\\n '{status: \"completed\", conclusion: $conclusion, details_url: $details_url,\n output: {title: $title, summary: $summary, text: $text}}')\n echo \"$body\" | gh api --method PATCH \"/repos/${REPO}/check-runs/${CHECK_RUN_ID}\" --input -\n env:\n # `GH_TOKEN` is the literal name `gh api` requires to auto-authenticate\n # -- not a stand-in for a shared/blanket credential. Its value is the\n # short-lived, Sentinel-App-scoped token minted above, same as the\n # checkout step uses; never secrets.HOLOCRON_SYNC_TOKEN (the one\n # genuinely shared PAT in this org, used by sync-dispatch.yml).\n GH_TOKEN: ${{ steps.app-token.outputs.token }}\n REPO: ${{ inputs.repo }}\n TASK: ${{ inputs.task }}\n CHECK_RUN_ID: ${{ inputs.check-run-id }}\n CONCLUSION: ${{ steps.run-task.outcome == 'success' && 'success' || 'failure' }}\n LOG_FILE: ${{ steps.run-task.outputs.log-file }}\n QUERY_URL: ${{ steps.axiom.outputs.query-url }}\n RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ steps.job-info.outputs.job_id }}\n";
168
168
  //#endregion
169
+ //#region src/templates/reusable/platform.notifyCheck.yml
170
+ var platform_notifyCheck_default$1 = "name: Notify Check\n\n# Proves the notification path end to end, from a real run: that each channel's\n# webhook secret exists, that its webhook accepts a post, and that the alert\n# role ping resolves. It posts one clearly labelled test message per channel and\n# fails the matching job when any step does not work, so a red job names the\n# channel to fix. Manual (workflow_dispatch) only: it posts real messages.\n#\n# Each channel names its own webhook secret, because `notifications setup` lets a\n# layout override the default name (and normalises punctuation), so deriving the\n# name from the channel would miss those. A channel with `\"mention\": true` also\n# requires the role-id secret and pings it: a webhook accepting the post proves\n# the channel works, not that the role ping does, so a missing or malformed role\n# id fails that job instead of passing quietly. Whether Discord lets that role be\n# mentioned at all is checked by `holocron notifications verify`, not here.\n#\n# Secrets reach this workflow through `secrets: inherit`, so any secret named in\n# `channels` is readable; the declared list below is for callers that pass secrets\n# explicitly.\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n channels:\n description: >\n JSON array of channels to check, each `{ \"name\", \"secret\", \"mention\" }`:\n `secret` is the org secret holding that channel's webhook URL and\n `mention: true` also requires and pings the role in\n HOLOCRON_NOTIFY_ALERT_ROLE.\n type: string\n required: false\n default: >-\n [{\"name\":\"sync\",\"secret\":\"HOLOCRON_NOTIFY_WEBHOOK_SYNC\"},\n {\"name\":\"alerts\",\"secret\":\"HOLOCRON_NOTIFY_WEBHOOK_ALERTS\",\"mention\":true},\n {\"name\":\"errors\",\"secret\":\"HOLOCRON_NOTIFY_WEBHOOK_ERRORS\"},\n {\"name\":\"uptime\",\"secret\":\"HOLOCRON_NOTIFY_WEBHOOK_UPTIME\"},\n {\"name\":\"releases\",\"secret\":\"HOLOCRON_NOTIFY_WEBHOOK_RELEASES\"},\n {\"name\":\"deploys\",\"secret\":\"HOLOCRON_NOTIFY_WEBHOOK_DEPLOYS\"}]\n secrets:\n HOLOCRON_NOTIFY_WEBHOOK_SYNC:\n description: Webhook for the sync channel.\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_ALERTS:\n description: Webhook for the alerts channel.\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_ERRORS:\n description: Webhook for the errors channel.\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_UPTIME:\n description: Webhook for the uptime channel.\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_RELEASES:\n description: Webhook for the releases channel.\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_DEPLOYS:\n description: Webhook for the deploys channel.\n required: false\n HOLOCRON_NOTIFY_ALERT_ROLE:\n description: Id of the role to mention on the alerts channel's test message. Optional.\n required: false\n\njobs:\n check:\n name: Check ${{ matrix.channel.name }}\n runs-on: ubuntu-latest\n timeout-minutes: 2\n permissions: {}\n strategy:\n # One channel failing must not hide the others: the point is the full picture.\n fail-fast: false\n matrix:\n channel: ${{ fromJSON(inputs.channels) }}\n steps:\n - name: Require the alert role id\n if: matrix.channel.mention\n run: |\n if [ -z \"$ROLE\" ]; then\n echo \"::error::HOLOCRON_NOTIFY_ALERT_ROLE is not set, so the ping on #$CHANNEL cannot be checked.\"\n exit 1\n fi\n env:\n ROLE: ${{ secrets.HOLOCRON_NOTIFY_ALERT_ROLE }}\n CHANNEL: ${{ matrix.channel.name }}\n\n - uses: theholocron/.github/.github/actions/notify@main\n name: Post a test message to ${{ matrix.channel.name }}\n with:\n strict: \"true\"\n webhook: ${{ secrets[matrix.channel.secret] }}\n # Only a channel marked `mention` pings, and strict mode rejects a malformed id.\n mention: ${{ matrix.channel.mention && secrets.HOLOCRON_NOTIFY_ALERT_ROLE || '' }}\n message: \"🧪 notify check — #${{ matrix.channel.name }} is wired up (${{ github.repository }}, ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})\"\n";
171
+ //#endregion
169
172
  //#region src/templates/reusable/platform.repoSync.yml
170
- var platform_repoSync_default$1 = "name: Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n steps:\n description: >\n Sync steps to run (default: all). Valid values:\n labels, properties, teams, topics, keywords, description, homepage, readme, workflows, wiki.\n Pass a space-separated list to run a subset, e.g. \"readme\" or \"readme wiki\".\n type: string\n required: false\n secrets:\n HOLOCRON_ADMIN_TOKEN:\n description: Fine-grained PAT with admin scopes (labels, properties, teams).\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n HOLOCRON_DEPLOY_TOKEN:\n description: Fine-grained PAT for GitHub Pages configuration.\n required: false\n HOLOCRON_ISSUES_TOKEN:\n description: Fine-grained PAT for issue management.\n required: false\n HOLOCRON_ORG_TOKEN:\n description: Org-scoped fine-grained PAT for team sync and org properties.\n required: false\n HOLOCRON_READ_TOKEN:\n description: Fine-grained PAT for read-only GitHub API calls.\n required: false\n HOLOCRON_SYNC_TOKEN:\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_SYNC:\n description: >\n Webhook for the sync channel: a sync PR opened and its\n auto-merge result. Unset = no post.\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_ALERTS:\n description: >\n Webhook for the alerts channel: a failed sync run, or a sync\n PR that needs a manual merge. Unset = no post. An optional\n HOLOCRON_NOTIFY_ALERT_ROLE variable (a role id) makes\n these posts mention that role.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n sync:\n name: Run holocron repo sync\n runs-on: ubuntu-latest\n timeout-minutes: 10\n # Serialise the find-or-create-PR and supersede steps repo-wide: the caller's\n # concurrency key is per ref, so runs from different refs could otherwise\n # interleave and leave several sync PRs open.\n concurrency:\n group: repo-sync-pr-${{ github.repository }}\n cancel-in-progress: false\n permissions:\n contents: write\n pull-requests: write\n # Job-level so the `holocron` composite action's steps inherit them.\n env:\n HOLOCRON_ADMIN_TOKEN: ${{ secrets.HOLOCRON_ADMIN_TOKEN }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n POSTHOG_PROJECT_TOKEN: ${{ vars.POSTHOG_PROJECT_TOKEN }}\n HOLOCRON_DEPLOY_TOKEN: ${{ secrets.HOLOCRON_DEPLOY_TOKEN }}\n HOLOCRON_ISSUES_TOKEN: ${{ secrets.HOLOCRON_ISSUES_TOKEN }}\n HOLOCRON_ORG_TOKEN: ${{ secrets.HOLOCRON_ORG_TOKEN }}\n HOLOCRON_READ_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Run holocron repo sync\n # The `holocron` action resolves @theholocron/cli from node_modules (or\n # builds the workspace when it's an unbuilt checkout — the holocron repo\n # itself). `inputs.steps` is a space-separated list or empty; the\n # `--steps <list>` arg is omitted when empty.\n uses: theholocron/.github/.github/actions/holocron@main\n with:\n command: repo sync\n args: ${{ inputs.steps != '' && format('--steps {0}', inputs.steps) || '' }}\n\n - name: Format generated files\n run: |\n pnpm exec prettier --write README.md docs/src/content/docs/index.mdx 2>/dev/null || true\n # `holocron repo sync` writes package.json fields (keywords, description,\n # homepage) with a plain assignment, which appends new keys at the\n # end — re-apply the canonical order the lint config enforces.\n pnpm exec eslint --fix --no-warn-ignored package.json 2>/dev/null || true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n id: auto-commit\n name: Commit sync changes\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n # One branch per source commit (full SHA, so distinct commits never collide): a PR left unreviewed never blocks the\n # next sync, and a re-run for the same commit updates its own branch.\n branch: ${{ format('chore/auto-sync-{0}', github.sha) }}\n commit-message: \"chore: sync from holocron.config\"\n commit-options: \"--no-verify\"\n\n - name: Open PR and enable auto-merge\n id: pr\n if: steps.auto-commit.outputs.changes-detected == 'true'\n run: |\n # Find or create this run's PR first: older PRs are only closed once\n # a replacement exists, so a failure here never leaves the changes\n # without an open PR.\n url=$(gh pr view \"$BRANCH\" --json url --jq .url 2>/dev/null || gh pr create \\\n --title \"chore: sync README and repo metadata\" \\\n --body \"Automated sync from holocron.config. Auto-merges once required checks pass.\" \\\n --base main \\\n --head \"$BRANCH\")\n created=$(gh pr view \"$url\" --json createdAt --jq .createdAt)\n\n # Supersede older sync PRs: same-repo only, exact generated or legacy\n # branch name, and created before this one (a slow older run can\n # never close a newer PR). --limit covers more than the default page.\n gh pr list --state open --limit 200 --json number,headRefName,isCrossRepository,createdAt \\\n --jq \".[] | select(.isCrossRepository | not) | select(.headRefName == \\\"chore/auto-sync\\\" or (.headRefName | test(\\\"^chore/auto-sync-[0-9a-f]{40}$\\\"))) | select(.headRefName != \\\"$BRANCH\\\") | select(.createdAt < \\\"$created\\\") | .number\" |\n while read -r n; do\n gh pr close \"$n\" --delete-branch --comment \"Superseded by $url.\" || true\n done\n\n # Delete pushed sync branches that never got a PR (e.g. a run\n # cancelled between push and PR creation). The repo-wide concurrency\n # group means no other run is mid-flight here.\n open=$(gh pr list --state open --limit 200 --json headRefName --jq '.[].headRefName')\n git ls-remote --heads origin 'refs/heads/chore/auto-sync-*' | sed 's|.*refs/heads/||' |\n while read -r b; do\n [ \"$b\" = \"$BRANCH\" ] && continue\n echo \"$b\" | grep -Eq '^chore/auto-sync-[0-9a-f]{40}$' || continue\n echo \"$open\" | grep -qxF \"$b\" || git push origin --delete \"$b\" || true\n done\n\n # A PR opened with the default GITHUB_TOKEN does not trigger\n # pull_request workflows, so required checks would never start and\n # auto-merge would wait forever.\n if [ \"$HAS_PAT\" != \"true\" ]; then\n echo \"::warning::Sync PR $url opened with GITHUB_TOKEN: checks will not run and auto-merge is skipped. Set HOLOCRON_SYNC_TOKEN.\"\n echo \"Sync PR $url — needs manual merge (no PAT).\" >> \"$GITHUB_STEP_SUMMARY\"\n result=\"needs a manual merge (no PAT, so checks will not run)\"\n attention=true\n elif gh pr merge \"$url\" --auto --squash; then\n echo \"Sync PR $url — auto-merge enabled.\" | tee -a \"$GITHUB_STEP_SUMMARY\"\n result=\"auto-merge enabled\"\n else\n echo \"::warning::Sync PR $url opened but auto-merge could not be enabled; merge it manually.\"\n echo \"Sync PR $url — needs manual merge.\" >> \"$GITHUB_STEP_SUMMARY\"\n result=\"needs a manual merge (auto-merge could not be enabled)\"\n attention=true\n fi\n {\n echo \"url=$url\"\n echo \"result=$result\"\n echo \"attention=${attention:-false}\"\n } >> \"$GITHUB_OUTPUT\"\n env:\n BRANCH: ${{ format('chore/auto-sync-{0}', github.sha) }}\n HAS_PAT: ${{ secrets.HOLOCRON_SYNC_TOKEN != '' || secrets.GH_TOKEN != '' }}\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/notify@main\n name: Notify of the sync PR\n if: steps.pr.outputs.url != '' && steps.pr.outputs.attention != 'true'\n with:\n webhook: ${{ secrets.HOLOCRON_NOTIFY_WEBHOOK_SYNC }}\n message: \"🔄 ${{ github.repository }}: sync PR ${{ steps.pr.outputs.url }} — ${{ steps.pr.outputs.result }}${{ github.run_attempt > 1 && format(' (attempt {0})', github.run_attempt) || '' }}\"\n\n - uses: theholocron/.github/.github/actions/notify@main\n name: Notify that a sync PR needs attention\n if: steps.pr.outputs.attention == 'true'\n with:\n webhook: ${{ secrets.HOLOCRON_NOTIFY_WEBHOOK_ALERTS }}\n mention: ${{ vars.HOLOCRON_NOTIFY_ALERT_ROLE }}\n message: \"⚠️ ${{ github.repository }}: sync PR ${{ steps.pr.outputs.url }} — ${{ steps.pr.outputs.result }}${{ github.run_attempt > 1 && format(' (attempt {0})', github.run_attempt) || '' }}\"\n\n - name: Broadcast wiki sync if navbar changed\n if: >-\n steps.auto-commit.outputs.changes-detected == 'true' &&\n github.event_name == 'push' &&\n (inputs.steps == '' || contains(inputs.steps, 'wiki'))\n run: |\n if git diff HEAD~1 --name-only | grep -q 'fern/docs.yml'; then\n gh workflow run sync-dispatch.yml \\\n --repo theholocron/.github \\\n --field \"steps=wiki\" \\\n || echo \"skipping broadcast — insufficient permissions\"\n fi\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n # A separate job, not a final step: a job-level timeout cancels the sync job\n # before any later step in it can run, so an in-job `if: failure()` step would\n # stay silent on exactly the hang we most want to hear about. `!cancelled()` is\n # false when the whole run was cancelled (a newer run superseded this one), so\n # that expected case stays quiet, while a failed or timed-out sync job alerts.\n notify-failure:\n name: Notify of a failed sync\n needs: sync\n if: ${{ !cancelled() && (needs.sync.result == 'failure' || needs.sync.result == 'cancelled') }}\n runs-on: ubuntu-latest\n timeout-minutes: 2\n permissions: {}\n steps:\n - uses: theholocron/.github/.github/actions/notify@main\n name: Notify of a failed sync\n with:\n webhook: ${{ secrets.HOLOCRON_NOTIFY_WEBHOOK_ALERTS }}\n mention: ${{ vars.HOLOCRON_NOTIFY_ALERT_ROLE }}\n message: \"❌ ${{ github.repository }}: repo sync ${{ needs.sync.result == 'cancelled' && 'timed out or was cancelled' || 'failed' }} — ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}${{ github.run_attempt > 1 && format(' (attempt {0})', github.run_attempt) || '' }}\"\n";
173
+ var platform_repoSync_default$1 = "name: Sync\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n inputs:\n steps:\n description: >\n Sync steps to run (default: all). Valid values:\n labels, properties, teams, topics, keywords, description, homepage, readme, workflows, wiki.\n Pass a space-separated list to run a subset, e.g. \"readme\" or \"readme wiki\".\n type: string\n required: false\n secrets:\n HOLOCRON_ADMIN_TOKEN:\n description: Fine-grained PAT with admin scopes (labels, properties, teams).\n required: false\n HOLOCRON_AXIOM_TOKEN:\n description: >\n Axiom API token. When set alongside the HOLOCRON_AXIOM_DATASET\n repo/org variable, the CLI ships this run's structured logs to Axiom.\n Falls back to the vendor-native AXIOM_TOKEN secret.\n required: false\n AXIOM_TOKEN:\n description: Vendor-native fallback for HOLOCRON_AXIOM_TOKEN.\n required: false\n HOLOCRON_DEPLOY_TOKEN:\n description: Fine-grained PAT for GitHub Pages configuration.\n required: false\n HOLOCRON_ISSUES_TOKEN:\n description: Fine-grained PAT for issue management.\n required: false\n HOLOCRON_ORG_TOKEN:\n description: Org-scoped fine-grained PAT for team sync and org properties.\n required: false\n HOLOCRON_READ_TOKEN:\n description: Fine-grained PAT for read-only GitHub API calls.\n required: false\n HOLOCRON_SYNC_TOKEN:\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_SYNC:\n description: >\n Webhook for the sync channel: a sync PR opened and its\n auto-merge result. Unset = no post.\n required: false\n HOLOCRON_NOTIFY_WEBHOOK_ALERTS:\n description: >\n Webhook for the alerts channel: a failed sync run, or a sync\n PR that needs a manual merge. Unset = no post. The optional\n HOLOCRON_NOTIFY_ALERT_ROLE secret (a role id) makes these posts\n mention that role.\n required: false\n HOLOCRON_NOTIFY_ALERT_ROLE:\n description: >\n Id of the role to mention on alerts. Written by `holocron\n notifications setup`; not sensitive, kept as a secret so the same\n token that writes the webhook secrets can write it. Optional.\n required: false\n GH_TOKEN:\n description: >\n Generic GitHub token fallback for gh CLI calls. Used when\n HOLOCRON_SYNC_TOKEN is not set.\n required: false\n\njobs:\n sync:\n name: Run holocron repo sync\n runs-on: ubuntu-latest\n timeout-minutes: 10\n # Serialise the find-or-create-PR and supersede steps repo-wide: the caller's\n # concurrency key is per ref, so runs from different refs could otherwise\n # interleave and leave several sync PRs open.\n concurrency:\n group: repo-sync-pr-${{ github.repository }}\n cancel-in-progress: false\n permissions:\n contents: write\n pull-requests: write\n # Job-level so the `holocron` composite action's steps inherit them.\n env:\n HOLOCRON_ADMIN_TOKEN: ${{ secrets.HOLOCRON_ADMIN_TOKEN }}\n HOLOCRON_AXIOM_TOKEN: ${{ secrets.HOLOCRON_AXIOM_TOKEN || secrets.AXIOM_TOKEN }}\n HOLOCRON_AXIOM_DATASET: ${{ vars.HOLOCRON_AXIOM_DATASET || vars.AXIOM_DATASET }}\n POSTHOG_PROJECT_TOKEN: ${{ vars.POSTHOG_PROJECT_TOKEN }}\n HOLOCRON_DEPLOY_TOKEN: ${{ secrets.HOLOCRON_DEPLOY_TOKEN }}\n HOLOCRON_ISSUES_TOKEN: ${{ secrets.HOLOCRON_ISSUES_TOKEN }}\n HOLOCRON_ORG_TOKEN: ${{ secrets.HOLOCRON_ORG_TOKEN }}\n HOLOCRON_READ_TOKEN: ${{ secrets.HOLOCRON_READ_TOKEN }}\n HOLOCRON_SYNC_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN }}\n steps:\n - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n name: Checkout repository\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - name: Run holocron repo sync\n # The `holocron` action resolves @theholocron/cli from node_modules (or\n # builds the workspace when it's an unbuilt checkout — the holocron repo\n # itself). `inputs.steps` is a space-separated list or empty; the\n # `--steps <list>` arg is omitted when empty.\n uses: theholocron/.github/.github/actions/holocron@main\n with:\n command: repo sync\n args: ${{ inputs.steps != '' && format('--steps {0}', inputs.steps) || '' }}\n\n - name: Format generated files\n run: |\n pnpm exec prettier --write README.md docs/src/content/docs/index.mdx 2>/dev/null || true\n # `holocron repo sync` writes package.json fields (keywords, description,\n # homepage) with a plain assignment, which appends new keys at the\n # end — re-apply the canonical order the lint config enforces.\n pnpm exec eslint --fix --no-warn-ignored package.json 2>/dev/null || true\n\n - uses: theholocron/.github/.github/actions/auto-commit@main\n id: auto-commit\n name: Commit sync changes\n with:\n token: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n # One branch per source commit (full SHA, so distinct commits never collide): a PR left unreviewed never blocks the\n # next sync, and a re-run for the same commit updates its own branch.\n branch: ${{ format('chore/auto-sync-{0}', github.sha) }}\n commit-message: \"chore: sync from holocron.config\"\n commit-options: \"--no-verify\"\n\n - name: Open PR and enable auto-merge\n id: pr\n if: steps.auto-commit.outputs.changes-detected == 'true'\n run: |\n # Find or create this run's PR first: older PRs are only closed once\n # a replacement exists, so a failure here never leaves the changes\n # without an open PR.\n url=$(gh pr view \"$BRANCH\" --json url --jq .url 2>/dev/null || gh pr create \\\n --title \"chore: sync README and repo metadata\" \\\n --body \"Automated sync from holocron.config. Auto-merges once required checks pass.\" \\\n --base main \\\n --head \"$BRANCH\")\n created=$(gh pr view \"$url\" --json createdAt --jq .createdAt)\n\n # Supersede older sync PRs: same-repo only, exact generated or legacy\n # branch name, and created before this one (a slow older run can\n # never close a newer PR). --limit covers more than the default page.\n gh pr list --state open --limit 200 --json number,headRefName,isCrossRepository,createdAt \\\n --jq \".[] | select(.isCrossRepository | not) | select(.headRefName == \\\"chore/auto-sync\\\" or (.headRefName | test(\\\"^chore/auto-sync-[0-9a-f]{40}$\\\"))) | select(.headRefName != \\\"$BRANCH\\\") | select(.createdAt < \\\"$created\\\") | .number\" |\n while read -r n; do\n gh pr close \"$n\" --delete-branch --comment \"Superseded by $url.\" || true\n done\n\n # Delete pushed sync branches that never got a PR (e.g. a run\n # cancelled between push and PR creation). The repo-wide concurrency\n # group means no other run is mid-flight here.\n open=$(gh pr list --state open --limit 200 --json headRefName --jq '.[].headRefName')\n git ls-remote --heads origin 'refs/heads/chore/auto-sync-*' | sed 's|.*refs/heads/||' |\n while read -r b; do\n [ \"$b\" = \"$BRANCH\" ] && continue\n echo \"$b\" | grep -Eq '^chore/auto-sync-[0-9a-f]{40}$' || continue\n echo \"$open\" | grep -qxF \"$b\" || git push origin --delete \"$b\" || true\n done\n\n # A PR opened with the default GITHUB_TOKEN does not trigger\n # pull_request workflows, so required checks would never start and\n # auto-merge would wait forever.\n if [ \"$HAS_PAT\" != \"true\" ]; then\n echo \"::warning::Sync PR $url opened with GITHUB_TOKEN: checks will not run and auto-merge is skipped. Set HOLOCRON_SYNC_TOKEN.\"\n echo \"Sync PR $url — needs manual merge (no PAT).\" >> \"$GITHUB_STEP_SUMMARY\"\n result=\"needs a manual merge (no PAT, so checks will not run)\"\n attention=true\n elif gh pr merge \"$url\" --auto --squash; then\n echo \"Sync PR $url — auto-merge enabled.\" | tee -a \"$GITHUB_STEP_SUMMARY\"\n result=\"auto-merge enabled\"\n else\n echo \"::warning::Sync PR $url opened but auto-merge could not be enabled; merge it manually.\"\n echo \"Sync PR $url — needs manual merge.\" >> \"$GITHUB_STEP_SUMMARY\"\n result=\"needs a manual merge (auto-merge could not be enabled)\"\n attention=true\n fi\n {\n echo \"url=$url\"\n echo \"result=$result\"\n echo \"attention=${attention:-false}\"\n } >> \"$GITHUB_OUTPUT\"\n env:\n BRANCH: ${{ format('chore/auto-sync-{0}', github.sha) }}\n HAS_PAT: ${{ secrets.HOLOCRON_SYNC_TOKEN != '' || secrets.GH_TOKEN != '' }}\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n - uses: theholocron/.github/.github/actions/notify@main\n name: Notify of the sync PR\n if: steps.pr.outputs.url != '' && steps.pr.outputs.attention != 'true'\n with:\n webhook: ${{ secrets.HOLOCRON_NOTIFY_WEBHOOK_SYNC }}\n message: \"🔄 ${{ github.repository }}: sync PR ${{ steps.pr.outputs.url }} — ${{ steps.pr.outputs.result }}${{ github.run_attempt > 1 && format(' (attempt {0})', github.run_attempt) || '' }}\"\n\n - uses: theholocron/.github/.github/actions/notify@main\n name: Notify that a sync PR needs attention\n if: steps.pr.outputs.attention == 'true'\n with:\n webhook: ${{ secrets.HOLOCRON_NOTIFY_WEBHOOK_ALERTS }}\n mention: ${{ secrets.HOLOCRON_NOTIFY_ALERT_ROLE }}\n message: \"⚠️ ${{ github.repository }}: sync PR ${{ steps.pr.outputs.url }} — ${{ steps.pr.outputs.result }}${{ github.run_attempt > 1 && format(' (attempt {0})', github.run_attempt) || '' }}\"\n\n - name: Broadcast wiki sync if navbar changed\n if: >-\n steps.auto-commit.outputs.changes-detected == 'true' &&\n github.event_name == 'push' &&\n (inputs.steps == '' || contains(inputs.steps, 'wiki'))\n run: |\n if git diff HEAD~1 --name-only | grep -q 'fern/docs.yml'; then\n gh workflow run sync-dispatch.yml \\\n --repo theholocron/.github \\\n --field \"steps=wiki\" \\\n || echo \"skipping broadcast — insufficient permissions\"\n fi\n env:\n GH_TOKEN: ${{ secrets.HOLOCRON_SYNC_TOKEN || secrets.GH_TOKEN || github.token }}\n\n # A separate job, not a final step: a job-level timeout cancels the sync job\n # before any later step in it can run, so an in-job `if: failure()` step would\n # stay silent on exactly the hang we most want to hear about. `!cancelled()` is\n # false when the whole run was cancelled (a newer run superseded this one), so\n # that expected case stays quiet, while a failed or timed-out sync job alerts.\n notify-failure:\n name: Notify of a failed sync\n needs: sync\n if: ${{ !cancelled() && (needs.sync.result == 'failure' || needs.sync.result == 'cancelled') }}\n runs-on: ubuntu-latest\n timeout-minutes: 2\n permissions: {}\n steps:\n - uses: theholocron/.github/.github/actions/notify@main\n name: Notify of a failed sync\n with:\n webhook: ${{ secrets.HOLOCRON_NOTIFY_WEBHOOK_ALERTS }}\n mention: ${{ secrets.HOLOCRON_NOTIFY_ALERT_ROLE }}\n message: \"❌ ${{ github.repository }}: repo sync ${{ needs.sync.result == 'cancelled' && 'timed out or was cancelled' || 'failed' }} — ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}${{ github.run_attempt > 1 && format(' (attempt {0})', github.run_attempt) || '' }}\"\n";
171
174
  //#endregion
172
175
  //#region src/templates/reusable/platform.repoValidation.yml
173
176
  var platform_repoValidation_default$1 = "name: Repo Validation\n\non: # yamllint disable-line rule:truthy\n workflow_call:\n secrets:\n TURBO_TOKEN:\n required: false\n\njobs:\n adrs:\n name: Validate ADRs and specs\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 with:\n fetch-depth: 0\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Validate ADR and spec frontmatter\n with:\n task: platform.repoValidation\n job: adrs\n\n registry:\n name: Validate registry consistency\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 - uses: theholocron/.github/.github/actions/holocron@main\n name: Validate registry consistency\n with:\n task: platform.repoValidation\n job: registry\n\n docs-presence:\n name: Validate docs presence\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 with:\n fetch-depth: 0\n\n - uses: theholocron/.github/.github/actions/setup@main\n name: Setup\n\n - uses: theholocron/.github/.github/actions/holocron@main\n name: Validate docs presence for new packages\n with:\n task: platform.repoValidation\n job: docsPresence\n env:\n BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}\n\n conclusion:\n name: Conclusion\n runs-on: ubuntu-latest\n if: always()\n needs: [adrs, registry, docs-presence]\n steps:\n - name: Check job statuses\n run: |\n if [[ \"$RESULTS\" == *\"failure\"* ]] || [[ \"$RESULTS\" == *\"cancelled\"* ]]; then\n exit 1\n fi\n env:\n RESULTS: ${{ join(needs.*.result, ',') }}\n";
@@ -249,6 +252,7 @@ const WORKFLOW_TEMPLATES = {
249
252
  "delivery.previewCheck": "name: Delivery\n\non: # yamllint disable-line rule:truthy\n deployment_status:\n\npermissions:\n contents: read\n # Must be a superset of what the reusable workflow's own job\n # requests (holocron#1058) -- GitHub hard-fails the whole run at\n # startup, zero jobs dispatched, if the callee asks for more than\n # the caller grants. Needed for the author-trust step's\n # commits/{sha}/pulls lookup.\n pull-requests: read\n\njobs:\n preview-check:\n name: Preview Check\n # environment_url is the only field documented to point at the live\n # app — target_url can point at a deployment-details page instead,\n # so there's no safe fallback to it. No environment_url means\n # nothing to check; skip the job entirely rather than hit the wrong\n # page.\n if: >-\n github.event.deployment_status.state == 'success' &&\n github.event.deployment.environment == 'Preview' &&\n github.event.deployment_status.environment_url != ''\n uses: theholocron/.github/.github/workflows/delivery.previewCheck.yml@main\n with:\n preview-url: ${{ github.event.deployment_status.environment_url }}\n # GitHub evaluates which version of this workflow file to run\n # from the default branch for a deployment_status event (unlike\n # push/pull_request) -- without this, the reusable workflow's\n # checkout would default to that same ref instead of the PR's\n # actual deployed commit.\n sha: ${{ github.event.deployment.sha }}\n secrets:\n # Named explicitly, not `secrets: inherit` -- this job needs only\n # these two secrets (holocron#1030/#1032), not every secret this\n # workflow's caller context has access to (e.g.\n # HOLOCRON_DEPLOYMENTS_TOKEN). VERCEL_TOKEN here is read-only use\n # (verifying deployment ownership), never a write/deploy\n # credential.\n VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}\n VERCEL_PROTECTION_BYPASS_SECRET: ${{ secrets.VERCEL_PROTECTION_BYPASS_SECRET }}\n",
250
253
  "delivery.previewDeploy": "name: Delivery\n\non: # yamllint disable-line rule:truthy\n pull_request: {}\n\nconcurrency:\n group: preview-deploy-${{ github.event.pull_request.number }}\n # Not true: a cancelled run could land between Vercel accepting the\n # upload and the report job posting a status, leaving a real preview\n # deployment with no corresponding GitHub check — worse than letting an\n # overlapping run for the same PR simply queue.\n cancel-in-progress: false\n\npermissions:\n contents: read\n deployments: write\n # Must be a superset of what the reusable workflow's own job requests\n # (holocron#1058) -- its new path-relevance check lists the PR's\n # changed files via the API (holocron#1023).\n pull-requests: read\n\njobs:\n preview-deploy:\n name: Preview Deploy\n uses: theholocron/.github/.github/workflows/delivery.previewDeploy.yml@main\n with:\n cwd: \".\"\n secrets: inherit\n",
251
254
  "platform.repoSync": "name: Platform\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main]\n paths:\n - holocron.config.ts\n - package.json\n - pnpm-workspace.yaml\n workflow_dispatch:\n inputs:\n steps:\n description: \"Sync steps to run (default: all)\"\n type: string\n required: false\n\nconcurrency:\n group: sync-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: write\n pull-requests: write\n\njobs:\n sync:\n name: Sync\n uses: theholocron/.github/.github/workflows/platform.repoSync.yml@main\n with:\n steps: ${{ inputs.steps }}\n secrets: inherit\n",
255
+ "platform.notifyCheck": "name: Platform\n\non: # yamllint disable-line rule:truthy\n workflow_dispatch: {}\n\npermissions: {}\n\njobs:\n notify-check:\n name: Notify Check\n uses: theholocron/.github/.github/workflows/platform.notifyCheck.yml@main\n secrets: inherit\n",
252
256
  "platform.commitStandards": "name: Platform\n\non: # yamllint disable-line rule:truthy\n pull_request:\n\nconcurrency:\n group: platform-commit-standards-${{ github.ref }}\n cancel-in-progress: true\n\npermissions:\n contents: read\n\njobs:\n commit-standards:\n name: Commit Standards\n uses: theholocron/.github/.github/workflows/platform.commitStandards.yml@main\n secrets: inherit\n",
253
257
  "platform.repoValidation": "name: Platform\n\non: # yamllint disable-line rule:truthy\n push:\n branches: [main, alpha]\n pull_request:\n\npermissions:\n contents: read\n\njobs:\n repo-validation:\n name: Repo Validation\n uses: theholocron/.github/.github/workflows/platform.repoValidation.yml@main\n secrets: inherit\n",
254
258
  "platform.syncTemplates": "name: Platform\n\n# Bootstrap note: this `uses:` a reusable workflow that must already exist\n# on theholocron/.github's main branch to resolve at all — a brand-new\n# reusable workflow here needs ONE manual `holocron sync github` run\n# (pushing directly to theholocron/.github) before this thin caller can\n# ever successfully trigger it, since GitHub resolves `uses:` at run time,\n# not at merge time. Same deadlock every reusable workflow added here hits\n# on its first introduction.\non: # yamllint disable-line rule:truthy\n push:\n # main only — this publishes to theholocron/.github, consumed by every\n # other repo's CI. alpha is the prerelease channel; publishing from it\n # would let unreleased/unstable template changes overwrite what main\n # just published, the same stable-vs-prerelease split this org already\n # enforces for npm's dist-tags and Sentinel's own deploy trigger.\n branches: [main]\n paths:\n - packages/astromech/src/templates/**\n - packages/astromech/src/generators/**\n - packages/astromech/src/registry/**\n - packages/cli/src/templates/**\n workflow_dispatch: {}\n\nconcurrency:\n group: sync-templates\n cancel-in-progress: false\n\npermissions:\n contents: read\n\njobs:\n sync-templates:\n name: Sync Templates\n # workflow_dispatch can target ANY ref, not only main — without this,\n # anyone able to dispatch this workflow (a broader group than who can\n # push to main) could run it against an arbitrary branch, checking out\n # and building that ref's own code with the sync token present, then\n # publishing that ref's templates to theholocron/.github.\n if: github.ref == 'refs/heads/main'\n uses: theholocron/.github/.github/workflows/platform.syncTemplates.yml@main\n secrets: inherit\n",
@@ -540,6 +544,7 @@ const REUSABLE_WORKFLOWS = {
540
544
  "delivery.previewCheck": delivery_previewCheck_default$1,
541
545
  "delivery.previewDeploy": delivery_previewDeploy_default$1,
542
546
  "platform.repoSync": platform_repoSync_default$1,
547
+ "platform.notifyCheck": platform_notifyCheck_default$1,
543
548
  "platform.commitStandards": platform_commitStandards_default$1,
544
549
  "platform.repoValidation": platform_repoValidation_default$1,
545
550
  "platform.syncTemplates": platform_syncTemplates_default$1,
@@ -750,6 +755,7 @@ const TASKS = {
750
755
  "delivery.previewCheck": { local: null },
751
756
  "delivery.previewDeploy": { local: null },
752
757
  "platform.repoSync": { local: { command: "sync" } },
758
+ "platform.notifyCheck": { local: null },
753
759
  "platform.syncTemplates": { local: { command: "sync github" } },
754
760
  "platform.commitStandards": {
755
761
  local: null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/astromech",
3
- "version": "5.0.0-alpha.185",
3
+ "version": "5.0.0-alpha.187",
4
4
  "description": "The Holocron task runner — one task manifest drives `holocron run`, `holocron run ci`, the CI workflows, package.json scripts, linters, and required checks.",
5
5
  "keywords": [
6
6
  "ci",
@@ -48,7 +48,7 @@
48
48
  "@theholocron/fs-utils": "^1.16.0",
49
49
  "@theholocron/json-utils": "^1.16.0",
50
50
  "@theholocron/pkg-utils": "^1.16.0",
51
- "@theholocron/datapad": "5.0.0-alpha.185"
51
+ "@theholocron/datapad": "5.0.0-alpha.187"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@commitlint/config-conventional": "^21.2.3",