Publish Release workflow (pikepdf/pikepdf)
The Publish Release workflow from pikepdf/pikepdf, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Publish Release workflow from the pikepdf/pikepdf repository, a real project running GitHub Actions. It is shown here with attribution under its MPL-2.0 license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
# SPDX-FileCopyrightText: 2023 James R. Barlow
# SPDX-License-Identifier: MPL-2.0
name: Publish Release
on:
push:
tags:
- "v*"
jobs:
publish:
name: Publish release
runs-on: ubuntu-latest
environment:
name: release
url: https://pypi.org/p/pikepdf
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Download artifacts from draft release
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
mkdir -p dist
gh release download "$GITHUB_REF_NAME" --dir dist --pattern '*.whl'
gh release download "$GITHUB_REF_NAME" --dir dist --pattern '*.tar.gz'
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
# PyPI doesn't support sigstore publishing, so generate after publishing to PyPI
- name: Sign the dists with Sigstore
uses: sigstore/gh-action-sigstore-python@v3.0.0
with:
inputs: |
./dist/*.tar.gz
./dist/*.whl
- name: Extract release notes
run: |
VERSION="${GITHUB_REF_NAME#v}"
MAJOR="${VERSION%%.*}"
MAJOR_PADDED=$(printf "%02d" "$MAJOR")
RELEASE_FILE="docs/releasenotes/version${MAJOR_PADDED}.md"
python3 << EOF
import re
version = "${VERSION}"
release_file = "${RELEASE_FILE}"
try:
with open(release_file) as f:
content = f.read()
# Find the section for this version
# Match from "## vX.Y.Z" until the next "## v" or end of file
pattern = rf"## v{re.escape(version)}\n(.*?)(?=\n## v|\Z)"
match = re.search(pattern, content, re.DOTALL)
notes = match.group(1).strip() if match else ""
except FileNotFoundError:
notes = ""
with open("release_notes.md", "w") as f:
f.write(notes)
EOF
- name: Publish release (convert draft to published)
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
# Update release: remove draft status, add release notes
gh release edit "$GITHUB_REF_NAME" \
--draft=false \
--notes-file release_notes.md
# Upload signatures to the release
gh release upload "$GITHUB_REF_NAME" dist/*.sigstore.json --clobber
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
# SPDX-FileCopyrightText: 2023 James R. Barlow # SPDX-License-Identifier: MPL-2.0 name: Publish Release on: push: tags: - "v*" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: publish: timeout-minutes: 30 name: Publish release runs-on: latchkey-small environment: name: release url: https://pypi.org/p/pikepdf permissions: contents: write id-token: write steps: - uses: actions/checkout@v4 - name: Download artifacts from draft release env: GITHUB_TOKEN: ${{ github.token }} run: | mkdir -p dist gh release download "$GITHUB_REF_NAME" --dir dist --pattern '*.whl' gh release download "$GITHUB_REF_NAME" --dir dist --pattern '*.tar.gz' - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 # PyPI doesn't support sigstore publishing, so generate after publishing to PyPI - name: Sign the dists with Sigstore uses: sigstore/gh-action-sigstore-python@v3.0.0 with: inputs: | ./dist/*.tar.gz ./dist/*.whl - name: Extract release notes run: | VERSION="${GITHUB_REF_NAME#v}" MAJOR="${VERSION%%.*}" MAJOR_PADDED=$(printf "%02d" "$MAJOR") RELEASE_FILE="docs/releasenotes/version${MAJOR_PADDED}.md" python3 << EOF import re version = "${VERSION}" release_file = "${RELEASE_FILE}" try: with open(release_file) as f: content = f.read() # Find the section for this version # Match from "## vX.Y.Z" until the next "## v" or end of file pattern = rf"## v{re.escape(version)}\n(.*?)(?=\n## v|\Z)" match = re.search(pattern, content, re.DOTALL) notes = match.group(1).strip() if match else "" except FileNotFoundError: notes = "" with open("release_notes.md", "w") as f: f.write(notes) EOF - name: Publish release (convert draft to published) env: GITHUB_TOKEN: ${{ github.token }} run: | # Update release: remove draft status, add release notes gh release edit "$GITHUB_REF_NAME" \ --draft=false \ --notes-file release_notes.md # Upload signatures to the release gh release upload "$GITHUB_REF_NAME" dist/*.sigstore.json --clobber
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Add a job timeout so a hung step cannot burn hours of runner time.
2 third-party actions are referenced by a movable tag. Pin them to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.