ci(github): Manual only

automatic triggering is disabled to prevent version mismatches
This commit is contained in:
nopeitsnothing
2026-05-25 19:18:52 -04:00
parent 121be79cd8
commit 1c3cf75cf0
5 changed files with 96 additions and 107 deletions
+5
View File
@@ -1,3 +1,8 @@
# 1. Push to main → build.yml runs automatically → note the run ID
# 2. Manually trigger sign.yml with that build run ID → note the sign run ID
# 3. Manually trigger release.yml with: version=v1.2.5, sign_run_id=<id>
# 4. Manually trigger changelog.yml with: version=v1.2.5
name: 📖 Build PDFs name: 📖 Build PDFs
on: on:
+3 -9
View File
@@ -1,12 +1,9 @@
name: 📝 Update Changelog name: 📝 Update Changelog
# Runs after build.yml completes on main — at that point we know what changed. # Manual only — automatic triggering is disabled to prevent version mismatches
# Can also be triggered manually to backfill a missing entry. # between the generated PDF and the GitHub release. Run this manually after
# a release is published and the version is confirmed.
on: on:
workflow_run:
workflows: ["📖 Build PDFs"]
types: [completed]
branches: [main]
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version: version:
@@ -25,9 +22,6 @@ permissions:
jobs: jobs:
changelog: changelog:
name: Prepend changelog entry name: Prepend changelog entry
if: >
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
+34 -54
View File
@@ -1,22 +1,17 @@
name: 🚀 Release name: 🚀 Release
# Can be triggered: # Manual only — run this deliberately after build and sign are confirmed good.
# 1. Automatically after sign.yml completes on main # Provide the exact version tag and the sign.yml run ID to pull artifacts from.
# 2. Manually, pointing at specific build/sign runs to pull artifacts from
on: on:
workflow_run:
workflows: ["🔏 Sign PDFs"]
types: [completed]
branches: [main]
workflow_dispatch: workflow_dispatch:
inputs: inputs:
sign_run_id: version:
description: 'sign.yml run ID to pull signatures from' description: 'Release version tag (e.g. v1.2.4) — must not already exist'
required: true required: true
type: string type: string
build_run_id: sign_run_id:
description: 'build.yml run ID to pull PDFs from (leave blank to use pdfs-signed from sign run)' description: 'sign.yml run ID to pull signatures and PDFs from'
required: false required: true
type: string type: string
prerelease: prerelease:
description: 'Mark as pre-release?' description: 'Mark as pre-release?'
@@ -31,9 +26,6 @@ permissions:
jobs: jobs:
release: release:
name: Publish GitHub Release name: Publish GitHub Release
if: >
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -44,40 +36,22 @@ jobs:
sparse-checkout: pgp sparse-checkout: pgp
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
# Resolve which run IDs to pull artifacts from # Download artifacts from the specified sign run
# ------------------------------------------------------------------ #
- name: 🔍 Resolve run IDs
id: runs
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
SIGN_RUN="${{ inputs.sign_run_id }}"
BUILD_RUN="${{ inputs.build_run_id }}"
else
SIGN_RUN="${{ github.event.workflow_run.id }}"
BUILD_RUN=""
fi
echo "sign_run=$SIGN_RUN" >> $GITHUB_OUTPUT
echo "build_run=$BUILD_RUN" >> $GITHUB_OUTPUT
echo "Sign run: $SIGN_RUN"
echo "Build run: ${BUILD_RUN:-'(using pdfs-signed from sign run)'}"
# ------------------------------------------------------------------ #
# Download artifacts
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
- name: 📥 Download signatures artifact - name: 📥 Download signatures artifact
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: signatures name: signatures
path: release/ path: release/
run-id: ${{ steps.runs.outputs.sign_run }} run-id: ${{ inputs.sign_run_id }}
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
- name: 📥 Download PDFs (from sign run) - name: 📥 Download signed PDFs artifact
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: pdfs-signed name: pdfs-signed
path: release/ path: release/
run-id: ${{ steps.runs.outputs.sign_run }} run-id: ${{ inputs.sign_run_id }}
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
- name: 📋 List release assets - name: 📋 List release assets
@@ -96,7 +70,7 @@ jobs:
echo "dark_b2=$(read_hash thgtoa-dark.pdf.b2)" >> $GITHUB_OUTPUT echo "dark_b2=$(read_hash thgtoa-dark.pdf.b2)" >> $GITHUB_OUTPUT
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
# VirusTotal — upload whichever PDFs are present # VirusTotal
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
- name: 🦠 Upload PDFs to VirusTotal - name: 🦠 Upload PDFs to VirusTotal
id: vt id: vt
@@ -124,28 +98,34 @@ jobs:
fi fi
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
# Tag + Release auto-increment vX.Y.Z from latest semver tag # Validate explicit version input — refuse to auto-increment or
# overwrite an existing tag
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
- name: 🏷️ Generate release tag - name: 🏷️ Validate release tag
id: tag id: tag
run: | run: |
git fetch --tags --quiet git fetch --tags --quiet
VERSION="${{ inputs.version }}"
LATEST=$(git tag --list 'v*' --sort=-version:refname \ # Enforce vX.Y.Z format
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ if ! echo "$VERSION" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
| head -1) echo "::error::Version '$VERSION' is not valid semver. Use format: v1.2.3"
LATEST=${LATEST:-v0.0.0} exit 1
fi
MAJOR=$(echo "$LATEST" | cut -d. -f1 | tr -d 'v') # Refuse to overwrite an existing tag
MINOR=$(echo "$LATEST" | cut -d. -f2) if git tag --list | grep -qx "$VERSION"; then
PATCH=$(echo "$LATEST" | cut -d. -f3) echo "::error::Tag '$VERSION' already exists. Bump the version."
PATCH=$((PATCH + 1)) exit 1
fi
TAG="v${MAJOR}.${MINOR}.${PATCH}" echo "tag=$VERSION" >> $GITHUB_OUTPUT
echo "Previous tag: $LATEST → New tag: $TAG" echo "name=$VERSION" >> $GITHUB_OUTPUT
echo "tag=$TAG" >> $GITHUB_OUTPUT echo "Tag: $VERSION"
echo "name=$TAG" >> $GITHUB_OUTPUT
# ------------------------------------------------------------------ #
# Create GitHub Release
# ------------------------------------------------------------------ #
- name: 🚀 Create GitHub Release - name: 🚀 Create GitHub Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
@@ -180,13 +160,13 @@ jobs:
### #️⃣ Hashes ### #️⃣ Hashes
**thgtoa.pdf** (light) **thgtoa.pdf** (light)
``` ```text
SHA-256 ${{ steps.hashes.outputs.light_sha256 }} SHA-256 ${{ steps.hashes.outputs.light_sha256 }}
BLAKE2b ${{ steps.hashes.outputs.light_b2 }} BLAKE2b ${{ steps.hashes.outputs.light_b2 }}
``` ```
**thgtoa-dark.pdf** (dark) **thgtoa-dark.pdf** (dark)
``` ```text
SHA-256 ${{ steps.hashes.outputs.dark_sha256 }} SHA-256 ${{ steps.hashes.outputs.dark_sha256 }}
BLAKE2b ${{ steps.hashes.outputs.dark_b2 }} BLAKE2b ${{ steps.hashes.outputs.dark_b2 }}
``` ```
+54 -20
View File
@@ -4,10 +4,10 @@ name: 🔏 Sign PDFs
# 1. Automatically after build.yml completes on main # 1. Automatically after build.yml completes on main
# 2. Manually, pointing at a specific build run to pull PDFs from # 2. Manually, pointing at a specific build run to pull PDFs from
on: on:
workflow_run: # workflow_run:
workflows: ["📖 Build PDFs"] # workflows: ["📖 Build PDFs"]
types: [completed] # types: [completed]
branches: [main] # branches: [main]
workflow_dispatch: workflow_dispatch:
inputs: inputs:
build_run_id: build_run_id:
@@ -17,15 +17,15 @@ on:
permissions: permissions:
actions: read # download artifacts from other runs actions: read # download artifacts from other runs
contents: read contents: write # needed to commit export/ files back to the repo
jobs: jobs:
sign: sign:
name: Hash & Sign PDFs name: Hash & Sign PDFs
# On workflow_run, only proceed if the build actually succeeded # On workflow_run, only proceed if the build actually succeeded
if: > # if: >
github.event_name == 'workflow_dispatch' || # github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success' # github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
light_sha256: ${{ steps.hashes.outputs.light_sha256 }} light_sha256: ${{ steps.hashes.outputs.light_sha256 }}
@@ -39,20 +39,15 @@ jobs:
with: with:
sparse-checkout: pgp sparse-checkout: pgp
- name: 🔑 Install GPG # Download PDFs from the manually specified run ID (required for manual dispatch)
run: |
sudo apt-get update -qq
sudo apt-get install -y gnupg
# Download PDFs from the triggering build run, or a manually specified one
- name: 📥 Resolve source run ID - name: 📥 Resolve source run ID
id: src id: src
run: | run: |
if [ -n "${{ inputs.build_run_id }}" ]; then if [ -z "${{ inputs.build_run_id }}" ]; then
echo "run_id=${{ inputs.build_run_id }}" >> $GITHUB_OUTPUT echo "::error::build_run_id is required — provide the build.yml run ID to pull PDFs from."
else exit 1
echo "run_id=${{ github.event.workflow_run.id }}" >> $GITHUB_OUTPUT
fi fi
echo "run_id=${{ inputs.build_run_id }}" >> $GITHUB_OUTPUT
- name: 📥 Download PDF artifacts - name: 📥 Download PDF artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@@ -102,15 +97,19 @@ jobs:
cat b2sums.txt cat b2sums.txt
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
# GPG sign # GPG sign (maintainer-verifiable detached signatures for release)
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
- name: 🔑 Install GPG
run: |
sudo apt-get update -qq
sudo apt-get install -y gnupg
- name: 🔏 Import GPG signing key - name: 🔏 Import GPG signing key
env: env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: | run: |
echo "$GPG_PRIVATE_KEY" | gpg --batch --import echo "$GPG_PRIVATE_KEY" | gpg --batch --import
# Pre-cache passphrase to prevent interactive prompt
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 \ echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 \
--pinentry-mode loopback --list-secret-keys --pinentry-mode loopback --list-secret-keys
@@ -131,6 +130,41 @@ jobs:
sign export/sha256sums.txt sign export/sha256sums.txt
sign export/b2sums.txt sign export/b2sums.txt
# ------------------------------------------------------------------ #
# Commit export/ back to main
# ------------------------------------------------------------------ #
- name: 📦 Checkout full repo for commit
uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
path: repo
- name: 📂 Copy export files into repo
run: cp -v export/* repo/export/
- name: 🔏 Configure SSH commit signing
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ACTIONS_SSH_SIGNING_KEY }}" > ~/.ssh/signing_key
chmod 600 ~/.ssh/signing_key
git config --global gpg.format ssh
git config --global user.signingKey ~/.ssh/signing_key
git config --global commit.gpgSign true
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- name: 📤 Commit and push export/ to main
working-directory: repo
run: |
git add export/
if git diff --cached --quiet; then
echo "Nothing to commit — export/ is already up to date."
else
git commit -S -m "chore(export): update PDFs, hashes and signatures [skip ci]"
git push origin main
fi
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
# Upload — PDFs + all signatures and hashes together # Upload — PDFs + all signatures and hashes together
# ------------------------------------------------------------------ # # ------------------------------------------------------------------ #
-24
View File
@@ -20,30 +20,6 @@ Notable changes to the guide and its tooling. Follows [Keep a Changelog](https:/
--- ---
## [v2026.5.25]
!!! Note "Meta"
- Released 2026-05-24 from [`3b55011`](https://github.com/Anon-Planet/thgtoa/commit/3b550119a8f70129096774b3303278b50fed1529)
!!! Note "Added"
- Explain missing v1.2.2 tag
!!! Note "Changed"
- Commitizen passes
- V1.2.3
- Auto-increment using [vX.X.X]
- Only use "vX.X.X" in version tags
!!! Note "Fixed"
- We use the Anonymous Planet RSK for releases
- Sign using RSK instead
- Prevent history dump and filter noise commits
- Actually save per-page PDFs for qpdf, not PNGs
## [v1.2.3] ## [v1.2.3]
CI/CD pipeline split into independent stages, dark PDF quality improved, release signing automated, and the changelog now updates itself on every build. Skipping v1.2.2 which was a placeholder and contained broken Python unsuitable for a tag/release. CI/CD pipeline split into independent stages, dark PDF quality improved, release signing automated, and the changelog now updates itself on every build. Skipping v1.2.2 which was a placeholder and contained broken Python unsuitable for a tag/release.