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