release-pipeline workflow (ml-tooling/lazydocs)
The release-pipeline workflow from ml-tooling/lazydocs, 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 release-pipeline workflow from the ml-tooling/lazydocs repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
# Based on https://github.com/ml-tooling/universal-build/blob/v0.6.12/workflows/build-pipeline.yml
name: release-pipeline
on:
workflow_dispatch:
inputs:
version:
description: "Version of this release"
required: true
milestone:
types: [closed]
env:
VERSION: ${{ secrets.VERSION }}
BRANCH_PREFIX: "release/v"
DEFAULT_BRANCH: main
jobs:
release:
runs-on: ubuntu-latest
steps:
- if: ${{ github.event.milestone != null && github.event.milestone.title != null }}
name: set-milestone-version
run: |
echo "VERSION=$(sed "s/^v//" <<< "${{ github.event.milestone.title }}")" >> $GITHUB_ENV
echo "PR_MILESTONE_LINK=-M ${{ github.event.milestone.title }}" >> $GITHUB_ENV
- if: ${{ github.event.inputs != null && github.event.inputs.version != null }}
name: set-input-version
run: echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
- name: check-version
run: 'if [[ ! "${{ env.VERSION }}" =~ ^([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then echo "The version is not valid: ${{ env.VERSION }}"; exit 1; fi'
- name: set-github-token
run: echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV
# Set host ip to env variable to be uside within container actions
- name: set-host-ip
run: echo "_HOST_IP=$(hostname -I | cut -d ' ' -f 1)" >> $GITHUB_ENV
# Fix git version for act if github token is provided
- if: ${{ env.GITHUB_ACTOR == 'nektos/act' && env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }}
name: install-latest-git
run: |
# Required for local checkout
apt-get update
apt-get install -y git
- if: ${{ env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }}
name: create-release-branch
uses: peterjgrainger/action-create-branch@v2.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
branch: "${{ env.BRANCH_PREFIX }}${{ env.VERSION }}"
- if: ${{ ! (env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '') }}
uses: actions/checkout@v2
- if: ${{ env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }}
uses: actions/checkout@v2
with:
fetch-depth: 0
ref: ${{ env.BRANCH_PREFIX }}${{ env.VERSION }}
token: ${{ env.GITHUB_TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: run-component-builds
uses: ./.github/actions/build-environment
with:
build_args: --make --force --version=${{ env.VERSION }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: run-linting-and-style-checks
uses: ./.github/actions/build-environment
with:
build_args: --check --force --version=${{ env.VERSION }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: run-component-tests
uses: ./.github/actions/build-environment
with:
build_args: --test --force --test-marker=slow --version=${{ env.VERSION }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: release-components
uses: ./.github/actions/build-environment
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
PYPI_REPOSITORY: ${{ secrets.PYPI_REPOSITORY }}
with:
build_args: --release --force --version=${{ env.VERSION }}
container_registry_url: ${{ secrets.CONTAINER_REGISTRY_URL }}
container_registry_username: ${{ secrets.CONTAINER_REGISTRY_USERNAME }}
container_registry_password: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }}
- if: ${{ env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }}
name: push-changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
branch: ${{ env.BRANCH_PREFIX }}${{ env.VERSION }}
commit_user_name: Release Bot
commit_user_email: actions@github.com
commit_message: Apply automatic release changes for v${{ env.VERSION }}
tagging_message: v${{ env.VERSION }}
skip_dirty_check: true
commit_options: "--allow-empty"
- if: ${{ env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }}
name: create-pull-request
shell: bash
run: |
# Stops script execution if a command has an error
set -e
curl -fsSL https://github.com/github/hub/raw/master/script/get | bash -s 2.14.2
# TODO: Milestone link currently does not work with closed milestones: ${{ env.PR_MILESTONE_LINK }} (problem with hub cli)
bin/hub pull-request -b ${{ env.DEFAULT_BRANCH }} -h ${{ env.BRANCH_PREFIX }}${{ env.VERSION }} --no-edit -m "Finalize release for version ${{ env.VERSION }}" -m "Automated pull request for release version ${{ env.VERSION }}" -l "skip changelog" || true
rm bin/hub
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Fix of release drafter to allow different events to trigger the release
# TODO: currently does not work with act
- if: ${{ env.GITHUB_ACTOR == 'nektos/act' && env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }}
name: no-relese-drafter-support
run: echo "The release drafter currently does not work with act, please create the release from the Github UI."
- if: ${{ env.GITHUB_ACTOR != 'nektos/act' && env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }}
name: checkout-fixed-release-drafter
uses: actions/checkout@v2
with:
repository: ml-tooling/release-drafter
path: ./.git/cloned-actions/release-drafter
- if: ${{ env.GITHUB_ACTOR != 'nektos/act' && env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }}
name: create-release-draft
uses: ./.git/cloned-actions/release-drafter
with:
version: ${{ env.VERSION }}
tag: v${{ env.VERSION }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Optional: upload release assets via actions/upload-release-asset@v1 and via upload_url from release drafter
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
# Based on https://github.com/ml-tooling/universal-build/blob/v0.6.12/workflows/build-pipeline.yml name: release-pipeline on: workflow_dispatch: inputs: version: description: "Version of this release" required: true milestone: types: [closed] env: VERSION: ${{ secrets.VERSION }} BRANCH_PREFIX: "release/v" DEFAULT_BRANCH: main jobs: release: timeout-minutes: 30 runs-on: latchkey-small steps: - if: ${{ github.event.milestone != null && github.event.milestone.title != null }} name: set-milestone-version run: | echo "VERSION=$(sed "s/^v//" <<< "${{ github.event.milestone.title }}")" >> $GITHUB_ENV echo "PR_MILESTONE_LINK=-M ${{ github.event.milestone.title }}" >> $GITHUB_ENV - if: ${{ github.event.inputs != null && github.event.inputs.version != null }} name: set-input-version run: echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV - name: check-version run: 'if [[ ! "${{ env.VERSION }}" =~ ^([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then echo "The version is not valid: ${{ env.VERSION }}"; exit 1; fi' - name: set-github-token run: echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV # Set host ip to env variable to be uside within container actions - name: set-host-ip run: echo "_HOST_IP=$(hostname -I | cut -d ' ' -f 1)" >> $GITHUB_ENV # Fix git version for act if github token is provided - if: ${{ env.GITHUB_ACTOR == 'nektos/act' && env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }} name: install-latest-git run: | # Required for local checkout apt-get update apt-get install -y git - if: ${{ env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }} name: create-release-branch uses: peterjgrainger/action-create-branch@v2.0.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: branch: "${{ env.BRANCH_PREFIX }}${{ env.VERSION }}" - if: ${{ ! (env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '') }} uses: actions/checkout@v2 - if: ${{ env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }} uses: actions/checkout@v2 with: fetch-depth: 0 ref: ${{ env.BRANCH_PREFIX }}${{ env.VERSION }} token: ${{ env.GITHUB_TOKEN }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: run-component-builds uses: ./.github/actions/build-environment with: build_args: --make --force --version=${{ env.VERSION }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: run-linting-and-style-checks uses: ./.github/actions/build-environment with: build_args: --check --force --version=${{ env.VERSION }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: run-component-tests uses: ./.github/actions/build-environment with: build_args: --test --force --test-marker=slow --version=${{ env.VERSION }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: release-components uses: ./.github/actions/build-environment env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PYPI_REPOSITORY: ${{ secrets.PYPI_REPOSITORY }} with: build_args: --release --force --version=${{ env.VERSION }} container_registry_url: ${{ secrets.CONTAINER_REGISTRY_URL }} container_registry_username: ${{ secrets.CONTAINER_REGISTRY_USERNAME }} container_registry_password: ${{ secrets.CONTAINER_REGISTRY_PASSWORD }} - if: ${{ env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }} name: push-changes uses: stefanzweifel/git-auto-commit-action@v4 with: branch: ${{ env.BRANCH_PREFIX }}${{ env.VERSION }} commit_user_name: Release Bot commit_user_email: actions@github.com commit_message: Apply automatic release changes for v${{ env.VERSION }} tagging_message: v${{ env.VERSION }} skip_dirty_check: true commit_options: "--allow-empty" - if: ${{ env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }} name: create-pull-request shell: bash run: | # Stops script execution if a command has an error set -e curl -fsSL https://github.com/github/hub/raw/master/script/get | bash -s 2.14.2 # TODO: Milestone link currently does not work with closed milestones: ${{ env.PR_MILESTONE_LINK }} (problem with hub cli) bin/hub pull-request -b ${{ env.DEFAULT_BRANCH }} -h ${{ env.BRANCH_PREFIX }}${{ env.VERSION }} --no-edit -m "Finalize release for version ${{ env.VERSION }}" -m "Automated pull request for release version ${{ env.VERSION }}" -l "skip changelog" || true rm bin/hub env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Fix of release drafter to allow different events to trigger the release # TODO: currently does not work with act - if: ${{ env.GITHUB_ACTOR == 'nektos/act' && env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }} name: no-relese-drafter-support run: echo "The release drafter currently does not work with act, please create the release from the Github UI." - if: ${{ env.GITHUB_ACTOR != 'nektos/act' && env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }} name: checkout-fixed-release-drafter uses: actions/checkout@v2 with: repository: ml-tooling/release-drafter path: ./.git/cloned-actions/release-drafter - if: ${{ env.GITHUB_ACTOR != 'nektos/act' && env.GITHUB_TOKEN != null && env.GITHUB_TOKEN != '' }} name: create-release-draft uses: ./.git/cloned-actions/release-drafter with: version: ${{ env.VERSION }} tag: v${{ env.VERSION }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Optional: upload release assets via actions/upload-release-asset@v1 and via upload_url from release drafter
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.
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
- Network fetches
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.