ci: gate PRs on unit tests only and move integration to a daily run - #292
Conversation
A pull request is now gated on one required check, 🧪 Tests, which covers ruff, ty and the unit suite on five Python versions. The integration marker no longer reaches ci.yml at all: it runs in the new scheduled_test.yml every day at 09:00 UTC and in release.yml before a tag, exactly as the CI/CD spec asks. Integration is advisory because it runs against a live Stream app that five SDK repos share, so another repo's run or a backend regression can redden it with nothing wrong in this one. Letting that block a merge is what the spec set out to avoid. The Release PR skip guard drops its github.actor clause. github.actor is the pusher, and clicking Update branch attributes the merge commit to whoever clicked, so keying on it stopped the skip firing on the normal release path. 🧪 Tests is a single job with no matrix, so it always publishes under that exact name. A matrix job skipped by `if:` publishes one check run with the template unexpanded, which is why the per-leg names could never work as required contexts.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (25)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe pull request separates unit-test merge gating from integration testing. It marks live-app tests, adds a reusable integration workflow, schedules daily integration runs, and keeps Release PR tagging dependent only on unit tests. ChangesCI test flow
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Bug fix · Severity of issue fixed: Medium Sequence Diagram(s)sequenceDiagram
participant PullRequest
participant CI
participant run_tests
participant tests-passed
PullRequest->>CI: trigger pull request checks
CI->>run_tests: run unit checks without credentials
run_tests->>tests-passed: provide unit result
tests-passed->>PullRequest: publish Tests status
sequenceDiagram
participant Scheduler
participant scheduled_test
participant run_integration
participant GitHubIssues
Scheduler->>scheduled_test: trigger daily or manual run
scheduled_test->>run_integration: invoke credentialed integration tests
run_integration->>scheduled_test: return integration result
scheduled_test->>GitHubIssues: report a failed run
Merge Risk: ⚪ Minimal · up to The separated unit and integration workflows have no identified actionable merge risk. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 56.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 19 files. (6 skipped: 6 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review found the daily run green without executing a test. Every
@pytest.mark.integration in the repo is under tests/rtc or in a *_manual.py file,
and `make test` ignores both, so `make test MARKER="integration"` collected nothing
and the Makefile turned pytest's exit 5 into success. Measured on this tree:
no tests collected (686 deselected) in 2.06s
run_integration.yml now carries the video leg alone, which does collect, and
run_tests.yml drops the marker input and is the unit lane only.
Other review fixes:
- The aggregator accepts `skipped` only when the Release PR condition actually
holds, so a guard typo or a stray path filter fails the check instead of
publishing it green with nothing run.
- `if: always()` becomes `!cancelled()`. A cancelled run left `🧪 Tests` red on
that SHA with only a re-run to clear it.
- The Release PR guard moves to ci.yml's calling job. Four copies existed because
a reusable workflow that is never called publishes no check, and the aggregator
removed that constraint; it also kept pull_request expressions alive in the
schedule and release callers, where they are dead weight.
- run_integration.yml keys its concurrency group on a constant rather than
github.workflow, which inside a reusable workflow is the caller's name. The
daily run and the pre-tag run both target main and would otherwise hit the
shared app at once. cancel-in-progress is false so the schedule cannot cancel
the gate a release is waiting on.
- The daily run opens or updates an issue when it fails. GitHub emails a
scheduled failure only to whoever last edited the cron line.
- ruff and ty no longer run in the daily job, so a lint failure on main cannot
redden an integration signal.
- DEVELOPMENT.md: `🧪 Tests` reports success on a Release PR, not skipped, and the
`integration` marker means WebRTC here, not "talks to the API".
Review showed the marker did not mean what the CI design assumed. All nine
@pytest.mark.integration in the repo were under tests/rtc or in a *_manual.py
file, so it selected WebRTC, while the chat and feeds suites hit the live app
carrying no marker at all. The pull-request gate was a live-app gate.
Now the marker means one thing: the test talks to a live Stream app. 17 modules
get a module-level pytestmark, and the two mixed modules get per-test marks. The
counts, measured with an empty .env, no STREAM_* variables set and the base URL
unreachable:
make test 476 passed, 1 skipped, 209 deselected
make test-video 312 passed, 1 skipped, 94 deselected
788 tests still run on a pull request and none of them opens a socket. The
non-video integration leg now collects 209 tests where it collected none.
Because the unit lane needs no credentials, run_tests.yml drops `environment: ci`
and every STREAM_* variable, and its callers stop passing secrets. That is
load-bearing twice: a fork PR, which gets no secrets, still goes green, and a
live test added without the marker fails loudly instead of quietly passing on
someone else's credentials.
test_from_env now sets the variables it reads through monkeypatch and asserts the
key lands, rather than depending on whatever the environment happens to hold.
release.yml drops test-integration from the release job's needs. A flaky
shared-app failure there would skip tagging while the Release PR was already
merged with autorelease: pending, so every later push would find a pending
release at a different sha and stand down, wedging releases until someone re-ran
one run or stripped the label by hand. The unit lane still gates the tag.
98 comment lines in the diff for 194 of code. The same two sentences sat above all 17 module-level pytestmarks, and "the app five SDK repos share" was explained in three workflows and again in DEVELOPMENT.md. Kept the five facts that cost time to learn and that someone would otherwise undo: the unit lane has no credentials on purpose, a matrix job skipped by `if:` publishes one check with the template unexpanded, github.actor is absent because Update branch reattributes the commit, github.workflow inside a reusable workflow is the caller's name, and test-integration is deliberately out of release's needs. Everything else now lives once, in DEVELOPMENT.md. Down to 25 comment lines. No behaviour change: lint, format and the offline lane re-verified.
Ticket
CHA-5511
Problem
mainhasstrict: truewith an empty required-checks list, so it forces the branch up to date and then requires nothing to be green.github.actor, which is the pusher, and clicking Update branch attributes that merge commit to whoever clicked.@pytest.mark.integrationdid not mean what the CI assumed. All nine of them were undertests/rtc/or in a*_manual.pyfile, so the marker selected WebRTC, while the chat and feeds suites hit the live app carrying no marker. The pull-request gate was a live-app gate.make test MARKER="integration"collected nothing and the Makefile turned pytest's exit 5 into success, so the non-video integration leg of the pre-tag gate had been passing without running a test.Solution
The marker now means one thing: this test talks to a live Stream app.
pytestmark, two mixed modules get per-test marks.run_tests.ymlis the unit lane and runs with no credentials: noenvironment:, noSTREAM_*, and its callers pass no secrets. A fork PR goes green, and a live test added without the marker fails loudly instead of quietly passing on someone else's credentials.run_integration.ymlis new and is the only place-m integrationruns, on both credential sets.ci.ymladdstests-passed, named🧪 Tests. No matrix, so it always publishes under that exact name: a matrix job skipped byif:publishes a single check run with the template unexpanded. It acceptsskippedonly when the Release PR condition actually holds, so a guard typo cannot publish it green with nothing run.scheduled_test.ymlis new: the integration lane daily at 09:00 UTC plusworkflow_dispatch, and a job that opens or updates an issue when it fails.release.ymldropstest-integrationfrom the release job'sneeds. A flaky failure there skipped tagging while the Release PR was already merged withautorelease: pending, so every later push found a pending release at a different sha and stood down. The unit lane still gates the tag.github.actorand moves toci.yml's calling job, one copy instead of four.Integration now gates nothing, anywhere. It runs against the app
d2sj6pudbhz7that five SDK repos share, so another repo's run or a backend regression reddens it with nothing wrong here.How to verify
Measured locally with an empty
.env, everySTREAM_*variable unset and no network reachable:788 tests still run on a pull request and none of them opens a socket. The non-video integration leg collects 209 tests where it collected
no tests collected (686 deselected)before.make lint && make typecheckboth pass.actionlint .github/workflows/*.yml. Two warnings aboutsecrets.STREAM_*_API_SECRETremain inrun_integration.yml, where those secrets really do come from thecienvironment;run_tests.ymlis clean now.🧪 Testspasses in seconds on askippedunit result, including after Update branch.gh workflow run "Scheduled tests" --repo GetStream/stream-pyruns the integration lane on demand.Review instructions
After this merges,
🧪 Testshas to be added to the required-checks list onmain, which is empty today. Until then the check runs but gates nothing, so land and edit in the same sitting.Summary by CodeRabbit
New Features
Bug Fixes
Documentation