Django application workflow (HackSoftware/Django-Styleguide-Example)
The Django application workflow from HackSoftware/Django-Styleguide-Example, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get run de-duplication, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Django application workflow from the HackSoftware/Django-Styleguide-Example 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: Django application
on: [push]
jobs:
docker_build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build docker
run: docker compose build
- name: Run ruff
run: docker compose run django ruff check styleguide_example/
- name: Run mypy
run: docker compose run django mypy --config mypy.ini styleguide_example/
- name: Run tests
run: docker compose run django py.test
build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:latest
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: github_actions
ports:
- 5432:5432
# needed because the postgres container does not provide a healthcheck
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.12.4
cache: "pip"
cache-dependency-path: |
requirements/local.txt
requirements/base.txt
# This is a more aggresive cache.
# The one above caches the wheel files, but still runs the installation for them
# While the cache below caches the entire Python directory.
- name: Cache pip
uses: actions/cache@v4
with:
path: /opt/hostedtoolcache/Python/3.12.4/x64/ # This path is specific to Ubuntu
key: python-${{ hashFiles('requirements/local.txt') }}-${{ hashFiles('requirements/base.txt') }}
- name: Install dependencies
run: pip install -r requirements/local.txt
- name: Run ruff
run: ruff check .
- name: Type check
run: mypy --config mypy.ini styleguide_example/
- name: Run tests
run: pytest
deploy_to_heroku:
runs-on: ubuntu-latest
needs: build
if: false
steps:
- uses: actions/checkout@v4
with:
fetch-depth: "0"
- name: Deploy to Heroku
env:
HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
HEROKU_APP_NAME: "hacksoft-styleguide-example"
run: git push --force https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git origin/master:master
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Django application on: [push] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: docker_build: timeout-minutes: 30 runs-on: latchkey-small steps: - uses: actions/checkout@v4 - name: Build docker run: docker compose build - name: Run ruff run: docker compose run django ruff check styleguide_example/ - name: Run mypy run: docker compose run django mypy --config mypy.ini styleguide_example/ - name: Run tests run: docker compose run django py.test build: timeout-minutes: 30 runs-on: latchkey-small services: postgres: image: postgres:latest env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: github_actions ports: - 5432:5432 # needed because the postgres container does not provide a healthcheck options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: 3.12.4 cache: "pip" cache-dependency-path: | requirements/local.txt requirements/base.txt # This is a more aggresive cache. # The one above caches the wheel files, but still runs the installation for them # While the cache below caches the entire Python directory. - name: Cache pip uses: actions/cache@v4 with: path: /opt/hostedtoolcache/Python/3.12.4/x64/ # This path is specific to Ubuntu key: python-${{ hashFiles('requirements/local.txt') }}-${{ hashFiles('requirements/base.txt') }} - name: Install dependencies run: pip install -r requirements/local.txt - name: Run ruff run: ruff check . - name: Type check run: mypy --config mypy.ini styleguide_example/ - name: Run tests run: pytest deploy_to_heroku: timeout-minutes: 30 runs-on: latchkey-small needs: build if: false steps: - uses: actions/checkout@v4 with: fetch-depth: "0" - name: Deploy to Heroku env: HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }} HEROKU_APP_NAME: "hacksoft-styleguide-example" run: git push --force https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git origin/master:master
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.
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.