Tox tests workflow (nephila/djangocms-blog)
The Tox tests workflow from nephila/djangocms-blog, explained and optimized by Latchkey.
CI health: F - at risk
Point runs-on at Latchkey and get caching, 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 Tox tests workflow from the nephila/djangocms-blog 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: Tox tests
on: [push, pull_request]
jobs:
test:
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.continue-on-error }}
strategy:
matrix:
python-version: ["3.11", "3.10", "3.9"]
django: [42, 41, 32]
cms: [311, 39]
continue-on-error: [false]
exclude:
- django: 41
cms: 39
- django: 42
cms: 39
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ matrix.toxenv }}
restore-keys: |
${{ runner.os }}-pip-${{ matrix.toxenv }}
- name: Cache tox
uses: actions/cache@v3
with:
path: .tox
key: ${{ runner.os }}-tox-${{ format('{{py{0}-django{1}-cms{2}}}', matrix.python-version, matrix.django, matrix.cms) }}-${{ hashFiles('setup.cfg') }}
restore-keys: |
${{ runner.os }}-tox-${{ format('{{py{0}-django{1}-cms{2}}}', matrix.python-version, matrix.django, matrix.cms) }}-
- name: Install dependencies
run: |
sudo apt update
sudo apt install gettext libcairo2-dev
python -m pip install --upgrade pip setuptools tox>4
- name: Test with tox
env:
TOX_ENV: ${{ format('py-django{1}-cms{2}', matrix.python-version, matrix.django, matrix.cms) }}
COMMAND: coverage run
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_SERVICE_NAME: github
run: |
tox -e$TOX_ENV
.tox/$TOX_ENV/bin/coverage xml
- name: Coveralls Parallel
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
- uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
files: ./coverage.xml
fail_ci_if_error: false
services:
redis:
image: redis
ports:
- 6379:6379
finish:
needs: test
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@v2
with:
parallel-finished: true
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: Tox tests on: [push, pull_request] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test: timeout-minutes: 30 if: "!contains(github.event.head_commit.message, '[skip ci]')" runs-on: latchkey-small continue-on-error: ${{ matrix.continue-on-error }} strategy: matrix: python-version: ["3.11", "3.10", "3.9"] django: [42, 41, 32] cms: [311, 39] continue-on-error: [false] exclude: - django: 41 cms: 39 - django: 42 cms: 39 steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: cache: 'pip' python-version: ${{ matrix.python-version }} - name: Cache pip uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ matrix.toxenv }} restore-keys: | ${{ runner.os }}-pip-${{ matrix.toxenv }} - name: Cache tox uses: actions/cache@v3 with: path: .tox key: ${{ runner.os }}-tox-${{ format('{{py{0}-django{1}-cms{2}}}', matrix.python-version, matrix.django, matrix.cms) }}-${{ hashFiles('setup.cfg') }} restore-keys: | ${{ runner.os }}-tox-${{ format('{{py{0}-django{1}-cms{2}}}', matrix.python-version, matrix.django, matrix.cms) }}- - name: Install dependencies run: | sudo apt update sudo apt install gettext libcairo2-dev python -m pip install --upgrade pip setuptools tox>4 - name: Test with tox env: TOX_ENV: ${{ format('py-django{1}-cms{2}', matrix.python-version, matrix.django, matrix.cms) }} COMMAND: coverage run COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} COVERALLS_SERVICE_NAME: github run: | tox -e$TOX_ENV .tox/$TOX_ENV/bin/coverage xml - name: Coveralls Parallel uses: coverallsapp/github-action@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel: true - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} flags: unittests files: ./coverage.xml fail_ci_if_error: false services: redis: image: redis ports: - 6379:6379 finish: timeout-minutes: 30 needs: test if: ${{ always() }} runs-on: latchkey-small steps: - name: Coveralls Finished uses: coverallsapp/github-action@v2 with: parallel-finished: true
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.
- 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.
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
This workflow runs 2 jobs (19 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.