项目作者: ReactiveCircus

项目描述 :
Templates for getting started with Cirrus CI for Android.
高级语言:
项目地址: git://github.com/ReactiveCircus/cirrusci-android-templates.git
创建时间: 2019-12-03T11:55:42Z
项目社区:https://github.com/ReactiveCircus/cirrusci-android-templates

开源协议:Apache License 2.0

下载


Cirrus CI Android Templates

Templates for getting started with Cirrus CI for Android.

If you want to learn more about Cirrus CI and why you might want to use it for Android, here’s an article I wrote: Exploring Cirrus CI for Android.

Installing Cirrus CI

  • Go to the Cirrus CI Application on GitHub Marketplace and setup a plan for your account or organization.
  • Add a .cirrus.yml file in your project’s root directory.

Now you’re ready to use the following templates as a starting point for writing your CI tasks.

Assembing APKs and Running Checks

The following task assembles the APKs from the app module and runs all checks (unit tests and Android Lint).

  1. assemble_and_check_task:
  2. timeout_in: 10m
  3. # trigger the task on commits on the main branch or any pull request
  4. only_if: $CIRRUS_BRANCH == "main" || CIRRUS_PR != ""
  5. env:
  6. JAVA_TOOL_OPTIONS: -Xmx6g
  7. GRADLE_OPTS: -Dorg.gradle.daemon=false -Dkotlin.incremental=false -Dkotlin.compiler.execution.strategy=in-process
  8. container:
  9. image: reactivecircus/android-sdk:latest
  10. cpu: 8
  11. memory: 16G
  12. assemble_and_check_script:
  13. ./gradlew app:assemble check

Running Instrumented Tests

The following task runs instrumented tests from all modules on API 21, 23, and 28.

The task also uses the skip keyword to skip the task unless there are changes to any Kotlin, XML or Gradle sources in the commit or pull request.

  1. connected_check_task:
  2. # custom task name
  3. name: Run Android instrumented tests (API $API_LEVEL)
  4. # timeout in 30 minutes
  5. timeout_in: 30m
  6. only_if: $CIRRUS_BRANCH == "main" || CIRRUS_PR != ""
  7. # skip the task unless sources have changed
  8. skip: "!changesInclude('.cirrus.yml', '*.gradle', '*.gradle.kts', '**/*.gradle', '**/*.gradle.kts', '*.properties', '**/*.properties', '**/*.kt', '**/*.xml')"
  9. env:
  10. matrix:
  11. - API_LEVEL: 21
  12. - API_LEVEL: 23
  13. - API_LEVEL: 28
  14. JAVA_TOOL_OPTIONS: -Xmx6g
  15. GRADLE_OPTS: -Dorg.gradle.daemon=false -Dkotlin.incremental=false -Dkotlin.compiler.execution.strategy=in-process
  16. container:
  17. image: reactivecircus/android-emulator-${API_LEVEL}:latest
  18. kvm: true
  19. cpu: 8
  20. memory: 24G
  21. create_device_script:
  22. echo no | avdmanager create avd --force --name "api-${API_LEVEL}" --abi "${TARGET}/${ARCH}" --package "system-images;android-${API_LEVEL};${TARGET};${ARCH}"
  23. start_emulator_background_script:
  24. $ANDROID_HOME/emulator/emulator -avd "api-${API_LEVEL}" -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none
  25. assemble_instrumented_tests_script:
  26. ./gradlew assembleDebugAndroidTest
  27. wait_for_emulator_script:
  28. adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 3; done; input keyevent 82'
  29. disable_animations_script: |
  30. adb shell settings put global window_animation_scale 0.0
  31. adb shell settings put global transition_animation_scale 0.0
  32. adb shell settings put global animator_duration_scale 0.0
  33. run_instrumented_tests_script:
  34. ./gradlew connectedDebugAndroidTest

Publishing Library Snapshot Release

The following config builds, tests and publishes a snapshot release for a multi-module library project. There are 3 tasks:

  • assemble_and_check_task - build the AAR and run all checks on each module
  • connected_check_task - run instrumented tests from all modules on API 21, 23, and 28.
  • publish_artifacts_task - after successful execution of both assemble_and_check_task and connected_check_task, deploy the snapshot build to Nexus Sonatype repository

