Skip to content

ci: skip the whole test job on Release PRs, not just its steps - #166

Merged
mogita merged 5 commits into
mainfrom
fix/cha-5511-go-job-level-skip
Sep 17, 2026
Merged

mogita merged 5 commits into
mainfrom
fix/cha-5511-go-job-level-skip

Conversation

@mogita

@mogita mogita commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Ticket

CHA-5511

Problem

Two things, the second found in review.

1. #165 had to guard this repo at step level, unlike the other five SDKs. main required the six matrix legs of test-build by name, and a job-level if: is evaluated before the matrix expands:

context "matrix" is not allowed here. available contexts are "github", "inputs", "needs", "vars"

so skipping the job would have produced one check run instead of six, leaving those required contexts permanently absent and the Release PR blocked. The job therefore still spun up six runners on every Release PR to check out the repo and do nothing. Those six contexts have since been removed from branch protection; main now requires only 👮 Conventional PR title.

2. The guard included github.actor == 'github-actions[bot]', which made it miss the documented release path. CONTRIBUTING.md:54:

If the PR is behind main, clicking Update branch also releases them, because that commit is attributed to you

With strict: true, a Release PR behind main must be updated before it can merge, and that merge commit is attributed to whoever clicked, so github.actor is a human and the suite ran in full. Confirmed on #163: 8c31d76 is exactly that merge commit, its run had actor=mogita, and the 1.19 integration leg took 3m51s.

Solution

Move the guard from the three steps to the job, and drop the github.actor clause:

if: >-
  ${{ contains(github.event.pull_request.labels.*.name, 'run-tests')
  || !(github.event.pull_request.user.login == 'github-actions[bot]'
  && github.event.pull_request.head.repo.full_name == github.repository
  && startsWith(github.head_ref, 'release-please--')) }}

The three remaining clauses cannot be forged: a PR author cannot be set to github-actions[bot], and the head repository must be this one, so the branch name is never trusted alone. The skip now fires on both Update branch and Approve and run.

A run-tests label forces the suite. This is not a convenience: with github.actor gone, neither a push nor Update branch changes the PR author or the branch name, and a re-run keeps the original actor, so the label is the only way to run the suite on a Release PR at all.

The hatch lives in its own workflow, label_tests.yml, rather than as a labeled trigger on build. types: cannot filter by label name, so every label would start a build run in which ci skips itself, tests-passed reads skipped and exits 0, and 👷 Tests is republished green on a SHA whose tests had failed. Keeping label events out of build is what prevents that.

Restoring the test gate

Stripping the six matrix contexts to unblock Release PRs also left main requiring only 👮 Conventional PR title, so any feature PR could merge with a red suite. tests-passed is one non-matrix context that fails unless ci reported success or skipped, so requiring it gates feature PRs while still letting a Release PR through.

Settings change needed after this merges: add 👷 Tests to required_status_checks on main. The context does not exist until the first run lands.

Corrections carried in this PR

  • The claim that lint.yml and reviewdog.yml compile version.go was wrong, and is removed. lint.yml runs only go mod tidy. reviewdog.yml pipes golangci-lint into reviewdog under bash -e with no pipefail, so the job takes reviewdog's status and its default -fail-level=none exits 0. The real compile checks are CodeQL's Analyze (go) and release.yml's pre-tag tests job. Both workflows still run on Release PRs, because neither touches the shared app and both finish inside CodeQL's window.
  • The note explaining that a job-level if: precedes matrix expansion is restored. It is the only record of why re-adding the six required contexts would block every Release PR forever.

Known trade

The flaky leg is relocated, not removed. release.yml's tests job calls this same workflow on the merge commit, so a flake now fires after the Release PR has merged, leaving autorelease: pending set and needing a manual re-run. Documented in CONTRIBUTING.md. The better fix is porting scheduled_test.yml's for _ in 1 2 3; do go test ... && break retry into run_tests.yml, which helps every PR rather than exempting one shape; that is a separate change.

How to verify

  1. This PR is not a Release PR, so all six legs should run as usual.
  2. On the next Release PR, build should report Skipped on either release path, while Lint, reviewdog and CodeQL run normally.
  3. Adding the run-tests label to a Release PR should bring the six legs back.

