Build Docs workflow (Unidata/siphon)
The Build Docs workflow from Unidata/siphon, explained and optimized by Latchkey.
CI health: B - good
Point runs-on at Latchkey and get job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Build Docs workflow from the Unidata/siphon repository, a real project running GitHub Actions. It is shown here with attribution under its BSD-3-Clause license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Build Docs
# We don't want pushes (or PRs) to gh-pages to kick anything off
on:
push:
branches:
- main
- '[0-9]+.[0-9]+.x'
tags:
- v[0-9]+.[0-9]+.[0-9]+
pull_request:
concurrency:
group: ${{ github.workflow}}-${{ github.head_ref }}
cancel-in-progress: true
jobs:
#
# Build our docs on Linux against multiple Pythons
#
Docs:
name: "Linux ${{ matrix.python-version }}"
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.11, 3.12, 3.13]
check-links: [false]
include:
- python-version: 3.14
check-links: true
outputs:
doc-version: ${{ steps.build-docs.outputs.doc-version }}
steps:
- name: Checkout source
uses: actions/checkout@v7
with:
fetch-depth: 150
- name: Get tags
run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- name: Install using PyPI
uses: Unidata/MetPy/.github/actions/install-pypi@main
with:
type: 'doc'
python-version: ${{ matrix.python-version }}
need-extras: true
need-cartopy: true
- name: Build docs
id: build-docs
uses: Unidata/MetPy/.github/actions/build-docs@main
with:
run-linkchecker: ${{ github.event_name == 'pull_request' && matrix.check-links == true }}
key: ${{ runner.os }}-${{ matrix.python-version }}
make-targets: ''
Deploy:
if: ${{ github.event_name != 'pull_request' }}
needs: Docs
environment:
name: github-pages
runs-on: ubuntu-latest
env:
DOC_VERSION: dev
permissions:
contents: write
steps:
- name: Download doc build
uses: actions/download-artifact@v8
with:
name: Linux-3.14-docs
path: ./docs/build/html
# This overrides the version "dev" with the proper version if we're building off a
# branch that's not main (which is confined to n.nn.x above) or on a tag.
- name: Set doc version
if: ${{ github.event_name != 'push' || !contains(github.ref, 'main') }}
run: echo "DOC_VERSION=v${{ needs.Docs.outputs.doc-version }}" >> $GITHUB_ENV
- name: Upload to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/build/html
exclude_assets: '.buildinfo,_static/jquery-*.js,_static/underscore-*.js'
destination_dir: ./${{ env.DOC_VERSION }}
keep_files: false
full_commit_message: Deploy ${{ env.DOC_VERSION }} to GitHub Pages
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Build Docs # We don't want pushes (or PRs) to gh-pages to kick anything off on: push: branches: - main - '[0-9]+.[0-9]+.x' tags: - v[0-9]+.[0-9]+.[0-9]+ pull_request: concurrency: group: ${{ github.workflow}}-${{ github.head_ref }} cancel-in-progress: true jobs: # # Build our docs on Linux against multiple Pythons # Docs: timeout-minutes: 30 name: "Linux ${{ matrix.python-version }}" runs-on: latchkey-small strategy: fail-fast: false matrix: python-version: [3.11, 3.12, 3.13] check-links: [false] include: - python-version: 3.14 check-links: true outputs: doc-version: ${{ steps.build-docs.outputs.doc-version }} steps: - name: Checkout source uses: actions/checkout@v7 with: fetch-depth: 150 - name: Get tags run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* - name: Install using PyPI uses: Unidata/MetPy/.github/actions/install-pypi@main with: type: 'doc' python-version: ${{ matrix.python-version }} need-extras: true need-cartopy: true - name: Build docs id: build-docs uses: Unidata/MetPy/.github/actions/build-docs@main with: run-linkchecker: ${{ github.event_name == 'pull_request' && matrix.check-links == true }} key: ${{ runner.os }}-${{ matrix.python-version }} make-targets: '' Deploy: timeout-minutes: 30 if: ${{ github.event_name != 'pull_request' }} needs: Docs environment: name: github-pages runs-on: latchkey-small env: DOC_VERSION: dev permissions: contents: write steps: - name: Download doc build uses: actions/download-artifact@v8 with: name: Linux-3.14-docs path: ./docs/build/html # This overrides the version "dev" with the proper version if we're building off a # branch that's not main (which is confined to n.nn.x above) or on a tag. - name: Set doc version if: ${{ github.event_name != 'push' || !contains(github.ref, 'main') }} run: echo "DOC_VERSION=v${{ needs.Docs.outputs.doc-version }}" >> $GITHUB_ENV - name: Upload to GitHub Pages uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs/build/html exclude_assets: '.buildinfo,_static/jquery-*.js,_static/underscore-*.js' destination_dir: ./${{ env.DOC_VERSION }} keep_files: false full_commit_message: Deploy ${{ env.DOC_VERSION }} to GitHub Pages
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. - 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 2 jobs (4 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.