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
|
||||
|
||||
on:
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
name: 📝 Update Changelog
|
||||
|
||||
# Runs after build.yml completes on main — at that point we know what changed.
|
||||
# Can also be triggered manually to backfill a missing entry.
|
||||
# Manual only — automatic triggering is disabled to prevent version mismatches
|
||||
# between the generated PDF and the GitHub release. Run this manually after
|
||||
# a release is published and the version is confirmed.
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["📖 Build PDFs"]
|
||||
types: [completed]
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
@@ -25,9 +22,6 @@ permissions:
|
||||
jobs:
|
||||
changelog:
|
||||
name: Prepend changelog entry
|
||||
if: >
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
name: 🚀 Release
|
||||
|
||||
# Can be triggered:
|
||||
# 1. Automatically after sign.yml completes on main
|
||||
# 2. Manually, pointing at specific build/sign runs to pull artifacts from
|
||||
# Manual only — run this deliberately after build and sign are confirmed good.
|
||||
# Provide the exact version tag and the sign.yml run ID to pull artifacts from.
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["🔏 Sign PDFs"]
|
||||
types: [completed]
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
sign_run_id:
|
||||
description: 'sign.yml run ID to pull signatures from'
|
||||
version:
|
||||
description: 'Release version tag (e.g. v1.2.4) — must not already exist'
|
||||
required: true
|
||||
type: string
|
||||
build_run_id:
|
||||
description: 'build.yml run ID to pull PDFs from (leave blank to use pdfs-signed from sign run)'
|
||||
required: false
|
||||
sign_run_id:
|
||||
description: 'sign.yml run ID to pull signatures and PDFs from'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Mark as pre-release?'
|
||||
@@ -31,9 +26,6 @@ permissions:
|
||||
jobs:
|
||||
release:
|
||||
name: Publish GitHub Release
|
||||
if: >
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -44,40 +36,22 @@ jobs:
|
||||
sparse-checkout: pgp
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Resolve which run IDs to pull artifacts from
|
||||
# ------------------------------------------------------------------ #
|
||||
- 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
|
||||
# Download artifacts from the specified sign run
|
||||
# ------------------------------------------------------------------ #
|
||||
- name: 📥 Download signatures artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: signatures
|
||||
path: release/
|
||||
run-id: ${{ steps.runs.outputs.sign_run }}
|
||||
run-id: ${{ inputs.sign_run_id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: 📥 Download PDFs (from sign run)
|
||||
- name: 📥 Download signed PDFs artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pdfs-signed
|
||||
path: release/
|
||||
run-id: ${{ steps.runs.outputs.sign_run }}
|
||||
run-id: ${{ inputs.sign_run_id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: 📋 List release assets
|
||||
@@ -96,7 +70,7 @@ jobs:
|
||||
echo "dark_b2=$(read_hash thgtoa-dark.pdf.b2)" >> $GITHUB_OUTPUT
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# VirusTotal — upload whichever PDFs are present
|
||||
# VirusTotal
|
||||
# ------------------------------------------------------------------ #
|
||||
- name: 🦠 Upload PDFs to VirusTotal
|
||||
id: vt
|
||||
@@ -124,28 +98,34 @@ jobs:
|
||||
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
|
||||
run: |
|
||||
git fetch --tags --quiet
|
||||
VERSION="${{ inputs.version }}"
|
||||
|
||||
LATEST=$(git tag --list 'v*' --sort=-version:refname \
|
||||
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
|
||||
| head -1)
|
||||
LATEST=${LATEST:-v0.0.0}
|
||||
# Enforce vX.Y.Z format
|
||||
if ! echo "$VERSION" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||
echo "::error::Version '$VERSION' is not valid semver. Use format: v1.2.3"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MAJOR=$(echo "$LATEST" | cut -d. -f1 | tr -d 'v')
|
||||
MINOR=$(echo "$LATEST" | cut -d. -f2)
|
||||
PATCH=$(echo "$LATEST" | cut -d. -f3)
|
||||
PATCH=$((PATCH + 1))
|
||||
# Refuse to overwrite an existing tag
|
||||
if git tag --list | grep -qx "$VERSION"; then
|
||||
echo "::error::Tag '$VERSION' already exists. Bump the version."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TAG="v${MAJOR}.${MINOR}.${PATCH}"
|
||||
echo "Previous tag: $LATEST → New tag: $TAG"
|
||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||
echo "name=$TAG" >> $GITHUB_OUTPUT
|
||||
echo "tag=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "name=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Tag: $VERSION"
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Create GitHub Release
|
||||
# ------------------------------------------------------------------ #
|
||||
- name: 🚀 Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
@@ -180,13 +160,13 @@ jobs:
|
||||
### #️⃣ Hashes
|
||||
|
||||
**thgtoa.pdf** (light)
|
||||
```
|
||||
```text
|
||||
SHA-256 ${{ steps.hashes.outputs.light_sha256 }}
|
||||
BLAKE2b ${{ steps.hashes.outputs.light_b2 }}
|
||||
```
|
||||
|
||||
**thgtoa-dark.pdf** (dark)
|
||||
```
|
||||
```text
|
||||
SHA-256 ${{ steps.hashes.outputs.dark_sha256 }}
|
||||
BLAKE2b ${{ steps.hashes.outputs.dark_b2 }}
|
||||
```
|
||||
|
||||
+54
-20
@@ -4,10 +4,10 @@ name: 🔏 Sign PDFs
|
||||
# 1. Automatically after build.yml completes on main
|
||||
# 2. Manually, pointing at a specific build run to pull PDFs from
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["📖 Build PDFs"]
|
||||
types: [completed]
|
||||
branches: [main]
|
||||
# workflow_run:
|
||||
# workflows: ["📖 Build PDFs"]
|
||||
# types: [completed]
|
||||
# branches: [main]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_run_id:
|
||||
@@ -17,15 +17,15 @@ on:
|
||||
|
||||
permissions:
|
||||
actions: read # download artifacts from other runs
|
||||
contents: read
|
||||
contents: write # needed to commit export/ files back to the repo
|
||||
|
||||
jobs:
|
||||
sign:
|
||||
name: Hash & Sign PDFs
|
||||
# On workflow_run, only proceed if the build actually succeeded
|
||||
if: >
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
# if: >
|
||||
# github.event_name == 'workflow_dispatch' ||
|
||||
# github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
light_sha256: ${{ steps.hashes.outputs.light_sha256 }}
|
||||
@@ -39,20 +39,15 @@ jobs:
|
||||
with:
|
||||
sparse-checkout: pgp
|
||||
|
||||
- name: 🔑 Install GPG
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y gnupg
|
||||
|
||||
# Download PDFs from the triggering build run, or a manually specified one
|
||||
# Download PDFs from the manually specified run ID (required for manual dispatch)
|
||||
- name: 📥 Resolve source run ID
|
||||
id: src
|
||||
run: |
|
||||
if [ -n "${{ inputs.build_run_id }}" ]; then
|
||||
echo "run_id=${{ inputs.build_run_id }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "run_id=${{ github.event.workflow_run.id }}" >> $GITHUB_OUTPUT
|
||||
if [ -z "${{ inputs.build_run_id }}" ]; then
|
||||
echo "::error::build_run_id is required — provide the build.yml run ID to pull PDFs from."
|
||||
exit 1
|
||||
fi
|
||||
echo "run_id=${{ inputs.build_run_id }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: 📥 Download PDF artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -102,15 +97,19 @@ jobs:
|
||||
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
|
||||
env:
|
||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||
run: |
|
||||
echo "$GPG_PRIVATE_KEY" | gpg --batch --import
|
||||
# Pre-cache passphrase to prevent interactive prompt
|
||||
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 \
|
||||
--pinentry-mode loopback --list-secret-keys
|
||||
|
||||
@@ -131,6 +130,41 @@ jobs:
|
||||
sign export/sha256sums.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
|
||||
# ------------------------------------------------------------------ #
|
||||
|
||||
@@ -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]
|
||||
|
||||
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