From 670521607df1698e240a1614933ef059ae6b6e79 Mon Sep 17 00:00:00 2001 From: Gareth Bowen Date: Tue, 22 Dec 2020 08:07:49 +1300 Subject: [PATCH] Use GitHub Actions for CI #129 --- .github/workflows/build.yml | 35 +++++++ .github/workflows/publish.yml | 174 ++++++++++++++++++++++++++++++++++ .travis.yml | 100 ------------------- README.md | 4 +- gradle.properties | 1 + secrets.tar.gz.enc | Bin 4192 -> 4192 bytes 6 files changed, 212 insertions(+), 102 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/publish.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..71242f37 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,35 @@ +name: Build and test + +on: [push, pull_request] + +jobs: + build: + name: Build + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: Test + run: make test + - name: Set up ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - name: Set up fastlane + run: gem install fastlane --no-document --quiet + - name: Unpack secrets + env: + ANDROID_SECRETS_KEY: ${{ secrets.ANDROID_SECRETS_KEY }} + ANDROID_SECRETS_IV: ${{ secrets.ANDROID_SECRETS_IV }} + run: | + openssl aes-256-cbc -K $ANDROID_SECRETS_KEY -iv $ANDROID_SECRETS_IV -in secrets.tar.gz.enc -out ./secrets.tar.gz -d + tar -xf ./secrets.tar.gz + - name: Assemble unbranded + uses: maierj/fastlane-action@v1.4.0 + env: + ANDROID_KEYSTORE_PATH: ${{ secrets.ANDROID_KEYSTORE_PATH }} + ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} + with: + lane: build + options: '{ "flavor": "unbranded" }' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..cbf51d06 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,174 @@ +name: Build and publish + +on: + push: + tags: v*.*.* + +env: + ANDROID_KEYSTORE_PATH: ${{ secrets.ANDROID_KEYSTORE_PATH }} + ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} + +jobs: + build: + name: Build + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: Set up ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - name: Set up fastlane + run: gem install fastlane --no-document --quiet + - name: Unpack secrets + env: + ANDROID_SECRETS_KEY: ${{ secrets.ANDROID_SECRETS_KEY }} + ANDROID_SECRETS_IV: ${{ secrets.ANDROID_SECRETS_IV }} + run: | + openssl aes-256-cbc -K $ANDROID_SECRETS_KEY -iv $ANDROID_SECRETS_IV -in secrets.tar.gz.enc -out ./secrets.tar.gz -d + tar -xf ./secrets.tar.gz + - name: Assemble unbranded + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "unbranded" }' + - name: Assemble gamma + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "medicmobilegamma" }' + - name: Assemble demo + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "medicmobiledemo" }' + - name: Assemble bracuganda + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "bracuganda" }' + - name: Assemble cic_guatemala + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "cic_guatemala" }' + - name: Assemble cmmb_kenya + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "cmmb_kenya" }' + - name: Assemble covid_moh_mali + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "covid_moh_mali" }' + - name: Assemble ebpp_indonesia + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "ebpp_indonesia" }' + - name: Assemble hope_through_health + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "hope_through_health" }' + - name: Assemble livinggoods + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "livinggoods" }' + - name: Assemble livinggoodskenya + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "livinggoodskenya" }' + - name: Assemble livinggoods_assisted_networks + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "livinggoods_assisted_networks" }' + - name: Assemble livinggoods_innovation_ke + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "livinggoods_innovation_ke" }' + - name: Assemble livinggoods_innovation_ke_supervisor + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "livinggoods_innovation_ke_supervisor" }' + - name: Assemble livinggoods_innovation_ke_hivst + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "livinggoods_innovation_ke_hivst" }' + - name: Assemble moh_kenya_siaya_red + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "moh_kenya_siaya_red" }' + - name: Assemble moh_kenya_siaya_green + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "moh_kenya_siaya_green" }' + - name: Assemble moh_kenya_siaya_black + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "moh_kenya_siaya_black" }' + - name: Assemble moh_mali + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "moh_mali" }' + - name: Assemble moh_zanzibar_training + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "moh_zanzibar_training" }' + - name: Assemble moh_zanzibar + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "moh_zanzibar" }' + - name: Assemble musomali + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "musomali" }' + - name: Assemble pih_malawi + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "pih_malawi" }' + - name: Assemble pih_malawi_supervisor + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "pih_malawi_supervisor" }' + - name: Assemble simprints + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "simprints" }' + - name: Assemble surveillance_covid19_kenya + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "surveillance_covid19_kenya" }' + - name: Assemble vhw_burundi + uses: maierj/fastlane-action@v1.4.0 + with: + lane: build + options: '{ "flavor": "vhw_burundi" }' + - name: GitHub release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + draft: true + files: build/outputs/apk/**/*.apk + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index aeffc6e5..00000000 --- a/.travis.yml +++ /dev/null @@ -1,100 +0,0 @@ -language: android -dist: trusty # Android builds are only supported on our Trusty image -jdk: oraclejdk8 -android: - components: - - tools - - platform-tools - - extra-android-m2repository - - build-tools-29.0.2 - - android-29 -env: -- GRADLE_OPTS="-XX:MaxPermSize=2048M" -stages: - - name: test - - name: alpha - if: tag =~ ^v.+-alpha\.[0-9]+$ # eg: v3.6.0-alpha.1 - - name: final - if: tag =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ # eg: v3.6.0 -jobs: - include: - - stage: test - script: make test - - - stage: alpha - script: fastlane build flavor:unbranded - script: fastlane build flavor:medicmobilegamma - script: fastlane build flavor:medicmobiledemo - - - stage: final - # flavors sorted alphabetically with three per job - script: - - fastlane build flavor:unbranded - - fastlane build flavor:medicmobilegamma - - fastlane build flavor:medicmobiledemo - - script: - - fastlane build flavor:bracuganda - - fastlane build flavor:cic_guatemala - - fastlane build flavor:cmmb_kenya - - script: - - fastlane build flavor:covid_moh_mali - - fastlane build flavor:ebpp_indonesia - - fastlane build flavor:hope_through_health - - script: - - fastlane build flavor:livinggoods - - fastlane build flavor:livinggoodskenya - - fastlane build flavor:livinggoods_assisted_networks - - script: - - fastlane build flavor:livinggoods_innovation_ke - - fastlane build flavor:livinggoods_innovation_ke_supervisor - - fastlane build flavor:livinggoods_innovation_ke_hivst - - script: -# - fastlane build flavor:moh_kenya_siaya_white - - fastlane build flavor:moh_kenya_siaya_red - - fastlane build flavor:moh_kenya_siaya_green - - fastlane build flavor:moh_kenya_siaya_black - - fastlane build flavor:moh_mali - - script: - - fastlane build flavor:moh_zanzibar_training - - fastlane build flavor:moh_zanzibar - - script: - - fastlane build flavor:musomali - - fastlane build flavor:pih_malawi - - fastlane build flavor:pih_malawi_supervisor - - script: - - fastlane build flavor:simprints - - fastlane build flavor:surveillance_covid19_kenya - - fastlane build flavor:vhw_burundi - - script: -before_install: -- openssl aes-256-cbc -K $encrypted_323c4a109760_key -iv $encrypted_323c4a109760_iv -in secrets.tar.gz.enc -out ./secrets.tar.gz -d -- tar -xf ./secrets.tar.gz -- gem update --system -- gem install fastlane --no-document --quiet -before_cache: -- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock -- rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -cache: - directories: - - "$HOME/.gradle/caches/" - - "$HOME/.gradle/wrapper/" - - "$HOME/.android/build-cache" -deploy: - - provider: releases - skip_cleanup: true - overwrite: true - api_key: - secure: Dm6ciqGeR3zT+/hdO4jq+2sMa/d3sHSQ1U9ya9tCu71+BMZfjRA8vgBAWgnp6xixCUTEppJNgRrKaCR9V12Yu8Yl3ceY3bGRd6xhR9uUK+PgFUSjptuiwgwE1Fbj7lxT1NG1ZptvnqYZ0YhPiAC5cmcJUuz/0g83fKJfDNrX9V6IGQObdiPqDJX3cVbU/5NpSbIsnNqQfaldMP2Y1m1gODMCifOqM2Mj1nHd+X9OzEpuICCZiiHJJBKafdifZKmPlSgYDjt3d6DCsn5YiNnNm5Rs4kqWJc4YvV2G+S4eMnL7XB4pg45zZQ6ZIwn3NPp5a4pfHTn5nGC/2Hqqe8cw+xURYf/qrOZp3mQgAYiJht9bivMhwlvCvTh2kw+xorTj7wlFDSyj78QLxjxidiAj0AkBdYlVttSXDXAoCTGKHDhFEtKNviVdB9TNfYwKTFin4BCPsPnBEQZB9pzqIwBha9INjutYUJ9aX1uC7a1grR7Oa6IL7NH0Z0sV7bYkoW91X0ZxQtsVnFduc2y6AwKzqlO1VKN0U55KmUnj0STCGSMHZoI1cObBJtCzUcUnH7NIEfeZLq/tQ8sRkFlCJ1g2bJI0VG8DMTP56krvHKNknLacN5SjloNCST3SL6qlYto95ypSlfU+u3qpC6kNdXa7Yvodk+5u7VVQcX18xczbYvs= - file_glob: true - file: ./build/outputs/apk/**/*.apk - on: - tags: true - repo: medic/medic-android - branch: master - - provider: script - script: fastlane deploy flavor:unbranded && fastlane deploy flavor:medicmobilegamma && fastlane deploy flavor:medicmobiledemo - skip_cleanup: true - on: - tags: true - repo: medic/medic-android - branch: master diff --git a/README.md b/README.md index 42566a00..54e1e249 100644 --- a/README.md +++ b/README.md @@ -72,13 +72,13 @@ To add a new brand: 1. Make sure all issues for this release have passed AT and been merged into `master` 2. Create a git tag starting with `v` and ending with the alpha version, e.g. `v1.2.3-alpha.1` and push the tag to GitHub. -3. Creating this tag will trigger [Travis CI](https://travis-ci.org/github/medic/medic-android) to build, sign, and properly version the build. The release-ready APKs are available for side-loading from [GitHub Releases](https://github.com/medic/medic-android/releases) and are uploaded to the Google Play Console in the "alpha" channel for only the `unbranded` and `gamma` flavors. +3. Creating this tag will trigger [GitHub Action](https://github.com/medic/medic-android/actions) to build, sign, and properly version the build. The release-ready APKs are available for side-loading from [GitHub Releases](https://github.com/medic/medic-android/releases). 4. Announce the release in #quality-assurance ## Final for users 1. Create a git tag starting with `v`, e.g. `v1.2.3` and push the tag to GitHub. -2. The exact same process as Step 3 above, but the `demo` flavour is updated also. +2. The exact same process as Step 3 above. 3. Announce the release on the [CHT forum](https://forum.communityhealthtoolkit.org), under the "Product - Releases" category. 4. Each flavor is then individually released to users via "Release Management" in the Google Play Console. Once a flavor has been tested and is ready to go live, click Release to Production diff --git a/gradle.properties b/gradle.properties index 5bac8ac5..f991a87d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,2 @@ android.useAndroidX=true +org.gradle.jvmargs=-Xmx2048m diff --git a/secrets.tar.gz.enc b/secrets.tar.gz.enc index b2668a99246a84633033faccd2ae4867d283f05b..6ca00e2b7e608a37b264ec49c291d4aab3e4f6e8 100644 GIT binary patch literal 4192 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 qd%Xjp;~aVI`BhIl$_MQ^J7-ww8cmQ@Sy