Skip to content

Commit c00a46d

Browse files
cakedev0claude
andcommitted
Reuse run.sh in pr-comparison.yml; remove broken validate-only preflight
Confirmed live on PR #31: the "Validate config" step used -e reporting (and run.sh's own preflight used -e default), but implementations_for_pixi_env() rejects any PIXI_ENVIRONMENT_NAME outside its real-env allowlist - so this preflight was broken for any config calling it (all_models.py and anything derived from it, e.g. this PR's own all_models_ridge_only.py), unconditionally, regardless of which real environment would go on to run. - run.sh: drop the recently-added --validate-only preflight block and its now-unused extract_configs helper. - scripts/classify_bench_session.py: drop the now-dead special-case for run.sh's removed --validate-only header line. - .github/workflows/pr-comparison.yml: reuse run.sh directly (one invocation with two env@owner:ref entries) instead of duplicating setup_sklearn_ref.sh + sklbench calls per side - matches CONTRIBUTING.md's documented PR-vs-base comparison pattern exactly, and collapses two log files/classify calls into one. Keep a config preflight, but scoped to this workflow with a real, always-installable env (sklearn-pypi) instead of a broken one - still worth catching a typo'd config before a many-minutes sklearn-dev clone+build. - scripts/resolve_sklearn_pr.py: output the fork's `owner` (matching run.sh's env@owner:ref shorthand) instead of a full clone_url, and validate the fork's repo is actually named "scikit-learn" (what that shorthand assumes) rather than silently mishandling a differently-named fork. - tests/test_config_loading.py: register all_models_ridge_only.py in ENV_SENSITIVE_CONFIGS alongside the other all_models.py-derived configs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 7c180f2 commit c00a46d

5 files changed

Lines changed: 50 additions & 78 deletions

File tree

.github/workflows/pr-comparison.yml

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
config: ${{ steps.parse.outputs.config }}
2323
runners: ${{ steps.parse.outputs.runners }}
2424
sklearn_pr_number: ${{ steps.parse.outputs.sklearn_pr_number }}
25-
sklearn_clone_url: ${{ steps.resolve.outputs.clone_url }}
25+
sklearn_owner: ${{ steps.resolve.outputs.owner }}
2626
sklearn_head_ref: ${{ steps.resolve.outputs.head_ref }}
2727
steps:
2828
- name: Check out repository (base, trusted)
@@ -138,7 +138,7 @@ jobs:
138138
PR_NUMBER: ${{ github.event.pull_request.number }}
139139
CONFIG: ${{ needs.gate_and_resolve.outputs.config }}
140140
SKLEARN_PR: ${{ needs.gate_and_resolve.outputs.sklearn_pr_number }}
141-
SKLEARN_CLONE_URL: ${{ needs.gate_and_resolve.outputs.sklearn_clone_url }}
141+
SKLEARN_OWNER: ${{ needs.gate_and_resolve.outputs.sklearn_owner }}
142142
SKLEARN_HEAD_REF: ${{ needs.gate_and_resolve.outputs.sklearn_head_ref }}
143143
steps:
144144
- name: Set scratch directories
@@ -174,7 +174,10 @@ jobs:
174174
uses: prefix-dev/setup-pixi@5185adfbffb4bd703da3010310260805d89ebb11 # v0.9.6
175175
with:
176176
pixi-version: v0.75.0
177-
environments: reporting
177+
# sklearn-pypi (lightweight, always installable, no sklearn-src/
178+
# path dependency) is used to validate the config below before
179+
# committing to the much slower sklearn-dev clone+build.
180+
environments: reporting sklearn-pypi
178181
locked: false
179182
frozen: true
180183
cache: false
@@ -185,35 +188,31 @@ jobs:
185188
run: rm -rf "${SKLBENCH_DATA_CACHE:-data_cache}/preprocessed"
186189

187190
- name: Validate config
188-
run: pixi run --frozen -e reporting python -m sklbench --config "$CONFIG" --validate-only
189-
190-
- name: Set up scikit-learn PR branch
191-
run: ./scripts/setup_sklearn_ref.sh --remote "$SKLEARN_CLONE_URL" --ref "$SKLEARN_HEAD_REF" --env sklearn-dev
192-
193-
- name: Run benchmark (PR branch)
194-
continue-on-error: true
195-
run: |
196-
pixi run --frozen -e sklearn-dev python -m sklbench --config "$CONFIG" --results-dir "$RESULTS_DIR" \
197-
2>&1 | tee "$RUNNER_TEMP/bench-pr.log"
198-
199-
- name: Set up scikit-learn main
200-
run: ./scripts/setup_sklearn_ref.sh --remote https://github.com/scikit-learn/scikit-learn.git --ref main --env sklearn-dev
191+
# A prior version of this check lived in run.sh itself, using
192+
# `-e default` - broken for any config calling
193+
# implementations_for_pixi_env() (e.g. all_models.py and anything
194+
# derived from it), since "default" isn't an accepted
195+
# PIXI_ENVIRONMENT_NAME. Removed there; kept here, scoped to this
196+
# workflow, using a real accepted env instead - catching a typo'd
197+
# config path/estimator name before a many-minutes sklearn-dev
198+
# clone+build is still worth it.
199+
run: pixi run --frozen -e sklearn-pypi python -m sklbench --config "$CONFIG" --validate-only
201200

