Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,6 @@ jobs:
if: needs.detect.outputs.ready == 'true'
uses: ./.github/workflows/run_tests.yml

# Deliberately absent from `release`'s `needs`. A failure here would skip tagging while
# the Release PR is already merged carrying `autorelease: pending`, so every later push
# would stand down and releases would stay wedged until someone cleared it by hand.
test-integration:
name: Test (integration)
needs: detect
if: needs.detect.outputs.ready == 'true'
uses: ./.github/workflows/run_integration.yml
secrets: inherit

# Irreversible half.
release:
name: 🚀 Tag and release
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/run_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ on:
workflow_call:
secrets: { }

# A constant, not `github.workflow`, which inside a reusable workflow resolves to the
# caller's name: the daily run and the pre-tag run would land in separate lanes and hit the
# shared app at once. Queue rather than cancel, so the schedule cannot kill a release gate.
concurrency:
group: run-integration-${{ github.ref }}
# Repository-wide, on purpose. The contended resource is the Stream app, not the branch,
# so keying on github.ref would let a *.x release run beside the daily run on the default
# branch. Not cancel-in-progress: a half-run leaves users and channels behind.
group: run-integration
Comment thread
mogita marked this conversation as resolved.
cancel-in-progress: false

env:
Expand Down
16 changes: 13 additions & 3 deletions .github/workflows/scheduled_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ jobs:
secrets: inherit

# A failure here lands on no PR, and GitHub emails it only to whoever last edited the cron.
# A schedule event carries no repository in its payload, so it passes by event name; it
# always runs on the default branch anyway.
report:
name: Report a red run
needs: integration
if: failure()
# Not failure(): a job that hits timeout-minutes concludes `cancelled`, and a hung run
# must report too. Default branch only: a manual dispatch on a feature branch must not
# touch the default branch's issue.
if: ${{ !cancelled() && needs.integration.result != 'success' && (github.event_name == 'schedule' || github.ref_name == github.event.repository.default_branch) }}
runs-on: ubuntu-latest
permissions:
issues: write
Expand All @@ -28,8 +33,13 @@ jobs:
TITLE: Daily integration run is red
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
num="$(gh issue list --repo "$GITHUB_REPOSITORY" --state open --search "in:title \"$TITLE\"" \
--json number,title --jq "map(select(.title == \"$TITLE\")) | .[0].number // empty")"
# Unguarded, a non-2xx would abort the step under `bash -e` and a red run would
# report nothing at all. Fail toward creating the issue, which is the loud way.
if ! num="$(gh issue list --repo "$GITHUB_REPOSITORY" --state open --search "in:title \"$TITLE\"" \
--json number,title --jq "map(select(.title == \"$TITLE\")) | .[0].number // empty")"; then
echo "::warning::Could not list open issues; creating a new one."
num=""
fi
if [ -n "$num" ]; then
gh issue comment "$num" --repo "$GITHUB_REPOSITORY" --body "Still red: $RUN_URL"
else
Expand Down
8 changes: 4 additions & 4 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,17 @@ make test-prometheus # requires getstream[telemetry] deps
| --- | --- | --- |
| Pull request | `run_tests.yml`: ruff, ty, and `-m "not integration"` on five Python versions | yes, `🧪 Tests` is the required check |
| Daily at 09:00 UTC | `run_integration.yml`: `-m integration`, both credential sets | no |
| Push to `main` with a release pending | both; only the unit lane gates the tag | unit yes, integration no |
| Push to `main` with a release pending | the unit lane | yes, it gates the tag |

`@pytest.mark.integration` means one thing: the test talks to a live Stream app. The unit
lane therefore runs with no credentials, no `environment:` and no `STREAM_*`. Keep it that
way. A fork PR gets no secrets and still goes green, and a live test added without the
marker fails in CI instead of quietly passing on someone else's credentials.

Integration gates nothing, anywhere. It runs against an app five SDK repos share, so
another repo's run or a backend regression can redden it with nothing wrong here, and a red
pre-tag run used to wedge every later release behind `autorelease: pending`. A red daily run
opens an issue titled "Daily integration run is red". Fix it, do not route around it.
another repo's run or a backend regression can redden it with nothing wrong here. It does not
run before a tag either. A red daily run opens an issue titled "Daily integration run is
red". Fix it, do not route around it.

A Release PR skips the lane and `🧪 Tests` passes in seconds on a `skipped` result. The
merge commit still runs it before the tag.
Expand Down
Loading