Android GitHub Actions Workflows
Create or adapt reusable GitHub Actions workflows for Android test automation.
This skill supports two modes:
unittestandroidtest
It is optimized for Gradle-based Android CI, test result publishing, artifacts, and emulator-backed instrumented tests.
When to Use
- The user wants a new GitHub Actions workflow for Android tests
- The user wants to refactor an existing Android test workflow into a reusable pattern
- The user wants to revise Gradle cache, artifact retention, triggers, or test-report publication for Android CI
- The user wants to review whether workflow actions such as report publishers or emulator runners should be updated
Non-Negotiable Rules
- Ask decisions one at a time with a recommendation.
- Do not assume hard-coded module names, branches, paths, Gradle tasks, or emulator settings.
- Reuse repository conventions when they exist.
- Separate common workflow blocks from mode-specific blocks.
- Before finalizing the workflow, verify whether third-party and GitHub action dependencies should stay pinned as-is or be updated.
Workflow
Step 1: Detect the job type
Determine whether the user needs:
unittest— Gradle unit tests running on the hostandroidtest— instrumented tests running on one or more emulators
If unclear, ask this first.
Step 2: Inspect the repository baseline
Search for these files before drafting the workflow:
find .github/workflows -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) 2>/dev/null
Step 3: Ask the common decisions
Ask these one at a time:
- Trigger strategy
pushpull_request- both
workflow_dispatch- branch filters
- path filters
- Test scope
- exact Gradle task
- test class
- package/group of tests
- Gradle cache strategy
- enable/disable cache
- restore/save behavior
- artifact retention policy
- which branch strategy to apply:
- shared cache across branches, written only by the default branch (default
gradle/actions/setup-gradlebehavior; scope it withcache-read-only) - per-branch cache, where each branch keeps its own warm entry — this needs a manual
actions/cachestep, since neithersetup-gradlenorsetup-javaaccepts a cache-key input
- shared cache across branches, written only by the default branch (default
- which step owns the cache:
setup-gradleorsetup-java cache: gradle, never both
- Reporting
- publish XML results
- upload HTML reports on failure or always
- artifact retention days
Step 4: Ask the androidtest-only decisions
If the mode is androidtest, also ask:
- API level or API matrix
- Single emulator or multiple emulators
- Emulator target and architecture
- AVD cache / snapshot strategy
- AVD cache key is always tied to the API level (and architecture), never to the branch — emulator images and system snapshots depend on the system image, so reusing them across branches is safe and desirable
- Emulator boot timeout
- Emulator options
- Whether to enable KVM permissions setup
Step 5: Verify workflow dependencies
Before generating or updating the workflow, verify the current tags for the actions you plan to use.
Use gh api and check the exact repositories involved:
gh api repos/actions/checkout/releases/latest --jq '.tag_name'
gh api repos/actions/setup-java/releases/latest --jq '.tag_name'
gh api repos/actions/cache/releases/latest --jq '.tag_name'
gh api repos/actions/upload-artifact/releases/latest --jq '.tag_name'
gh api repos/gradle/actions/releases/latest --jq '.tag_name'
gh api repos/reactivecircus/android-emulator-runner/releases/latest --jq '.tag_name'
gh api repos/EnricoMi/publish-unit-test-result-action/releases/latest --jq '.tag_name'
Rules:
- Keep stable major tags unless the user asks for exact SHAs.
- Do not bump versions blindly; compare the workflow's current
uses:entries against the latest stable tags. - Prioritize dependency checks for report-publishing actions and AVD/emulator actions.
- If an update looks risky or breaking, surface it instead of silently changing it.
Step 6: Build the workflow from reusable blocks
Always structure the generated workflow in layers:
Common blocks
nameonconcurrencypermissions- checkout
- JDK setup
- Gradle setup/cache
- CI Gradle properties setup
- test result publication
- artifact upload
- cleanup / summary steps when they add value
unittest-specific blocks
- host-only Gradle execution
- unit-test XML paths
- unit-test HTML report paths
- optional manual Gradle cache restore/save strategy
androidtest-specific blocks
- KVM permissions
- AVD cache
- AVD snapshot creation
- emulator-runner execution
- instrumented-test XML paths
- instrumented-test HTML report paths
Step 7: Output contract
When you finish, provide:
- The workflow file content
- A short note listing the decisions made
- A short note listing which action dependencies were checked and whether any were updated
Decision Tree
If the user wants unittest
- Prefer a fast Ubuntu job
- Prefer host Gradle execution
- Prefer XML publication and HTML upload on failure
- Ask whether cache should use
actions/cacheexplicitly orsetup-java cache: gradleonly
If the user wants androidtest
- Prefer one emulator first unless the user explicitly wants a matrix
- Ask whether AVD snapshots should be cached
- Ask whether multiple API levels should run in parallel
- Verify
reactivecircus/android-emulator-runnerbefore reusing its version
Output Quality Bar
- The workflow must be reusable outside the current repository
- Repo-specific defaults should stay parameterized or clearly labeled
- The final YAML must be internally consistent: trigger filters, cache keys, report paths, and Gradle commands should match each other
- Do not mix unit-test and instrumented-test report paths
Reference Files
If you need more detail, load:
references/workflow-patterns.md