Skip to content

Commit f830f0b

Browse files
tschmclaude
andcommitted
fix CI: add notebook change detection, expand release matrix, clean up dead code
- main.yml: add detect-notebooks-change job; gate notebooks on it to skip expensive runs on unrelated PRs (always fires on push to main) - main.yml: remove dead if: false codecov upload step - release.yml: drop Linux-only container from test job; add macOS and Windows to release test matrix (5 → 15 jobs) - release.yml: rename PY_VERSION → PKG_VERSION to avoid confusion with the Python interpreter version Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4184e47 commit f830f0b

2 files changed

Lines changed: 56 additions & 19 deletions

File tree

.github/workflows/main.yml

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,19 +225,50 @@ jobs:
225225
--cov=./ \
226226
--cov-report=xml
227227
228-
# Upload currently disabled
229-
- name: Upload coverage to Codecov
230-
if: false
231-
uses: codecov/codecov-action@v5
228+
229+
# ================================================================
230+
# 5️⃣ NOTEBOOK CHANGE DETECTION
231+
#
232+
# Checks whether any notebook-relevant paths changed.
233+
# Skips expensive notebook execution on unrelated PRs.
234+
#
235+
# On push to main, always runs notebooks (something was merged).
236+
# On PRs, diffs against origin/main to detect changes in:
237+
# - cookbook/ (notebooks themselves)
238+
# - pypfopt/ (library code notebooks depend on)
239+
# - pyproject.toml (dependency changes)
240+
# ================================================================
241+
detect-notebooks-change:
242+
needs: code-quality
243+
runs-on: ubuntu-latest
244+
outputs:
245+
notebooks: ${{ steps.check.outputs.notebooks }}
246+
247+
steps:
248+
- uses: actions/checkout@v4
232249
with:
233-
files: ./coverage.xml
234-
fail_ci_if_error: true
250+
fetch-depth: 0
251+
252+
- name: Fetch main branch
253+
run: git fetch origin main
254+
255+
- name: Check if notebook-related files changed
256+
id: check
257+
run: |
258+
if [ "${{ github.event_name }}" = "push" ]; then
259+
echo "notebooks=true" >> $GITHUB_OUTPUT
260+
elif git diff --quiet origin/main -- cookbook/ pypfopt/ pyproject.toml; then
261+
echo "notebooks=false" >> $GITHUB_OUTPUT
262+
else
263+
echo "notebooks=true" >> $GITHUB_OUTPUT
264+
fi
235265
236266
237267
# ================================================================
238-
# 5️⃣ NOTEBOOK TESTING
268+
# 6️⃣ NOTEBOOK TESTING
239269
#
240270
# Executes Jupyter notebooks via nbmake.
271+
# Only runs when notebook-relevant files changed (see above).
241272
#
242273
# For each Python version:
243274
# - Install interpreter via uv
@@ -250,7 +281,8 @@ jobs:
250281
# - No silent drift between code and notebooks
251282
# ================================================================
252283
notebooks:
253-
needs: code-quality
284+
needs: detect-notebooks-change
285+
if: ${{ needs.detect-notebooks-change.outputs.notebooks == 'true' }}
254286
runs-on: ubuntu-latest
255287

256288
strategy:

.github/workflows/release.yml

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,16 @@ jobs:
5858
5959
# Read version from pyproject.toml using Python
6060
# We rely on tomllib (Python 3.11+) for robust parsing.
61-
PY_VERSION=$(python - <<'PY'
61+
PKG_VERSION=$(python - <<'PY'
6262
import pathlib, tomllib
6363
data = tomllib.loads(pathlib.Path("pyproject.toml").read_text())
6464
print(data["project"]["version"])
6565
PY
6666
)
6767
6868
# Fail fast if mismatch
69-
if [ "$GH_TAG_NAME" != "$PY_VERSION" ]; then
70-
echo "::error::Tag ($GH_TAG_NAME) does not match pyproject version ($PY_VERSION)"
69+
if [ "$GH_TAG_NAME" != "$PKG_VERSION" ]; then
70+
echo "::error::Tag ($GH_TAG_NAME) does not match pyproject version ($PKG_VERSION)"
7171
exit 1
7272
fi
7373
@@ -137,10 +137,7 @@ jobs:
137137
# ================================================================
138138
test:
139139
needs: build
140-
runs-on: ubuntu-latest
141-
142-
container:
143-
image: ghcr.io/astral-sh/uv:0.9.30-bookworm
140+
runs-on: ${{ matrix.os }}
144141

145142
strategy:
146143
fail-fast: false
@@ -150,25 +147,31 @@ jobs:
150147
# - pyproject.toml requires-python
151148
# - your long-term support policy
152149
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
150+
os: [ubuntu-latest, macos-latest, windows-latest]
153151

154152
steps:
155153
- uses: actions/checkout@v4
156154

155+
- uses: astral-sh/setup-uv@v7
156+
with:
157+
enable-cache: true
158+
157159
- uses: actions/download-artifact@v4
158160
with:
159161
name: dist
160162
path: wheelhouse
161163

162164
- name: Install and pin Python ${{ matrix.python-version }}
165+
shell: bash
163166
run: |
164-
# Read version from pyproject.toml
165-
PY_VERSION=$(python - <<'PY'
167+
# Read package version from pyproject.toml
168+
PKG_VERSION=$(python - <<'PY'
166169
import pathlib, tomllib
167170
data = tomllib.loads(pathlib.Path("pyproject.toml").read_text())
168171
print(data["project"]["version"])
169172
PY
170173
)
171-
echo "PY_VERSION=${PY_VERSION}" >> $GITHUB_ENV
174+
echo "PKG_VERSION=${PKG_VERSION}" >> $GITHUB_ENV
172175
173176
# Install requested interpreter version
174177
uv python install ${{ matrix.python-version }}
@@ -181,10 +184,12 @@ jobs:
181184
uv run python --version
182185
183186
- name: Install built wheel with dev dependencies
187+
shell: bash
184188
run: |
185189
# Install the wheel artifact (NOT source install)
186190
# [dev,all_extras] assumes these are declared as optional dependencies.
187-
uv pip install "wheelhouse/pyportfolioopt-${PY_VERSION}-py3-none-any.whl[dev,all_extras]"
191+
uv venv --clear
192+
uv pip install "wheelhouse/pyportfolioopt-${PKG_VERSION}-py3-none-any.whl[dev,all_extras]"
188193
189194
- name: Verify dependency graph integrity
190195
run: |

0 commit comments

Comments
 (0)