Skip to content

Ingest pkghaus/vale-debian v3.18.0-1 #74

Ingest pkghaus/vale-debian v3.18.0-1

Ingest pkghaus/vale-debian v3.18.0-1 #74

Workflow file for this run

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