From 23911fceb59f9dd085a5c3b2f80de6ae49a03ea1 Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Thu, 8 Oct 2026 13:07:17 +0000 Subject: [PATCH] ci: build signed debug and release next builds on every main push Commit a public debug keystore and point the debug signing config at it, and add a next build type (release-like, same key). Both carry the .next application id, so next builds install alongside the release and update each other without exposing the release key. A GitHub workflow builds both APKs on every push to main and uploads them as artifacts. --- .github/workflows/build-next.yml | 39 +++++++++++++++++++++++++++++++ app/build.gradle.kts | 15 ++++++++++++ app/debug.keystore | Bin 0 -> 2666 bytes 3 files changed, 54 insertions(+) create mode 100644 .github/workflows/build-next.yml create mode 100644 app/debug.keystore diff --git a/.github/workflows/build-next.yml b/.github/workflows/build-next.yml new file mode 100644 index 00000000..5b6bbfcb --- /dev/null +++ b/.github/workflows/build-next.yml @@ -0,0 +1,39 @@ +name: Build Next + +on: + push: + branches: [main] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "21" + - name: Set up Android SDK + uses: android-actions/setup-android@v4 + - name: Install platform and build tools + run: sdkmanager "platforms;android-37" "build-tools;37.0.0" + - name: Build next builds + run: | + chmod +x gradlew + ./gradlew :app:assembleDebug :app:assembleNext --no-daemon + - name: Collect next builds + run: | + cp app/build/outputs/apk/debug/app-debug.apk subtracks-next-debug.apk + cp app/build/outputs/apk/next/app-next.apk subtracks-next.apk + - name: Upload next builds + uses: actions/upload-artifact@v4 + with: + name: subtracks-next + path: | + subtracks-next-debug.apk + subtracks-next.apk diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2c7b100e..f00b8610 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -80,6 +80,13 @@ android { .add("src/integrationTest/kotlin") signingConfigs { + // Committed on purpose: a public key for debug and next builds, never for distribution. + getByName("debug") { + storeFile = file("debug.keystore") + storePassword = "android" + keyAlias = "androiddebugkey" + keyPassword = "android" + } val keystorePath = providers.environmentVariable("RELEASE_KEYSTORE").orNull if (keystorePath != null) { create("release") { @@ -92,6 +99,9 @@ android { } buildTypes { + debug { + applicationIdSuffix = ".next" + } release { isMinifyEnabled = true isShrinkResources = true @@ -99,6 +109,11 @@ android { // Release signing when the keystore is supplied (CI); debug elsewhere so local build/install works. signingConfig = signingConfigs.findByName("release") ?: signingConfigs.getByName("debug") } + create("next") { + initWith(getByName("release")) + applicationIdSuffix = ".next" + signingConfig = signingConfigs.getByName("debug") + } } } diff --git a/app/debug.keystore b/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..cdd8a81d64cc87e774776692a6688802def16515 GIT binary patch literal 2666 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