main required the six matrix legs of test-build by name, and a job-level
`if:` is evaluated before the matrix expands, so skipping the job would have
produced one check run instead of six and left those required contexts
permanently absent. The guard therefore sat on the steps, and the job still
spun up six runners to check out the repo and do nothing.

Those six contexts have been removed from branch protection, so the job can
now skip outright and this repo uses the same rule as the other five SDKs.

lint.yml and reviewdog.yml stay unguarded: golangci-lint compiles the
package, so they are the only check on release-please's rewrite of version.go.
@mogita
mogita requested a review from tbarbugli as a code owner September 17, 2026 16:08
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:08 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:08 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:08 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:08 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:08 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:08 — with GitHub Actions Active
Comment thread .github/workflows/run_tests.yml Outdated
Comment thread .github/workflows/run_tests.yml Outdated
Comment thread .github/workflows/run_tests.yml Outdated
Comment thread .github/workflows/run_tests.yml
Comment thread .github/workflows/run_tests.yml
@mogita

mogita commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Two findings that sit outside the diff.

Branch protection now gates nothing. required_status_checks.contexts on main is exactly ["👮 Conventional PR title"]. 👮 Lint, 🐶 Reviewdog, CodeQL and all six ci / 👷 Test & Build legs are advisory, so any ordinary feature PR can merge with a red suite once it has one code-owner approval. Unblocking Release PRs by stripping the matrix contexts removed the test gate for every PR, not just Release PRs.

An aggregating job keeps both properties: add one job to ci.yml with needs: [ci], if: always(), failing unless needs.ci.result is success or skipped; require only that context and leave the matrix legs non-required. A skipped job satisfies a required check, so the Release-PR skip still works.

CONTRIBUTING.md is not updated. Line 54 presents Update branch and Approve and run as interchangeable ways to release the held checks. After this PR they differ by roughly 20 minutes and by whether the suite runs at all: Approve and run gives one skipped build check, Update branch gives a full six-leg run including the shared-app integration leg. Line 87's major-release recipe ("Click Update branch on the major Release PR, then merge it") always takes the expensive path.

The github.actor clause made the skip miss the path CONTRIBUTING tells
maintainers to take. With strict: true the Release PR has to be brought up to
date whenever main moves, and Update branch attributes that merge commit to
the person who clicked, so github.actor is a human and the guard fell through
to running the full suite. Verified on #163: 8c31d76 is exactly that merge,
and its run had actor=mogita and spent 3m51s on the 1.19 integration leg.

Dropping the clause fires the skip on both Update branch and Approve and run.
The remaining three clauses still cannot be forged: a PR author cannot be set
to github-actions[bot], and the head repository must be this one.

The cost is that a human commit pushed onto a Release PR is no longer tested
here. release.yml calls this same workflow against the merge commit before it
tags, which is what actually gates the release, and a `run-tests` label now
forces the suite on any Release PR, since a re-run keeps the original actor
and neither workflow has a dispatch trigger.

Also corrects two comments. The claim that lint.yml and reviewdog.yml compile
version.go was wrong on both counts: lint.yml only runs `go mod tidy`, and
reviewdog.yml pipes golangci-lint into reviewdog under `bash -e` without
pipefail, so the job takes reviewdog's exit status and its default
-fail-level=none returns 0. And the note that a job-level `if:` is evaluated
before the matrix expands is restored, because it is the only record of why
re-adding the six required contexts would block every Release PR forever.
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:42 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:42 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:42 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:42 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:42 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 16:42 — with GitHub Actions Active
Comment thread .github/workflows/run_tests.yml
The label was wired into run_tests.yml but nothing triggered on it. ci.yml is
`on: pull_request` with no `types:`, and the default activity types are
opened, synchronize and reopened, so applying the label started no run and
the escape hatch did nothing. That matters more than it sounds: with the
github.actor clause gone, neither a push nor Update branch forces the suite
either, so the label is the only way to run it on a Release PR.

Adds `labeled` to the trigger, and an `if:` on the caller job so only
`run-tests` counts. Without that guard every label would fire the six-leg
suite against the shared Stream app, including release-please stamping
`autorelease: pending`.

