Skip to content

Commit ea54af4

Browse files
authored
Update Regression CI (#546)
1 parent 4ea4c16 commit ea54af4

File tree

5 files changed

+137
-256
lines changed

5 files changed

+137
-256
lines changed
+105-19
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,61 @@
1-
# .github/workflows/regression_tests.yml
1+
# .github/workflows/update_regression_tests.yml
2+
3+
# for details on triggering a workflow from a comment, see:
4+
# https://dev.to/zirkelc/trigger-github-workflow-for-comment-on-pull-request-45l2
25
name: Regression Tests
36

47
on:
5-
# pull_request:
6-
# branches:
7-
# - main
8+
issue_comment: # trigger from comment; event runs on the default branch
9+
types: [created]
810

911
jobs:
10-
regression_tests:
11-
name: regression_tests
12+
update_regression_tests:
13+
name: update_regression_tests
1214
runs-on: ubuntu-20.04
15+
# Trigger from a comment that contains '/test_regression'
16+
if: github.event.issue.pull_request && contains(github.event.comment.body, '/test_regression')
17+
# workflow needs permissions to write to the PR
18+
permissions:
19+
contents: write
20+
pull-requests: write
21+
issues: read
1322

1423
steps:
24+
- name: Create initial status comment
25+
uses: actions/github-script@v7
26+
id: initial-comment
27+
with:
28+
github-token: ${{ secrets.GITHUB_TOKEN }}
29+
script: |
30+
const response = await github.rest.issues.createComment({
31+
issue_number: context.issue.number,
32+
owner: context.repo.owner,
33+
repo: context.repo.repo,
34+
body: '## Regression Test\n⏳ Workflow is currently running...'
35+
});
36+
return response.data.id;
37+
38+
- name: Check if PR is from fork
39+
id: check-fork
40+
uses: actions/github-script@v7
41+
with:
42+
github-token: ${{ secrets.GITHUB_TOKEN }}
43+
script: |
44+
const pr = await github.rest.pulls.get({
45+
owner: context.repo.owner,
46+
repo: context.repo.repo,
47+
pull_number: context.issue.number
48+
});
49+
return pr.data.head.repo.fork;
50+
1551
- uses: actions/checkout@v3
1652
with:
53+
ref: main
1754
lfs: true
18-
fetch-depth: 0 # This ensures we can checkout main branch too
19-
20-
- uses: actions/setup-python@v4
55+
fetch-depth: 0
56+
57+
- name: Set up Python
58+
uses: actions/setup-python@v4
2159
with:
2260
python-version: '3.10'
2361
architecture: 'x64'
@@ -26,14 +64,62 @@ jobs:
2664
run: |
2765
python -m pip install --upgrade pip
2866
pip install -e ".[dev]"
29-
30-
- name: Run benchmarks and compare to baseline
31-
if: github.event.pull_request.base.ref == 'main'
67+
68+
- name: Update baseline
69+
id: update-baseline
70+
run: |
71+
NEW_BASELINE=1 pytest -m regression
72+
cp tests/regression_test_baselines.json /tmp/regression_test_baselines.json
73+
74+
- name: Get PR branch
75+
uses: xt0rted/pull-request-comment-branch@v3
76+
id: comment-branch
77+
with:
78+
repo_token: ${{ secrets.GITHUB_TOKEN }}
79+
80+
- name: Checkout PR branch
81+
uses: actions/checkout@v3
82+
with:
83+
ref: ${{ steps.comment-branch.outputs.head_sha }} # using head_sha vs. head_ref makes this work for forks
84+
lfs: true
85+
fetch-depth: 0 # This ensures we can checkout main branch too
86+
87+
- name: Run comparison
88+
id: comparison
3289
run: |
33-
# Check if regression test results exist in main branch
34-
if [ -f 'git cat-file -e main:tests/regression_test_baselines.json' ]; then
35-
git checkout main tests/regression_test_baselines.json
36-
else
37-
echo "No regression test results found in main branch"
38-
fi
39-
pytest -m regression
90+
cp /tmp/regression_test_baselines.json tests/regression_test_baselines.json
91+
pytest -m regression
92+
93+
- name: Update comment with results
94+
uses: actions/github-script@v7
95+
if: always() # Run this step even if previous steps fail
96+
with:
97+
github-token: ${{ secrets.GITHUB_TOKEN }}
98+
script: |
99+
const fs = require('fs');
100+
let status = '${{ steps.comparison.outcome }}' === 'success' ? '✅' : '❌';
101+
let message = '## Regression Baseline Update\n' + status + ' Process completed\n\n';
102+
103+
try {
104+
const TestReport = fs.readFileSync('tests/regression_test_report.txt', 'utf8');
105+
message += '```\n' + TestReport + '\n```\n\n';
106+
107+
// Add information about where the changes were pushed
108+
if ('${{ steps.comparison.outcome }}' === 'success') {
109+
if (!${{ fromJson(steps.check-fork.outputs.result) }}) {
110+
message += '✨ Changes have been pushed directly to this PR\n';
111+
} else {
112+
const prNumber = '${{ steps.create-pr.outputs.pull-request-number }}';
113+
message += `✨ Changes have been pushed to a new PR #${prNumber} because this PR is from a fork\n`;
114+
}
115+
}
116+
} catch (error) {
117+
message += '⚠️ No test report was generated\n';
118+
}
119+
120+
await github.rest.issues.updateComment({
121+
comment_id: ${{ steps.initial-comment.outputs.result }},
122+
owner: context.repo.owner,
123+
repo: context.repo.repo,
124+
body: message
125+
});

.github/workflows/update_regression_baseline.yml

-141
This file was deleted.

CHANGELOG.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66
```python
77
net.record("i_IonotropicSynapse")
88
```
9-
- Add regression tests and supporting workflows for maintaining baselines (#475, @jnsbck).
10-
- PRs now trigger both tests and regression tests.
11-
- Baselines are maintained in the main branch.
9+
- Add regression tests and supporting workflows for maintaining baselines (#475, #546, @jnsbck).
10+
- Regression tests can be triggered by commenting on a PR.
1211
- Regression tests can be done locally by running `NEW_BASELINE=1 pytest -m regression` i.e. on `main` and then `pytest -m regression` on `feature`, which will produce a test report (printed to the console and saved to .txt).
13-
- If a PR introduces new baseline tests or reduces runtimes, then a new baseline can be created by commenting "/update_regression_baselines" on the PR.
1412

1513
- refactor plotting (#539, @jnsbck).
1614
- rm networkx dependency

tests/conftest.py

+30
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,36 @@ def get_or_compute_swc2jaxley_params(
206206
params = {}
207207

208208

209+
def pytest_collection_modifyitems(config, items):
210+
if config.getoption("--runslow"):
211+
# --runslow given in cli: do not skip slow tests
212+
return
213+
skip_slow = pytest.mark.skip(reason="need --runslow option to run")
214+
for item in items:
215+
if "slow" in item.keywords:
216+
item.add_marker(skip_slow)
217+
218+
219+
def pytest_collection_modifyitems(config, items):
220+
NEW_BASELINE = (
221+
int(os.environ["NEW_BASELINE"]) if "NEW_BASELINE" in os.environ else 0
222+
)
223+
224+
dirname = os.path.dirname(__file__)
225+
baseline_fname = os.path.join(dirname, "regression_test_baselines.json")
226+
227+
def should_skip_regression():
228+
return not NEW_BASELINE and not os.path.exists(baseline_fname)
229+
230+
if should_skip_regression():
231+
for item in items:
232+
if "regression" in item.keywords:
233+
skip_regression = pytest.mark.skip(
234+
reason="need NEW_BASELINE env to run"
235+
)
236+
item.add_marker(skip_regression)
237+
238+
209239
@pytest.fixture(scope="session", autouse=True)
210240
def print_session_report(request, pytestconfig):
211241
"""Cleanup a testing directory once we are finished."""

0 commit comments

Comments
 (0)