Ingest pkghaus/vale-debian v3.18.0-1 #74
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: Ingest and publish | |
| # Dispatch runs are named after the package that cued them; every other | |
| # event keeps GitHub's default title (the empty fallback string does that). | |
| run-name: >- | |
| ${{ github.event_name == 'repository_dispatch' | |
| && format('Ingest {0} {1}', github.event.client_payload.repository, github.event.client_payload.tag) | |
| || '' }} | |
| # Builds whatever the fleet's newest tags provide that the archive does not yet | |
| # carry, includes it into the reprepro pool, and publishes the result to GitHub | |
| # Pages at https://apt.pkg.haus. | |
| # | |
| # Published pool files are immutable: the plan only ever adds missing versions, | |
| # and reprepro refuses a different binary under an existing version. A run with | |
| # nothing missing publishes nothing and touches nothing. | |
| # | |
| # State model: the published tree (db/, dists/, pool/) lives on the `archive` | |
| # branch. Every job that needs archive state clones that branch into public/; | |
| # the publish job commits the updated tree back and deploys it to Pages. | |
| # | |
| # Runs when a fleet repository reports a validated tag (repository_dispatch | |
| # from action-debian-build's notify job), on manual dispatch, and on pushes | |
| # that change the archive's own configuration. | |
| on: | |
| repository_dispatch: | |
| types: [package-tagged] | |
| workflow_dispatch: | |
| push: | |
| branches: [master, main] | |
| paths: | |
| - repos.txt | |
| - conf/** | |
| - scripts/** | |
| permissions: | |
| contents: read | |
| # Two ingests interleaving would race on the archive branch; one at a time, | |
| # never cancelled mid-publish. | |
| concurrency: | |
| group: ingest | |
| cancel-in-progress: false | |
| jobs: | |
| plan: | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| outputs: | |
| has_work: ${{ steps.plan.outputs.has_work }} | |
| matrix: ${{ steps.plan.outputs.matrix }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Check signing-key expiry | |
| env: | |
| ARCHIVE_SIGNING_KEY: ${{ secrets.ARCHIVE_SIGNING_KEY }} | |
| run: scripts/check-key-expiry.sh | |
| - name: Fetch archive state | |
| env: | |
| REPO_URL: ${{ github.server_url }}/${{ github.repository }} | |
| # Distinguishes "the branch does not exist" (first run: start empty) | |
| # from "the clone failed" (fail the run): falling back to an empty tree | |
| # on a transient failure would publish an archive missing its pool. | |
| run: | | |
| if git ls-remote --exit-code "$REPO_URL" refs/heads/archive >/dev/null; then | |
| git clone --branch archive --single-branch --depth 1 "$REPO_URL" public | |
| else | |
| echo "no archive branch yet -- starting empty" | |
| mkdir -p public | |
| fi | |
| - name: Install reprepro | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends reprepro | |
| - name: Plan | |
| id: plan | |
| # The matrix fans out one leg per plan row (package x suite x arch), | |
| # so each leg's artifact can carry the real package filename. | |
| run: | | |
| scripts/ingest.sh plan > plan.tsv | |
| echo "--- plan ---" | |
| column -t -s "$(printf '\t')" plan.tsv || true | |
| if [ -s plan.tsv ]; then | |
| echo "has_work=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_work=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| jq -Rnc '[inputs | split("\t") | |
| | {repo: .[0], pkg: .[2], suite: .[3], arch: .[4], version: .[5], | |
| runner: (if .[4] == "arm64" then "ubuntu-24.04-arm" else "ubuntu-24.04" end)}]' \ | |
| < plan.tsv > matrix.json | |
| echo "matrix=$(cat matrix.json)" >> "$GITHUB_OUTPUT" | |
| - name: Upload plan | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: plan | |
| path: plan.tsv | |
| retention-days: 7 | |
| build: | |
| name: build / ${{ matrix.pkg }} / ${{ matrix.suite }} / ${{ matrix.arch }} | |
| needs: plan | |
| if: needs.plan.outputs.has_work == 'true' | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 120 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJSON(needs.plan.outputs.matrix) }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Download plan | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: plan | |
| - name: Build this leg's package | |
| env: | |
| SUITE: ${{ matrix.suite }} | |
| REPO: ${{ matrix.repo }} | |
| run: scripts/ingest.sh build plan.tsv "$SUITE" "$REPO" | |
| - name: Upload packages | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| # The real Debian filename: one leg builds exactly one plan row. | |
| name: ${{ matrix.pkg }}_${{ matrix.version }}_${{ matrix.arch }}.deb | |
| path: build/* | |
| if-no-files-found: error | |
| retention-days: 7 | |
| publish: | |
| # Runs even when build was skipped: the pool index and keyring are | |
| # re-rendered idempotently, and the commit step no-ops when nothing | |
| # changed. Only a failed or cancelled upstream job stops a publish. | |
| needs: [plan, build] | |
| if: ${{ !cancelled() && needs.plan.result == 'success' && contains(fromJSON('["success", "skipped"]'), needs.build.result) }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: write | |
| pages: write | |
| id-token: write | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deploy.outputs.page_url }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Fetch archive state | |
| env: | |
| REPO_URL: ${{ github.server_url }}/${{ github.repository }} | |
| # Distinguishes "the branch does not exist" (first run: start empty) | |
| # from "the clone failed" (fail the run): falling back to an empty tree | |
| # on a transient failure would publish an archive missing its pool. | |
| run: | | |
| if git ls-remote --exit-code "$REPO_URL" refs/heads/archive >/dev/null; then | |
| git clone --branch archive --single-branch --depth 1 "$REPO_URL" public | |
| else | |
| echo "no archive branch yet -- starting empty" | |
| mkdir -p public | |
| fi | |
| - name: Download built packages | |
| if: needs.build.result == 'success' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| pattern: '*.deb' | |
| path: build | |
| merge-multiple: true | |
| - name: Install reprepro | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends reprepro | |
| - name: Import the archive signing key | |
| env: | |
| ARCHIVE_SIGNING_KEY: ${{ secrets.ARCHIVE_SIGNING_KEY }} | |
| run: | | |
| printf '%s' "$ARCHIVE_SIGNING_KEY" | gpg --batch --import | |
| gpg --list-secret-keys | |
| - name: Include and export | |
| if: needs.build.result == 'success' | |
| run: scripts/ingest.sh include build | |
| - name: Export the public keyring alongside the archive | |
| run: gpg --export > public/pkghaus-archive-keyring.gpg | |
| # After include (so the diff sees the new state), before render | |
| # (so the news page reflects this publish). Runs on empty plans | |
| # too: notices still merge, and an unchanged set emits nothing. | |
| - name: Update the news log | |
| run: scripts/news.sh | |
| - name: Render the pool index | |
| run: scripts/render-index.sh | |
| - name: Commit archive state | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| run: | | |
| cd public | |
| git init -q -b archive 2>/dev/null || true | |
| git add -A | |
| git -c user.name=pkghaus-ingest -c user.email=github@pkg.haus \ | |
| commit -qm "Ingest $(date -u '+%Y-%m-%d %H:%M:%S UTC')" || { | |
| echo "nothing changed"; exit 0; } | |
| # Plain push: the concurrency group serialises ingests, so a non-ff | |
| # here means something unexpected happened and should fail loudly. | |
| git push \ | |
| "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}" \ | |
| archive | |
| - name: Upload Pages artifact | |
| uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 | |
| with: | |
| path: public | |
| - name: Deploy to Pages | |
| id: deploy | |
| uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 | |
| # Ordered after the deployment on purpose: purging first would let the | |
| # edge refill with the previous render for a full day. | |
| - name: Purge listing pages from the edge cache | |
| env: | |
| CLOUDFLARE_PURGE_TOKEN: ${{ secrets.CLOUDFLARE_PURGE_TOKEN }} | |
| CLOUDFLARE_ZONE_ID: ${{ vars.CLOUDFLARE_ZONE_ID }} | |
| run: scripts/purge-cache.sh |