202-
- name: Run benchmark (main)
201+
- name: Run comparison benchmark
202+
# Reuses run.sh exactly as CONTRIBUTING.md's "Running Against
203+
# scikit-learn Branches" documents for a PR-vs-base comparison:
204+
# sequential setup_sklearn_ref.sh + sklbench run per env@owner:ref
205+
# entry, one shared sklearn-src/ checkout re-pointed between them.
203206
continue-on-error: true
204207
run: |
205-
pixi run --frozen -e sklearn-dev python -m sklbench --config "$CONFIG" --results-dir "$RESULTS_DIR" \
206-
2>&1 | tee "$RUNNER_TEMP/bench-main.log"
207-
208-
- name: Classify PR-branch run
209-
id: classify_pr
210-
continue-on-error: true
211-
run: pixi run --frozen -e reporting python scripts/classify_bench_session.py "$RUNNER_TEMP/bench-pr.log"
208+
./run.sh "sklearn-dev@${SKLEARN_OWNER}:${SKLEARN_HEAD_REF}" sklearn-dev@scikit-learn:main \
209+
--config "$CONFIG" --results-dir "$RESULTS_DIR" \
210+
2>&1 | tee "$RUNNER_TEMP/bench.log"
212211
213-
- name: Classify main run
214-
id: classify_main
212+
- name: Classify benchmark session
213+
id: classify
215214
continue-on-error: true
216-
run: pixi run --frozen -e reporting python scripts/classify_bench_session.py "$RUNNER_TEMP/bench-main.log"
215+
run: pixi run --frozen -e reporting python scripts/classify_bench_session.py "$RUNNER_TEMP/bench.log"
217216

218217
- name: Generate comparison dashboard
219218
# working-directory is RESULTS_DIR's parent, so its bare `results/`
@@ -248,8 +247,7 @@ jobs:
248247
- name: Build and post comment
249248
if: always()
250249
env:
251-
CLASSIFY_PR: ${{ steps.classify_pr.outcome }}
252-
CLASSIFY_MAIN: ${{ steps.classify_main.outcome }}
250+
CLASSIFY_OUTCOME: ${{ steps.classify.outcome }}
253251
DEPLOY_OUTCOME: ${{ steps.deploy.outcome }}
254252
GITHUB_TOKEN: ${{ github.token }}
255253
run: |
@@ -260,8 +258,7 @@ jobs:
260258
echo "**${{ matrix.runner }}**: scikit-learn PR #$SKLEARN_PR vs \`main\`, config \`$CONFIG\`"
261259
echo
262260
echo "Dashboard: $url"
263-
[ "$CLASSIFY_PR" != "success" ] && echo "- Caveat: PR-branch run session did not complete cleanly."
264-
[ "$CLASSIFY_MAIN" != "success" ] && echo "- Caveat: main run session did not complete cleanly."
261+
[ "$CLASSIFY_OUTCOME" != "success" ] && echo "- Caveat: one or both benchmark sessions did not complete cleanly."
265262
echo
266263
echo "Full run: $run_url"
267264
} > "$RUNNER_TEMP/comment.md"

run.sh

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,6 @@
33
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
44
source "$script_dir/scripts/pixi_env_check.sh"
55

