Files
Krow-workspace/docs/RELEASE/APK_SIGNING_IMPLEMENTATION_SUMMARY.md
Achintha Isuru 8b9a58adb1 feat: Add mobile CI/CD secrets setup for APK signing
- Updated Makefile to include new command for setting up mobile CI secrets.
- Enhanced tools.mk with setup-mobile-ci-secrets target.
- Created setup-mobile-github-secrets.sh script for configuring GitHub Secrets for APK signing.
- Added APK signing implementation summary documentation.
- Created detailed APK signing setup guide.
- Added GitHub secrets checklist for easy reference.
2026-03-05 13:55:38 -05:00

364 lines
14 KiB
Markdown
Raw 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.
# APK Signing Implementation - Complete Summary
**Status**: ✅ Implementation Complete | 🟡 Secrets Configuration Pending
**Last Updated**: 2024
---
## 📋 What Was Implemented
### 1. GitHub Actions Workflow Updates
**File**: `.github/workflows/product-release.yml`
**New Steps Added**:
1. **🔐 Setup APK Signing** (before build)
- Detects app (worker/client) and environment (dev/stage/prod)
- Decodes keystore from GitHub Secrets
- Sets CodeMagic-compatible environment variables
- Configures `CI=true` for build.gradle.kts detection
- Gracefully handles missing secrets with warnings
2. **✅ Verify APK Signature** (after build)
- Verifies APK is properly signed using `jarsigner`
- Displays certificate details
- Shows signer information
- Provides helpful warnings if unsigned
**How It Works**:
```yaml
Setup Signing:
- Reads: ${{ secrets.WORKER_KEYSTORE_DEV_BASE64 }}
- Decodes to: /tmp/keystores/release.jks
- Sets env: CI=true, CM_KEYSTORE_PATH_STAFF=/tmp/keystores/release.jks
Build APK:
- Runs: make mobile-staff-build PLATFORM=apk MODE=release
- build.gradle.kts detects CI=true
- Uses environment variables for signing
Verify Signature:
- Checks with: jarsigner -verify app-release.apk
- Displays certificate info
```
### 2. Documentation Created
**Files Created**:
| File | Purpose | Lines |
|------|---------|-------|
| [docs/RELEASE/APK_SIGNING_SETUP.md](../../docs/RELEASE/APK_SIGNING_SETUP.md) | Complete setup guide | 300+ |
| [docs/RELEASE/GITHUB_SECRETS_CHECKLIST.md](../../docs/RELEASE/GITHUB_SECRETS_CHECKLIST.md) | Quick reference checklist | 120+ |
| [.github/scripts/setup-github-secrets.sh](../../.github/scripts/setup-github-secrets.sh) | Helper script | 200+ |
### 3. Scripts Created
**File**: `.github/scripts/setup-github-secrets.sh`
**Purpose**: Interactive helper to:
- Show which secrets are needed
- Generate base64 from existing keystores
- Display keytool information
- Provide copy-paste commands
**Usage**:
```bash
./.github/scripts/setup-github-secrets.sh
```
---
## 🔑 GitHub Secrets Required
**Total: 24 Secrets** (6 keystores × 4 properties each)
### Secret Naming Pattern:
```
{APP}_KEYSTORE_{ENV}_BASE64
{APP}_KEYSTORE_PASSWORD_{ENV}
{APP}_KEY_ALIAS_{ENV}
{APP}_KEY_PASSWORD_{ENV}
```
Where:
- `{APP}` = `WORKER` or `CLIENT`
- `{ENV}` = `DEV`, `STAGING`, or `PROD`
### Full List:
**Worker Mobile (12 secrets)**:
- `WORKER_KEYSTORE_DEV_BASE64`, `WORKER_KEYSTORE_PASSWORD_DEV`, `WORKER_KEY_ALIAS_DEV`, `WORKER_KEY_PASSWORD_DEV`
- `WORKER_KEYSTORE_STAGING_BASE64`, `WORKER_KEYSTORE_PASSWORD_STAGING`, `WORKER_KEY_ALIAS_STAGING`, `WORKER_KEY_PASSWORD_STAGING`
- `WORKER_KEYSTORE_PROD_BASE64`, `WORKER_KEYSTORE_PASSWORD_PROD`, `WORKER_KEY_ALIAS_PROD`, `WORKER_KEY_PASSWORD_PROD`
**Client Mobile (12 secrets)**:
- `CLIENT_KEYSTORE_DEV_BASE64`, `CLIENT_KEYSTORE_PASSWORD_DEV`, `CLIENT_KEY_ALIAS_DEV`, `CLIENT_KEY_PASSWORD_DEV`
- `CLIENT_KEYSTORE_STAGING_BASE64`, `CLIENT_KEYSTORE_PASSWORD_STAGING`, `CLIENT_KEY_ALIAS_STAGING`, `CLIENT_KEY_PASSWORD_STAGING`
- `CLIENT_KEYSTORE_PROD_BASE64`, `CLIENT_KEYSTORE_PASSWORD_PROD`, `CLIENT_KEY_ALIAS_PROD`, `CLIENT_KEY_PASSWORD_PROD`
---
## 🚀 How to Configure
### Step 1: Prepare Dev Keystores
Dev keystores are already in the repository:
- Worker: `apps/mobile/apps/staff/android/app/krow_with_us_staff_dev.jks`
- Client: `apps/mobile/apps/client/android/app/krow_with_us_client_dev.jks`
Generate base64:
```bash
# Worker Dev
base64 -i apps/mobile/apps/staff/android/app/krow_with_us_staff_dev.jks
# Client Dev
base64 -i apps/mobile/apps/client/android/app/krow_with_us_client_dev.jks
```
### Step 2: Retrieve Staging/Prod Keystores
**Option A**: From CodeMagic
1. Go to CodeMagic → Team Settings → Code signing identities
2. Download keystores: `krow_staff_staging.jks`, `krow_staff_prod.jks`, etc.
3. Generate base64 for each
**Option B**: From Secure Storage
1. Retrieve from your organization's key management system
2. Generate base64 for each
### Step 3: Add to GitHub
1. Go to: **Repository → Settings → Secrets and variables → Actions**
2. Click: **New repository secret**
3. Add all 24 secrets (use checklist: [GITHUB_SECRETS_CHECKLIST.md](../../docs/RELEASE/GITHUB_SECRETS_CHECKLIST.md))
### Step 4: Test the Workflow
```bash
# Test with dev environment first
# Go to: Actions → Product Release → Run workflow
# Select:
# - App: worker-mobile-app
# - Environment: dev
# - Version type: patch
# - Create GitHub Release: true
```
**Expected Output**:
```
🔐 Setting up Android signing for worker-mobile-app in dev environment...
✅ Keystore decoded successfully
📦 Keystore size: 3.2K
✅ Signing environment configured for STAFF (dev environment)
🔑 Using key alias: krow_staff_dev
📱 Building Staff (Worker) APK...
✅ APK built successfully
🔍 Verifying APK signature...
✅ APK is properly signed!
📜 Certificate Details: [shows cert info]
```
---
## 🔒 Security Considerations
### ✅ Safe Practices
1. **Dev keystores in repo**: Acceptable for development
- Committed: `krow_with_us_staff_dev.jks`, `krow_with_us_client_dev.jks`
- Password: `krowwithus` (public knowledge)
2. **Staging/Prod keystores**: ONLY in GitHub Secrets
- Never commit to repository
- Encrypted at rest by GitHub
- Only accessible in workflow runs
3. **Keystore cleanup**: Workflow stores in `${{ runner.temp }}`
- Automatically deleted after job completes
- Not persisted in artifacts or logs
### ⚠️ Important Notes
1. **Same keystores as CodeMagic**: Use identical keystores to ensure app updates work
2. **Signature consistency**: Apps signed with different keystores cannot update each other
3. **Key rotation**: Document process for rotating production keys
4. **Backup keystores**: Keep secure backups - lost keystores = can't update app
---
## 🧪 Testing Checklist
Before using in production:
- [ ] Configure all 24 GitHub Secrets
- [ ] Run workflow with `dev` environment
- [ ] Download APK artifact
- [ ] Verify signature: `jarsigner -verify -verbose app.apk`
- [ ] Install APK on Android device
- [ ] Launch app and verify functionality
- [ ] Compare signature fingerprints with CodeMagic builds
- [ ] Test `stage` environment
- [ ] Test `prod` environment (after full validation)
---
## 📊 Architecture Overview
```
┌─────────────────────────────────────────────────────────────┐
│ GitHub Actions Workflow: product-release.yml │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Validate & Create Release │
│ └─> Extract version from pubspec.yaml │
│ └─> Create Git tag │
│ └─> Create GitHub Release │
│ │
│ 2. Build Mobile Artifacts │
│ │ │
│ ├─> Setup Node.js + Firebase CLI │
│ ├─> Setup Java 17 │
│ ├─> Setup Flutter 3.24.5 │
│ ├─> Install Melos │
│ ├─> Install Dependencies │
│ │ │
│ ├─> 🔐 Setup APK Signing (NEW) │
│ │ ├─> Detect app (worker/client) │
│ │ ├─> Detect environment (dev/stage/prod) │
│ │ ├─> Read GitHub Secret: │
│ │ │ {APP}_KEYSTORE_{ENV}_BASE64 │
│ │ ├─> Decode base64 → .jks file │
│ │ ├─> Set environment variables: │
│ │ │ - CI=true │
│ │ │ - CM_KEYSTORE_PATH_STAFF=/tmp/keystore.jks │
│ │ │ - CM_KEYSTORE_PASSWORD_STAFF=*** │
│ │ │ - CM_KEY_ALIAS_STAFF=krow_staff_dev │
│ │ │ - CM_KEY_PASSWORD_STAFF=*** │
│ │ └─> ✅ Ready for signed build │
│ │ │
│ ├─> 🏗️ Build APK │
│ │ └─> make mobile-staff-build PLATFORM=apk │
│ │ └─> Flutter build detects CI=true │
│ │ └─> build.gradle.kts uses env vars │
│ │ └─> Signs APK with keystore │
│ │ │
│ ├─> ✅ Verify APK Signature (NEW) │
│ │ ├─> jarsigner -verify app-release.apk │
│ │ ├─> Show certificate details │
│ │ └─> Confirm signing successful │
│ │ │
│ ├─> 📤 Upload APK as Artifact │
│ │ └─> 30-day retention in GitHub Actions │
│ │ │
│ └─> 📦 Attach APK to GitHub Release │
│ └─> krow-withus-worker-mobile-dev-v0.1.0.apk │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Build Configuration: build.gradle.kts │
├─────────────────────────────────────────────────────────────┤
│ │
│ signingConfigs { │
│ create("release") { │
│ if (System.getenv()["CI"] == "true") { │
│ // ✅ GitHub Actions / CodeMagic │
│ storeFile = file( │
│ System.getenv()["CM_KEYSTORE_PATH_STAFF"] │
│ ) │
│ storePassword = │
│ System.getenv()["CM_KEYSTORE_PASSWORD_*"] │
│ keyAlias = │
│ System.getenv()["CM_KEY_ALIAS_*"] │
│ keyPassword = │
│ System.getenv()["CM_KEY_PASSWORD_*"] │
│ } else { │
│ // Local Development │
│ use key.properties file │
│ } │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## 📖 Documentation Index
1. **[APK_SIGNING_SETUP.md](../../docs/RELEASE/APK_SIGNING_SETUP.md)**
- Complete setup guide with all details
- Security best practices
- Troubleshooting guide
- Keystore management commands
2. **[GITHUB_SECRETS_CHECKLIST.md](../../docs/RELEASE/GITHUB_SECRETS_CHECKLIST.md)**
- Quick reference for all 24 secrets
- Copy-paste checklist
- Dev environment values
3. **[setup-mobile-github-secrets.sh](../../.github/scripts/setup-mobile-github-secrets.sh)**
- Interactive helper script
- Shows existing keystores
- Generates base64 commands
- Displays keytool info
4. **[product-release.yml](../../.github/workflows/product-release.yml)**
- Updated workflow with signing
- Lines 198-294: Setup APK Signing
- Lines 330-364: Verify APK Signature
---
## ✅ Next Steps
### Immediate (Required for Signed APKs)
1. **Configure GitHub Secrets** (30 minutes)
- Start with dev environment (test first)
- Use helper script: `.github/scripts/setup-mobile-github-secrets.sh`
- Follow checklist: `docs/RELEASE/GITHUB_SECRETS_CHECKLIST.md`
2. **Test Dev Signing** (15 minutes)
- Run workflow with dev environment
- Download APK and verify signature
- Install on device and test
3. **Configure Staging/Prod** (30 minutes)
- Retrieve keystores from CodeMagic/secure storage
- Add to GitHub Secrets
- Test each environment
### Future Enhancements (Optional)
- [ ] Add AAB (Android App Bundle) support for Play Store
- [ ] Implement iOS signing for IPA files
- [ ] Add automated Play Store upload
- [ ] Set up GitHub Environments with protection rules
- [ ] Add Slack notifications for releases
---
## 🆘 Support
If you encounter issues:
1. Check workflow logs for signing step output
2. Verify GitHub Secrets are configured correctly
3. Run helper script: `.github/scripts/setup-mobile-github-secrets.sh`
4. Review: `docs/RELEASE/APK_SIGNING_SETUP.md` → Troubleshooting section
**Common Issues**:
- "Keystore not found" → Secret not configured or wrong name
- "Wrong password" → Secret value doesn't match actual keystore
- APK unsigned → CI=true not set or build.gradle.kts issue
- App won't install over existing → Different keystore used
---
**Implementation Date**: 2024
**Implemented By**: GitHub Copilot (Claude Sonnet 4.5)
**Status**: ✅ Code Complete | 🟡 Awaiting Secrets Configuration