Build workflow (anyoptimization/pymoo)
The Build workflow from anyoptimization/pymoo, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get caching, 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 workflow from the anyoptimization/pymoo repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Build
on:
pull_request:
types: [opened, synchronize, reopened, labeled]
push:
branches: [deploy]
# Only semver-shaped tags (e.g. 0.6.3, 0.6.3.dev1) can trigger a publish -
# a stray tag like `latest` or a typo no longer reaches PyPI. (P-2)
tags: ["*.*.*"]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check_approval:
runs-on: ubuntu-latest
outputs:
should_build: ${{ steps.check.outputs.should_build }}
steps:
- name: Check if build should run
id: check
run: |
if [[ "${{ github.event_name }}" == "push" ]]; then
# Always build on push to deploy branch or tags
echo "should_build=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
# Always build on manual trigger
echo "should_build=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
# Check for approval label on PRs
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'build-approved') }}" == "true" ]]; then
echo "should_build=true" >> $GITHUB_OUTPUT
else
echo "should_build=false" >> $GITHUB_OUTPUT
fi
else
echo "should_build=false" >> $GITHUB_OUTPUT
fi
build_wheels:
name: Build wheel for ${{ matrix.os }}-${{ matrix.build }}${{ matrix.python }}-${{ matrix.arch }}
runs-on: ${{ matrix.os }}
needs: check_approval
if: needs.check_approval.outputs.should_build == 'true'
strategy:
# Ensure that a wheel builder finishes even if another fails
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, ubuntu-24.04-arm, macos-latest]
python: [310, 311, 312, 313, 314]
arch: [auto64, universal2]
build: ["cp"]
exclude:
- os: ubuntu-latest
arch: universal2
- os: ubuntu-24.04-arm
arch: universal2
- os: windows-latest
arch: universal2
steps:
- uses: actions/checkout@v5
- uses: astral-sh/setup-uv@v7
- uses: pypa/cibuildwheel@v3.2
env:
CIBW_BUILD_FRONTEND: "build[uv]"
CIBW_BUILD: "${{ matrix.build }}${{ matrix.python }}*"
CIBW_SKIP: "*t-*"
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_TEST_COMMAND: >
uv run python -c "import sys; import pymoo; print(pymoo); from pymoo.functions import is_compiled; sys.exit(0 if is_compiled() else 42)"
- uses: actions/upload-artifact@v4
with:
name: "artifact-${{ matrix.os }}-${{ matrix.build }}-${{ matrix.python }}-${{ matrix.arch }}"
path: ./wheelhouse/*.whl
build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
needs: check_approval
if: needs.check_approval.outputs.should_build == 'true'
steps:
- uses: actions/checkout@v5
- uses: astral-sh/setup-uv@v7
- run: uv build --sdist
- uses: actions/upload-artifact@v4
with:
name: artifact-source
path: dist/*.tar.gz
merge:
name: Merge sdist and wheel artifacts
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
steps:
- uses: actions/upload-artifact/merge@v4
with:
name: pymoo
delete-merged: true
publish_testpypi:
name: Publish to TestPyPI (dry-run)
# Manual "Run workflow" button only - a safe dry-run target.
needs: merge
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
environment:
name: testpypi
url: https://test.pypi.org/p/pymoo
permissions:
id-token: write # required for PyPI Trusted Publishing (OIDC)
steps:
- uses: actions/download-artifact@v4
with:
name: pymoo
path: dist
- uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
skip-existing: true
verify_version:
name: Tag matches version.py
# Guard against tag/version drift before anything is published. (P-2)
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Assert git tag == pymoo.version.__version__
run: |
TAG="${GITHUB_REF_NAME}"
# read version.py in isolation (no full-package import / compiled ext)
VER=$(python -c "import runpy; print(runpy.run_path('pymoo/version.py')['__version__'])")
echo "tag=$TAG version.py=$VER"
if [ "$TAG" != "$VER" ]; then
echo "::error::Tag '$TAG' != version.py '$VER' - bump version.py or fix the tag before publishing."
exit 1
fi
release_gate:
name: Release smoke (fast tests + golden)
# A quick correctness gate on the tagged commit before publishing. The full
# OS×Python matrix runs in nightly.yml; this is the cheap pre-publish check.
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: pip
- name: Install pymoo (compiled) + deps
run: |
pip install --upgrade pip "setuptools>=77" "Cython>=0.29" "numpy>=2.0.0"
pip install -e .
python setup.py build_ext --inplace
pip install -r tests/requirements.txt
pip install pyclawd pytest-xdist
- name: Compiled extensions present
run: python -c "from pymoo.functions import is_compiled; import sys; print('compiled:', is_compiled()); sys.exit(0 if is_compiled() else 1)"
- name: Fast unit tier + golden
run: |
pytest -n auto -m "not long and not slow and not examples and not docs and not golden"
pytest -m golden
publish_pypi:
name: Publish to PyPI
# Real release only - runs when a version tag (e.g. 0.6.2) is pushed,
# AND the tag matches version.py AND the release smoke gate passed.
needs: [merge, verify_version, release_gate]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
environment:
name: pypi
url: https://pypi.org/p/pymoo
permissions:
id-token: write # required for PyPI Trusted Publishing (OIDC)
steps:
- uses: actions/download-artifact@v4
with:
name: pymoo
path: dist
- uses: pypa/gh-action-pypi-publish@release/v1
The same workflow, on Latchkey
Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.
name: Build on: pull_request: types: [opened, synchronize, reopened, labeled] push: branches: [deploy] # Only semver-shaped tags (e.g. 0.6.3, 0.6.3.dev1) can trigger a publish - # a stray tag like `latest` or a typo no longer reaches PyPI. (P-2) tags: ["*.*.*"] workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: check_approval: timeout-minutes: 30 runs-on: latchkey-small outputs: should_build: ${{ steps.check.outputs.should_build }} steps: - name: Check if build should run id: check run: | if [[ "${{ github.event_name }}" == "push" ]]; then # Always build on push to deploy branch or tags echo "should_build=true" >> $GITHUB_OUTPUT elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then # Always build on manual trigger echo "should_build=true" >> $GITHUB_OUTPUT elif [[ "${{ github.event_name }}" == "pull_request" ]]; then # Check for approval label on PRs if [[ "${{ contains(github.event.pull_request.labels.*.name, 'build-approved') }}" == "true" ]]; then echo "should_build=true" >> $GITHUB_OUTPUT else echo "should_build=false" >> $GITHUB_OUTPUT fi else echo "should_build=false" >> $GITHUB_OUTPUT fi build_wheels: timeout-minutes: 30 name: Build wheel for ${{ matrix.os }}-${{ matrix.build }}${{ matrix.python }}-${{ matrix.arch }} runs-on: ${{ matrix.os }} needs: check_approval if: needs.check_approval.outputs.should_build == 'true' strategy: # Ensure that a wheel builder finishes even if another fails fail-fast: false matrix: os: [windows-latest, ubuntu-latest, ubuntu-24.04-arm, macos-latest] python: [310, 311, 312, 313, 314] arch: [auto64, universal2] build: ["cp"] exclude: - os: ubuntu-latest arch: universal2 - os: ubuntu-24.04-arm arch: universal2 - os: windows-latest arch: universal2 steps: - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v7 - uses: pypa/cibuildwheel@v3.2 env: CIBW_BUILD_FRONTEND: "build[uv]" CIBW_BUILD: "${{ matrix.build }}${{ matrix.python }}*" CIBW_SKIP: "*t-*" CIBW_ARCHS: ${{ matrix.arch }} CIBW_TEST_COMMAND: > uv run python -c "import sys; import pymoo; print(pymoo); from pymoo.functions import is_compiled; sys.exit(0 if is_compiled() else 42)" - uses: actions/upload-artifact@v4 with: name: "artifact-${{ matrix.os }}-${{ matrix.build }}-${{ matrix.python }}-${{ matrix.arch }}" path: ./wheelhouse/*.whl build_sdist: timeout-minutes: 30 name: Build source distribution runs-on: latchkey-small needs: check_approval if: needs.check_approval.outputs.should_build == 'true' steps: - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v7 - run: uv build --sdist - uses: actions/upload-artifact@v4 with: name: artifact-source path: dist/*.tar.gz merge: timeout-minutes: 30 name: Merge sdist and wheel artifacts needs: [build_wheels, build_sdist] runs-on: latchkey-small steps: - uses: actions/upload-artifact/merge@v4 with: name: pymoo delete-merged: true publish_testpypi: timeout-minutes: 30 name: Publish to TestPyPI (dry-run) # Manual "Run workflow" button only - a safe dry-run target. needs: merge runs-on: latchkey-small if: github.event_name == 'workflow_dispatch' environment: name: testpypi url: https://test.pypi.org/p/pymoo permissions: id-token: write # required for PyPI Trusted Publishing (OIDC) steps: - uses: actions/download-artifact@v4 with: name: pymoo path: dist - uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ skip-existing: true verify_version: timeout-minutes: 30 name: Tag matches version.py # Guard against tag/version drift before anything is published. (P-2) if: startsWith(github.ref, 'refs/tags/') runs-on: latchkey-small steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: cache: 'pip' python-version: '3.12' - name: Assert git tag == pymoo.version.__version__ run: | TAG="${GITHUB_REF_NAME}" # read version.py in isolation (no full-package import / compiled ext) VER=$(python -c "import runpy; print(runpy.run_path('pymoo/version.py')['__version__'])") echo "tag=$TAG version.py=$VER" if [ "$TAG" != "$VER" ]; then echo "::error::Tag '$TAG' != version.py '$VER' - bump version.py or fix the tag before publishing." exit 1 fi release_gate: timeout-minutes: 30 name: Release smoke (fast tests + golden) # A quick correctness gate on the tagged commit before publishing. The full # OS×Python matrix runs in nightly.yml; this is the cheap pre-publish check. if: startsWith(github.ref, 'refs/tags/') runs-on: latchkey-small steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: python-version: '3.12' cache: pip - name: Install pymoo (compiled) + deps run: | pip install --upgrade pip "setuptools>=77" "Cython>=0.29" "numpy>=2.0.0" pip install -e . python setup.py build_ext --inplace pip install -r tests/requirements.txt pip install pyclawd pytest-xdist - name: Compiled extensions present run: python -c "from pymoo.functions import is_compiled; import sys; print('compiled:', is_compiled()); sys.exit(0 if is_compiled() else 1)" - name: Fast unit tier + golden run: | pytest -n auto -m "not long and not slow and not examples and not docs and not golden" pytest -m golden publish_pypi: timeout-minutes: 30 name: Publish to PyPI # Real release only - runs when a version tag (e.g. 0.6.2) is pushed, # AND the tag matches version.py AND the release smoke gate passed. needs: [merge, verify_version, release_gate] runs-on: latchkey-small if: startsWith(github.ref, 'refs/tags/') environment: name: pypi url: https://pypi.org/p/pymoo permissions: id-token: write # required for PyPI Trusted Publishing (OIDC) steps: - uses: actions/download-artifact@v4 with: name: pymoo path: dist - uses: pypa/gh-action-pypi-publish@release/v1
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. - Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
3 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.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
This workflow runs 8 jobs (47 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.