name: UI Tests (Full 14 Shards via Label) # Triggered by adding the `test:ui-full-shards` label to a PR. # Calls docker-tests.yml with strict-mode=true so the sharded ui-tests # matrix runs — it's otherwise gated on strict-mode and only fires at # release time. # # NOTE on duplicated work: docker-tests.yml in strict mode runs its FULL # job graph (image build, pytest, infra, etc.), so triggering this label # re-runs everything that the normal PR docker-tests already ran. That's # acceptable cost for a deliberate opt-in trigger; cheaper than refactoring # docker-tests.yml to expose just ui-tests as a standalone reusable workflow. on: pull_request: types: [labeled] # Manual fallback — useful for one-off maintainer runs and for smoke-testing # the wrapper when label-triggered workflows can't fire (e.g. on the PR that # first introduces this file, before it lands on main). workflow_dispatch: # No concurrency group — intentionally omitted, matching docker-tests.yml. # See its top-level comment for the rationale (#3554 / #3599). permissions: {} # Minimal top-level for OSSF Scorecard Token-Permissions jobs: full-shards: name: Full UI Shards # Fire on the label add, OR on any manual dispatch (maintainer override). if: >- github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.label.name == 'test:ui-full-shards') uses: ./.github/workflows/docker-tests.yml with: strict-mode: true permissions: # MUST match the scopes docker-tests.yml's jobs DECLARE, not just the # ones whose steps run. Reusable-workflow permission validation is # compile-time: a called job that declares `contents: write` (the # pytest/gh-pages job) fails the whole run at startup with # "requesting 'contents: write', but is only allowed 'contents: none'" # if the caller grants less — producing a 0-job startup_failure with # no logs. #4209 dropped contents:write here for OSSF Scorecard, which # silently broke this wrapper on every run since (the gh-pages STEP is # runtime-gated to push@main, but the JOB still declares the scope). # ci-gate.yml grants the same pair, which is why it works. contents: write # docker-tests jobs checkout + declare gh-pages deploy scope pull-requests: write # docker-tests pytest job posts PR comments secrets: OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}