Sonatype credentials can be encrypted on Cirrus CI and safely added to the .cirrus.yml file.

  1. assemble_and_check_task:
  2. only_if: $CIRRUS_BRANCH == "main" || CIRRUS_PR != ""
  3. env:
  4. JAVA_TOOL_OPTIONS: -Xmx6g
  5. GRADLE_OPTS: -Dorg.gradle.daemon=false
  6. container:
  7. image: reactivecircus/android-sdk:latest
  8. cpu: 8
  9. memory: 16G
  10. assemble_and_check_script:
  11. ./gradlew assemble check
  12. connected_check_task:
  13. only_if: $CIRRUS_BRANCH == "main" || CIRRUS_PR != ""
  14. env:
  15. matrix:
  16. - API_LEVEL: 21
  17. - API_LEVEL: 23
  18. - API_LEVEL: 28
  19. JAVA_TOOL_OPTIONS: -Xmx6g
  20. GRADLE_OPTS: -Dorg.gradle.daemon=false
  21. container:
  22. image: reactivecircus/android-emulator-${API_LEVEL}:latest
  23. kvm: true
  24. cpu: 8
  25. memory: 24G
  26. create_device_script:
  27. avdmanager create avd --force --name "api-${API_LEVEL}" --abi "${TARGET}/${ARCH}" --package "system-images;android-${API_LEVEL};${TARGET};${ARCH}" --device "Nexus 6"
  28. start_emulator_background_script:
  29. $ANDROID_HOME/emulator/emulator -avd "api-${API_LEVEL}" -no-window -no-snapshot -noaudio -no-boot-anim -camera-back none
  30. assemble_instrumented_tests_script:
  31. ./gradlew assembleDebugAndroidTest
  32. wait_for_emulator_script:
  33. adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 3; done; input keyevent 82'
  34. disable_animations_script:
  35. - adb shell settings put global window_animation_scale 0.0
  36. - adb shell settings put global transition_animation_scale 0.0
  37. - adb shell settings put global animator_duration_scale 0.0
  38. run_instrumented_tests_script:
  39. ./gradlew connectedDebugAndroidTest
  40. publish_artifacts_task:
  41. depends_on:
  42. - assemble_and_check
  43. - connected_check
  44. env:
  45. JAVA_TOOL_OPTIONS: -Xmx6g
  46. GRADLE_OPTS: -Dorg.gradle.daemon=false
  47. SONATYPE_NEXUS_USERNAME: ENCRYPTED[xxx]
  48. SONATYPE_NEXUS_PASSWORD: ENCRYPTED[xxx]
  49. container:
  50. image: reactivecircus/android-sdk:latest
  51. cpu: 8
  52. memory: 16G
  53. deploy_snapshot_script:
  54. ./gradlew clean androidSourcesJar androidJavadocsJar uploadArchives --no-daemon --no-parallel

Local Gradle Build Cache

The following task uses the cache instruction to cache the ~/.gradle/cache directory:

  1. assemble_and_check_task:
  2. only_if: $CIRRUS_BRANCH == "main" || CIRRUS_PR != ""
  3. env:
  4. JAVA_TOOL_OPTIONS: -Xmx6g
  5. GRADLE_OPTS: -Dorg.gradle.daemon=false
  6. container:
  7. image: reactivecircus/android-sdk:latest
  8. cpu: 8
  9. memory: 16G
  10. gradle_cache:
  11. folder: ~/.gradle/caches
  12. # replace buildSrc/dependencies.gradle with whatever file you put your dependency versions in
  13. fingerprint_script: cat buildSrc/dependencies.gradle && cat gradle/wrapper/gradle-wrapper.properties
  14. assemble_and_check_script:
  15. ./gradlew assemble check
  16. # cleanup non-deterministic files to avoid unnecessary cache upload
  17. cleanup_script:
  18. - rm -rf ~/.gradle/caches/[0-9].*
  19. - rm -rf ~/.gradle/caches/transforms-1
  20. - rm -rf ~/.gradle/caches/journal-1
  21. - rm -rf ~/.gradle/caches/jars-3/*/buildSrc.jar
  22. - find ~/.gradle/caches/ -name "*.lock" -type f -delete

Remote Gradle Build Cache

Cirrus CI also supports Gradle’s remote HTTP build cache.

Follow the instructions to setup remote build cache for your project.

No change to the .cirrus.yml file is required.

Archiving Test Results

The following task stores the test results as JUnit XML artifacts which can be accessed from the build dashboard.

  1. assemble_and_check_task:
  2. only_if: $CIRRUS_BRANCH == "main" || CIRRUS_PR != ""
  3. env:
  4. JAVA_TOOL_OPTIONS: -Xmx6g
  5. GRADLE_OPTS: -Dorg.gradle.daemon=false
  6. container:
  7. image: reactivecircus/android-sdk:latest
  8. cpu: 8
  9. memory: 16G
  10. assemble_and_check_script:
  11. ./gradlew assemble check
  12. always:
  13. junit_artifacts:
  14. path: "**/test-results/**/*.xml"
  15. type: text/xml
  16. format: junit

Delaying task execution - Required PR Labels

The following task will only be run after the required initial-review label has been added to the pull request.

  1. connected_check_task:
  2. required_pr_labels: initial-review
  3. only_if: $CIRRUS_BRANCH == "main" || CIRRUS_PR != ""
  4. env:
  5. matrix:
  6. - API_LEVEL: 21
  7. - API_LEVEL: 23
  8. - API_LEVEL: 28
  9. JAVA_TOOL_OPTIONS: -Xmx6g
  10. GRADLE_OPTS: -Dorg.gradle.daemon=false -Dkotlin.incremental=false -Dkotlin.compiler.execution.strategy=in-process
  11. container:
  12. image: reactivecircus/android-emulator-${API_LEVEL}:latest
  13. kvm: true
  14. cpu: 8
  15. memory: 24G
  16. create_device_script:
  17. echo no | avdmanager create avd --force --name "api-${API_LEVEL}" --abi "${TARGET}/${ARCH}" --package "system-images;android-${API_LEVEL};${TARGET};${ARCH}"
  18. start_emulator_background_script:
  19. $ANDROID_HOME/emulator/emulator -avd "api-${API_LEVEL}" -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none
  20. assemble_instrumented_tests_script:
  21. ./gradlew assembleDebugAndroidTest
  22. wait_for_emulator_script:
  23. adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 3; done; input keyevent 82'
  24. disable_animations_script: |
  25. adb shell settings put global window_animation_scale 0.0
  26. adb shell settings put global transition_animation_scale 0.0
  27. adb shell settings put global animator_duration_scale 0.0
  28. run_instrumented_tests_script:
  29. ./gradlew connectedDebugAndroidTest