Build Nightly APK #94
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: Build Nightly APK | |
| on: | |
| schedule: | |
| # Runs at 02:17 America/Buenos_Aires. | |
| - cron: "17 5 * * *" | |
| workflow_dispatch: | |
| permissions: | |
| actions: read | |
| contents: read | |
| concurrency: | |
| group: nightly-apk-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| changes: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| current-sha: ${{ steps.nightly-changes.outputs.current-sha }} | |
| previous-sha: ${{ steps.nightly-changes.outputs.previous-sha }} | |
| should-build: ${{ steps.nightly-changes.outputs.should-build }} | |
| short-sha: ${{ steps.nightly-changes.outputs.short-sha }} | |
| steps: | |
| - name: Check for new main changes | |
| id: nightly-changes | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const workflow_id = 'nightly-apk.yml'; | |
| const currentSha = context.sha; | |
| const shortSha = currentSha.slice(0, 7); | |
| if (context.eventName === 'workflow_dispatch') { | |
| core.setOutput('current-sha', currentSha); | |
| core.setOutput('previous-sha', ''); | |
| core.setOutput('short-sha', shortSha); | |
| core.setOutput('should-build', 'true'); | |
| await core.summary | |
| .addHeading('Nightly APK') | |
| .addRaw(`Manual run requested for ${currentSha}. Building APKs.`) | |
| .write(); | |
| return; | |
| } | |
| const runs = await github.paginate(github.rest.actions.listWorkflowRuns, { | |
| owner, | |
| repo, | |
| workflow_id, | |
| branch: 'main', | |
| status: 'success', | |
| per_page: 20, | |
| }); | |
| const previousRun = runs.find((run) => run.id !== context.runId); | |
| const previousSha = previousRun?.head_sha ?? ''; | |
| const shouldBuild = previousSha !== currentSha; | |
| core.setOutput('current-sha', currentSha); | |
| core.setOutput('previous-sha', previousSha); | |
| core.setOutput('short-sha', shortSha); | |
| core.setOutput('should-build', shouldBuild ? 'true' : 'false'); | |
| const summary = core.summary.addHeading('Nightly APK'); | |
| if (shouldBuild) { | |
| summary.addRaw( | |
| previousSha | |
| ? `main moved from ${previousSha} to ${currentSha}. Building APKs.` | |
| : `No previous successful nightly was found. Building APKs for ${currentSha}.` | |
| ); | |
| } else { | |
| summary.addRaw(`main is still at ${currentSha}. Skipping APK build.`); | |
| } | |
| await summary.write(); | |
| build: | |
| needs: changes | |
| if: needs.changes.outputs.should-build == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: "21" | |
| - name: Setup Gradle | |
| uses: gradle/actions/setup-gradle@v6.2.0 | |
| # The shared CI keystore lives in the CI_KEYSTORE_B64 + CI_KEYSTORE_PASSWORD | |
| # repo secrets so every workflow signs with the same stable key and builds | |
| # install over each other. Without the secrets we fall back to a throwaway | |
| # keystore with a random one-off password (signature varies per run). | |
| - name: Set up CI keystore | |
| env: | |
| CI_KEYSTORE_B64: ${{ secrets.CI_KEYSTORE_B64 }} | |
| CI_KEYSTORE_PASSWORD: ${{ secrets.CI_KEYSTORE_PASSWORD }} | |
| run: | | |
| if [ -n "$CI_KEYSTORE_B64" ] && [ -n "$CI_KEYSTORE_PASSWORD" ]; then | |
| KEYSTORE_PASSWORD="$CI_KEYSTORE_PASSWORD" | |
| printf '%s' "$CI_KEYSTORE_B64" | base64 -d > pixelplayeross-ci.jks | |
| else | |
| KEYSTORE_PASSWORD="$(openssl rand -hex 24)" | |
| keytool -genkey -v -keystore pixelplayeross-ci.jks -alias pixelplayeross-ci-key -keyalg RSA -keysize 4096 -validity 10000 \ | |
| -storepass "$KEYSTORE_PASSWORD" -keypass "$KEYSTORE_PASSWORD" \ | |
| -dname "CN=PixelPlayerOSS CI Throwaway, OU=Dev, O=PixelPlayerOSS, L=World, S=World, C=US" | |
| fi | |
| { | |
| echo "storeFile=pixelplayeross-ci.jks" | |
| echo "storePassword=$KEYSTORE_PASSWORD" | |
| echo "keyAlias=pixelplayeross-ci-key" | |
| echo "keyPassword=$KEYSTORE_PASSWORD" | |
| } > keystore.properties | |
| - name: Build Phone nightly release APKs | |
| run: ./gradlew :app:assembleRelease -Ppixelplayer.enableAbiSplits=true | |
| - name: Verify Phone nightly split APKs | |
| run: | | |
| BUILD_TOOLS_VERSION="$(ls "$ANDROID_HOME/build-tools" | sort -V | tail -n 1)" | |
| for apk in \ | |
| app/build/outputs/apk/release/app-arm64-v8a-release.apk \ | |
| app/build/outputs/apk/release/app-armeabi-v7a-release.apk | |
| do | |
| "$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION/aapt2" dump badging "$apk" >/dev/null | |
| "$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION/apksigner" verify --verbose "$apk" | |
| done | |
| - name: Upload Phone nightly split APK artifacts | |
| uses: actions/upload-artifact@v7.0.1 | |
| with: | |
| name: PixelPlayerOSS-phone-nightly-${{ needs.changes.outputs.short-sha }} | |
| path: | | |
| app/build/outputs/apk/release/app-arm64-v8a-release.apk | |
| app/build/outputs/apk/release/app-armeabi-v7a-release.apk | |
| if-no-files-found: error | |
| compression-level: 0 | |
| retention-days: 14 |