Nikola CI workflow (getnikola/nikola)
The Nikola CI workflow from getnikola/nikola, explained and optimized by Latchkey.
CI health: D - needs work
Point runs-on at Latchkey and get caching, run de-duplication, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Nikola CI workflow from the getnikola/nikola 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: Nikola CI
on:
# Run on all pushes to master (including merge of PR)
push:
branches: master
# Run on all changes in pull requests
pull_request:
# Run every Saturday at 17:10 UTC to ensure stability (dependency changes not breaking things)
schedule:
- cron: '10 17 * * 6'
jobs:
nikola:
name: Nikola tests (Python ${{ matrix.python }} on ${{ matrix.image }})
strategy:
fail-fast: false
matrix:
python: ['3.10', '3.11', '3.12', '3.13', '3.14']
image:
- ubuntu-latest
include:
- python: '3.14'
image: macos-latest
- python: '3.14'
image: windows-latest
runs-on: '${{ matrix.image }}'
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '${{ matrix.python }}'
- name: Install Nikola
run: |
python -m pip install --upgrade-strategy eager -U .[extras,tests]
- name: Run tests
run: |
py.test tests/
- name: Run nikola
run: |
nikola
- name: Run nikola help
run: |
nikola help
baseline:
name: Baseline testing (Python ${{ matrix.python }} on ${{ matrix.image }})
strategy:
fail-fast: false
matrix:
python: ['3.14']
image:
- ubuntu-latest
runs-on: '${{ matrix.image }}'
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '${{ matrix.python }}'
- name: Install extra requirements
run: |
python -m pip install --upgrade-strategy eager freezegun
- name: Install Nikola
run: |
python -m pip install --upgrade-strategy eager -U .[extras]
- name: Compare to baseline
run: |
scripts/baseline.sh check
flake8:
name: Linting (flake8, pydocstyle)
strategy:
matrix:
python:
- '3.14'
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '${{ matrix.python }}'
- name: Install requirements
run: |
python -m pip install --upgrade-strategy eager -U flake8 pydocstyle
- name: Run flake8
run: |
flake8 nikola/ tests/
- name: Run pydocstyle
run: |
pydocstyle --count --match-dir='(?!^\\.)(?!data).*' nikola/
basereq:
name: Build demo site with base requirements
strategy:
matrix:
python: ['3.11', '3.12', '3.13', '3.14']
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '${{ matrix.python }}'
- name: Install Nikola
run: |
python -m pip install --upgrade-strategy eager -U .
- name: Run help
run: |
nikola help
working-directory: /
- name: Run init
run: |
nikola init -qd nsite
working-directory: /tmp/
- name: Run build
run: |
nikola build
working-directory: /tmp/nsite
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: Nikola CI on: # Run on all pushes to master (including merge of PR) push: branches: master # Run on all changes in pull requests pull_request: # Run every Saturday at 17:10 UTC to ensure stability (dependency changes not breaking things) schedule: - cron: '10 17 * * 6' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: nikola: timeout-minutes: 30 name: Nikola tests (Python ${{ matrix.python }} on ${{ matrix.image }}) strategy: fail-fast: false matrix: python: ['3.10', '3.11', '3.12', '3.13', '3.14'] image: - ubuntu-latest include: - python: '3.14' image: macos-latest - python: '3.14' image: windows-latest runs-on: '${{ matrix.image }}' steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: cache: 'pip' python-version: '${{ matrix.python }}' - name: Install Nikola run: | python -m pip install --upgrade-strategy eager -U .[extras,tests] - name: Run tests run: | py.test tests/ - name: Run nikola run: | nikola - name: Run nikola help run: | nikola help baseline: timeout-minutes: 30 name: Baseline testing (Python ${{ matrix.python }} on ${{ matrix.image }}) strategy: fail-fast: false matrix: python: ['3.14'] image: - ubuntu-latest runs-on: '${{ matrix.image }}' steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: cache: 'pip' python-version: '${{ matrix.python }}' - name: Install extra requirements run: | python -m pip install --upgrade-strategy eager freezegun - name: Install Nikola run: | python -m pip install --upgrade-strategy eager -U .[extras] - name: Compare to baseline run: | scripts/baseline.sh check flake8: timeout-minutes: 30 name: Linting (flake8, pydocstyle) strategy: matrix: python: - '3.14' runs-on: latchkey-small steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: cache: 'pip' python-version: '${{ matrix.python }}' - name: Install requirements run: | python -m pip install --upgrade-strategy eager -U flake8 pydocstyle - name: Run flake8 run: | flake8 nikola/ tests/ - name: Run pydocstyle run: | pydocstyle --count --match-dir='(?!^\\.)(?!data).*' nikola/ basereq: timeout-minutes: 30 name: Build demo site with base requirements strategy: matrix: python: ['3.11', '3.12', '3.13', '3.14'] runs-on: latchkey-small steps: - name: Check out code uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: cache: 'pip' python-version: '${{ matrix.python }}' - name: Install Nikola run: | python -m pip install --upgrade-strategy eager -U . - name: Run help run: | nikola help working-directory: / - name: Run init run: | nikola init -qd nsite working-directory: /tmp/ - name: Run build run: | nikola build working-directory: /tmp/nsite
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.
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 4 jobs (11 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.