name: Build Android APK on: push: branches: [main] tags: ["v*"] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: # Node >= 23.6 runs the TypeScript test files natively (type-stripping), # matching the local toolchain. No build step or extra deps required. node-version: 24 cache: npm - name: Install dependencies run: npm install --legacy-peer-deps - name: Typecheck run: npm run typecheck - name: Unit tests run: npm test build: runs-on: ubuntu-latest env: EXPO_PUBLIC_SENTRY_DSN: ${{ secrets.EXPO_PUBLIC_SENTRY_DSN }} EXPO_PUBLIC_POSTHOG_KEY: ${{ secrets.EXPO_PUBLIC_POSTHOG_KEY }} EXPO_PUBLIC_CHATWOOT_INBOX_IDENTIFIER: ${{ secrets.EXPO_PUBLIC_CHATWOOT_INBOX_IDENTIFIER }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_ORG: ${{ secrets.SENTRY_ORG }} SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: 20 cache: npm - uses: actions/setup-java@v5 with: distribution: temurin java-version: 17 - name: Setup Android SDK uses: android-actions/setup-android@v4 - name: Cache Gradle uses: actions/cache@v5 with: path: | ~/.gradle/caches ~/.gradle/wrapper android/.gradle key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle*', 'android/gradle/wrapper/gradle-wrapper.properties') }} restore-keys: | ${{ runner.os }}-gradle- - name: Install dependencies run: npm install --legacy-peer-deps - name: Set Sentry release identifiers # sentry.gradle (applied from android/app/build.gradle) defaults the # upload's --release/--dist to `${applicationId}@${versionName}+${versionCode}`, # which does NOT match the release/dist Sentry.init() reports at runtime # (`opencode-mobile@${app.json version}`, see src/lib/sentry.ts). That # mismatch made every uploaded source map land under a release Sentry # never looks up, so symbolication silently failed. Pin the Gradle-side # values to exactly what the app reports. run: | VERSION=$(node -p "require('./app.json').expo.version") echo "SENTRY_RELEASE=opencode-mobile@${VERSION}" >> "$GITHUB_ENV" echo "SENTRY_DIST=${VERSION}" >> "$GITHUB_ENV" echo "Sentry release=opencode-mobile@${VERSION} dist=${VERSION}" - name: Expo prebuild run: npx expo prebuild --platform android --no-install - name: Setup signing run: | if [[ "${{ github.ref }}" == refs/tags/v* && -n "${{ secrets.KEYSTORE_BASE64 }}" ]]; then echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > android/app/release.keystore echo "RELEASE_STORE_FILE=release.keystore" >> "$GITHUB_ENV" echo "RELEASE_STORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> "$GITHUB_ENV" echo "RELEASE_KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> "$GITHUB_ENV" echo "RELEASE_KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> "$GITHUB_ENV" echo "Signing: production keystore" else keytool -genkey -v -keystore android/app/debug.keystore -storepass android \ -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 \ -dname "CN=Android Debug,O=Android,C=US" echo "Signing: debug keystore (non-release build)" fi - name: Build APK working-directory: android run: ./gradlew assembleRelease - name: Upload APK artifact uses: actions/upload-artifact@v7 with: name: app-release path: android/app/build/outputs/apk/release/app-release.apk release: needs: build if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/download-artifact@v8 with: name: app-release - name: Create Release uses: softprops/action-gh-release@v2 with: files: app-release.apk generate_release_notes: true