1name: Android Client 2 3on: 4 workflow_dispatch: 5 inputs: 6 releaseAPK: 7 description: 'type "release-apk" to confirm upload to S3' 8 required: false 9 releaseGooglePlay: 10 description: 'type "release-google-play" to confirm release to Google Play' 11 required: false 12 schedule: 13 - cron: '20 5 * * 1,3,5' # 5:20 AM UTC time on every Monday, Wednesday and Friday 14 pull_request: 15 paths: 16 - .github/workflows/client-android.yml 17 - secrets/** 18 - android/** 19 - fastlane/** 20 - Gemfile.lock 21 - .ruby-version 22 - yarn.lock 23 push: 24 branches: [master, sdk-*] 25 paths: 26 - .github/workflows/client-android.yml 27 - secrets/** 28 - android/** 29 - fastlane/** 30 - Gemfile.lock 31 - .ruby-version 32 - yarn.lock 33 34concurrency: 35 group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} 36 cancel-in-progress: true 37 38jobs: 39 build: 40 runs-on: ubuntu-18.04 41 steps: 42 - name: Checkout 43 uses: actions/checkout@v2 44 with: 45 submodules: true 46 - name: ♻️ Restore workspace node modules 47 uses: actions/cache@v2 48 id: node-modules-cache 49 with: 50 path: | 51 # See "workspaces" → "packages" in the root package.json for the source of truth of 52 # which node_modules are affected by the root yarn.lock 53 node_modules 54 apps/*/node_modules 55 home/node_modules 56 packages/*/node_modules 57 packages/@unimodules/*/node_modules 58 react-native-lab/react-native/node_modules 59 key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }} 60 - name: ♻️ Restore node modules in tools 61 uses: actions/cache@v2 62 with: 63 path: tools/node_modules 64 key: ${{ runner.os }}-tools-modules-${{ hashFiles('tools/yarn.lock') }} 65 - name: Yarn install 66 run: yarn install --frozen-lockfile 67 - name: Setup Ruby and install gems 68 uses: ruby/setup-ruby@v1 69 with: 70 bundler-cache: true 71 - name: Install git-crypt 72 run: sudo apt-get install git-crypt 73 - name: Decrypt secrets if possible 74 env: 75 GIT_CRYPT_KEY_BASE64: ${{ secrets.GIT_CRYPT_KEY_BASE64 }} 76 run: | 77 if [ -z "${GIT_CRYPT_KEY_BASE64}" ]; then 78 echo 'git-crypt key not present in environment' 79 else 80 git crypt unlock <(echo $GIT_CRYPT_KEY_BASE64 | base64 --decode) 81 fi 82 - name: ♻️ Restore Gradle caches 83 uses: actions/cache@v2 84 with: 85 path: ~/.gradle/caches 86 key: ${{ runner.os }}-gradle-${{ hashFiles('android/*.gradle*') }} 87 restore-keys: | 88 ${{ runner.os }}-gradle- 89 - name: ♻️ Restore Android NDK from cache 90 uses: actions/cache@v2 91 id: cache-android-ndk 92 with: 93 path: /usr/local/lib/android/sdk/ndk/19.2.5345600/ 94 key: ${{ runner.os }}-ndk-19.2.5345600 95 restore-keys: | 96 ${{ runner.os }}-ndk- 97 - name: Install NDK 98 if: steps.cache-android-ndk.outputs.cache-hit != 'true' 99 run: | 100 sudo $ANDROID_SDK_ROOT/tools/bin/sdkmanager --install "ndk;19.2.5345600" 101 - name: Check which flavor to build 102 id: flavor 103 uses: dorny/paths-filter@v2 104 with: 105 # this action fails when base is not set on schedule event 106 base: ${{ github.ref }} 107 filters: | 108 versioned: 109 - android/versioned-abis/** 110 - android/versioned-react-native/** 111 - android/expoview/src/versioned/** 112 - android/expoview/src/main/java/versioned/** 113 - android/**/*.gradle 114 - name: Build APK 115 env: 116 ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }} 117 ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} 118 ANDROID_KEY_ALIAS: ExponentKey 119 ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} 120 ANDROID_NDK_HOME: /usr/local/lib/android/sdk/ndk/19.2.5345600/ 121 IS_RELEASE_BUILD: ${{ github.event.inputs.releaseAPK == 'release-apk' || github.event.inputs.releaseGooglePlay == 'release-google-play' }} 122 IS_VERSIONED_FLAVOR: ${{ github.event_name == 'schedule' || steps.flavor.outputs.versioned == 'true' }} 123 run: | 124 if [ "$IS_RELEASE_BUILD" == "false" ]; then 125 export NDK_ABI_FILTERS="x86_64" 126 BUILD_TYPE="Debug" 127 echo "Using ABI filters: $NDK_ABI_FILTERS" 128 else 129 BUILD_TYPE="Release" 130 fi 131 [[ "$IS_VERSIONED_FLAVOR" == "true" ]] && FLAVOR="Versioned" || FLAVOR="Unversioned" 132 echo "Building with $FLAVOR flavor" 133 if [ -z "$ANDROID_KEYSTORE_B64" ]; then 134 echo "External build detected, APK will not be signed" 135 bin/fastlane android build build_type:$BUILD_TYPE flavor:$FLAVOR sign:false 136 else 137 echo "Internal build detected, APK will be signed" 138 echo $ANDROID_KEYSTORE_B64 | base64 -d > android/app/release-key.jks 139 bin/fastlane android build build_type:$BUILD_TYPE flavor:$FLAVOR 140 fi 141 - name: Upload APK artifact 142 uses: actions/upload-artifact@v2 143 with: 144 name: android-apk 145 path: android/app/build/outputs/apk 146 - name: Store daemon logs for debugging crashes 147 if: failure() 148 uses: actions/upload-artifact@v2 149 with: 150 name: gradle-daemon-logs 151 path: ~/.gradle/daemon 152 - name: Upload APK to S3 and update staging versions endpoint 153 if: ${{ github.event.inputs.releaseAPK == 'release-apk' }} 154 run: bin/expotools client-build --platform android --release 155 env: 156 AWS_ACCESS_KEY_ID: AKIAJ3SWUQ4QLNQC7FXA 157 AWS_SECRET_ACCESS_KEY: ${{ secrets.android_client_build_aws_secret_key }} 158 EXPO_VERSIONS_SECRET: ${{ secrets.expo_versions_secret }} 159 - name: Upload APK to Google Play and release to production 160 if: ${{ github.event.inputs.releaseGooglePlay == 'release-google-play' }} 161 run: bin/fastlane android prod_release 162 env: 163 SUPPLY_JSON_KEY_DATA: ${{ secrets.SUPPLY_JSON_KEY_DATA }} 164 - name: Notify on Slack 165 uses: 8398a7/action-slack@v3 166 if: failure() && (github.event.ref == 'refs/heads/master' || startsWith(github.event.ref, 'refs/heads/sdk-')) 167 env: 168 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 169 SLACK_WEBHOOK_URL: ${{ secrets.slack_webhook_android }} 170 with: 171 channel: '#platform-android' 172 status: ${{ job.status }} 173 fields: job,message,ref,eventName,author,took 174 author_name: Expo Go (Android) 175