Pipeline Android

Pipeline Android

Apresentada no TDC Porto Alegre 2018

2dc2a52d38ee8c184deeceaadf9ed6ba?s=128

Rafael Toledo

December 05, 2018
Tweet

Transcript

  1. PIPELINE ANDROID Automatizando da sua máquina até a loja

  2. /_rafaeltoledo /rafaeltoledo

  3. POR QUE AUTOMATIZAR É IMPORTANTE? 3

  4. 4 Ow, instala pra mim aí?

  5. Ow, instala pra mim aí? 5 Ow, instala pra mim

    aí? Ow, instala pra mim aí? Ow, instala pra mim aí? Ow, instala pra mim aí? Ow, instala pra mim aí?
  6. 6

  7. 7 Qual o caminho do nosso código? ?

  8. 8 Qual o caminho do nosso código? Ow, instala pra

    mim aí?
  9. 9 Qual o caminho do nosso código? ?

  10. Por que eu preciso disso? • Integração de código •

    Todo mundo na mesma página • Execução de testes e validação contínua • Cobertura de código e outras métricas • Releases frequentes 10
  11. None
  12. None
  13. Jenkins Concourse Soluções on-premise

  14. 14 Script

  15. 15 Script Shell Script

  16. 16 Script

  17. 17 Script Python

  18. PLANEJANDO O PIPELINE 18

  19. 19 Pipeline

  20. 20 Onde fazer o build?

  21. E como ficam os meus segredos nesse bolo todo? 21

  22. None
  23. Como guardar os segredos do meu repositório? • Variáveis de

    Ambiente • Arquivos pequenos podem ser codificados em Base64 • Arquivos maiores podem estar criptografados no repositório - e a chave como variável de ambiente • Ou podem estar em outro serviço (Google Drive, Dropbox) e serem baixados via API 23
  24. Pipeline • Importante granularizar para isolar os pontos de erro

    • Dividir em blocos (passos) maiores, para diferentes cenários 24
  25. 25 Pipeline Lint e testes de JVM Pull Requests

  26. 26 Pipeline Lint e testes de JVM Pull Requests

  27. 27 Pipeline Lint e testes de JVM Pull Requests Testes

    instrumentados Check de Segurança Integração na master
  28. 28 Pipeline Firebase Test Lab Lint e testes de JVM

    Pull Requests Testes instrumentados Check de Segurança Integração na master
  29. 29 Pipeline Lint e testes de JVM Pull Requests Testes

    instrumentados Check de Segurança Integração na master Upload Google Play App Center Upload de Build Este passo pode, Inclusive, ser manual
  30. VAMOS COLOCAR A MÃO NA MASSA?

  31. 31 Variáveis de Ambiente no CI

  32. workflows: version: 2 build_and_test: jobs: - build - test_instrumented: requires:

    - build - google_play_upload: requires: - test_instrumented
  33. references: workspace: &workspace ~/recipes-android

  34. config_android: &config_android working_directory: *workspace docker: - image: circleci/android:api-28-alpha environment: TERM:

    dumb JAVA_TOOL_OPTIONS: "-Xmx1g" GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=2 -Dkotlin.incremental=false" CIRCLE_JDK_VERSION: oraclejdk8
  35. config_gcloud: &config_gcloud working_directory: *workspace docker: - image: google/cloud-sdk:latest environment: TERM:

    dumb
  36. cache_key: &cache_key key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}-{{

    checksum "gradle/wrapper/gradle-wrapper.properties" }}
  37. restore_cache: &restore_cache restore_cache: <<: *cache_key save_cache: &save_cache save_cache: <<: *cache_key

    paths: - ~/.gradle/caches - ~/.gradle/wrapper
  38. persist_to_workspace: &persist_to_workspace persist_to_workspace: root: . paths: - ftl-tests - build

    - app/build - distribution - fastlane - changelog.txt - Gemfile
  39. attach_workspace: &attach_workspace attach_workspace: at: *workspace

  40. PARTE I - BUILD E TESTES 40

  41. jobs: build: <<: *config_android steps: - checkout - *restore_cache

  42. - run: name: Accept licenses command: yes | sdkmanager --licenses

    || true - run: name: Decrypt release key command: openssl aes-256-cbc -d -in distribution/release.keystore-cipher -out distribution/release.keystore -md sha256 -k $CIPHER_DECRYPT_KEY
  43. - run: name: Setup Firebase JSON configuration file command: echo

    $FIREBASE_CONFIG_JSON | base64 -di > app/google-services.json - run: name: Run Linters command: ./gradlew check detekt --stacktrace
  44. - run: name: Build command: ./gradlew assemble bundleRelease assembleAndroidTest --stacktrace

  45. - store_test_results: path: app/build/test-results - store_artifacts: path: app/build/reports destination: reports

    - store_artifacts: path: app/build/outputs/apk destination: apks
  46. - *save_cache - *persist_to_workspace

  47. PARTE II - FIREBASE TEST LAB 47

  48. 5 execuções / dia em devices 10 execuções / dia

    em emuladores
  49. test_instrumented: <<: *config_gcloud steps: - *attach_workspace

  50. - run: name: Setup Google Cloud auth command: ftl-tests/setup.sh

  51. - run: name: Setup Google Cloud auth command: ftl-tests/setup.sh

  52. #!/bin/sh if [ "$GCLOUD_SERVICE_KEY" = "" ]; then echo "GCLOUD_SERVICE_KEY

    env variable is empty. Exiting." exit 1 fi # Export to secrets file echo $GCLOUD_SERVICE_KEY | base64 -di > client-secret.json # Set project ID gcloud config set project lowcarb-6eaa7
  53. ... # Auth account gcloud auth activate-service-account lowcarb-ftl@lowcarb-6eaa7.iam.gserviceaccount.com --key-file client-secret.json

    # Delete secret rm client-secret.json
  54. - run: name: Run tests on Firebase Test Lab command:

    ftl-tests/run-tests.sh
  55. #!/bin/sh # Run tests on test lab gcloud firebase test

    android run \ --type instrumentation \ --app app/build/outputs/apk/debug/app-debug.apk \ --test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk \ --device model=Nexus6P,version=27,locale=en_US,orientation=portrait \ --timeout 30m \ --results-bucket cloud-test-lowcarb-6eaa7 \ --no-record-video \ --no-performance-metrics
  56. - run: name: Download results command: ftl-tests/download-results.sh firebase_test_results when: always

  57. #!/bin/sh TEST_DIR=$1 # Create directory for results mkdir "$TEST_DIR" #

    Pull down test results gsutil -m cp -r -U "`gsutil ls gs://cloud-test-lowcarb-6eaa7 | tail -1`*" "$TEST_DIR"
  58. - store_artifacts: path: firebase_test_results - store_test_results: path: firebase_test_results

  59. None
  60. PARTE III - GOOGLE PLAY 60

  61. https://docs.fastlane.tools/getting-started/android/setup/ 61

  62. lane :beta do gradle(task: 'assemble', build_type: 'Release') upload_to_play_store(track: 'beta') slack(message:

    'Successfully distributed a new beta build') end
  63. https://docs.fastlane.tools/getting-started/android/screenshots 63

  64. google_play_upload: <<: *config_android steps: - *attach_workspace

  65. - run: name: Setup Google Play upload key command: |

    touch distribution/google-play-key.json echo "${GOOGLE_PLAY_UPLOAD_KEY}" >> "distribution/google-play-key.json"
  66. - run: name: Setup Fastlane command: gem install fastlane -

    run: name: Install JSON parser command: sudo apt-get update && sudo apt-get install -y jq
  67. - run: name: Prepare changelog command: | mkdir "fastlane/metadata/android/pt-BR/changelogs" &&

    touch "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt" mv changelog.txt "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt"
  68. None
  69. - run: name: Prepare changelog command: | mkdir "fastlane/metadata/android/pt-BR/changelogs" &&

    touch "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt" mv changelog.txt "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt"
  70. - run: name: Prepare changelog command: | mkdir "fastlane/metadata/android/pt-BR/changelogs" &&

    touch "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt" mv changelog.txt "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt"
  71. - run: name: Prepare changelog command: | mkdir "fastlane/metadata/android/pt-BR/changelogs" &&

    touch "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt" mv changelog.txt "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt"
  72. [ { "outputType": { "type": "APK" }, "apkInfo": { "type":

    "MAIN", "splits": [], "versionCode": 262, "versionName": "0.0.1.00c2466", "enabled": true, "outputFile": "app-release.apk", "fullName": "release", "baseName": "release" }, "path": "app-release.apk", "properties": {} } ]
  73. [ { "outputType": { "type": "APK" }, "apkInfo": { "type":

    "MAIN", "splits": [], "versionCode": 262, "versionName": "0.0.1.00c2466", "enabled": true, "outputFile": "app-release.apk", "fullName": "release", "baseName": "release" }, "path": "app-release.apk", "properties": {} } ]
  74. - run: name: Prepare changelog command: | mkdir "fastlane/metadata/android/pt-BR/changelogs" &&

    touch "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt" mv changelog.txt "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt"
  75. - run: name: Prepare changelog command: | mkdir "fastlane/metadata/android/pt-BR/changelogs" &&

    touch "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt" mv changelog.txt "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt"
  76. - run: name: Prepare changelog command: | mkdir "fastlane/metadata/android/pt-BR/changelogs" &&

    touch "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt" mv changelog.txt "fastlane/metadata/android/pt-BR/changelogs/$(cat app/build/outputs/apk/release/output.json | jq -r '.[0].apkInfo.versionCode').txt"
  77. - run: name: Deploy to Google Play command: bundle exec

    fastlane deploy
  78. platform :android do desc "Deploy a new version to the

    Google Play Internal track" lane :deploy do upload_to_play_store(track: 'internal', aab: 'app/build/outputs/bundle/release/app.aab', skip_upload_apk: true) end end
  79. platform :android do desc "Deploy a new version to the

    Google Play Internal track" lane :deploy do upload_to_play_store(track: 'internal', aab: 'app/build/outputs/bundle/release/app.aab', skip_upload_apk: true) end end
  80. https://developer.android.com/platform/technology/app-bundle/ 80

  81. - run: name: Update Changelog command: bundle exec fastlane supply

    --skip_upload_apk true --skip_upload_aab true
  82. VAMOS VER RODANDO?

  83. Links CIRCLECI https://circleci.com JENKINS https://jenkins.io FIREBASE TEST LAB https://firebase.google.com/docs/test-lab/ SEGMENTIO

    ANALYTICS (SETUP CIRCLECI + FIREBASE) https://github.com/segmentio/analytics-android 83
  84. Links GIST COM OS ARQUIVOS DE CONFIGURAÇÃO https://gist.github.com/rafaeltoledo/10b30e17c3e3096fea4572098194b16f 84

  85. OBRIGADO Slides disponíveis em: speakerdeck.com/rafaeltoledo thoughtworks.com/pt/careers 85