|
8 | 8 | - 'diff_diff/**' |
9 | 9 | - 'pyproject.toml' |
10 | 10 | - '.github/workflows/notebooks.yml' |
| 11 | + # the interop drift guard runs only in this workflow (balance installed) |
| 12 | + - 'tests/test_t26_composition_drift_calibration_drift.py' |
11 | 13 | pull_request: |
12 | 14 | branches: [main] |
13 | 15 | types: [opened, synchronize, reopened, labeled, unlabeled] |
|
16 | 18 | - 'diff_diff/**' |
17 | 19 | - 'pyproject.toml' |
18 | 20 | - '.github/workflows/notebooks.yml' |
| 21 | + # the interop drift guard runs only in this workflow (balance installed) |
| 22 | + - 'tests/test_t26_composition_drift_calibration_drift.py' |
19 | 23 | schedule: |
20 | 24 | # Weekly Sunday 6am UTC — smoke test that notebooks still execute cleanly |
21 | 25 | - cron: '0 6 * * 0' |
@@ -58,11 +62,16 @@ jobs: |
58 | 62 | --nbmake-timeout=600 \ |
59 | 63 | --ignore=docs/tutorials/06_power_analysis.ipynb \ |
60 | 64 | --ignore=docs/tutorials/10_trop.ipynb \ |
| 65 | + --ignore=docs/tutorials/26_composition_drift_calibration.ipynb \ |
61 | 66 | -v \ |
62 | 67 | --tb=short |
63 | 68 | # Excluded notebooks (too slow for pure-Python CI without Rust backend): |
64 | 69 | # 06_power_analysis — SyntheticDiD simulate_power Monte Carlo (>600s) |
65 | 70 | # 10_trop — LOOCV grid search (>600s) |
| 71 | + # Excluded notebooks (external interop dependency): |
| 72 | + # 26_composition_drift_calibration — requires the balance package; |
| 73 | + # runs in the isolated interop-notebooks job below so this job's |
| 74 | + # minimal env keeps enforcing that tutorials add no dependencies |
66 | 75 |
|
67 | 76 | - name: Upload failed notebook outputs |
68 | 77 | if: failure() |
|
71 | 80 | name: failed-notebook-outputs |
72 | 81 | path: docs/tutorials/*.ipynb |
73 | 82 | retention-days: 7 |
| 83 | + |
| 84 | + interop-notebooks: |
| 85 | + name: Execute balance-interop notebook |
| 86 | + # Same ready-for-ci label gate as execute-notebooks (keep in sync). |
| 87 | + if: >- |
| 88 | + github.event_name != 'pull_request' |
| 89 | + || (contains(github.event.pull_request.labels.*.name, 'ready-for-ci') |
| 90 | + && (github.event.action != 'labeled' && github.event.action != 'unlabeled' |
| 91 | + || github.event.label.name == 'ready-for-ci')) |
| 92 | + runs-on: ubuntu-latest |
| 93 | + |
| 94 | + steps: |
| 95 | + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 |
| 96 | + |
| 97 | + - name: Set up Python |
| 98 | + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 |
| 99 | + with: |
| 100 | + # 3.12+: balance's legacy numpy<2 / scipy<1.14 / scikit-learn<1.4 |
| 101 | + # pins apply only to python < 3.12 |
| 102 | + python-version: '3.12' |
| 103 | + |
| 104 | + - name: Install dependencies |
| 105 | + # balance is a tutorial-only dependency: it is installed ONLY in this |
| 106 | + # isolated job, never in package requirements or the main notebooks |
| 107 | + # job. The weekly cron on this workflow doubles as a cross-package |
| 108 | + # integration smoke of diff-diff HEAD against latest PyPI balance. |
| 109 | + run: | |
| 110 | + pip install numpy pandas scipy matplotlib nbmake pytest ipykernel "balance>=0.21" |
| 111 | + # Add repo root to Python path so Jupyter kernels can import diff_diff |
| 112 | + # (pip install -e . requires the Rust/maturin toolchain; .pth avoids that) |
| 113 | + python -c "import site; print(site.getsitepackages()[0])" | xargs -I{} sh -c 'echo "$PWD" > {}/diff_diff_dev.pth' |
| 114 | +
|
| 115 | + - name: Execute interop notebook |
| 116 | + env: |
| 117 | + DIFF_DIFF_BACKEND: python |
| 118 | + run: | |
| 119 | + pytest --nbmake docs/tutorials/26_composition_drift_calibration.ipynb \ |
| 120 | + --nbmake-timeout=600 \ |
| 121 | + -v \ |
| 122 | + --tb=short |
| 123 | +
|
| 124 | + - name: Run interop drift guard |
| 125 | + # balance is present only in this job, so this is the drift test's |
| 126 | + # CI home (it importorskips balance everywhere else). |
| 127 | + env: |
| 128 | + DIFF_DIFF_BACKEND: python |
| 129 | + run: | |
| 130 | + pytest tests/test_t26_composition_drift_calibration_drift.py -v --tb=short |
| 131 | +
|
| 132 | + - name: Upload failed notebook outputs |
| 133 | + if: failure() |
| 134 | + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 |
| 135 | + with: |
| 136 | + name: failed-interop-notebook-outputs |
| 137 | + path: docs/tutorials/26_composition_drift_calibration.ipynb |
| 138 | + retention-days: 7 |
0 commit comments