chore: bump kmp-toolkit to 00b8e0f #506
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Screenshots | |
| # Self-maintaining Roborazzi baselines. | |
| # | |
| # Why this exists: pixel-exact baselines only match the environment they were recorded in. Recording them | |
| # by hand on a laptop guarantees they drift from CI's Linux renderer (font antialiasing), which is what kept | |
| # reding the old "verify" job. Instead, CI records the baselines *itself* and proposes them back | |
| # (as a PR, since main requires the Quality Gate check), so: | |
| # - a NEW screen automatically gets a baseline the first time it runs here, | |
| # - a CHANGED screen self-heals (the new rendering is captured), | |
| # - CI never fails for rendering reasons unrelated to code. | |
| # | |
| # CI's runner image renders deterministically run-to-run, so re-recording an unchanged screen produces a | |
| # byte-identical PNG -> git sees no change -> no commit. Only genuinely new/changed screens get committed. | |
| # | |
| # On a PR the baselines are uploaded as an artifact for review instead of committed. | |
| on: | |
| push: | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| workflow_dispatch: # manual "refresh all baselines now" button in the Actions tab | |
| concurrency: | |
| group: screenshots-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: write # allows the bot to push a refresh branch | |
| pull-requests: write # allows the bot to open the baseline-refresh PR | |
| jobs: | |
| record: | |
| name: Record & commit baselines | |
| runs-on: ubuntu-latest | |
| env: | |
| GRADLE_OPTS: "-Dorg.gradle.daemon=false" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| # versionCode derives from `git rev-list --count HEAD`. A shallow clone | |
| # reports 1, which silently produced versionCode 2 on every published APK. | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v6 | |
| with: | |
| java-version: '25' | |
| distribution: 'temurin' | |
| - name: Setup Gradle | |
| uses: gradle/actions/setup-gradle@v6 | |
| with: | |
| cache-read-only: ${{ github.event_name == 'pull_request' }} | |
| cache-cleanup: on-success | |
| - name: Grant execute permission for gradlew | |
| run: chmod +x ./gradlew | |
| # noGms variant: gms Play Services maps crash the Robolectric fork. | |
| - name: Record screenshots (regenerate baselines in the CI environment) | |
| run: ./scripts/run-jvm-tests.sh recordRoborazziNoGmsDebug | |
| # recordRoborazziNoGmsDebug excludes com.mileway.Screenshot*Test (app/build.gradle.kts's | |
| # screenshotTestFilter — isolated into its own forked JVM, Z.5b) — that gallery was never | |
| # gated by CI at all, which is how ScreenshotGalleryTest's Konnection/TripDraftOutbox crashes | |
| # went unnoticed. This step is the actual gate: a real crash/error here fails the job before | |
| # the baseline-refresh PR step below runs. ScreenshotGalleryTest force-records its own PNGs | |
| # into docs/screenshots (see its class doc), so any change it makes is picked up by the | |
| # existing "git add docs/screenshots" step next. | |
| - name: Run screenshot gallery + catalog tests (crash/regression gate) | |
| # This job RECORDS — the next step git-adds docs/screenshots and opens a refresh PR when | |
| # they drift. Without this env var the tests take the compare path instead, write nothing, | |
| # and fail against baselines the job was supposed to be producing. It has to be an env var, | |
| # not a -P property: a Gradle property does not reach a forked test JVM, which is the same | |
| # trap that left the whole capture pipeline silently no-op'ing for weeks. | |
| env: | |
| ROBORAZZI_RECORD: 'true' | |
| run: ./scripts/run-jvm-tests.sh :app:screenshotTestNoGmsDebug | |
| # main: baselines drifted. main is protected by the "Quality Gate required" ruleset, so the bot | |
| # can't push straight to it — open a refresh PR instead (idempotent branch name per source SHA; | |
| # re-runs force-push the same branch and reuse the open PR). | |
| # | |
| # KNOWN FRICTION — these PRs need a human click before they can merge. | |
| # A PR opened with ${{ github.token }} does get `pull_request` workflow runs, but GitHub parks | |
| # every one of them at `action_required` (the workflow-approval gate that exists to stop | |
| # Actions from recursively triggering Actions). Until someone approves, the PR's | |
| # statusCheckRollup is empty, so it can't satisfy the "Quality Gate required on main" ruleset | |
| # and it sits BLOCKED. That is how 7 of these branches accumulated. | |
| # Approve from the PR's Checks tab, or: | |
| # gh api -X POST repos/$GITHUB_REPOSITORY/actions/runs/<run-id>/approve | |
| # Verified 2026-07-26: branch -b21f02a has 5 pull_request runs, all `action_required`; | |
| # branch -7032123 has the same 5 runs `success` (they were approved) and its PR merged. | |
| # | |
| # To remove the friction entirely, the PR must be created by a non-Actions identity — a | |
| # fine-grained PAT or a GitHub App token in place of ${{ github.token }} below. A push | |
| # trigger on the bot branch does NOT work: that push is itself GITHUB_TOKEN-generated and | |
| # fires nothing (no bot branch has ever had a push-event run). | |
| - name: Open baseline-refresh PR | |
| if: github.event_name == 'push' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add docs/screenshots | |
| if git diff --cached --quiet; then | |
| echo "Baselines already up to date — nothing to commit." | |
| exit 0 | |
| fi | |
| # Stable branch name, NOT per-SHA: the push below is a force-push, so one branch | |
| # and one open PR get reused for every refresh. A ${GITHUB_SHA}-suffixed branch | |
| # opened a fresh PR per commit to main, and they stacked up conflicting on the | |
| # same PNGs (7 open at once in Kursi, 2 in Mileway on 2026-08-27). | |
| branch="bot/refresh-screenshot-baselines" | |
| git checkout -b "$branch" | |
| git commit -m "chore(screenshots): refresh baselines for ${GITHUB_SHA::7}" | |
| git push --force origin "$branch" | |
| if ! gh pr list --head "$branch" --state open --json number --jq '.[0].number' | grep -q .; then | |
| # PR creation needs Settings→Actions→"Allow GitHub Actions to create and approve pull | |
| # requests". If that's off, don't fail the pipeline — the refresh branch is already | |
| # pushed above; warn with the branch so a human can open the PR (or enable the setting). | |
| gh pr create --base main --head "$branch" \ | |
| --title "chore(screenshots): refresh render-harness baselines" \ | |
| --body "Automated Roborazzi baseline refresh — screens changed on main and CI re-recorded them. Review the PNG diffs and merge." \ | |
| || echo "::warning::Could not auto-open the baseline-refresh PR (branch pushed: $branch). Enable Settings→Actions→'Allow GitHub Actions to create and approve pull requests', or open the PR by hand." | |
| fi | |
| # PR: don't mutate the branch; surface the freshly rendered screenshots for human review. | |
| - name: Upload screenshots (PR review) | |
| if: github.event_name == 'pull_request' | |
| uses: actions/upload-artifact@v7 | |
| # An artifact is a convenience; the account's 500 MB artifact quota must not fail the gate. | |
| continue-on-error: true | |
| with: | |
| name: screenshots | |
| path: docs/screenshots/ | |
| retention-days: 2 |