Run the tests on pull requests - #11
Merged
Merged
Conversation
greenido
added this pull request to stack #12
September 25, 2026 15:03
greenido
force-pushed
the
ci/test-on-pull-requests
branch
from
September 25, 2026 15:03
a6e7550 to
7026783
Compare
Nothing did. deploy.yml triggers only on a push to main, so a PR's checks were a secrets scan and nothing else: a regression was found by the deploy that followed the merge, not by the PR that caused it. ci.yml runs lint, typecheck, test and build on every pull request. Each step runs even when an earlier one fails, so one push surfaces every problem rather than the first, with an explicit gate at the end so the job cannot go green with a red step. Pushes to main stay covered by deploy.yml, which now also typechecks. Both workflows read the Node version from .nvmrc instead of hardcoding a major. Two things had to change for that to be worth much. The suites were chained in package.json with `&&`, so the first failure hid every suite after it -- a round trip through CI per broken suite. scripts/run-tests.js runs all of them and lists the results. And each suite had to be registered by hand, which is easy to forget: tests/new-features.test.ts and tests/weather-api.test.ts never were, and had gone unrun for their whole existence. Suites are now discovered from tests/, so a file is picked up by existing. Ones that reach the network mark themselves `@network` and are excluded from `yarn test`, since CI must not fail because NOAA is having a morning. Running those two for the first time found weather-api.test.ts could not compile at all: it guarded its entry point with `import.meta.url`, which is invalid under the CommonJS module setting the test config uses. Fixed to `require.main === module`; all three network suites now pass. Nine per-suite scripts collapse into `yarn test <name>`, which filters by substring. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
greenido
force-pushed
the
ci/test-on-pull-requests
branch
from
September 25, 2026 15:04
7026783 to
6462368
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gap
deploy.ymltriggers only onpush: branches: [main]. So a pull request's checks were a GitGuardian secrets scan and nothing else — a regression was caught by the deploy after the merge, not by the PR that introduced it. Both PRs in this stack show exactly one check.ci.ymlnow runs lint, typecheck, test and build on everypull_request. Each step runs even when an earlier one fails (if: !cancelled()), so one push surfaces every problem instead of just the first, with an explicit gate at the end so the job can't go green with a red step. Pushes tomainstay covered bydeploy.yml, which now also typechecks — splitting them means no commit gets tested twice.Both workflows read the Node version from
.nvmrcrather than hardcoding'22', which had already drifted from the pinned22.13.0.Two things that made CI worth less than it looked
The suites were chained with
&&. The first failure hid the other eight — one round trip through CI per broken suite.scripts/run-tests.jsruns all of them and prints a summary:Verified with throwaway probes named so the passing one sorts after the failing one — it ran, and the job still exited 1.
Each suite had to be registered by hand. Easy to forget, and two never were:
tests/new-features.test.tsandtests/weather-api.test.tshad gone unrun for their entire existence. Suites are now discovered fromtests/, so a*.test.tsfile is picked up by existing. Network-hitting suites declare themselves with an@networkmarker in their header and are excluded fromyarn test— CI must not go red because NOAA is having a morning.What running those two for the first time found
weather-api.test.tscould not compile at all:It guarded its entry point with
import.meta.url === \file://${process.argv[1]}`, which is invalid under the CommonJS module settingtsconfig.test.jsonuses. Note this passedyarn typecheck, because the app'stsconfig.jsonsetsmodule: esnext— it only broke when actually executed. Fixed torequire.main === module`.All three network suites now pass:
new-features,providers,weather-api(4 tests).Script changes
Nine near-identical
test:*entries collapse into one filtered entry point:README updated for all of it.
Verification
yarn lint,yarn typecheck,yarn test(9 suites, 176 assertions),yarn test:network(3 suites) andyarn buildall pass locally. Exit codes confirmed in both directions: 1 with a failing suite, 0 without.This PR validates itself — being a
pull_request,ci.ymlruns against its own branch, so the checks on this PR are the new workflow.Note
ci.ymlusespull_request, notpull_request_target, so a fork's PR runs with a read-only token and no secrets. That's the right default here; it does mean a first-time contributor's run may need approval under your repo settings.🤖 Generated with Claude Code