Bump version workflow (xiaosu-zhu/McQuic)
The Bump version workflow from xiaosu-zhu/McQuic, 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 Bump version workflow from the xiaosu-zhu/McQuic 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
# This is a basic workflow to help you get started with Actions
name: Bump version
# Controls when the action will run.
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
inputs:
release-tag:
description: 'Tag of release branch'
required: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
check-version-and-create-branch:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions-ecosystem/action-regex-match@v2
id: regex-match
with:
text: ${{ github.event.inputs.release-tag }}
# https://www.python.org/dev/peps/pep-0440
# [N!]N(.N)*[{a|b|rc}N][.postN][.devN]
regex: '^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$'
- name: Check branch name
if: steps.regex-match.outputs.match == ''
run: echo "Given release tag wrong, quit." && exit 1
- name: Set up Python 3.9
uses: actions/setup-python@v3
with:
python-version: '3.9'
- uses: actions/checkout@master
- name: Update version
run: sed -i '1s/.*/__version__ = \"${{ github.event.inputs.release-tag }}\"/' mcquic/__init__.py && python ci/pre_commit/finalize.py conda/meta.yaml ${{ github.event.inputs.release-tag }}
- name: Generate models hash
run: |
python -m pip install requests
python ci/pre_commit/update_model_hash.py mcquic/demo.py
- name: Commit changes
uses: EndBug/add-and-commit@v4
with:
author_name: Xiaosu Zhu
author_email: xiaosu.zhu@outlook.com
message: "Bump version to ${{ github.event.inputs.release-tag }}"
- name: Create tag
uses: tvdias/github-tagger@v0.0.2
with:
repo-token: ${{ secrets.PUSH_TO_RELEASE }}
tag: v${{ github.event.inputs.release-tag }}
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.PUSH_TO_RELEASE }}
branch: v${{ github.event.inputs.release-tag }}
tags: true
force: true
linux-wheels:
needs: [check-version-and-create-branch]
runs-on: ubuntu-latest
container: quay.io/pypa/manylinux2014_x86_64
strategy:
matrix:
python-version: [cp39-cp39]
env:
PYPI_BUILDING: SET
ADD_ENTRY: SET
steps:
- uses: actions/checkout@master
with:
ref: v${{ github.event.inputs.release-tag }}
- name: Install dependencies
run: /opt/python/${{ matrix.python-version }}/bin/python -m pip install build twine
- name: Build wheel
run: /opt/python/${{ matrix.python-version }}/bin/python -m build --wheel .
- name: Run auditwheel for manylinux wheel
run: auditwheel repair -w dist dist/*
- name: Remove linux wheel
run: rm dist/*-linux_x86_64.whl
- name: Publish distribution π¦ to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Release
uses: softprops/action-gh-release@v1
with:
files: |
dist/*
tag_name: v${{ github.event.inputs.release-tag }}
name: Release ${{ github.event.inputs.release-tag }}
macos-wheels:
needs: [check-version-and-create-branch]
runs-on: macos-latest
strategy:
matrix:
python-version: [3.9]
env:
PYPI_BUILDING: SET
ADD_ENTRY: SET
steps:
- uses: actions/checkout@v3
with:
ref: v${{ github.event.inputs.release-tag }}
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build wheel
run: |
python -m build --wheel .
- name: Publish distribution π¦ to PyPI
run: python -m twine upload --skip-existing dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
- name: Release
uses: softprops/action-gh-release@v1
with:
files: |
dist/*
tag_name: v${{ github.event.inputs.release-tag }}
name: Release ${{ github.event.inputs.release-tag }}
windows-wheels:
needs: [check-version-and-create-branch]
runs-on: windows-latest
strategy:
matrix:
python-version: [3.9]
env:
PYPI_BUILDING: SET
ADD_ENTRY: SET
steps:
- uses: actions/checkout@v3
with:
ref: v${{ github.event.inputs.release-tag }}
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build wheel
run: |
python -m build --wheel .
- name: Publish distribution π¦ to PyPI
run: python -m twine upload --skip-existing dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
- name: Release
uses: softprops/action-gh-release@v1
with:
files: |
dist/*
tag_name: v${{ github.event.inputs.release-tag }}
name: Release ${{ github.event.inputs.release-tag }}
pypi-sdist:
needs: [check-version-and-create-branch]
runs-on: ubuntu-latest
env:
PYPI_BUILDING: SET
ADD_ENTRY: SET
steps:
- uses: actions/checkout@v3
with:
ref: v${{ github.event.inputs.release-tag }}
- name: Set up Python 3.8
uses: actions/setup-python@v3
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Create and source distribution
run: |
python -m build --sdist .
- name: Publish distribution π¦ to PyPI
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Release
uses: softprops/action-gh-release@v1
with:
files: |
dist/*
tag_name: v${{ github.event.inputs.release-tag }}
name: Release ${{ github.event.inputs.release-tag }}
build-native:
needs: [check-version-and-create-branch]
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
# The type of runner that the job will run on
runs-on: ${{ matrix.os }}
env:
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@master
with:
ref: v${{ github.event.inputs.release-tag }}
- name: Set up Python 3.9
uses: actions/setup-python@v3
with:
python-version: "3.9"
- name: Write entry points and remove PEP 518 `pyproject.toml`
run: |
python ci/pre_build/conda_entry_points.py conda/meta.yaml
rm pyproject.toml
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
- name: Setup conda
uses: conda-incubator/setup-miniconda@v2
with:
auto-activate-base: true
activate-environment: ""
- name: Run conda build and publish π¦
run: |
conda install anaconda-client conda-build pybind11 conda-verify
conda config --set anaconda_upload yes
conda build -c conda-forge -c pytorch -c xiaosu-zhu --output-folder build conda/
- name: Rename built packages
run: |
python ci/post_build/rename_package.py build/
- name: Release
uses: softprops/action-gh-release@v1
with:
files: build/*/*.tar.bz2
tag_name: v${{ github.event.inputs.release-tag }}
name: Release ${{ github.event.inputs.release-tag }}
build-cross-arm:
needs: [check-version-and-create-branch]
# The type of runner that the job will run on
runs-on: macos-latest
env:
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@master
with:
ref: v${{ github.event.inputs.release-tag }}
- name: Set up Python 3.9
uses: actions/setup-python@v3
with:
python-version: "3.9"
- name: Write entry points and remove PEP 518 `pyproject.toml`
run: |
python ci/pre_build/conda_entry_points.py conda/meta.yaml
rm pyproject.toml
- name: Setup conda
uses: conda-incubator/setup-miniconda@v2
with:
auto-activate-base: true
activate-environment: ""
- name: Run conda build and publish π¦
run: |
conda install anaconda-client conda-build pybind11 conda-verify
conda config --set anaconda_upload yes
conda build --variants "{"cxx_compiler": ["clangxx"], "target_platform": ["osx-arm64"]}" -c conda-forge -c pytorch -c xiaosu-zhu --output-folder build conda/
- name: Rename built packages
run: |
python ci/post_build/rename_package.py build/
- name: Release
uses: softprops/action-gh-release@v1
with:
files: build/*/*.tar.bz2
tag_name: v${{ github.event.inputs.release-tag }}
name: Release ${{ github.event.inputs.release-tag }}
build-docker:
needs: [check-version-and-create-branch]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: ./docker
push: true
tags: |
${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
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.
# This is a basic workflow to help you get started with Actions name: Bump version # Controls when the action will run. on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: inputs: release-tag: description: 'Tag of release branch' required: true env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: check-version-and-create-branch: timeout-minutes: 30 # The type of runner that the job will run on runs-on: latchkey-small # Steps represent a sequence of tasks that will be executed as part of the job steps: - uses: actions-ecosystem/action-regex-match@v2 id: regex-match with: text: ${{ github.event.inputs.release-tag }} # https://www.python.org/dev/peps/pep-0440 # [N!]N(.N)*[{a|b|rc}N][.postN][.devN] regex: '^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$' - name: Check branch name if: steps.regex-match.outputs.match == '' run: echo "Given release tag wrong, quit." && exit 1 - name: Set up Python 3.9 uses: actions/setup-python@v3 with: cache: 'pip' python-version: '3.9' - uses: actions/checkout@master - name: Update version run: sed -i '1s/.*/__version__ = \"${{ github.event.inputs.release-tag }}\"/' mcquic/__init__.py && python ci/pre_commit/finalize.py conda/meta.yaml ${{ github.event.inputs.release-tag }} - name: Generate models hash run: | python -m pip install requests python ci/pre_commit/update_model_hash.py mcquic/demo.py - name: Commit changes uses: EndBug/add-and-commit@v4 with: author_name: Xiaosu Zhu author_email: xiaosu.zhu@outlook.com message: "Bump version to ${{ github.event.inputs.release-tag }}" - name: Create tag uses: tvdias/github-tagger@v0.0.2 with: repo-token: ${{ secrets.PUSH_TO_RELEASE }} tag: v${{ github.event.inputs.release-tag }} - name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.PUSH_TO_RELEASE }} branch: v${{ github.event.inputs.release-tag }} tags: true force: true linux-wheels: timeout-minutes: 30 needs: [check-version-and-create-branch] runs-on: latchkey-small container: quay.io/pypa/manylinux2014_x86_64 strategy: matrix: python-version: [cp39-cp39] env: PYPI_BUILDING: SET ADD_ENTRY: SET steps: - uses: actions/checkout@master with: ref: v${{ github.event.inputs.release-tag }} - name: Install dependencies run: /opt/python/${{ matrix.python-version }}/bin/python -m pip install build twine - name: Build wheel run: /opt/python/${{ matrix.python-version }}/bin/python -m build --wheel . - name: Run auditwheel for manylinux wheel run: auditwheel repair -w dist dist/* - name: Remove linux wheel run: rm dist/*-linux_x86_64.whl - name: Publish distribution π¦ to PyPI uses: pypa/gh-action-pypi-publish@master with: password: ${{ secrets.PYPI_API_TOKEN }} - name: Release uses: softprops/action-gh-release@v1 with: files: | dist/* tag_name: v${{ github.event.inputs.release-tag }} name: Release ${{ github.event.inputs.release-tag }} macos-wheels: timeout-minutes: 30 needs: [check-version-and-create-branch] runs-on: macos-latest strategy: matrix: python-version: [3.9] env: PYPI_BUILDING: SET ADD_ENTRY: SET steps: - uses: actions/checkout@v3 with: ref: v${{ github.event.inputs.release-tag }} - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: cache: 'pip' python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install build twine - name: Build wheel run: | python -m build --wheel . - name: Publish distribution π¦ to PyPI run: python -m twine upload --skip-existing dist/* env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - name: Release uses: softprops/action-gh-release@v1 with: files: | dist/* tag_name: v${{ github.event.inputs.release-tag }} name: Release ${{ github.event.inputs.release-tag }} windows-wheels: timeout-minutes: 30 needs: [check-version-and-create-branch] runs-on: windows-latest strategy: matrix: python-version: [3.9] env: PYPI_BUILDING: SET ADD_ENTRY: SET steps: - uses: actions/checkout@v3 with: ref: v${{ github.event.inputs.release-tag }} - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: cache: 'pip' python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install build twine - name: Build wheel run: | python -m build --wheel . - name: Publish distribution π¦ to PyPI run: python -m twine upload --skip-existing dist/* env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - name: Release uses: softprops/action-gh-release@v1 with: files: | dist/* tag_name: v${{ github.event.inputs.release-tag }} name: Release ${{ github.event.inputs.release-tag }} pypi-sdist: timeout-minutes: 30 needs: [check-version-and-create-branch] runs-on: latchkey-small env: PYPI_BUILDING: SET ADD_ENTRY: SET steps: - uses: actions/checkout@v3 with: ref: v${{ github.event.inputs.release-tag }} - name: Set up Python 3.8 uses: actions/setup-python@v3 with: cache: 'pip' python-version: "3.9" - name: Install dependencies run: | python -m pip install --upgrade pip pip install build twine - name: Create and source distribution run: | python -m build --sdist . - name: Publish distribution π¦ to PyPI uses: pypa/gh-action-pypi-publish@master with: password: ${{ secrets.PYPI_API_TOKEN }} - name: Release uses: softprops/action-gh-release@v1 with: files: | dist/* tag_name: v${{ github.event.inputs.release-tag }} name: Release ${{ github.event.inputs.release-tag }} build-native: timeout-minutes: 30 needs: [check-version-and-create-branch] strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] # The type of runner that the job will run on runs-on: ${{ matrix.os }} env: ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }} # Steps represent a sequence of tasks that will be executed as part of the job steps: - uses: actions/checkout@master with: ref: v${{ github.event.inputs.release-tag }} - name: Set up Python 3.9 uses: actions/setup-python@v3 with: cache: 'pip' python-version: "3.9" - name: Write entry points and remove PEP 518 `pyproject.toml` run: | python ci/pre_build/conda_entry_points.py conda/meta.yaml rm pyproject.toml - name: Setup MSVC uses: ilammy/msvc-dev-cmd@v1 - name: Setup conda uses: conda-incubator/setup-miniconda@v2 with: auto-activate-base: true activate-environment: "" - name: Run conda build and publish π¦ run: | conda install anaconda-client conda-build pybind11 conda-verify conda config --set anaconda_upload yes conda build -c conda-forge -c pytorch -c xiaosu-zhu --output-folder build conda/ - name: Rename built packages run: | python ci/post_build/rename_package.py build/ - name: Release uses: softprops/action-gh-release@v1 with: files: build/*/*.tar.bz2 tag_name: v${{ github.event.inputs.release-tag }} name: Release ${{ github.event.inputs.release-tag }} build-cross-arm: timeout-minutes: 30 needs: [check-version-and-create-branch] # The type of runner that the job will run on runs-on: macos-latest env: ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }} # Steps represent a sequence of tasks that will be executed as part of the job steps: - uses: actions/checkout@master with: ref: v${{ github.event.inputs.release-tag }} - name: Set up Python 3.9 uses: actions/setup-python@v3 with: cache: 'pip' python-version: "3.9" - name: Write entry points and remove PEP 518 `pyproject.toml` run: | python ci/pre_build/conda_entry_points.py conda/meta.yaml rm pyproject.toml - name: Setup conda uses: conda-incubator/setup-miniconda@v2 with: auto-activate-base: true activate-environment: "" - name: Run conda build and publish π¦ run: | conda install anaconda-client conda-build pybind11 conda-verify conda config --set anaconda_upload yes conda build --variants "{"cxx_compiler": ["clangxx"], "target_platform": ["osx-arm64"]}" -c conda-forge -c pytorch -c xiaosu-zhu --output-folder build conda/ - name: Rename built packages run: | python ci/post_build/rename_package.py build/ - name: Release uses: softprops/action-gh-release@v1 with: files: build/*/*.tar.bz2 tag_name: v${{ github.event.inputs.release-tag }} name: Release ${{ github.event.inputs.release-tag }} build-docker: timeout-minutes: 30 needs: [check-version-and-create-branch] runs-on: latchkey-small permissions: contents: read packages: write steps: - name: Checkout repository uses: actions/checkout@v3 - name: Log in to the Container registry uses: docker/login-action@v1 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v3 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Build and push Docker image uses: docker/build-push-action@v2 with: context: ./docker push: true tags: | ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}
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.
11 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
- Container pulls and builds
This workflow runs 8 jobs (10 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.