act caches each action as one shared git clone under /root/.cache/act/<hash> and re-pulls it per job. The three python matrix jobs start within the same second on the self-hosted runner, race on that directory, and the loser dies with "lstat /root/.cache/act/<hash>/.npmrc: no such file or directory" before any test runs — a red main with zero suite output and a different victim each push (3.12, then 3.11). The action was only fetching a binary; the matrix interpreter is selected per command by uvx --python. A run: step has no action-cache entry and cannot race, and keeps the jobs parallel — serialising the matrix would cost 3x the wall clock and still leave actions/checkout shared across four jobs. The uv version is pinned under the same rule as ruff. The accompanying test parses uses: directives rather than the raw text, so the comment can still name the action it avoids, and uses re instead of PyYAML because CI runs uvx pytest, whose environment holds pytest and nothing else.
86 lines
3.2 KiB
YAML
86 lines
3.2 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main, "feat/**", "fix/**"]
|
|
pull_request:
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
shell:
|
|
name: shell (shellcheck + syntax)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: bash syntax check
|
|
run: |
|
|
fail=0
|
|
while IFS= read -r f; do
|
|
bash -n "$f" || { echo "::error file=$f::bash syntax error"; fail=1; }
|
|
done < <(find . -name '*.sh' -not -path './.git/*')
|
|
exit $fail
|
|
|
|
# Pinned to a release tag, not @master: a third-party action on a moving
|
|
# branch runs whatever that branch contains at the time CI fires.
|
|
- name: shellcheck
|
|
uses: ludeeus/action-shellcheck@2.0.0
|
|
env:
|
|
SHELLCHECK_OPTS: -S warning -e SC1091
|
|
|
|
python:
|
|
name: python ${{ matrix.python }}
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
# TrueNAS SCALE middleware runs 3.11+; keep the patch importable across
|
|
# the versions it may be injected into.
|
|
python: ["3.11", "3.12", "3.13"]
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
# uv-managed interpreters instead of actions/setup-python: the prebuilt-CPython
|
|
# download path setup-python relies on does not work on the self-hosted Gitea
|
|
# runner (all three matrix jobs failed at setup there while passing on GitHub);
|
|
# uv works identically on both.
|
|
#
|
|
# Installed by a plain `run:` step rather than astral-sh/setup-uv, because
|
|
# act -- the engine behind the Gitea runner -- caches each ACTION as a single
|
|
# shared git clone under /root/.cache/act/<hash> and re-pulls it per job. The
|
|
# three matrix jobs start within the same second on one runner, so they race
|
|
# on that directory and whichever loses dies with
|
|
#
|
|
# lstat /root/.cache/act/<hash>/.npmrc: no such file or directory
|
|
#
|
|
# before a single test runs -- a red `main` with zero suite output, and a
|
|
# different victim each time (3.12 on one push, 3.11 on the next). A `run:`
|
|
# step has no action-cache entry, so it cannot race. Serialising the matrix
|
|
# would have been the other option; it costs 3x the wall clock and still
|
|
# leaves actions/checkout sharing a cache across the four jobs.
|
|
#
|
|
# Pinned for the same reason ruff is pinned below: an unpinned uv means any
|
|
# upstream release can turn main red with no code change here.
|
|
- name: install uv
|
|
env:
|
|
UV_VERSION: "0.11.21"
|
|
run: |
|
|
curl -LsSf "https://astral.sh/uv/${UV_VERSION}/install.sh" | sh
|
|
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
|
|
- name: ruff
|
|
# Pinned: an unpinned ruff means any upstream release can turn main red
|
|
# with no code change.
|
|
run: uvx ruff@0.16.1 check patch tests tools
|
|
|
|
- name: pytest
|
|
run: uvx --python ${{ matrix.python }} pytest tests -v
|
|
|
|
- name: verify injected middleware blocks compile
|
|
# Belt-and-braces: the *_BLOCK strings are appended into live middlewared
|
|
# modules. A syntax error there would break the box at boot.
|
|
run: uvx --python ${{ matrix.python }} pytest tests/test_apply_blocks.py -v
|