Skip to content

ci: エミュレータスクショ廃止とGradleキャッシュ有効化でCI時間を短縮#85

Merged
yuga-hashimoto merged 2 commits into
mainfrom
claude/app-crash-question-tool-fixes-yfhkco
Jul 25, 2026
Merged

ci: エミュレータスクショ廃止とGradleキャッシュ有効化でCI時間を短縮#85
yuga-hashimoto merged 2 commits into
mainfrom
claude/app-crash-question-tool-fixes-yfhkco

Conversation

@yuga-hashimoto

@yuga-hashimoto yuga-hashimoto commented Jul 25, 2026

Copy link
Copy Markdown
Owner

実測

#84 での4回の push を計測した結果、両ワークフローとも1ステップに時間が集中していました。

Android CI   19分36秒  うち「Test, lint and build APKs」  18分14秒 (93%)
capture      17分02秒  うちエミュレータのステップ          16分15秒 (95%)

capture のステップの内訳は、#83 の失敗ログに出ていた通りGradle ビルドだけで 16分43秒BUILD FAILED in 16m 43s / 63 actionable tasks: 63 executed)。つまりエミュレータが遅いのではなく、アプリを2回コールドビルドしているのが原因でした。

変更内容

1. エミュレータスクリーンショットワークフローを削除

CI で最も高価(PRあたり17分)でしたが、コストに見合っていませんでした。

UiScreenshotInstrumentedTest と、それ専用のフィクスチャ PreviewRuntimeTarget も削除します。他の instrumented test(ChatFlowE2ETest / ChatVoiceInstrumentedTest / LocalRuntimeUpdaterInstrumentedTest)は変更していません。

失われるもの: 主要10画面が実機ランタイムで描画できるかの確認。復活させるなら、画面固有の文言ではなく testTag ベースのアサーションにして、同じ腐り方をしない形にすべきです。

2. Gradle ビルドキャッシュと並列実行を有効化

gradle/actions/setup-gradle~/.gradle を main から永続化していますが、org.gradle.caching が未設定だったため再利用されていたのは依存 jar だけで、タスク出力は毎回作り直しでした。

org.gradle.caching=true
org.gradle.parallel=true

3. PR で assembleRelease を実行しない

isMinifyEnabled = true なので R8 の難読化+リソース圧縮がフルで回っており、このワークフローで最も重いタスクです。配布物は release.yml が別途ビルドしますし、main へのマージ時には引き続きビルドするので担保は維持されます。

4. android.ymlconcurrency を追加

android.yml にはありませんでした。そのため #84 では4回分の Android CI がすべて完走し、うち3回は完全な無駄でした。main への push はキャンセルせず完走させます。

効果

3 の効果はこのPRの run で既に確認できています:

ジョブ Before (#84) After (#85)
test-and-build 19分36秒 15分38秒
capture 17分02秒 削除

1 と合わせて、PRあたりの実時間は約20分 → 約16分、消費計算量は半減します。2 のキャッシュ効果は main にマージして1回走った後の PR から上乗せされます。

検証

  • 削除後に compileDebugAndroidTestKotlin / testDebugUnitTest / detekt / spotlessCheck を実行 → 成功
  • android.yml の YAML パースを確認

なお docs/superpowers/plans/ 配下の過去の計画文書が削除ファイルに言及していますが、日付入りの履歴文書なので書き換えていません。

🤖 Generated with Claude Code

https://claude.ai/code/session_01L3eN8AmoAcBDCTEeMTY3ba

claude added 2 commits July 25, 2026 10:46
Measured on the four pushes to #84 — nearly all of the wall clock is one step
in each workflow, and both are dominated by Gradle recompiling from scratch:

    Android CI      19m36s   of which "Test, lint and build APKs"   18m14s
    capture         17m02s   of which the emulator step             16m15s
                             (#83's log shows the gradle build alone
                              accounting for 16m43s of that step)

The emulator itself is not the problem; building the app twice from cold is.

- Enable the Gradle build cache and parallel execution. `setup-gradle` already
  persists `~/.gradle` from main, but without `org.gradle.caching` only
  dependency jars were reused, never task output — so every run recompiled the
  whole app.
- Run the screenshot workflow on main as well. `setup-gradle` writes its cache
  only from the default branch and keys it per job, so a job that never runs on
  main never has a warm cache to restore. `capture` has always started cold for
  exactly this reason; a run on merge gives pull requests something to restore.
- Stop building the release APK on pull requests. `assembleRelease` runs R8 with
  minification and resource shrinking and is the most expensive task here; the
  published artifact comes from release.yml, and main still builds it on every
  merge, so the coverage is kept.
- Cancel superseded pull request runs. android.yml had no `concurrency` block,
  so all four pushes to #84 ran to completion, three of them pointlessly.

Verified `testDebugUnitTest`, `lintDebug`, `detekt`, `spotlessCheck` locally
with the new Gradle settings, and both workflow files parse. The CI timings
themselves can only be confirmed by the runs this change produces.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L3eN8AmoAcBDCTEeMTY3ba
It is the most expensive thing in CI (17 minutes per pull request) and it was
not buying a proportional amount. It never compared against golden images —
the PNGs were only uploaded as an artifact for a human to look at, and the one
automated check was a hand-maintained list of Japanese strings expected to be
on screen.

That list drifts. `5e290b1` removed the composer's workspace chip on 23 July
and the assertion for it stayed, so the job failed on #80, #81, #82 and #83 —
all merged with it red — until #84 repaired three separate stale assertions.
And because the assertions run before the capture, a single stale string took
the render smoke test and the screenshots down with it: for two days the job
was pure cost.

Removes the workflow along with `UiScreenshotInstrumentedTest` and the
`PreviewRuntimeTarget` fixture that only it used. The other instrumented tests
(`ChatFlowE2ETest`, `ChatVoiceInstrumentedTest`,
`LocalRuntimeUpdaterInstrumentedTest`) are untouched.

What is lost: nothing checks that the ten main screens still render on a real
Android runtime. If that coverage is wanted back, it should return as a render
check with tag-based assertions rather than screen-specific wording, so it
cannot rot the same way.

Verified `compileDebugAndroidTestKotlin`, `testDebugUnitTest`, `detekt` and
`spotlessCheck` after the removal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L3eN8AmoAcBDCTEeMTY3ba
@yuga-hashimoto yuga-hashimoto changed the title ci: Gradleキャッシュ有効化と無駄なビルド削減でCI時間を短縮 ci: エミュレータスクショ廃止とGradleキャッシュ有効化でCI時間を短縮 Jul 25, 2026
@yuga-hashimoto
yuga-hashimoto marked this pull request as ready for review July 25, 2026 12:13
@yuga-hashimoto
yuga-hashimoto merged commit f1d170b into main Jul 25, 2026
2 checks passed
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.

2 participants