Skip to content
This repository was archived by the owner on Jun 3, 2026. It is now read-only.

Build and Release

Aarsh edited this page May 28, 2026 · 3 revisions

Build & Release

The canonical release flow uses Gradle Play Publisher (GPP) wired in app/build.gradle.kts, with secrets pumped in by ./retrieve_secrets.sh. Both Windows and headless Ubuntu work; the Linux path is what CLI_RELEASE_GUIDE.md was originally written for.


Gradle tasks day-to-day

Task Output When
:app:assembleDebug app/build/outputs/apk/debug/app-debug.apk local dev, attach to GitHub pre-release
:app:bundleRelease app/build/outputs/bundle/release/app-release.aab (signed) uploaded to Play
:app:assembleRelease app/build/outputs/apk/release/app-release.apk (signed) rarely needed; Play accepts AAB only
:app:lintDebug app/build/reports/lint-results-debug.html sanity, also runs as lintVitalRelease during release builds
:app:signingReport console get SHA-1 / SHA-256 of your local debug keystore for Firebase Auth
:app:publishBundle uploads AAB to Play the release step (Beta by default — see below)
clean wipes build/ when in doubt

R8 (isMinifyEnabled = true) and resource shrinking are on for release builds. Firestore model classes are kept via proguard-rules.pro.


Cutting a beta release (steady-state pattern)

Beta is the default track for publishBundle. The typical flow:

# 1. Refresh secrets if you haven't this session
./retrieve_secrets.sh

# 2. Bump version in app/build.gradle.kts
#    versionCode: +1
#    versionName: e.g. "3.8-beta.8"

# 2b. Update the Play "What's New" (<=500 chars) — GPP uploads it automatically
#     app/src/main/play/release-notes/en-IN/default.txt

# 3. Sanity build first
./gradlew :app:assembleDebug

# 4. Commit + tag
git add app/build.gradle.kts <other changes>
git commit -m "feat: v3.8-beta.8 — <one-line summary>"
git tag -a v3.8-beta.8 -m "v3.8-beta.8 - <one-line summary>"
git push origin main
git push origin v3.8-beta.8

# 5. Build the signed AAB (also rebuilds the debug APK if not cached)
./gradlew :app:bundleRelease :app:assembleDebug

# 6. GitHub pre-release (attach the debug APK for sideload testers)
gh release create v3.8-beta.8 \
  --repo aarshps/varisankya-android \
  --title "v3.8-beta.8 - <summary> [emoji]" \
  --prerelease \
  --target main \
  --notes-file release-notes.md \
  app/build/outputs/apk/debug/app-debug.apk

# 7. Push to Play Beta
./gradlew :app:publishBundle

GPP's track defaults to beta (configured in app/build.gradle.kts). The upload appears immediately in Play Console → Testing → Open testing.


Play Store "What's New"

The Play changelog is separate from the GitHub release body and is not copied from it. GPP reads it from a version-controlled file and uploads it as part of every publishBundle:

app/src/main/play/release-notes/en-IN/default.txt   # ≤ 500 chars, all tracks

Update this file on every release before publishing. default.txt applies to all tracks; add beta.txt / production.txt siblings only if a track needs different copy. The notes attach to whatever versionCode is uploaded in that run — they cannot be re-attached to an already-uploaded versionCode via GPP (the artifact upload would conflict), so a missed update must be fixed in the Play Console directly or by shipping a new versionCode.

Historical note: before v3.8 this file didn't exist, so every publishBundle (including the v3.8 production push) went up with an empty "What's New". Keeping the file current is the fix.


Promoting to production

Same :app:publishBundle task, override the track at the CLI:

./gradlew :app:publishBundle -PplayTrack=production

For GitHub, drop the --prerelease flag (or promote an existing pre-release via the Releases UI).

Promotion-time checklist:

  • Beta has soaked for ≥ a few days with real testers exercising new flows.
  • No new crashes have shown up in Crashlytics / DebugView for the version code being promoted.
  • Analytics & Audit shows the changed flows are actually being used (or, for removed flows, that nobody's hit them).
  • app/src/main/play/release-notes/en-IN/default.txt updated for this version (GPP pushes it automatically on publishBundle; ≤ 500 chars; Play's changelog is separate from GitHub's).

GitHub release-notes format

Per CLI_RELEASE_GUIDE.md and what the v3.8-beta.* releases established:

Brief summary line.

## ✨ What's New
• Bullet — new feature.

## 🛠 Fixes & Improvements
• Bullet — bug fix.
• App version bumped to <Version> (Version Code <Code>).

## 🧪 Testing checklist
- [ ] Specific scenario the new code exercises.

Enjoying Varisankya? Consider leaving a star on GitHub! ⭐️

Title: vX.Y[-beta.N] - <concise summary> [emoji] — e.g. v3.8-beta.7 - Native Pixel polish & robust averaging ✨.


Signing setup

The release signing config in app/build.gradle.kts reads from local.properties:

signingConfigs {
    create("release") {
        val storeFilePath = localProperties.getProperty("RELEASE_STORE_FILE")
        if (storeFilePath != null) {
            storeFile = file(storeFilePath)
            storePassword = localProperties.getProperty("RELEASE_STORE_PASSWORD")
            keyAlias = localProperties.getProperty("RELEASE_KEY_ALIAS")
            keyPassword = localProperties.getProperty("RELEASE_KEY_PASSWORD")
        }
    }
}

retrieve_secrets.sh writes those four keys into local.properties (and the matching keystore file into the repo root). Do not commit any of them — .gitignore already covers local.properties and the upload key.

If you need to rotate the upload key, you also need to register the new SHA-1 in the Firebase Console for com.hora.varisankya (otherwise Google Sign-In breaks on release builds). See Firebase Setup.


Where artifacts go

Path Purpose
app/build/outputs/apk/debug/app-debug.apk Attach to GitHub pre-release for sideload testers.
app/build/outputs/bundle/release/app-release.aab Uploaded to Play by publishBundle.
app/build/outputs/mapping/release/mapping.txt R8 mapping — needed to deobfuscate stack traces. Crashlytics auto-uploads if wired; manually upload via Play Console otherwise.
app/build/reports/lint-results-debug.html Lint findings.

All of build/ is gitignored; safe to ./gradlew clean whenever.


CI

There is no CI committed at the time of writing. Releases are cut by hand from your workstation or the headless Ubuntu box. If you wire up GitHub Actions later, secrets need to come from a secrets store (don't bake Bitwarden CLI into CI — use Actions secrets directly), and the publishBundle step needs the same service-account JSON we currently retrieve.

Clone this wiki locally