diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f7654e96..c511f5ac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 diff --git a/.github/workflows/run_integration.yml b/.github/workflows/run_integration.yml index a6ffcfa3..15154d4e 100644 --- a/.github/workflows/run_integration.yml +++ b/.github/workflows/run_integration.yml @@ -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 cancel-in-progress: false env: diff --git a/.github/workflows/scheduled_test.yml b/.github/workflows/scheduled_test.yml index 5f7ba0e3..3a589382 100644 --- a/.github/workflows/scheduled_test.yml +++ b/.github/workflows/scheduled_test.yml @@ -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 @@ -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 diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 8544dcd0..aa40b09c 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -44,7 +44,7 @@ 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 @@ -52,9 +52,9 @@ way. A fork PR gets no secrets and still goes green, and a live test added witho 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.