Closer/docs/release/internal-testing-checklist.md

173 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Closer — Internal Testing Build Checklist [SUPERSEDED]
> **Status (stamped 2026-07-11): SUPERSEDED by `docs/release/store-assets.md` (§5 signing, §8
> pre-launch) and the ship-readiness plan (`release_guide.md`, Phases 12b), which reflect the
> current release-guard build config, keystore plan, and Play internal-testing path.** Also note a
> factual error below: the applicationId is `closer.app` — `app.closer` is the code namespace (the
> same swap that produced the Manage-subscription deep-link bug fixed in `4e807cb0`). Kept as
> historical context only.
>
> Steps to prepare, sign, and distribute an internal testing build for the private MVP. Assumes Android Gradle Plugin 8.7.3, Kotlin 2.0.21, minSdk 26, targetSdk/compileSdk 35, and ~~`app.closer`~~ **`closer.app`** applicationId.
Internal testing should verify the product goal: **private, mutual-reveal relationship questions with real encryption and calmer UX**.
---
## 1. Pre-build Checklist
### 1.1 Source readiness
- [ ] All feature branches for the MVP merged into the internal testing branch.
- [ ] No unintended `TODO` / `FIXME` blockers in release code (documented in `docs/qa/private-mvp-checklist.md`).
- [ ] No `com.couplesconnect` package references remain (verified via `grep -RIn` across `app/src`).
- [ ] No debug-only logging left in non-debug code paths (verbose/debug logs removed; error logging acceptable).
- [ ] Version matches private MVP: `versionName` should be `0.1.x` and `versionCode` incremented for each distributed build.
- [ ] `local.properties` contains required secrets but is not committed to git.
### 1.2 Secrets and API keys
- [ ] `google-services.json` is present in `app/` and matches the internal testing package (`app.closer`).
- [ ] RevenueCat API key defined in `local.properties` as `RC_API_KEY`.
- [ ] Firebase App Check debug token removed or disabled for release.
- [ ] No hardcoded API keys, tokens, or credentials in Kotlin/XML source.
### 1.3 Build configuration
- [ ] `build.gradle.kts` has `isMinifyEnabled = true` and `isShrinkResources = true` for `release`.
- [ ] ProGuard rules file (`proguard-rules.pro`) reviewed for Compose, Hilt, Room, Firebase, RevenueCat, and Navigation.
- [ ] `compileSdk = 35`, `targetSdk = 35`, `minSdk = 26`.
- [ ] `namespace = "app.closer"` and `applicationId = "app.closer"`.
- [ ] Kotlin `jvmTarget = "17"` and Java 17 compatibility set.
- [ ] `buildConfig = true` and `compose = true` enabled.
---
## 2. Signing Config Checklist
### 2.1 Keystore
- [ ] Internal testing keystore generated or available (`.jks` / `.keystore`).
- [ ] Keystore password, key alias, and key password stored securely in CI or password manager — not in repo.
- [ ] Keystore used for signing is backed up in a secure location (1Password, team vault, hardware token).
- [ ] Key validity period covers expected lifetime of the app (Google Play requires validity past 22 Oct 2033 for app signing key uploads).
### 2.2 Gradle signing configuration
- [ ] `signingConfigs` block in `app/build.gradle.kts` configured:
```kotlin
signingConfigs {
create("release") {
storeFile = file(System.getenv("KEYSTORE_PATH") ?: "release.keystore")
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
}
}
```
- [ ] `buildTypes.release` references `signingConfigs.getByName("release")`.
- [ ] Local debug builds still use the default debug keystore.
### 2.3 Verify signed APK/AAB
- [ ] Build release APK or AAB: `./gradlew :app:assembleRelease` or `:app:bundleRelease`.
- [ ] Confirm output is signed: `apksigner verify --verbose app-release.apk`.
- [ ] Check certificate fingerprints and expiration.
- [ ] Verify v1 (JAR) and v2/v3 APK signatures are present.
---
## 3. Firebase / Production Environment Checklist
### 3.1 Firebase project
- [ ] Internal testing Firebase project created/separate from production.
- [ ] `app.closer` Android app registered with correct SHA-1/SHA-256 certificates.
- [ ] `google-services.json` downloaded and placed in `app/`.
### 3.2 Firebase services
- [ ] **Authentication**: Email/password provider enabled (and any OAuth providers used in the app).
- [ ] **Firestore**: Security rules reviewed; internal testing rules should match expected MVP rules.
- [ ] **Cloud Messaging**: Server key / FCM v1 credentials available for backend/push testing.
- [ ] **Crashlytics**: Crashlytics plugin applied and mapping file upload enabled.
- [ ] **Analytics**: No PII logged; events reviewed.
- [ ] **Remote Config**: Default values in-app handle absent remote values.
- [ ] **App Check**: Play Integrity provider configured for release builds; debug provider only for debug/internal.
### 3.3 Firebase secrets
- [ ] No Firebase API keys or FCM tokens committed.
- [ ] CI injects `google-services.json` or uses environment-based substitution.
---
## 4. Test Account Setup
### 4.1 Device / emulator accounts
- [ ] At least two test user accounts available (User A and User B) for couple pairing flows.
- [ ] Test accounts use `+` or tagged email addresses for isolation (e.g., `qa+a@closer.app`, `qa+b@closer.app`).
- [ ] Passwords stored in team vault; accounts enabled in Firebase Auth allowlist if applicable.
### 4.2 Data seeding
- [ ] Seed questions and categories in Firestore/remote config for internal testing.
- [ ] Seed at least one premium category and one free category.
- [ ] Prepare test RevenueCat products with sandbox pricing.
- [ ] Ensure test accounts have predictable subscription states (free, premium, expired).
### 4.3 Test scenarios matrix
| Scenario | User A | User B |
|----------|--------|--------|
| Unpaired new install | fresh account | fresh account |
| Paired couple | paired with B | paired with A |
| Premium unlock | subscribed | not subscribed |
| Different answer states | answered daily | not answered |
| Invite expiry | create invite | accept after expiry |
---
## 5. Distribution Checklist
### 5.1 Firebase App Distribution
- [ ] Firebase App Distribution Gradle plugin applied (optional but recommended).
- [ ] App Distribution configured with tester groups (e.g., `mvp-internal`, `qa-team`).
- [ ] Build variant selected: `release` (signed).
- [ ] Distribution command run: `./gradlew :app:assembleRelease :app:appDistributionUploadRelease`.
- [ ] Testers receive email/notification with download link.
- [ ] APK install succeeds and app launches.
### 5.2 Alternative distribution
- [ ] If not using App Distribution, use internal Google Play track with closed testing.
- [ ] Signed AAB uploaded to Play Console internal testing track.
- [ ] Testers added to internal testing list.
- [ ] Play Console review status tracked (internal tests may be immediately available).
### 5.3 Verification after install
- [ ] App installs and opens on target device.
- [ ] Onboarding flow reachable.
- [ ] Auth and pairing flows tested end-to-end on distributed build.
- [ ] Push notification received and quiet-hours suppression works.
- [ ] Paywall loads products in sandbox (where RevenueCat configured).
- [ ] Crashlytics reports non-fatal test event and appears in console.
---
## 6. Build Commands Reference
```bash
# Debug compile (fast smoke test)
./gradlew :app:compileDebugKotlin
# Debug install
./gradlew :app:installDebug
# Release APK (signed)
./gradlew :app:assembleRelease
# Release AAB (signed)
./gradlew :app:bundleRelease
# Firebase App Distribution upload
./gradlew :app:assembleRelease :app:appDistributionUploadRelease
```
---
## 7. Sign-off
| Role | Name | Date | Notes |
|------|------|------|-------|
| Build engineer | | | |
| QA lead | | | |
| Product owner | | | |