Android 建置與部署流水線

Mobile
7 個節點 · 7 條連接mobile
ex-android-build-deploy.osop.yaml
# Android Build & Deploy Pipeline
# From source checkout to Play Console distribution

osop_version: "2.0"
id: android-build-deploy
name: "Android 建置與部署流水線"

nodes:
  - id: checkout
    type: git
    purpose: Clone repository and checkout release branch
    runtime:
      action: checkout
      repo: git@github.com:org/android-app.git
      branch: "${BRANCH:-main}"
    outputs: [source_dir]

  - id: gradle_build
    type: cli
    purpose: Build release APK and AAB using Gradle
    runtime:
      os: linux
      command: ./gradlew assembleRelease bundleRelease
    inputs: [source_dir]
    outputs: [apk_path, aab_path]
    timeout_sec: 600
    explain:
      what: Compiles source, processes resources, generates APK and AAB
      why: AAB is required for Play Store; APK kept for internal distribution

  - id: unit_tests
    type: cli
    purpose: Run JUnit and Robolectric unit tests
    runtime:
      os: linux
      command: ./gradlew testReleaseUnitTest
    timeout_sec: 300

  - id: instrumented_tests
    type: cicd
    purpose: Run Espresso instrumented tests on emulator farm
    runtime:
      platform: firebase_test_lab
      command: >
        gcloud firebase test android run
        --type instrumentation
        --app build/outputs/apk/release/app-release.apk
        --test build/outputs/apk/androidTest/release/app-release-androidTest.apk
        --device model=Pixel6,version=33
    timeout_sec: 900
    retry_policy:
      max_retries: 2
      backoff_sec: 60
    explain:
      what: Runs UI tests on real device profiles in Firebase Test Lab
      why: Catches device-specific regressions that unit tests miss

  - id: sign_apk
    type: cli
    purpose: Sign release artifacts with upload key
    runtime:
      os: linux
      command: >
        jarsigner -keystore ${KEYSTORE_PATH}
        -storepass ${STORE_PASS}
        build/outputs/bundle/release/app-release.aab release-key
    security:
      credentials: [KEYSTORE_PATH, STORE_PASS, KEY_ALIAS]

  - id: upload_play_console
    type: api
    purpose: Upload signed AAB to Google Play Console internal track
    runtime:
      endpoint: google_play
      method: POST
      url: https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PACKAGE}/edits
    inputs: [signed_aab_path]
    outputs: [release_id, track]
    timeout_sec: 300

  - id: notify
    type: api
    purpose: Post build result to Slack and update JIRA ticket
    runtime:
      endpoint: slack
      method: POST
      url: https://hooks.slack.com/services/${WEBHOOK_ID}
    inputs: [release_id, build_status]

edges:
  - from: checkout
    to: gradle_build
    mode: sequential

  - from: gradle_build
    to: unit_tests
    mode: sequential

  - from: unit_tests
    to: instrumented_tests
    mode: sequential

  - from: instrumented_tests
    to: sign_apk
    mode: sequential

  - from: sign_apk
    to: upload_play_console
    mode: sequential

  - from: upload_play_console
    to: notify
    mode: sequential

  - from: instrumented_tests
    to: notify
    mode: error
    condition: tests_failed