diff --git a/.github/CLAUDE.md b/.github/CLAUDE.md index b5429de51..e092f6256 100644 --- a/.github/CLAUDE.md +++ b/.github/CLAUDE.md @@ -17,6 +17,7 @@ including the PR title format and the Go checks that CI gates on, are in the roo | `release-binaries.yaml` | Tag push (`v*`), manual; push to main publishes the main-latest channel when `MAIN_CHANNEL_ENABLED` is set | Release tarballs — see [Release binaries](#release-binaries) | | `pr-verifier.yml` | PR | PR title check | | `spellcheck_action.yml` | PR | Spellcheck on markdown files — **disabled** (`if: false`) | +| `site-dispatch.yaml` | Push to main on `scripts/install.sh`, manual | Sends `docs-updated` to `rossoctl/.github`, so the site's `/cortex/install.sh` copy updates in minutes, not at its daily schedule. Needs the `SITE_DISPATCH_TOKEN` secret; without it, a warning only | Also: `release-smoke-linux.yaml`, `dependabot-tidy.yml`, `install-stats.yaml`, `project.yml`, `self-assign.yml`, `stale.yaml`. diff --git a/.github/workflows/site-dispatch.yaml b/.github/workflows/site-dispatch.yaml new file mode 100644 index 000000000..1785a9706 --- /dev/null +++ b/.github/workflows/site-dispatch.yaml @@ -0,0 +1,101 @@ +# Site dispatch: tell the website to rebuild when the installer changes here. +# +# The one-liner `curl -fsSL https://www.rossoctl.dev/cortex/install.sh | sh` +# runs a copy of scripts/install.sh that the website in rossoctl/.github keeps. +# Its build (npm run sync-docs) copies the file from this repository's main. +# +# Without this workflow, the site copies the installer only on its daily 06:17 +# UTC schedule, which GitHub can start hours late. Then a new installer option +# fails as "unknown option" for up to a day after the merge (install.sh --praxis +# on 2026-11-10). This workflow sends the repository_dispatch event that the +# site's "Deploy site to Pages" workflow already listens for (type: +# docs-updated), so the site has the new installer a few minutes after the +# merge. rossoctl/rossoctl sends the same event for its docs. +# +# ONE-TIME SETUP: the secret SITE_DISPATCH_TOKEN. +# GITHUB_TOKEN is scoped to this repository, so it cannot dispatch to another +# one. Create a fine-grained personal access token, or a GitHub App token, +# with "Contents: read and write" on rossoctl/.github ONLY, and store it here +# as the repository secret SITE_DISPATCH_TOKEN: +# +# gh secret set SITE_DISPATCH_TOKEN --repo rossoctl/cortex +# +# Until that secret exists, this workflow gives a warning and exits 0. It +# does not fail a merge, and the site's daily schedule still copies the file. +name: Site dispatch + +on: + push: + branches: [main] + paths: + # The only file the site copies from this repository. + - "scripts/install.sh" + workflow_dispatch: {} + +permissions: + contents: read + +# One dispatch at a time. A burst of merges then gives one rebuild of the site. +concurrency: + group: site-dispatch + cancel-in-progress: false + +jobs: + dispatch: + name: Ask rossoctl/.github to rebuild + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Send repository_dispatch to rossoctl/.github + id: dispatch + env: + GH_TOKEN: ${{ secrets.SITE_DISPATCH_TOKEN }} + SHA: ${{ github.sha }} + ACTOR: ${{ github.actor }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + set -euo pipefail + + if [ -z "${GH_TOKEN}" ]; then + echo "notified=false" >> "$GITHUB_OUTPUT" + msg="The website was not notified. It copies the installer on its daily 06:17 UTC" + msg="${msg} schedule. See the setup note in this workflow file." + echo "::warning title=SITE_DISPATCH_TOKEN is not set::${msg}" + exit 0 + fi + + echo "Dispatching docs-updated for ${SHA} to rossoctl/.github" + + # The receiver is the "Deploy site to Pages" workflow in rossoctl/.github + # (on: repository_dispatch, types: [docs-updated]). client_payload only + # records which commit in this repository caused the rebuild. + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + repos/rossoctl/.github/dispatches \ + -f event_type=docs-updated \ + -f "client_payload[source_repo]=${GITHUB_REPOSITORY}" \ + -f "client_payload[sha]=${SHA}" \ + -f "client_payload[actor]=${ACTOR}" \ + -f "client_payload[run_url]=${RUN_URL}" + + echo "notified=true" >> "$GITHUB_OUTPUT" + echo "Dispatched. The site build runs at:" + echo "https://github.com/rossoctl/.github/actions/workflows/deploy.yaml" + + - name: Summary + if: always() + env: + NOTIFIED: ${{ steps.dispatch.outputs.notified }} + run: | + { + echo "### Site dispatch" + echo "" + if [ "${NOTIFIED}" = "true" ]; then + echo "Sent \`docs-updated\` to rossoctl/.github. The site copies" + echo "\`scripts/install.sh\` from this commit." + else + echo "\`SITE_DISPATCH_TOKEN\` is not set, so the site was not notified." + echo "It copies the installer on its daily 06:17 UTC schedule." + fi + } >> "$GITHUB_STEP_SUMMARY"