You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b1e3be3
Browse filesBrowse the repository at this point in the historyBrowse files
A check that cannot run no longer reports success (#768)
* A check that cannot run no longer reports success
The Skill Evals job exited 0 when ANTHROPIC_API_KEY was unset, which it is
here: no repository secret, no organization secret, and fork pull requests
never receive one. Every eval file was covered by a green tick that meant
nothing had run.
The key is genuinely unavailable, so this is a skip rather than a failure —
failing every pull request that touches a skill would be noise nobody reads.
But a step-level `if` leaves the job green, so the job is split: a preflight
decides whether the evals can run, and Skill Evals now reports Skipped when
they cannot, with a warning annotation and a step summary naming how many
cases were not run. test.yml is in the paths filter, so this pull request
proves it on itself.
And the guard in connect_skilleval_test.go named a limitation it could not
enforce: the mock, expect_sequence and accept_response patterns are read by
the Ruby runner under Onigmo, and a Go test compiling with RE2 cannot speak
for them. scripts/check-eval-patterns.rb closes it from the other side — it
compiles every pattern in every case file under Onigmo itself, run from
make check and from the Integration Tests job.
It does not run the evals. It catches the malformed pattern that was landing
unnoticed: a broken mock in a connector case passes the Go guard today and
fails this one. Its own floors are the assertion rather than setup for it —
no case files found, no patterns compiled, or a runner that compiles more
pattern kinds than this checker models are each a failure, because a checker
that has fallen behind reports success over the keys it still knows.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Close the review's two findings, both the same shape as the PR's
The preflight declared contents: read only, while dorny/paths-filter
enumerates the pull request's files through the REST API. It works on this
repository because the repository is public, which is incidental rather than
a reason. Granted pull-requests: read, matching the other path-filter job in
this workflow.
The worse half of that finding is what the preflight does when the filter
cannot answer. At this pinned version the action fails the step rather than
returning an empty set, so the gate goes red rather than quietly deciding
nothing changed — but the gate should not depend on that. It now refuses any
answer that is not true or false: a preflight that cannot tell must not be
allowed to say no, which is this pull request's own defect one level up.
And the pattern checker normalized malformed cases into compilable ones. A
scalar accept: became a one-item list and compiled; a string where a mock
belongs was compiled as if it were the mock's pattern. Both pass a checker
that coerces and crash the runner, which calls .each on the first and indexes
the second as a mapping — NoMethodError and TypeError respectively, confirmed
against ruby before the fix. Shape is now checked before content, with a nil
value still allowed because the runner reads these as (c[key] || []).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Ruby in both documented setups, and a dev shell list that is checked
make check now runs check-eval-patterns on every invocation, and bin/ci is
make check. Neither .mise.toml nor the flake's dev shell provided Ruby, so
CONTRIBUTING's "the development shell provides Go and the tools required by
bin/ci" stopped being true the moment that target was added — a contributor
following the documented setup exactly would fail the standard local gate and
read it as their machine being wrong.
Pinned at 3.3 in both, matching the ruby/setup-ruby pins in test.yml, with the
sync comment .mise.toml keeps for every other pin. Verified rather than
assumed: mise install fetches 3.3.12 and the check runs under it.
The flake side could not be verified the same way — there is no nix on this
machine — and it turned out nothing verified it anywhere either, because the
nix job builds packages.default and never looks at the dev shell. A misspelled
attribute in that list lands green and breaks nix develop for whoever follows
CONTRIBUTING, which is this pull request's subject in another file. The job now
evaluates the dev shell derivation, which resolves every attribute in seconds
without building any of them. ruby_3_3 exists at the nixpkgs revision
flake.lock pins, read from that revision directly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
# test.yml is in its own filter so the job proves itself on the PR
268
+
# that introduces or edits it.
249
269
filters: |
250
270
skill:
251
271
- 'skills/basecamp/SKILL.md'
252
272
- 'skills/basecamp-connect/SKILL.md'
253
273
- 'skill-evals/**'
274
+
- '.github/workflows/test.yml'
275
+
276
+
- name: Decide whether the evals can run
277
+
id: decide
278
+
env:
279
+
CHANGED: ${{ steps.filter.outputs.skill }}
280
+
# Presence only, never the value. Fork PRs receive no secrets, so this
281
+
# is false there by construction and the skip below is the honest
282
+
# answer for them too.
283
+
HAS_KEY: ${{ secrets.ANTHROPIC_API_KEY != '' }} # zizmor: ignore[secrets-outside-env] -- a presence test, not the key; adding an environment would block PR-triggered runs
284
+
run: |
285
+
# A preflight that cannot tell must not be allowed to say no. The
286
+
# filter answers true or false; anything else means it did not answer,
287
+
# and treating that as "nothing to run" would rebuild the defect this
288
+
# job exists to remove, one level up (Copilot on #768).
289
+
case "$CHANGED" in
290
+
true|false) ;;
291
+
*)
292
+
echo "::error::the paths filter did not answer (skill='$CHANGED'), so this preflight cannot say whether the evals are needed"
293
+
exit 1
294
+
;;
295
+
esac
296
+
297
+
if [ "$CHANGED" != "true" ]; then
298
+
echo "run=false" >> "$GITHUB_OUTPUT"
299
+
echo "No skill or eval changes on this pull request." >> "$GITHUB_STEP_SUMMARY"
echo "::warning title=Skill Evals did not run::ANTHROPIC_API_KEY is not configured for this repository, so none of the $cases eval cases were run on a pull request that changes them. The Skill Evals job below reports Skipped, not success."
308
+
{
309
+
echo "### Skill Evals: NOT RUN"
310
+
echo
311
+
echo "This pull request changes a skill or its evals, and **$cases eval cases were not run**."
312
+
echo "\`ANTHROPIC_API_KEY\` is not configured for this repository, and fork pull requests never receive secrets."
313
+
echo
314
+
echo "What still covers these files:"
315
+
echo "- \`make check-eval-patterns\` compiles every pattern in every case under Onigmo, the engine the runner uses."
316
+
echo "- \`TestConnectSkillEvalRejectsHoldTheServeValueRule\` holds the \`--serve\` value rule in the connector cases."
317
+
echo
318
+
echo "Neither runs a case. If these evals must gate this repository, configure the secret; until then this job is Skipped rather than green."
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} # zizmor: ignore[secrets-outside-env] -- fork PRs don't receive secrets so untrusted code never sees the key; adding an environment would block PR-triggered runs
265
345
run: |
346
+
# The gate decided the key is there. If it is not, the gate is broken,
347
+
# and that is a failure rather than a quiet exit 0 — the whole point
348
+
# of this job is that it never reports success without running a case.
266
349
if [ -z "$ANTHROPIC_API_KEY" ]; then
267
-
echo "::warning::ANTHROPIC_API_KEY not configured, skipping skill evals"
268
-
exit 0
350
+
echo "::error::the preflight said the evals could run, but ANTHROPIC_API_KEY is empty here"
351
+
exit 1
269
352
fi
270
353
make skill-eval
271
354
@@ -544,3 +627,13 @@ jobs:
544
627
- name: Build the flake
545
628
if: steps.filter.outputs.nix == 'true'
546
629
run: scripts/nix-build-check.sh
630
+
631
+
# `nix build` builds packages.default, so nothing here ever looked at the
632
+
# dev shell's package list — a misspelled attribute in it would land green
633
+
# and break `nix develop` for whoever followed CONTRIBUTING. Evaluating the
634
+
# derivation resolves every attribute without building any of them, which
635
+
# costs seconds and is the difference between a list that is checked and a
636
+
# list that is merely written down.
637
+
- name: Check the dev shell's package list resolves
0 commit comments