Pull Request Validation workflow (scverse/scanpy)
The Pull Request Validation workflow from scverse/scanpy, 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 Pull Request Validation workflow from the scverse/scanpy 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: Pull Request Validation
on:
pull_request:
branches:
- main
types:
# title changes
- edited
# milestone changes
- milestoned
- demilestoned
# label changes for “no milestone”
- labeled
- unlabeled
# initial check
- opened
- edited
- reopened
# code change (e.g. this workflow)
- synchronize
jobs:
# This job verifies that the milestone is present or not necessary
# and determines if “check-relnotes” needs to be run.
check-milestone:
name: Check title, milestone, and labels
runs-on: ubuntu-latest
steps:
- name: Check if milestone or “no milestone” label is present
uses: flying-sheep/check@v1
with:
success: ${{ github.event.pull_request.user.login == 'pre-commit-ci[bot]' || github.event.pull_request.milestone != null || contains(github.event.pull_request.labels.*.name, 'no milestone') }}
- name: Check if the “Release notes” checkbox is checked and filled
uses: kaisugi/action-regex-match@v1.0.2
id: checked-relnotes
with:
text: ${{ github.event.pull_request.body }}
regex: '^\s*- \[x\].*Release notes.*not necessary because:(.*)$'
flags: m
- name: Check PR title
id: check-title
uses: amannn/action-semantic-pull-request@v6
env: # Needs repo options: “Squash and merge” with commit message set to “PR title”
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
no-relnotes-reason: ${{ steps.checked-relnotes.outputs.group1 }}
type: ${{ steps.check-title.outputs.type }}
# This job verifies that the relevant release notes file has been modified.
check-relnotes:
name: Check for release notes
runs-on: ubuntu-latest
needs: check-milestone
if: github.event.pull_request.user.login != 'pre-commit-ci[bot]' && needs.check-milestone.outputs.no-relnotes-reason == '' && !contains(fromJSON('["style","refactor","test","build","docs","ci"]'), needs.check-milestone.outputs.type)
steps:
- uses: actions/checkout@v7
with: { filter: 'blob:none', fetch-depth: 0 }
- name: Find out if a relevant release fragment is added
uses: dorny/paths-filter@v4
id: changes
with:
filters: | # this is intentionally a string
relnotes: 'docs/release-notes/${{ github.event.pull_request.number }}.${{ (contains(github.event.pull_request.title, '!') && 'breaking') || needs.check-milestone.outputs.type }}.md'
- name: Check if a relevant release fragment is added
uses: flying-sheep/check@v1
with:
success: ${{ steps.changes.outputs.relnotes }}
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Pull Request Validation on: pull_request: branches: - main types: # title changes - edited # milestone changes - milestoned - demilestoned # label changes for “no milestone” - labeled - unlabeled # initial check - opened - edited - reopened # code change (e.g. this workflow) - synchronize concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # This job verifies that the milestone is present or not necessary # and determines if “check-relnotes” needs to be run. check-milestone: timeout-minutes: 30 name: Check title, milestone, and labels runs-on: latchkey-small steps: - name: Check if milestone or “no milestone” label is present uses: flying-sheep/check@v1 with: success: ${{ github.event.pull_request.user.login == 'pre-commit-ci[bot]' || github.event.pull_request.milestone != null || contains(github.event.pull_request.labels.*.name, 'no milestone') }} - name: Check if the “Release notes” checkbox is checked and filled uses: kaisugi/action-regex-match@v1.0.2 id: checked-relnotes with: text: ${{ github.event.pull_request.body }} regex: '^\s*- \[x\].*Release notes.*not necessary because:(.*)$' flags: m - name: Check PR title id: check-title uses: amannn/action-semantic-pull-request@v6 env: # Needs repo options: “Squash and merge” with commit message set to “PR title” GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} outputs: no-relnotes-reason: ${{ steps.checked-relnotes.outputs.group1 }} type: ${{ steps.check-title.outputs.type }} # This job verifies that the relevant release notes file has been modified. check-relnotes: timeout-minutes: 30 name: Check for release notes runs-on: latchkey-small needs: check-milestone if: github.event.pull_request.user.login != 'pre-commit-ci[bot]' && needs.check-milestone.outputs.no-relnotes-reason == '' && !contains(fromJSON('["style","refactor","test","build","docs","ci"]'), needs.check-milestone.outputs.type) steps: - uses: actions/checkout@v7 with: { filter: 'blob:none', fetch-depth: 0 } - name: Find out if a relevant release fragment is added uses: dorny/paths-filter@v4 id: changes with: filters: | # this is intentionally a string relnotes: 'docs/release-notes/${{ github.event.pull_request.number }}.${{ (contains(github.event.pull_request.title, '!') && 'breaking') || needs.check-milestone.outputs.type }}.md' - name: Check if a relevant release fragment is added uses: flying-sheep/check@v1 with: success: ${{ steps.changes.outputs.relnotes }}
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.
4 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 per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.