Also drops a comment in ci.yml claiming main requires the matrix checks by
name, which stopped being true when those six contexts were removed.
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 18:05 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 18:05 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 18:05 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 18:05 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 18:05 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 18:05 — with GitHub Actions Active
Comment thread .github/workflows/ci.yml Outdated
…gate

Two consequences of earlier changes in this PR.

Adding `labeled` to the trigger gave every label the power to cancel a
running suite. A labeled event lands in the same concurrency group as the
synchronize it may be racing, and concurrency is resolved when the run is
queued, before the ci job's `if:` is evaluated, so a skipped job never
releases the slot. Adding `bug` to a PR mid-run cancelled it and replaced it
with a run whose only job skips. cancel-in-progress now excludes labeled
events; a push still cancels an older run.

Removing the six matrix contexts from branch protection to unblock Release
PRs also removed the test gate from every ordinary PR: main requires only the
PR-title check, so a feature PR can merge with a red suite. tests-passed
restores it with one non-matrix context that reports whether the job ran or
skipped, so requiring it gates feature PRs without blocking Release PRs.

Requiring `👷 Tests` on main is a settings change, not part of this commit.
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:07 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:07 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:07 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:07 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:07 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:07 — with GitHub Actions Active
@mogita

mogita commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Handled the first, and the second is now stale. Sorry for the slow reply, I worked the inline threads and did not see this one until now.

Branch protection. Valid, and it is the cost I named when recommending the change without proposing a replacement. Added your aggregating job:

  tests-passed:
    name: 👷 Tests
    needs: ci
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Check the test job
        env:
          RESULT: ${{ needs.ci.result }}
        run: |
          case "$RESULT" in
            success|skipped) echo "test job: $RESULT" ;;
            *) echo "::error::test job reported $RESULT"; exit 1 ;;
          esac

Not a matrix, so it reports on a Release PR too, where needs.ci.result is skipped and it passes. Requiring 👷 Tests on main gates feature PRs again without blocking Release PRs. That is a settings change, not part of the diff: it has to be added after this merges, or the context will not exist yet.

CONTRIBUTING. This was written against the diff before dea50ce. Dropping the github.actor clause removed the asymmetry you describe: the guard now reads the PR author, the head repository and the branch name, and Update branch changes none of them, so both paths give one skipped build check. Line 87's major-release recipe no longer takes the expensive path either.

CONTRIBUTING.md is updated in this PR regardless, with a bullet stating that the suite does not run on a Release PR whichever path you take, that the run-tests label forces it, and that release.yml runs the suite on the merge commit before tagging with manual recovery if it fails.

Comment thread .github/workflows/ci.yml
…gate

Triggering build on `labeled` let any label turn a red gate green. types:
cannot filter by label name, so every label started a build run; ci skipped
itself, tests-passed ran under always(), read needs.ci.result as skipped and
exited 0, republishing 👷 Tests as green on a SHA whose tests had failed.
Branch protection reads the latest check run for a context, so the red one no
longer counted. Giving tests-passed the same label guard would not help: a
job skipped by `if:` still posts a check run with conclusion skipped, which
branch protection also treats as satisfied.

The hatch moves to its own workflow. No label event reaches build any more,
so nothing but a real build run can publish 👷 Tests, and the cancellation
fix from the previous commit is no longer needed: types:, the ci guard and
the cancel-in-progress expression all revert.

Job id `forced` keeps the forced run's check names off `ci / …`, so they
cannot stand in for build's own.
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:32 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:32 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:32 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:32 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:32 — with GitHub Actions Active
@mogita
mogita deployed to feeds-enabled-shard September 17, 2026 19:32 — with GitHub Actions Active
@mogita
mogita merged commit 2c45ee3 into main Sep 17, 2026
14 checks passed
@mogita
mogita deleted the fix/cha-5511-go-job-level-skip branch September 17, 2026 19:35

This branch was successfully deployed

1 active deployment
feeds-enabled-shard — ddf9a25a Deployed Sep 17, 2026 by mogita via ci / 👷 Test & Build 1.20 #550
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant