Android APK Build #83
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Android APK Build | |
| permissions: | |
| contents: write | |
| on: | |
| push: | |
| branches: [main, dev] | |
| paths: ['app/**'] | |
| pull_request: | |
| branches: [main, dev] | |
| paths: ['app/**'] | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| # A cloud build is a poll, not a compile, so anything approaching this is a | |
| # hang. The previous local build had no limit and sat for hours. | |
| timeout-minutes: 60 | |
| defaults: | |
| run: | |
| working-directory: ./app | |
| steps: | |
| - name: Setup repo | |
| uses: actions/checkout@v4 | |
| - name: Setup node | |
| uses: actions/setup-node@v4.0.2 | |
| with: | |
| node-version: 20.x | |
| cache: 'npm' | |
| cache-dependency-path: ./app/package-lock.json | |
| # No JDK or Android SDK: EAS compiles this in the cloud. Installing a | |
| # toolchain the runner never uses cost minutes on every run. | |
| - name: Setup Expo | |
| uses: expo/expo-github-action@v8 | |
| with: | |
| expo-version: latest | |
| eas-version: latest | |
| token: ${{ secrets.EXPO_TOKEN }} | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Initialize EAS | |
| run: eas init --force --non-interactive | |
| # Cloud build. `--local` compiled the whole app on a 2-core runner, which | |
| # took hours and routinely had to be cancelled. | |
| - name: Build Android APK | |
| run: | | |
| set -euo pipefail | |
| eas build --platform android --profile local --non-interactive --wait --json \ | |
| > "$RUNNER_TEMP/build.json" | |
| url=$(jq -r '.[0].artifacts.buildUrl // .[0].artifacts.applicationArchiveUrl' \ | |
| "$RUNNER_TEMP/build.json") | |
| if [ -z "$url" ] || [ "$url" = "null" ]; then | |
| echo "No artifact URL in the build result:"; cat "$RUNNER_TEMP/build.json"; exit 1 | |
| fi | |
| curl -fsSL -o "${{ github.workspace }}/app-release.apk" "$url" | |
| ls -la "${{ github.workspace }}/app-release.apk" | |
| # Attached to every run, so a build off any branch is installable without | |
| # needing a GitHub release. | |
| - name: Upload APK as a workflow artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: chronicle-android-apk | |
| path: ${{ github.workspace }}/app-release.apk | |
| retention-days: 30 | |
| - name: Generate release tag | |
| id: tag | |
| run: | | |
| echo "RELEASE_TAG=android-v1.0.0-$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT | |
| echo "RELEASE_NAME=Friend Lite Android $(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_OUTPUT | |
| echo "BUILD_TIME=$(date +'%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_OUTPUT | |
| - name: Create Release | |
| id: create_release | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/create-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: ${{ steps.tag.outputs.RELEASE_TAG }} | |
| release_name: ${{ steps.tag.outputs.RELEASE_NAME }} | |
| body: | | |
| ## 📱 Android APK Build | |
| **Built from commit:** ${{ github.sha }} | |
| **Branch:** ${{ github.ref_name }} | |
| **Build time:** ${{ steps.tag.outputs.BUILD_TIME }} | |
| Ready to install on Android devices! | |
| draft: false | |
| prerelease: true | |
| # Same condition as Create Release above. Without it this ran on every | |
| # branch with an empty upload_url and failed after the build had already | |
| # succeeded. | |
| - name: Upload Android APK to Release | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ steps.create_release.outputs.upload_url }} | |
| asset_path: ${{ github.workspace }}/app-release.apk | |
| asset_name: friend-lite-android.apk | |
| asset_content_type: application/vnd.android.package-archive |