1- # GitHub Actions CI workflow: lint, type-check, test, notebooks, upload artifacts
2- # - Python matrix: 3.10, 3.11, 3.12
3- # - Uses pip cache to speed up installs
4- # - Runs isort (check), Black (check), Flake8 (with bugbear), Mypy, Pytest (with coverage)
5- # - Executes notebooks (if any) using jupyter nbconvert
61name : CI
72
83on :
1914 - cron : ' 0 3 * * *'
2015 workflow_dispatch :
2116
22- env :
23- PIP_CACHE_DIR : ~/.cache/pip
24-
2517jobs :
2618 lint-type-test :
2719 name : Lint / Type-check / Test (Python ${{ matrix.python-version }})
3022 matrix :
3123 python-version : ['3.10', '3.11', '3.12']
3224 steps :
33- - name : Checkout repo
34- uses : actions/checkout@v4
25+ - uses : actions/checkout@v4
3526
3627 - name : Setup Python
3728 uses : actions/setup-python@v4
@@ -50,96 +41,74 @@ jobs:
5041 run : |
5142 python -m pip install --upgrade pip
5243 if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
53- pip install " black==24.*" " isort==5.*" " flake8==7.*" " flake8-bugbear==23.*" " mypy==1.*" " pytest==8.*" " pytest-cov" " nbval" " jupyter" " coverage"
44+ pip install black==24.* isort==5.* flake8==7.* flake8-bugbear==23.* mypy==1.* pytest==8.* pytest-cov nbval jupyter coverage nbconvert nbformat
5445
55- - name : Run isort (check)
56- run : |
57- isort --version
58- isort --check-only .
46+ - name : Run isort
47+ run : isort --check-only .
5948
60- - name : Run Black (check)
61- run : |
62- black --version
63- black --check .
49+ - name : Run Black
50+ run : black --check .
6451
65- - name : Run Flake8 (including bugbear checks)
66- run : |
67- flake8 .
52+ - name : Run Flake8
53+ run : flake8 .
6854
6955 - name : Run Mypy
70- run : |
71- mypy .
56+ run : mypy .
7257
73- - name : Run Pytest (with coverage)
74- continue-on-error : false
75- run : |
76- pytest --maxfail=1 --disable-warnings -q --cov=. --cov-report=xml
58+ - name : Run Pytest with coverage
59+ run : pytest --maxfail=1 --disable-warnings -q --cov=. --cov-report=xml
7760
78- - name : Upload test/coverage artifacts
79- if : always()
61+ - name : Upload test and coverage artifacts
8062 uses : actions/upload-artifact@v4
8163 with :
8264 name : coverage-and-tests-${{ matrix.python-version }}
8365 path : |
8466 coverage.xml
8567 .pytest_cache || true
8668
87- - name : Upload coverage to Codecov (optional)
88- if : ${{ secrets.CODECOV_TOKEN != '' }}
89- uses : codecov/codecov-action@v4
90- with :
91- files : coverage.xml
92- token : ${{ secrets.CODECOV_TOKEN }}
93-
9469 notebooks :
95- name : Execute Jupyter notebooks (single runner)
70+ name : Execute Jupyter notebooks
9671 runs-on : ubuntu-latest
9772 needs : lint-type-test
9873 strategy :
9974 matrix :
10075 python-version : ['3.11']
10176 steps :
102- - name : Checkout repo
103- uses : actions/checkout@v4
77+ - uses : actions/checkout@v4
10478
10579 - name : Setup Python
10680 uses : actions/setup-python@v4
10781 with :
10882 python-version : ${{ matrix.python-version }}
10983
110- - name : Cache pip for notebooks
84+ - name : Cache pip
11185 uses : actions/cache@v4
11286 with :
11387 path : ~/.cache/pip
11488 key : notebooks-pip-${{ matrix.python-version }}-${{ hashFiles('**/requirements.txt') }}
11589 restore-keys : |
11690 notebooks-pip-${{ matrix.python-version }}-
11791
118- - name : Install jupyter & nbconvert
92+ - name : Install Jupyter & nbconvert
11993 run : |
12094 python -m pip install --upgrade pip
121- if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
122- pip install "jupyter" "nbconvert" "nbformat"
95+ pip install jupyter nbconvert nbformat
12396
124- - name : Find and execute notebooks
97+ - name : Execute notebooks
12598 run : |
12699 set -euo pipefail
127100 mapfile -t NOTEBOOKS < <(git ls-files '*.ipynb' || true)
128101 if [ ${#NOTEBOOKS[@]} -eq 0 ]; then
129- echo "No notebooks found in repository — skipping execution ."
102+ echo "No notebooks found — skipping."
130103 exit 0
131104 fi
132- echo "Found notebooks:"
133- printf '%s\n' "${NOTEBOOKS[@]}"
134105 for nb in "${NOTEBOOKS[@]}"; do
135106 echo "Executing $nb"
136107 out="/tmp/$(basename "$nb" .ipynb)-executed.ipynb"
137108 jupyter nbconvert --to notebook --execute "$nb" --ExecutePreprocessor.timeout=600 --output "$out"
138- echo "$out"
139109 done
140110
141- - name : Upload executed notebooks (artifact)
142- if : always()
111+ - name : Upload executed notebooks
143112 uses : actions/upload-artifact@v4
144113 with :
145114 name : executed-notebooks
0 commit comments