6-
# Collects --config/-c values from a sklbench arg list into the array named
7-
# by $1 (argparse nargs='+' semantics: consume tokens up to the next
8-
# '-'-prefixed flag).
9-
extract_configs() {
10-
local -n out_ref="$1"
11-
shift
12-
local i=0
13-
local rest=("$@")
14-
while [ "$i" -lt "${#rest[@]}" ]; do
15-
if [ "${rest[$i]}" = "--config" ] || [ "${rest[$i]}" = "-c" ]; then
16-
i=$((i + 1))
17-
while [ "$i" -lt "${#rest[@]}" ] && [[ "${rest[$i]}" != -* ]]; do
18-
out_ref+=("${rest[$i]}")
19-
i=$((i + 1))
20-
done
21-
else
22-
i=$((i + 1))
23-
fi
24-
done
25-
}
26-
276
usage() {
287
echo "Usage: $0 env1 [env2 ...] [sklbench args...]" >&2
298
echo " Runs 'pixi run -e <env> python -m sklbench <args...>' for each" >&2
@@ -72,16 +51,6 @@ if [ "${#envs[@]}" -eq 0 ]; then
7251
exit 2
7352
fi
7453

75-
configs=()
76-
extract_configs configs "${args[@]}"
77-
if [ "${#configs[@]}" -gt 0 ]; then
78-
echo "=== pixi run --frozen -e default python -m sklbench --config ${configs[*]} --validate-only ===" >&2
79-
if ! pixi run --frozen -e default python -m sklbench --config "${configs[@]}" --validate-only; then
80-
echo "error: config validation failed, aborting before running any environment" >&2
81-
exit 1
82-
fi
83-
fi
84-
8554
status=0
8655
for env_spec in "${envs[@]}"; do
8756
env="$env_spec"

scripts/classify_bench_session.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,6 @@ def split_by_env(log_text: str) -> dict[str, list[str]]:
4040
for line in log_text.splitlines():
4141
header = ENV_HEADER_RE.match(line)
4242
if header:
43-
# run.sh also prints a header in this same "=== pixi run ... ==="
44-
# form for its pre-flight `--validate-only` config check, which
45-
# isn't a real per-environment benchmark session and never emits
46-
# progress output. Treat it as a comment rather than a session
47-
# boundary so it doesn't get misclassified as a crashed env.
48-
if "--validate-only" in line:
49-
current_env = None
50-
continue
5143
current_env = header.group(1)
5244
sessions.setdefault(current_env, [])
5345
continue

scripts/resolve_sklearn_pr.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"""
2-
Resolve a scikit-learn PR number to its source fork's clone URL and branch,
3-
via the GitHub REST API directly (urllib, stdlib only) - same rationale as
2+
Resolve a scikit-learn PR number to its source fork's owner and branch, via
3+
the GitHub REST API directly (urllib, stdlib only) - same rationale as
44
scripts/create_pr.py: this org restricts workflows to an allowlist of
55
GitHub Actions, so there's no dedicated action for this either.
66
7-
Returns the fork's own clone_url verbatim rather than reconstructing one
8-
from its owner login, since run.sh's `env@owner:ref` shorthand assumes the
9-
fork repo is named "scikit-learn", which isn't guaranteed for an arbitrary
10-
PR's fork - callers should use scripts/setup_sklearn_ref.sh directly with
11-
this clone_url instead of going through run.sh's shorthand.
7+
Outputs just `owner`, matching run.sh's `env@owner:ref` shorthand, which
8+
hardcodes the fork's repo name as "scikit-learn" and reconstructs the
9+
remote as `https://github.com/<owner>/scikit-learn.git` itself. Since a
10+
PR's fork isn't guaranteed to be named "scikit-learn", this explicitly
11+
checks the fork's repo name and fails clearly (ok=false) rather than
12+
silently handing run.sh an owner whose repo it can't actually find.
1213
"""
1314

1415
import argparse
@@ -69,8 +70,20 @@ def main() -> int:
6970
)
7071
return 0
7172

73+
if fork_repo["name"] != "scikit-learn":
74+
write_output(args.github_output, "ok", "false")
75+
write_output(
76+
args.github_output,
77+
"error",
78+
f"the source fork for {args.repo} PR #{args.pr_number} is named "
79+
f"{fork_repo['name']!r}, not 'scikit-learn' - not supported, since "
80+
"this flow runs the comparison via run.sh's env@owner:ref "
81+
"shorthand, which assumes the fork repo is named scikit-learn",
82+
)
83+
return 0
84+
7285
write_output(args.github_output, "ok", "true")
73-
write_output(args.github_output, "clone_url", fork_repo["clone_url"])
86+
write_output(args.github_output, "owner", fork_repo["owner"]["login"])
7487
write_output(args.github_output, "head_ref", head["ref"])
7588
return 0
7689

tests/test_config_loading.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
Path("configs/all_models_fast.py"): ARRAY_API_ENVS,
2323
Path("configs/all_models.py"): ARRAY_API_ENVS,
2424
Path("configs/all_models_scaling.py"): GENERAL_ENVS,
25+
Path("configs/all_models_ridge_only.py"): ARRAY_API_ENVS,
2526
}
2627

2728

0 commit comments

Comments
 (0)