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: [main, 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/@expo/*/node_modules 58 packages/@unimodules/*/node_modules 59 react-native-lab/react-native/node_modules 60 key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }} 61 - run: echo "$(pwd)/bin" >> $GITHUB_PATH 62 - name: ♻️ Restore node modules in tools 63 uses: actions/cache@v2 64 with: 65 path: tools/node_modules 66 key: ${{ runner.os }}-tools-modules-${{ hashFiles('tools/yarn.lock') }} 67 - name: Yarn install 68 run: yarn install --frozen-lockfile 69 - name: Setup Ruby and install gems 70 uses: ruby/setup-ruby@v1 71 with: 72 bundler-cache: true 73 - name: Install git-crypt 74 run: sudo apt-get install git-crypt 75 - name: Decrypt secrets if possible 76 env: 77 GIT_CRYPT_KEY_BASE64: ${{ secrets.GIT_CRYPT_KEY_BASE64 }} 78 run: | 79 if [ -z "${GIT_CRYPT_KEY_BASE64}" ]; then 80 echo 'git-crypt key not present in environment' 81 else 82 git crypt unlock <(echo $GIT_CRYPT_KEY_BASE64 | base64 --decode) 83 fi 84 - name: ♻️ Restore Gradle caches 85 uses: actions/cache@v2 86 with: 87 path: ~/.gradle/caches 88 key: ${{ runner.os }}-gradle-${{ hashFiles('android/*.gradle*') }} 89 restore-keys: | 90 ${{ runner.os }}-gradle- 91 - name: ♻️ Restore Android NDK from cache 92 uses: actions/cache@v2 93 id: cache-android-ndk 94 with: 95 path: /usr/local/lib/android/sdk/ndk/21.4.7075529/ 96 key: ${{ runner.os }}-ndk-21.4.7075529 97 restore-keys: | 98 ${{ runner.os }}-ndk- 99 - name: Install NDK 100 if: steps.cache-android-ndk.outputs.cache-hit != 'true' 101 run: | 102 sudo $ANDROID_SDK_ROOT/tools/bin/sdkmanager --install "ndk;21.4.7075529" 103 - name: Check which flavor to build 104 id: flavor 105 uses: dorny/paths-filter@v2 106 with: 107 # this action fails when base is not set on schedule event 108 base: ${{ github.ref }} 109 filters: | 110 versioned: 111 - android/versioned-abis/** 112 - android/versioned-react-native/** 113 - android/expoview/src/versioned/** 114 - android/expoview/src/main/java/versioned/** 115 - android/**/*.gradle 116 - name: Build APK 117 env: 118 ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }} 119 ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} 120 ANDROID_KEY_ALIAS: ExponentKey 121 ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} 122 ANDROID_NDK_HOME: /usr/local/lib/android/sdk/ndk/21.4.7075529/ 123 IS_APP_BUNDLE: ${{ github.event.inputs.releaseGooglePlay == 'release-google-play' }} 124 IS_RELEASE_BUILD: ${{ github.event.inputs.releaseAPK == 'release-apk' || github.event.inputs.releaseGooglePlay == 'release-google-play' }} 125 IS_VERSIONED_FLAVOR: ${{ github.event_name == 'schedule' || steps.flavor.outputs.versioned == 'true' }} 126 run: | 127 if [ "$IS_RELEASE_BUILD" == "false" ]; then 128 export NDK_ABI_FILTERS="x86_64" 129 BUILD_TYPE="Debug" 130 echo "Using ABI filters: $NDK_ABI_FILTERS" 131 else 132 BUILD_TYPE="Release" 133 fi 134 [[ "$IS_VERSIONED_FLAVOR" == "true" ]] && FLAVOR="Versioned" || FLAVOR="Unversioned" 135 echo "Building with $FLAVOR flavor" 136 if [ -z "$ANDROID_KEYSTORE_B64" ]; then 137 echo "External build detected, APK will not be signed" 138 bin/fastlane android build build_type:$BUILD_TYPE flavor:$FLAVOR sign:false 139 else 140 echo "Internal build detected, APK will be signed" 141 echo $ANDROID_KEYSTORE_B64 | base64 -d > android/app/release-key.jks 142 bin/fastlane android build build_type:$BUILD_TYPE flavor:$FLAVOR aab:$IS_APP_BUNDLE 143 fi 144 - name: Upload APK artifact 145 uses: actions/upload-artifact@v2 146 with: 147 name: android-apk 148 path: android/app/build/outputs/apk 149 - name: Store daemon logs for debugging crashes 150 if: failure() 151 uses: actions/upload-artifact@v2 152 with: 153 name: gradle-daemon-logs 154 path: ~/.gradle/daemon 155 - name: Upload APK to S3 and update staging versions endpoint 156 if: ${{ github.event.inputs.releaseAPK == 'release-apk' }} 157 run: bin/expotools client-build --platform android --release 158 env: 159 AWS_ACCESS_KEY_ID: AKIAJ3SWUQ4QLNQC7FXA 160 AWS_SECRET_ACCESS_KEY: ${{ secrets.android_client_build_aws_secret_key }} 161 EXPO_VERSIONS_SECRET: ${{ secrets.expo_versions_secret }} 162 - name: Upload APK to Google Play and release to production 163 if: ${{ github.event.inputs.releaseGooglePlay == 'release-google-play' }} 164 run: bin/fastlane android prod_release 165 env: 166 SUPPLY_JSON_KEY_DATA: ${{ secrets.SUPPLY_JSON_KEY_DATA }} 167 - name: Notify on Slack 168 uses: 8398a7/action-slack@v3 169 if: failure() && (github.event.ref == 'refs/heads/main' || startsWith(github.event.ref, 'refs/heads/sdk-')) 170 env: 171 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 172 SLACK_WEBHOOK_URL: ${{ secrets.slack_webhook_android }} 173 with: 174 channel: '#expo-android' 175 status: ${{ job.status }} 176 fields: job,message,ref,eventName,author,took 177 author_name: Expo Go (Android) 178