Skip to content

ADR-0081: Android validation runs on PRs (and the merge queue when used), not again on main pushes

  • Status: Accepted
  • Date: 2026-11-01

Context

ADR-0041/issue #343 added a push: branches: [main] trigger to android-tests.yml so the default branch re-ran the unit/lint and instrumented suites after merge. That made main a second full-device validation point: every merge requeued the same emulator-heavy suite that the PR run had just executed. When a merge queue is enabled, the merge_group run has also already tested the exact tree being merged. The duplicated main run consumes the shared KVM runner for roughly another instrumented-lane duration while adding no new source coverage; release artifacts already have their own tag-triggered gates. A merge queue is optional, so the policy must not assume it is always present.

Decision

android-tests.yml validates pull requests targeting main and, when a merge queue is enabled, its merge-group entries. It deliberately has no push trigger. The PR-head run is the single required validation for a direct or admin merge that does not pass through a merge queue.

  • The required check names stay Unit Testing & Linting Android App and Instrumented Testing on Emulator, so branch protection keeps waiting on the same jobs.
  • The PR paths-ignore filter stays unchanged (.idea/**, .opencode/**, docs/**, **.md); workflow edits and Android sources still trigger the gates.
  • merge_group remains enabled so a merge queue can wait on the same required checks when it is used; merge-group runs are never cancelled by a later submission, while only superseded pull_request runs are cancelled.
  • Release, build, publish and Play promotion workflows are untouched. Their tag/release checks remain the artifact gate.

A direct push to main that bypasses PR validation therefore does not re-run this suite. That is a technical enforcement limit, not a policy allowance: the policy requires PR validation, and a merge queue is an additional exact-tree check when the repository enables one, not a precondition for every merge. The supporting contract tests fail if the pull_request or merge_group triggers disappear, if push returns, or if the required check names change.

Consequences

A tree is device-tested on its PR once. When a merge queue is configured, its run adds validation of the exact landing tree instead of a duplicate main-push run; without a merge queue, the PR-head result is the accepted evidence for a direct/admin merge. Contributors must not rely on a post-merge main run to catch a regression; local full-gate requirements and the PR checks are the contract. Workflow-only PRs still validate the configuration they change because .github/** is not ignored.

Verification

scripts/test-workflow-paths.sh asserts the PR filter, required names, merge_group, and the absence of push. scripts/test-ci-hygiene.sh asserts the same trigger shape alongside its timeout and coverage wiring. Both run in the docs-guard workflow. Release/build workflow contracts (test-ci-smoke-matrix.sh, test-build-artifacts-version.sh, test-play-release-workflow.sh) continue to pin their unchanged gates.