mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-08-10 16:37:34 +00:00
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.
201 lines
7.2 KiB
Go
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
|