feat(ci): publish PR Android APK to comment (#28283)
* feat(ci): publish PR Android APK to R2 with installable links Adds a universal debug APK to PR builds and uploads it to a public R2 bucket alongside the existing GitHub Actions artifact. Posts a sticky PR comment with tap-to-install links and a QR code so testers can install directly on their device without unzipping artifacts. Required setup: - Secrets: R2_APK_ACCESS_KEY_ID, R2_APK_SECRET_ACCESS_KEY, R2_APK_ACCOUNT_ID, R2_APK_BUCKET - Optional repo variable: APK_PUBLIC_HOST (defaults to apk.immich.app) - R2 bucket configured with a public custom domain matching APK_PUBLIC_HOST * chore(ci): drop R2 upload, link directly to GitHub artifact Surfaces the existing release-apk-signed artifact in a sticky PR comment with a QR code. Avoids new infra and secrets — the trade-off is GitHub login and a zip wrapper instead of tap-to-install. * feat(ci): build PR APK as release and publish to GitHub Release PR builds now produce a release APK signed with the release keystore. The universal APK is published as a GitHub Release asset under tag 'pr-<num>' (prerelease), giving testers a direct, unzipped, tap-to- install URL plus a QR code in the PR comment. The release-apk-signed artifact is unchanged. * chore(ci): drop GitHub Release, publish universal APK as own artifact Reverts the prerelease publish. Uploads the universal release APK as a separate single-file artifact so its download URL gives a zip containing only that APK — no extra files to dig through. The QR in the PR comment points at this universal-only artifact. * chore(ci): build only universal APK for PR, drop split artifact PR builds skip the arm64-only split — release-apk-signed now contains just the universal app-release.apk, so the download zip is a single file. Removes the redundant separate universal artifact and points the PR comment QR at the main artifact URL. * feat(mobile): suffix PR APK applicationId so it installs alongside production Each PR build now becomes app.alextran.immich.pr<num> via PR_NUMBER env read in build.gradle, so testers can install multiple PR builds and the Play Store version on the same device without uninstalling. Also tags the version with -pr<num> for visibility. * feat(ci): allow PR APK build to run on forks Forks can now run the Android build job. Steps that need repo secrets (create-workflow-token, Create Keystore) are skipped when the PR is from a fork, the checkout falls back to GITHUB_TOKEN, and build.gradle falls back to debug signing if the release keystore isn't materialised. The PR comment still requires write access, so it's gated to non-fork PRs — fork APKs are reachable from the workflow run's artifact tab.pull/28282/head^2
parent
41f285aa3e
commit
8b3c9bf9c3
|
|
@ -51,6 +51,7 @@ jobs:
|
|||
should_run: ${{ steps.check.outputs.should_run }}
|
||||
steps:
|
||||
- id: token
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
|
|
@ -60,7 +61,7 @@ jobs:
|
|||
id: check
|
||||
uses: immich-app/devtools/actions/pre-job@91f342bb4477c4bc10c576ae739da875d85aa164 # pre-job-action-v2.0.4
|
||||
with:
|
||||
github-token: ${{ steps.token.outputs.token }}
|
||||
github-token: ${{ steps.token.outputs.token || github.token }}
|
||||
filters: |
|
||||
mobile:
|
||||
- 'mobile/**'
|
||||
|
|
@ -73,12 +74,13 @@ jobs:
|
|||
needs: pre-job
|
||||
permissions:
|
||||
contents: read
|
||||
# Skip when PR from a fork
|
||||
if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
|
||||
pull-requests: write
|
||||
if: ${{ github.actor != 'dependabot[bot]' && fromJSON(needs.pre-job.outputs.should_run).mobile == true }}
|
||||
runs-on: mich
|
||||
|
||||
steps:
|
||||
- id: token
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
uses: immich-app/devtools/actions/create-workflow-token@caa599d954228439ea3e8ce1c3328f41ab120ee6 # create-workflow-token-action-v2.0.0
|
||||
with:
|
||||
client-id: ${{ secrets.PUSH_O_MATIC_APP_CLIENT_ID }}
|
||||
|
|
@ -88,9 +90,10 @@ jobs:
|
|||
with:
|
||||
ref: ${{ inputs.ref || github.sha }}
|
||||
persist-credentials: false
|
||||
token: ${{ steps.token.outputs.token }}
|
||||
token: ${{ steps.token.outputs.token || github.token }}
|
||||
|
||||
- name: Create the Keystore
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
env:
|
||||
KEY_JKS: ${{ secrets.KEY_JKS }}
|
||||
working-directory: ./mobile
|
||||
|
|
@ -144,20 +147,40 @@ jobs:
|
|||
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
|
||||
ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }}
|
||||
IS_MAIN: ${{ github.ref == 'refs/heads/main' }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
if [[ $IS_MAIN == 'true' ]]; then
|
||||
flutter build apk --release
|
||||
flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64,android-x64
|
||||
else
|
||||
flutter build apk --debug --split-per-abi --target-platform android-arm64
|
||||
flutter build apk --release
|
||||
fi
|
||||
|
||||
- name: Publish Android Artifact
|
||||
id: upload-apk
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: release-apk-signed
|
||||
path: mobile/build/app/outputs/flutter-apk/*.apk
|
||||
|
||||
- name: Comment APK download link on PR
|
||||
if: ${{ github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork }}
|
||||
uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3.11.0
|
||||
env:
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
APK_URL: ${{ steps.upload-apk.outputs.artifact-url }}
|
||||
with:
|
||||
github-token: ${{ steps.token.outputs.token }}
|
||||
message-id: 'mobile-android-apk'
|
||||
message: |
|
||||
📱 **Android release APK (universal)** — `${{ env.HEAD_SHA }}`
|
||||
|
||||
Download: ${{ env.APK_URL }}
|
||||
|
||||
<img src="https://api.qrserver.com/v1/create-qr-code/?size=240x240&data=${{ env.APK_URL }}" alt="QR code" />
|
||||
|
||||
GitHub login required. Downloads as a zip containing a single `app-release.apk` — extract and install. Installs as a separate app (applicationId `app.alextran.immich.pr${{ github.event.pull_request.number }}`), so it coexists with the Play Store version and any other PR builds.
|
||||
|
||||
- name: Save Gradle Cache
|
||||
id: cache-gradle-save
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
|
|
|
|||
|
|
@ -64,8 +64,15 @@ android {
|
|||
}
|
||||
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
def hasKeystore = file("../key.jks").exists() && file("../key.jks").length() > 0
|
||||
signingConfig hasKeystore ? signingConfigs.release : signingConfigs.debug
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
|
||||
def prNumber = System.getenv("PR_NUMBER")
|
||||
if (prNumber) {
|
||||
applicationIdSuffix ".pr${prNumber}"
|
||||
versionNameSuffix "-pr${prNumber}"
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace 'app.alextran.immich'
|
||||
|
|
|
|||
Loading…
Reference in New Issue