Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 1 addition & 45 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,7 @@ jobs:
# Every test job runs unless this job succeeded and positively reported
# code=false, so a broken detector costs time rather than coverage.
changes:
name: Detect code changes
runs-on: ubuntu-latest
outputs:
code: ${{ steps.filter.outputs.code }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Decide whether anything testable changed
id: filter
env:
BASE_REF: ${{ github.base_ref }}
run: |
# Conservative by construction: only a recognised documentation path
# votes "no code". Anything unrecognised -- and every push build, which
# has no base to diff against -- runs the full suite.
if [ -z "$BASE_REF" ]; then
echo "Push build: running everything."
echo "code=true" >> "$GITHUB_OUTPUT"
exit 0
fi

git fetch --no-tags origin "$BASE_REF"
base=$(git merge-base FETCH_HEAD HEAD)
# --no-renames: a rename is reported as its destination alone, so moving
# a module under docs/ would otherwise hide the deleted code path.
changed=$(git diff --no-renames --name-only "$base" HEAD)

echo "Changed files:"
echo "$changed"

# `grep -v` exits 1 when everything was filtered out, which is exactly
# the documentation-only case, so it must not trip `set -e`.
testable=$(echo "$changed" | grep -Ev '(\.md$|^docs/|^\.github/ISSUE_TEMPLATE/)' || true)

if [ -z "$testable" ]; then
echo "Documentation only: skipping the test jobs."
echo "code=false" >> "$GITHUB_OUTPUT"
else
echo "Testable changes present:"
echo "$testable"
echo "code=true" >> "$GITHUB_OUTPUT"
fi
uses: ./.github/workflows/detect-code-changes.yml

unit-tests:
name: Unit Tests
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/detect-code-changes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Detect code changes

on:
workflow_call:
outputs:
code:
description: '"true" when anything outside the documentation paths changed.'
value: ${{ jobs.filter.outputs.code }}

jobs:
filter:
name: Detect code changes
runs-on: ubuntu-latest
outputs:
code: ${{ steps.filter.outputs.code }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Decide whether anything testable changed
id: filter
env:
BASE_REF: ${{ github.base_ref }}
run: |
# Conservative by construction: only a recognised documentation path
# votes "no code". Anything unrecognised -- and every push build, which
# has no base to diff against -- runs the full suite.
if [ -z "$BASE_REF" ]; then
echo "Push build: running everything."
echo "code=true" >> "$GITHUB_OUTPUT"
exit 0
fi

git fetch --no-tags origin "$BASE_REF"
base=$(git merge-base FETCH_HEAD HEAD)
# --no-renames: a rename is reported as its destination alone, so moving
# a module under docs/ would otherwise hide the deleted code path.
changed=$(git diff --no-renames --name-only "$base" HEAD)

echo "Changed files:"
echo "$changed"

# `grep -v` exits 1 when everything was filtered out, which is exactly
# the documentation-only case, so it must not trip `set -e`.
testable=$(echo "$changed" | grep -Ev '(\.md$|^docs/|^\.github/ISSUE_TEMPLATE/)' || true)

if [ -z "$testable" ]; then
echo "Documentation only: skipping the test jobs."
echo "code=false" >> "$GITHUB_OUTPUT"
else
echo "Testable changes present:"
echo "$testable"
echo "code=true" >> "$GITHUB_OUTPUT"
fi
24 changes: 21 additions & 3 deletions .github/workflows/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@ on:
branches: [ main, '3.0' ]

jobs:
# The matrix runs unless this job succeeded and positively reported
# code=false, so a broken detector costs time rather than coverage.
changes:
uses: ./.github/workflows/detect-code-changes.yml

test:
name: ${{ matrix.py }} - ${{ matrix.os }}
needs: changes
# The matrix must expand even when there is nothing to install: a job-level
# skip reports one unexpanded check, so the six required contexts would
# never appear and every documentation-only PR would hang at "Expected".
if: always()
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand All @@ -23,23 +33,31 @@ jobs:
py: "3.14"

steps:
# The predicate is written once here, as a step output, rather than
# repeated on every step below.
- name: Decide whether to install
id: gate
run: echo "skip=${{ needs.changes.result == 'success' && needs.changes.outputs.code == 'false' }}" >> "$GITHUB_OUTPUT"

- name: Checkout code
if: steps.gate.outputs.skip != 'true'
uses: actions/checkout@v4

- name: Setup Python
if: steps.gate.outputs.skip != 'true'
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.py }}

- name: Free up disk space (Linux only)
if: runner.os == 'Linux'
if: runner.os == 'Linux' && steps.gate.outputs.skip != 'true'
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
sudo apt-get clean
sudo rm -rf ~/.cache/pip /tmp/* /var/tmp/*

- name: Install pufferlib (Linux)
if: runner.os == 'Linux'
if: runner.os == 'Linux' && steps.gate.outputs.skip != 'true'
run: |
python -m pip install -U pip "setuptools<81" wheel numpy
# CPU-only torch. The CUDA stack is ~3 GB of wheels and no longer
Expand All @@ -48,7 +66,7 @@ jobs:
pip install -e . --no-build-isolation

- name: Install pufferlib (macOS)
if: runner.os != 'Linux'
if: runner.os != 'Linux' && steps.gate.outputs.skip != 'true'
run: |
python -m pip install -U pip
# Deliberately a plain install: macOS wheels are already CPU-only, so
Expand Down
Loading