diff --git a/.github/workflows/main-check.yml b/.github/workflows/main-check.yml index 73905b944..6fc20148e 100644 --- a/.github/workflows/main-check.yml +++ b/.github/workflows/main-check.yml @@ -23,3 +23,67 @@ jobs: run_unit_tests: false upload_artifacts: true secrets: inherit + + # Republishes the debug APKs validate-and-build already produced as a rolling "snapshot" + # prerelease that moves to HEAD on every push to main, so testers get a stable download + # link instead of digging through Actions artifacts (which require a GitHub login and + # expire after 7 days). + publish-snapshot: + needs: validate-and-build + if: github.repository == 'meshtastic/Meshtastic-Android' + runs-on: ubuntu-24.04-arm + permissions: + contents: write + env: + # CROWDIN_GITHUB_TOKEN (a PAT), not the default GITHUB_TOKEN, because the repo's tag + # rulesets block the default token from creating/deleting tags — same token every other + # tag-touching workflow here uses. + GH_TOKEN: ${{ secrets.CROWDIN_GITHUB_TOKEN }} + steps: + - name: Checkout code + uses: actions/checkout@v7.0.0 + with: + fetch-depth: 0 # git rev-list --count needs full history for the versionCode + token: ${{ secrets.CROWDIN_GITHUB_TOKEN }} + persist-credentials: false # no git push here; gh does the authed work via GH_TOKEN + + - name: Download debug APKs + uses: actions/download-artifact@v8 + with: + name: app-debug-apks + path: artifacts + + # A moving tag reuses the same release URL forever, and Obtainium fingerprints the + # asset URL — so without a changing filename it would never detect a new build. + # Embed the (monotonic) versionCode in each APK name; same formula the app build uses. + - name: Rename APKs with versionCode + run: | + COMMIT_COUNT=$(git rev-list --count HEAD) + OFFSET=$(grep '^VERSION_CODE_OFFSET=' config.properties | cut -d'=' -f2) + VERSION_CODE=$((COMMIT_COUNT + OFFSET)) + echo "VERSION_CODE=$VERSION_CODE" >> "$GITHUB_ENV" + mkdir -p upload + find artifacts -name '*.apk' | while read -r f; do + cp "$f" "upload/$(basename "$f" .apk)-${VERSION_CODE}.apk" + done + ls -l upload + + # Delete the previous snapshot release AND its tag, then recreate both at HEAD. This + # prunes the now-stale (differently-named) APKs so they don't pile up, and sidesteps the + # Releases API refusing to retarget an already-existing tag. + - name: Remove previous snapshot release + run: gh release delete snapshot --yes --cleanup-tag || true + + - name: Publish snapshot release + run: | + cat > notes.md <> "$GITHUB_ENV" + - name: Build Android APKs run: ./gradlew androidApp:assembleFdroidDebug androidApp:assembleGoogleDebug -Pci=true --parallel --configuration-cache --continue diff --git a/obtainium-test-builds.md b/obtainium-test-builds.md index 320524d8e..ac75dcb8e 100644 --- a/obtainium-test-builds.md +++ b/obtainium-test-builds.md @@ -23,12 +23,21 @@ release is published (un-drafted) when a build is promoted to closed or higher. | **stable** | Production | published, marked *Latest* | ✅ Yes | | **open** beta | Beta (Open) | published prerelease, tag `vX.Y.Z-open.N` | ✅ Yes | | **closed** beta | Alpha (Closed) | published prerelease, tag `vX.Y.Z-closed.N` | ✅ Yes | +| **snapshot** | — (not on Play) | rolling prerelease, tag `snapshot` | ✅ Yes | -Only **one** test build is "live" on GitHub at a time: as a build is promoted, -its release object moves forward (its tag changes from `-closed.N` to `-open.N` -to the clean production tag). So a `-closed`/`-open` build is installable only -while it is currently parked in that channel — once promoted onward, the old -channel tag no longer has a release. +Only **one** promoted test build is "live" on GitHub at a time: as a build is +promoted, its release object moves forward (its tag changes from `-closed.N` to +`-open.N` to the clean production tag). So a `-closed`/`-open` build is +installable only while it is currently parked in that channel — once promoted +onward, the old channel tag no longer has a release. + +**Snapshot** is different: it's an automated debug build of the latest commit on +`main`, rebuilt and re-published under the single moving `snapshot` tag on every +push. It never goes to Play. Because debug builds use a `.debug` application-ID +suffix (`com.geeksville.mesh.fdroid.debug` / `com.geeksville.mesh.google.debug`) +and the debug signing key, a snapshot installs as its **own separate app** — it +sits alongside a Play/stable/beta install, so the uninstall-first warning above +does **not** apply to it. ## Setup @@ -60,14 +69,34 @@ channel tag no longer has a release. - **Filter release titles by regular expression:** `-closed\.` - **Filter APKs by regular expression:** see [Picking the APK](#picking-the-apk) -### Bleeding edge (newest test build, any channel) +### Bleeding edge (newest promoted test build, any channel) - **Include prereleases:** on -- *(no release-title filter)* +- **Filter release titles by regular expression:** `-(closed|open)\.` - **Filter APKs by regular expression:** see [Picking the APK](#picking-the-apk) -Obtainium installs the newest published prerelease — whatever is currently in -open or closed. +Obtainium installs the newest promoted prerelease — whatever is currently in +open or closed. The title filter is required to skip the always-newer `snapshot` +prerelease; without it Obtainium would follow snapshot instead. + +### Snapshot (latest commit on `main`) + +- **Include prereleases:** on +- **Filter release titles by regular expression:** `^Snapshot` +- **Filter APKs by regular expression:** debug-signed names, see below + +Follows `main` directly — updates on every push. These are **debug builds** +(`.debug` package, debug key), so they install as a separate app and won't +disturb a stable/beta install. The APKs are named `…-debug-.apk` +(not `-release.apk`), so use debug-suffixed filters: + +| You want | Regex | +|---|---| +| Google flavor, most phones (arm64) | `google-arm64-v8a-debug-\d+\.apk` | +| fdroid flavor, most phones (arm64) | `fdroid-arm64-v8a-debug-\d+\.apk` | +| fdroid flavor, one-size-fits-all | `fdroid-universal-debug-\d+\.apk` | + +Snapshot releases attach only the debug APKs — no `.aab` or desktop installers. > **If your channel filter finds nothing:** when no build is parked in that > exact channel, the title filter matches no current release (old channel tags