Run tests workflow (vas3k/vas3k.club)
The Run tests workflow from vas3k/vas3k.club, explained and optimized by Latchkey.
CI health: A - excellent
Point runs-on at Latchkey and get caching, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Run tests workflow from the vas3k/vas3k.club 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
name: Run tests
on:
pull_request:
workflow_call:
concurrency:
# For pull requests, cancel all currently-running jobs for this workflow
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
id: setup-python
with:
python-version: '3.12'
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: false
- name: Install requirements
run: |
uv pip install --system flake8
- name: run flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings.
flake8 . --count --exit-zero --statistics
frontend-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
working-directory: ./frontend
run: npm ci
- name: Run frontend tests
working-directory: ./frontend
run: npm run test:ci
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: frontend-coverage
path: frontend/coverage/
retention-days: 14
test:
runs-on: ubuntu-latest
timeout-minutes: 15
services:
postgres:
image: postgres:14-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: vas3k_club
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:6-alpine
env:
ALLOW_EMPTY_PASSWORD: yes
ports:
- 6379:6379
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
id: setup-python
with:
python-version: '3.12'
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
cache-dependency-glob: "**/Pipfile.lock"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22'
- name: Cache webpack build
uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
id: cache-webpack
with:
path: |
frontend/static/dist
frontend/webpack-stats.json
key: ${{ runner.os }}-webpack-${{ hashFiles('frontend/package*.json', 'frontend/webpack*.js', 'frontend/static/js/**', 'frontend/static/css/**') }}
restore-keys: |
${{ runner.os }}-webpack-
- name: Webpack build
if: steps.cache-webpack.outputs.cache-hit != 'true'
working-directory: ./frontend
run: |
node -v
npm -v
npm ci
npm run build
- name: Install pip dependencies
run: |
uv pip install --system pipenv
pipenv requirements --dev > requirements.txt
uv pip install --system -r requirements.txt
- name: Run tests
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: vas3k_club
POSTGRES_HOST: localhost
REDIS_DB: 0
REDIS_HOST: localhost
PYTHONUNBUFFERED: 1
TESTS_RUN: da
run: |
make test-ci
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: Run tests on: pull_request: workflow_call: concurrency: # For pull requests, cancel all currently-running jobs for this workflow # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} permissions: contents: read jobs: lint: runs-on: latchkey-small timeout-minutes: 5 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 id: setup-python with: python-version: '3.12' - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: enable-cache: false - name: Install requirements run: | uv pip install --system flake8 - name: run flake8 run: | # stop the build if there are Python syntax errors or undefined names flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. flake8 . --count --exit-zero --statistics frontend-test: runs-on: latchkey-small timeout-minutes: 10 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: '22' cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install dependencies working-directory: ./frontend run: npm ci - name: Run frontend tests working-directory: ./frontend run: npm run test:ci - name: Upload coverage report if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: frontend-coverage path: frontend/coverage/ retention-days: 14 test: runs-on: latchkey-small timeout-minutes: 15 services: postgres: image: postgres:14-alpine env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: vas3k_club options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 redis: image: redis:6-alpine env: ALLOW_EMPTY_PASSWORD: yes ports: - 6379:6379 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 id: setup-python with: python-version: '3.12' - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: enable-cache: true cache-dependency-glob: "**/Pipfile.lock" - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: cache: 'npm' node-version: '22' - name: Cache webpack build uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0 id: cache-webpack with: path: | frontend/static/dist frontend/webpack-stats.json key: ${{ runner.os }}-webpack-${{ hashFiles('frontend/package*.json', 'frontend/webpack*.js', 'frontend/static/js/**', 'frontend/static/css/**') }} restore-keys: | ${{ runner.os }}-webpack- - name: Webpack build if: steps.cache-webpack.outputs.cache-hit != 'true' working-directory: ./frontend run: | node -v npm -v npm ci npm run build - name: Install pip dependencies run: | uv pip install --system pipenv pipenv requirements --dev > requirements.txt uv pip install --system -r requirements.txt - name: Run tests env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: vas3k_club POSTGRES_HOST: localhost REDIS_DB: 0 REDIS_HOST: localhost PYTHONUNBUFFERED: 1 TESTS_RUN: da run: | make test-ci
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.
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 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.