mirror of
https://github.com/Anon-Planet/thgtoa.git
synced 2026-06-11 00:02:29 +02:00
ci(github): Manual only
automatic triggering is disabled to prevent version mismatches
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
# ------------------------------------------------------------------ #
|
# ------------------------------------------------------------------ #
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user