Files
docker_practice/.github/workflows/preview-pdf.yml
T
yeasy 898fb10bbe ci: track the latest mdPress release instead of a per-repo pinned version
Per the author: mdPress should default to the latest release.

The cluster had drifted to three versions (0.7.10 x4, 0.7.11 x9, 0.7.14 x1),
and nine of those were pinned to bytes upstream had rebuilt under an existing
tag — the exact thing the harness move to 0.7.14 refused to do on principle.
Pinning also took CI down cluster-wide twice when a tag was rebuilt, because
the digest no longer matched. Latest is now 0.7.15; nothing was on it.

Each of the 43 install sites now resolves the newest release at build time by
following the /releases/latest redirect (no api.github.com call, so no
unauthenticated rate limit on shared runner IPs) and exports the version via
GITHUB_ENV.

Integrity is kept, not dropped: the archive is verified against that same
release's published checksums.txt, and a missing entry aborts the step rather
than passing silently. The honest trade-off is that this verifies the download
rather than pinning an immutable artifact — a rebuilt release is now followed
instead of failing the build. That is the intended behaviour here, since the
rebuild breakage was the problem being solved and upstream is the same author.

Tests updated in step: 12 suites asserted the literal MDPRESS_SHA256 as a
proxy for "this download is checksum-verified". They now assert checksums.txt,
which is where that guarantee lives.
2026-07-23 13:47:03 -07:00

201 lines
7.2 KiB
Go

name: Update Preview PDF
on:
push:
branches:
- master
workflow_dispatch:
permissions: {}
concurrency:
group: preview-pdf
cancel-in-progress: true
jobs:
build:
permissions:
contents: read
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install locked Node dependencies
env:
PUPPETEER_SKIP_DOWNLOAD: "true"
run: npm ci
- name: Check project rules and metadata
run: |
python3 check_project_rules.py
npm test
- name: Install Chromium
uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2
with:
chrome-version: stable
- name: Install CJK fonts and PDF inspection tools
run: |
sudo apt-get update
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra poppler-utils
- name: Resolve latest mdPress release
run: |
url="$(curl -fsSL --retry 3 -o /dev/null -w '%{url_effective}' https://github.com/yeasy/mdPress/releases/latest)"
version="${url##*/v}"
test -n "$version" || { echo "could not resolve latest mdPress release"; exit 1; }
echo "MDPRESS_VERSION=$version" >> "$GITHUB_ENV"
echo "resolved mdPress $version"
- name: Install mdPress (checksum-verified)
run: |
archive="$RUNNER_TEMP/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz"
curl -fsSL --retry 3 \
"https://github.com/yeasy/mdPress/releases/download/v${MDPRESS_VERSION}/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz" \
-o "$archive"
expected="$(curl -fsSL --retry 3 "https://github.com/yeasy/mdPress/releases/download/v${MDPRESS_VERSION}/checksums.txt" \
| awk -v f="mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz" '$2==f {print $1}')"
test -n "$expected" || { echo "no published checksum for mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz"; exit 1; }
echo "${expected} $archive" | sha256sum -c -
tar xzf "$archive" -C "$RUNNER_TEMP" mdpress
mkdir -p "$RUNNER_TEMP/bin"
install -m 0755 "$RUNNER_TEMP/mdpress" "$RUNNER_TEMP/bin/mdpress"
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
- name: Prepare PDF sources
run: python3 tools/prepare_pdf_sources.py --book-dir . --out "$RUNNER_TEMP/docker_practice-pdf-src"
- name: Build latest preview PDF
working-directory: ${{ runner.temp }}/docker_practice-pdf-src
run: |
mkdir -p "$GITHUB_WORKSPACE/dist"
mdpress build --format pdf --output "$GITHUB_WORKSPACE/dist/docker_practice.pdf"
- name: Verify preview PDF
run: |
title=$(python3 -c 'import json; print(json.load(open("book.json", encoding="utf-8"))["title"])')
python3 tools/verify_artifacts.py \
--title "$title" \
--pdf dist/docker_practice.pdf \
--checksums dist/SHA256SUMS
(cd dist && sha256sum -c SHA256SUMS)
- name: Upload verified preview bundle
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-practice-preview
path: dist/
if-no-files-found: error
publish:
permissions:
contents: write
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
steps:
- name: Download verified preview bundle
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: docker-practice-preview
path: dist
- name: Recheck preview checksum
run: (cd dist && sha256sum -c SHA256SUMS)
- name: Write release notes
run: |
cat > dist/release-notes.md <<EOF
Auto-updated preview PDF from \`${GITHUB_SHA::7}\`.
- Branch: \`${GITHUB_REF_NAME}\`
- Commit: https://github.com/${GITHUB_REPOSITORY}/commit/${GITHUB_SHA}
- Run: https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}
This is a mutable preview without formal provenance. Use a tagged release for attested artifacts.
EOF
- name: Synchronize mutable preview tag
shell: bash
run: |
set -euo pipefail
if [[ ! "$GITHUB_REPOSITORY" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then
echo "Invalid GITHUB_REPOSITORY: $GITHUB_REPOSITORY" >&2
exit 1
fi
if [[ ! "$GITHUB_SHA" =~ ^[0-9a-f]{40}$ ]]; then
echo "Invalid GITHUB_SHA" >&2
exit 1
fi
probe_dir=$(mktemp -d)
trap 'rm -rf "$probe_dir"' EXIT
set +e
gh api --include --method GET \
"repos/${GITHUB_REPOSITORY}/git/ref/tags/preview-pdf" \
>"$probe_dir/response" 2>"$probe_dir/error"
probe_rc=$?
set -e
http_status=$(awk '$1 ~ /^HTTP\// && $2 ~ /^[0-9][0-9][0-9]$/ { status=$2 } END { print status }' "$probe_dir/response")
if [[ $probe_rc -eq 0 && "$http_status" == "200" ]]; then
gh api --silent --method PATCH \
"repos/${GITHUB_REPOSITORY}/git/refs/tags/preview-pdf" \
--raw-field sha="$GITHUB_SHA" \
--field force=true
elif [[ $probe_rc -ne 0 && "$http_status" == "404" ]]; then
gh api --silent --method POST \
"repos/${GITHUB_REPOSITORY}/git/refs" \
--raw-field ref="refs/tags/preview-pdf" \
--raw-field sha="$GITHUB_SHA"
else
cat "$probe_dir/response" >&2
cat "$probe_dir/error" >&2
echo "Preview tag lookup failed (exit=$probe_rc, HTTP=${http_status:-unavailable}); refusing to mutate refs or releases." >&2
exit 1
fi
- name: Create or update preview release
shell: bash
run: |
set -euo pipefail
error_file=$(mktemp)
trap 'rm -f "$error_file"' EXIT
set +e
gh release view preview-pdf >/dev/null 2>"$error_file"
release_rc=$?
set -e
if [[ $release_rc -eq 0 ]]; then
gh release edit preview-pdf \
--title "Latest Preview PDF" \
--notes-file dist/release-notes.md \
--prerelease
elif [[ "$(tr -d '\r' < "$error_file")" == "release not found" ]]; then
gh release create preview-pdf \
--title "Latest Preview PDF" \
--notes-file dist/release-notes.md \
--prerelease \
--latest=false \
--verify-tag
else
cat "$error_file" >&2
echo "Preview release lookup failed (exit=$release_rc); refusing to create or edit the release." >&2
exit 1
fi
- name: Replace preview assets
run: |
gh release delete-asset preview-pdf latest.pdf -y || true
gh release upload preview-pdf \
dist/docker_practice.pdf \
dist/SHA256SUMS \
--clobber