SuperAPI AI Directory

github-actions-android

Deployment & operations

View repository

Updated 10-16 10:54

About this skill

GitHub Actions — Android (Play)

Generic CI: github-actions. Here: signing, AAB, and the store. App: android-development. JVM tests: android-unit-testing. IAP (billing) ≠ upload: play-billing.

Detect native (gradlew) vs Expo/RN (eas.json). Do not mix eas build and bundleRelease in the same job unnecessarily.

Non-negotiable rules

  • Play receives AAB (bundleRelease), not APK — APK only for sideload/Firebase App Distribution.
  • Keystore / passwords only in GitHub Secrets. Never .jks / .keystore in git.
  • Play App Signing enabled: CI uses the upload key.
  • Play service account (JSON) in a secret, least privilege (Release to testing / production).
  • versionCode deterministic (versioned file or github.run_number documented — one source).
  • Track internal (or alpha) in automated CI; production with environment: production + reviewer.

CI (native)

jobs:
  test:
    runs-on: ubuntu-latest
    permissions: { contents: read }
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: "17"   # o JDK do projeto
          cache: gradle
      - run: chmod +x gradlew
      - run: ./gradlew --no-daemon lintDebug testDebugUnitTest
  • Wrapper gradlew required. Same JDK as compileOptions.
  • Instrumented (connectedCheck / emulator): not in the default PR. Use Firebase Test Lab or job workflow_dispatch — android-instrumented-testing.
  • Cache Gradle via setup-java cache: gradle.

Signing

Typical secrets: ANDROID_KEYSTORE_BASE64, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_ALIAS, ANDROID_KEY_PASSWORD.

  • Decode the keystore in the release job (base64 -d). Delete it at the end if writing to disk.
  • signingConfigs release reads env (ORG_GRADLE_PROJECT_… or gradle.properties generated on the runner).
  • Debug signing only in debug. Never signingConfig signingConfigs.debug in release.

Release and Play

deploy-play:
  needs: test
  if: github.ref == 'refs/heads/main' && github.event_name == 'push'
  runs-on: ubuntu-latest
  environment: internal   # ou production
  steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-java@v4
      with: { distribution: temurin, java-version: "17", cache: gradle }
    - run: ./gradlew --no-daemon bundleRelease
    # Fastlane supply ou action de Play Publisher
  • Fastlane supply / upload_to_play_store or maintained action (e.g. Play Publisher) — whichever the repo already uses.
  • Service account JSON: PLAY_SERVICE_ACCOUNT_JSON.
  • Tracks: internal → alpha/beta → production. Promote in the Console or an explicit lane; do not jump to prod in the first workflow.
  • Changelog en-US/pt-BR in fastlane/metadata if the team versions notes.
  • Artifact: upload the .aab (upload-artifact) in addition to the store, short retention.

Versioning

  • versionName visible (product semver / calver).
  • versionCode always goes up. Conflict on Play = red CI, not --force.
  • Flavors (prod/staging): correct bundle and package name; do not publish debug to Play.

Expo / React Native

  • EXPO_TOKEN (or Expo OIDC if the project has it).
  • eas build --platform android --profile production and eas submit --platform android or download the AAB and use the same supply.
  • Profile eas.json for production points to the same internal track first.
  • Do not run gradlew at the Expo root if the binary is EAS's responsibility.

Anti-patterns

  • Committing the keystore "just for CI"
  • APK on the Play Store
  • assembleRelease without signingConfig
  • Production track on every push
  • Emulator in the PR for every change
  • Recycle the service account JSON with the owner of the entire org

Integration with other skills

  • Pipeline: github-actions
  • App: android-development
  • Tests: android-unit-testing / android-instrumented-testing
  • iOS: github-actions-ios
  • Go-live: production-readiness

Completion criteria

  • lint + unit in the PR
  • AAB signed with upload key via secrets
  • Upload to a non-prod track (or protected prod)
  • versionCode unique and increasing
  • No keystore in git