neiam
/feedpug
feedpub
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
Version dev builds 0.1.0-dev-<timestamp>, and hand it to the container
e44a7c9 · Gabriel Morell · 2026-09-14 00:42
Message
{commit_body(@commit)}
Files changed
modified
.forgejo/workflows/android.yml
+12
−0
@@ -74,9 +74,21 @@ jobs:
| 74 | 74 | |
| 75 | 75 | - name: Build and sign the APK |
| 76 | 76 | if: steps.keystore.outputs.skip != 'true' |
| 77 | + env: | |
| 78 | + RUN_NUMBER: ${{ github.run_number }} | |
| 77 | 79 | run: | |
| 80 | + set -euo pipefail | |
| 81 | + | |
| 82 | + # One stamp for the whole run, computed here rather than | |
| 83 | + # inside Gradle, so every artifact a run produces agrees on | |
| 84 | + # its version even if the build is retried a step at a time. | |
| 85 | + stamp=$(date -u +%s) | |
| 86 | + echo "version: 0.1.0-dev-$stamp (versionCode $RUN_NUMBER)" | |
| 87 | + | |
| 78 | 88 | docker buildx build \ |
| 79 | 89 | --target android-export \ |
| 90 | + --build-arg GITHUB_RUN_NUMBER="$RUN_NUMBER" \ | |
| 91 | + --build-arg SOURCE_DATE_EPOCH="$stamp" \ | |
| 80 | 92 | --secret id=keystore,src=./release.jks \ |
| 81 | 93 | --secret id=keystore_password,src=./keystore.pass \ |
| 82 | 94 | --output type=local,dest=./apk \ |
modified
android/Dockerfile
+18
−1
@@ -78,9 +78,26 @@ RUN ./gradlew --no-daemon :app:dependencies --configuration releaseRuntimeClassp
| 78 | 78 | FROM deps AS build |
| 79 | 79 | |
| 80 | 80 | ARG BUILD_TOOLS=34.0.0 |
| 81 | + | |
| 82 | +# A container build inherits nothing from the runner's environment, so | |
| 83 | +# the version has to be handed in explicitly. Without these, Gradle's | |
| 84 | +# getenv lookups come back empty inside here and every run builds | |
| 85 | +# versionCode 1 — the same filename with different bytes, which the | |
| 86 | +# registry refuses with a 409. | |
| 87 | +# | |
| 88 | +# Declared in this stage rather than at the top so they don't invalidate | |
| 89 | +# the SDK and dependency layers, which is most of the build time. | |
| 90 | +ARG GITHUB_RUN_NUMBER | |
| 91 | +ARG SOURCE_DATE_EPOCH | |
| 92 | +ARG RELEASE_VERSION | |
| 93 | +ENV GITHUB_RUN_NUMBER=${GITHUB_RUN_NUMBER} \ | |
| 94 | + SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} \ | |
| 95 | + RELEASE_VERSION=${RELEASE_VERSION} | |
| 96 | + | |
| 81 | 97 | COPY app ./app |
| 82 | 98 | |
| 83 | −RUN ./gradlew --no-daemon :app:assembleRelease | |
| 99 | +RUN echo "building versionCode=${GITHUB_RUN_NUMBER:-1}" \ | |
| 100 | + && ./gradlew --no-daemon :app:assembleRelease | |
| 84 | 101 | |
| 85 | 102 | # Sign as a separate step from Gradle so the keystore never reaches a |
| 86 | 103 | # build script, a Gradle cache, or an image layer. BuildKit secrets are |
modified
android/app/build.gradle.kts
+24
−5
@@ -5,10 +5,27 @@ plugins {
| 5 | 5 | alias(libs.plugins.kotlin.serialization) |
| 6 | 6 | } |
| 7 | 7 | |
| 8 | −// Bumped by hand for a real release; the build metadata after it comes | |
| 9 | −// from CI. | |
| 8 | +// Bumped by hand; everything after it is generated. | |
| 10 | 9 | val baseVersion = "0.1.0" |
| 11 | 10 | |
| 11 | +// Seconds, and taken from the environment when it's there. CI sets it | |
| 12 | +// once per run so every artifact from that run agrees; a local build | |
| 13 | +// computes it, which is fine because local builds are never published. | |
| 14 | +// | |
| 15 | +// SOURCE_DATE_EPOCH first because it's the cross-toolchain convention | |
| 16 | +// for exactly this, and honouring it means a reproducible-build harness | |
| 17 | +// that already sets it gets a reproducible versionName for free. | |
| 18 | +val buildTimestamp: Long = | |
| 19 | + (System.getenv("SOURCE_DATE_EPOCH") ?: System.getenv("BUILD_TIMESTAMP")) | |
| 20 | + ?.toLongOrNull() | |
| 21 | + ?: (System.currentTimeMillis() / 1000) | |
| 22 | + | |
| 23 | +// A real release overrides the whole string; until there is one, every | |
| 24 | +// build says so in its name rather than claiming to be 0.1.0. | |
| 25 | +val appVersionName: String = | |
| 26 | + System.getenv("RELEASE_VERSION")?.takeIf { it.isNotBlank() } | |
| 27 | + ?: "$baseVersion-dev-$buildTimestamp" | |
| 28 | + | |
| 12 | 29 | android { |
| 13 | 30 | namespace = "org.neiam.feedpug.app" |
| 14 | 31 | compileSdk = 34 |
@@ -29,9 +46,11 @@ android {
| 29 | 46 | // never published. |
| 30 | 47 | versionCode = (System.getenv("GITHUB_RUN_NUMBER") ?: "").toIntOrNull() ?: 1 |
| 31 | 48 | |
| 32 | − // The commit is what you want when someone reports a bug | |
| 33 | − // against a build. Local builds just say "dev". | |
| 34 | − versionName = "$baseVersion+" + ((System.getenv("GITHUB_SHA") ?: "dev").take(7)) | |
| 49 | + // Not the commit: versionCode is the CI run number, and a run | |
| 50 | + // knows its own commit, so the sha is one lookup away and the | |
| 51 | + // timestamp orders builds at a glance in a list that versionCode | |
| 52 | + // alone renders as bare integers. | |
| 53 | + versionName = appVersionName | |
| 35 | 54 | } |
| 36 | 55 | |
| 37 | 56 | buildTypes { |
Parents: 53dbc26