diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml new file mode 100644 index 0000000..2e82eae --- /dev/null +++ b/.github/workflows/android-release.yml @@ -0,0 +1,116 @@ +name: Build & release Android APK + +# Fires whenever a semver tag is pushed (e.g. v6.1.1). Use +# scripts/release.sh --push from your laptop to mint the +# tag; this workflow does everything downstream. +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + workflow_dispatch: + inputs: + version: + description: 'Manual tag to build (e.g. v6.1.1)' + required: true + +permissions: + contents: write # needed to create GitHub releases from the runner + +jobs: + build: + name: Build signed APK + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Resolve tag + id: tag + run: | + TAG="${GITHUB_REF_NAME}" + if [[ -z "$TAG" || "$TAG" == "main" ]]; then + TAG="${{ github.event.inputs.version }}" + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + + - name: Set up Node 20 + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: npm + cache-dependency-path: mobile/package-lock.json + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Cache Gradle packages + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('mobile/android/**/*.gradle*', 'mobile/android/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: gradle-${{ runner.os }}- + + - name: Install Capacitor + sync + working-directory: mobile + run: | + npm install --no-audit --no-fund + npx cap sync android + + - name: Restore keystore from secret + env: + KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} + run: | + echo "$KEYSTORE_B64" | base64 -d > $RUNNER_TEMP/pedscribe-release.jks + ls -la $RUNNER_TEMP/pedscribe-release.jks + + - name: Build signed release APK + working-directory: mobile/android + env: + KS_PASS: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + KEY_PASS: ${{ secrets.ANDROID_KEY_PASSWORD }} + run: | + ./gradlew assembleRelease \ + -Pandroid.injected.signing.store.file=$RUNNER_TEMP/pedscribe-release.jks \ + -Pandroid.injected.signing.store.password="$KS_PASS" \ + -Pandroid.injected.signing.key.alias="$KEY_ALIAS" \ + -Pandroid.injected.signing.key.password="$KEY_PASS" \ + --no-daemon --stacktrace + + - name: Locate APK + id: apk + run: | + APK=$(find mobile/android/app/build/outputs/apk/release -name '*.apk' | head -1) + test -n "$APK" || { echo "no APK found"; exit 1; } + echo "path=$APK" >> "$GITHUB_OUTPUT" + echo "found: $APK ($(stat -c%s "$APK") bytes)" + + - name: Rename APK with version + id: rename + run: | + DST="pedscribe-${{ steps.tag.outputs.version }}.apk" + cp "${{ steps.apk.outputs.path }}" "$DST" + echo "path=$DST" >> "$GITHUB_OUTPUT" + + - name: Create or update GitHub release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.tag.outputs.tag }} + name: PedScribe ${{ steps.tag.outputs.version }} + make_latest: 'true' + generate_release_notes: true + files: | + ${{ steps.rename.outputs.path }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}