repo-index #193
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: repo-index | |
| # Regenerates the package listing published at https://xerootg.github.io/. | |
| # | |
| # The input is each repo's pacman database -- the `.db` that `repo-add` writes | |
| # at the end of every build -- so the page is derived from the same artifact | |
| # pacman itself downloads and cannot drift from what a client would install. | |
| # Nothing on the page is hand-maintained. | |
| # | |
| # This is deliberately a separate workflow rather than a step bolted onto the | |
| # three publishers. Those run on different schedules, take between two minutes | |
| # and three hours, and two of them never check out the Pages repo at all; | |
| # having each one rewrite a shared index would race on the same push. Instead | |
| # every publisher wakes this job when it finishes, and this job is the only | |
| # writer. | |
| on: | |
| workflow_run: | |
| workflows: ["Build Pacman Repo", "ghidra-noprompt", "orca-slicer"] | |
| types: [completed] | |
| schedule: | |
| # Catches anything the workflow_run hooks miss, and keeps the "last checked" | |
| # stamp on the page honest during a quiet week. | |
| - cron: "35 9 * * *" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| # One writer. Never cancel a run mid-push. | |
| group: "${{ github.workflow }}" | |
| cancel-in-progress: false | |
| jobs: | |
| index: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| # Where PAGES_BOT_APP_ID / PAGES_BOT_PRIVATE_KEY live. | |
| environment: prod | |
| steps: | |
| - name: Checkout this repo | |
| uses: actions/checkout@v7 | |
| with: | |
| path: tooling | |
| - name: Get GitHub App token for GitHub Pages | |
| id: app-token | |
| uses: actions/create-github-app-token@v3.2.0 | |
| with: | |
| app-id: ${{ secrets.PAGES_BOT_APP_ID }} | |
| private-key: ${{ secrets.PAGES_BOT_PRIVATE_KEY }} | |
| owner: ${{ github.repository_owner }} | |
| repositories: ${{ github.repository_owner }}.github.io | |
| - name: Checkout the GitHub Pages repo | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: ${{ github.repository_owner }}/${{ github.repository_owner }}.github.io | |
| ref: main | |
| path: pages | |
| token: ${{ steps.app-token.outputs.token }} | |
| - name: Collect the repo databases | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p dbs | |
| # Every repo is release-hosted now, [custom] included. A download | |
| # failure is not fatal: the generator keeps that repo's last known | |
| # contents rather than reporting every one of its packages as removed. | |
| # The .sig comes along too -- the generator reads the issuer out of it | |
| # to decide whether the page may advertise SigLevel = Required. | |
| for pair in "custom-repo:custom" "pacman-repo:ghidra" "orca-repo:orca"; do | |
| tag="${pair%%:*}"; name="${pair##*:}" | |
| if gh release download "$tag" --pattern "${name}.db" --dir dbs --clobber; then | |
| echo "fetched ${name}.db from $tag" | |
| else | |
| echo "::warning::could not download ${name}.db from release $tag" | |
| fi | |
| # Absent before that repo's first signed publish; not an error. | |
| gh release download "$tag" --pattern "${name}.db.sig" --dir dbs --clobber \ | |
| || echo "no signature published for [$name] yet" | |
| done | |
| ls -l dbs/ | |
| - name: Refresh the published signing key | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| # The site serves the public key, but the build that signs no longer | |
| # touches the Pages repo, so bring it across from the release. Taken | |
| # from the release rather than kept in git so it always matches the | |
| # key actually signing. | |
| if gh release download custom-repo --pattern xerootg.asc --dir pages --clobber; then | |
| echo "refreshed pages/xerootg.asc" | |
| else | |
| echo "::warning::no xerootg.asc published yet" | |
| fi | |
| - name: Generate the index | |
| id: gen | |
| run: | | |
| # --pubkey is the key users are told to trust; the .db.sig files decide | |
| # whether a repo is advertised as signed at all. The generator fails | |
| # if the two disagree. | |
| python3 tooling/.github/scripts/build-repo-index.py \ | |
| --config tooling/.github/repo-index.json \ | |
| --db-dir dbs \ | |
| --pubkey pages/xerootg.asc \ | |
| --out-dir pages | |
| - name: Commit and push | |
| if: steps.gen.outputs.changed == 'true' | |
| working-directory: pages | |
| env: | |
| SUMMARY: ${{ steps.gen.outputs.summary }} | |
| run: | | |
| set -euo pipefail | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add -A index.html .nojekyll data/ xerootg.asc | |
| if git diff --cached --quiet; then | |
| echo "Nothing staged after all." | |
| exit 0 | |
| fi | |
| git commit -m "Update package index: ${SUMMARY}" | |
| # Retry only the push. This is the one step that can lose a race with | |
| # build-repo pushing packages into the same repo, and a rebase onto | |
| # the new tip is the correct resolution -- the two touch different | |
| # paths. | |
| delay=2 | |
| for attempt in 1 2 3 4 5; do | |
| if git push origin main; then | |
| echo "Pushed on attempt $attempt." | |
| exit 0 | |
| fi | |
| echo "Push failed (attempt $attempt); refetching and rebasing." | |
| sleep "$delay"; delay=$((delay * 2)) | |
| git fetch origin main || true | |
| git rebase origin/main || { git rebase --abort || true; } | |
| done | |
| echo "::error::could not push the index after 5 attempts" | |
| exit 1 | |
| - name: Summary | |
| if: always() | |
| env: | |
| CHANGED: ${{ steps.gen.outputs.changed }} | |
| SUMMARY: ${{ steps.gen.outputs.summary }} | |
| PACKAGES: ${{ steps.gen.outputs.packages }} | |
| run: | | |
| { | |
| echo "### Package index" | |
| echo | |
| echo "- Packages indexed: ${PACKAGES:-unknown}" | |
| echo "- Changes this run: ${SUMMARY:-none}" | |
| echo "- Published: ${CHANGED:-false}" | |
| echo | |
| echo "<https://${{ github.repository_owner }}.github.io/>" | |
| } >> "$GITHUB_STEP_SUMMARY" |