SKILL.md
---
name: android-release-build-setup
description: Complete Android release build configuration - orchestrates keystore, ProGuard, and signing setup
category: android
version: 2.0.0
---
# Android Release Build Setup
This skill orchestrates complete Android release build configuration by running three atomic skills in sequence.
## What This Does
Sets up everything needed for Android release builds:
1. **Keystore Generation** - Production and local dev keystores
2. **ProGuard/R8 Configuration** - Code minification and optimization
3. **Signing Configuration** - Dual-source signing (CI/CD + local dev)
## Prerequisites
- Android project with Gradle
- JDK installed (for keytool command)
- Project uses Kotlin DSL (build.gradle.kts)
## Process
This skill runs three sub-skills in order:
### Step 1: Generate Keystores
Follow the skill at: `~/claude-devtools/skills/android-keystore-generation/SKILL.md`
**What it does:**
- Creates production keystore (for CI/CD only)
- Creates local development keystore
- Generates KEYSTORE_INFO.txt with credentials
- Updates .gitignore
**Verify before continuing:**
```bash
ls keystores/*.jks
cat keystores/KEYSTORE_INFO.txt
```
---
### Step 2: Configure ProGuard/R8
Follow the skill at: `~/claude-devtools/skills/android-proguard-setup/SKILL.md`
**What it does:**
- Creates proguard-rules.pro with safe defaults
- Enables minification in build.gradle.kts
- Enables resource shrinking
**Verify before continuing:**
```bash
test -f app/proguard-rules.pro
grep "isMinifyEnabled = true" app/build.gradle.kts
```
---
### Step 3: Configure Signing
Follow the skill at: `~/claude-devtools/skills/android-signing-config/SKILL.md`
**What it does:**
- Adds signingConfigs to build.gradle.kts
- Creates gradle.properties.template
- Configures ~/.gradle/gradle.properties (with permission)
- Adds validation for missing signing config
**Verify before continuing:**
```bash
./gradlew assembleRelease
jarsigner -verify app/build/outputs/apk/release/app-release.apk
```
---
## Final Verification (MANDATORY)
After all three skills complete, verify the complete setup:
```bash
# 1. Clean build
./gradlew clean
# 2. Build release APK
./gradlew assembleRelease
# 3. Verify APK exists
ls -lh app/build/outputs/apk/release/app-release.apk
# 4. Verify ProGuard mapping generated
ls -lh app/build/outputs/mapping/release/mapping.txt
# 5. Verify signing
jarsigner -verify -verbose -certs app/build/outputs/apk/release/app-release.apk
```
**All checks must pass** before marking this skill as complete.
## Completion Criteria
Do NOT mark complete unless ALL are verified:
✅ **Keystores generated and secured**
- [ ] production-release.jks exists in keystores/
- [ ] local-dev-release.jks exists in keystores/
- [ ] KEYSTORE_INFO.txt created with passwords
- [ ] keystores/ added to .gitignore
✅ **ProGuard configured**
- [ ] proguard-rules.pro exists with safe defaults
- [ ] isMinifyEnabled = true in build.gradle.kts
- [ ] isShrinkResources = true in build.gradle.kts
✅ **Signing configured**
- [ ] signingConfigs.release exists in build.gradle.kts
- [ ] Release buildType uses signingConfig
- [ ] gradle.properties configured (local) OR environment variables set (CI)
✅ **MANDATORY: Build verification**
- [ ] `./gradlew assembleDebug` succeeds
- [ ] `./gradlew assembleRelease` succeeds
- [ ] app/build/outputs/apk/release/app-release.apk exists
- [ ] app/build/outputs/mapping/release/mapping.txt exists
- [ ] `jarsigner -verify` confirms APK is signed correctly
## Summary Report
After completion, provide this summary:
```
✅ Android Release Build Setup Complete!
📦 Keystores Generated:
Production: keystores/production-release.jks (CI/CD only)
Local Dev: keystores/local-dev-release.jks (local testing)
Credentials: keystores/KEYSTORE_INFO.txt
🔒 ProGuard/R8 Configuration:
✓ Minification enabled
✓ Resource shrinking enabled
✓ Safe default rules: app/proguard-rules.pro
⚙️ Build Configuration:
✓ Signing config added to app/build.gradle.kts
✓ Dual-source strategy (env vars + gradle.properties)
✓ Validation on release builds
📋 Next Steps:
For Local Development:
./gradlew assembleRelease
./gradlew installRelease
For CI/CD (GitHub Actions):
Add GitHub Secrets (see KEYSTORE_INFO.txt):
- SIGNING_KEY_STORE_BASE64
- SIGNING_KEY_ALIAS
- SIGNING_STORE_PASSWORD
- SIGNING_KEY_PASSWORD
⚠️ CRITICAL REMINDERS:
- NEVER commit keystores to git
- NEVER use production keystore locally
- ALWAYS back up production keystore securely
- Loss of production keystore = cannot update app!
```
## Integration with Other Skills
This skill is prerequisite for:
- `android-e2e-testing-setup` - Tests release builds
- `android-release-validation` - Validates signed APK/AAB
- `android-playstore-publishing` - Uses keystore for CI/CD workflow
- `android-playstore-pipeline` - Orchestrates full setup
## Troubleshooting
If any skill fails:
1. Fix the specific issue in that skill
2. Re-run that skill until it completes
3. Continue with remaining skills
4. Run final verification
Common issues:
- **Keystore generation fails** → Install JDK
- **ProGuard breaks build** → Add keep rules
- **Signing fails** → Check gradle.properties paths
templates/gitignore-additions.txt
# Android Release Build - Keystores and Secrets
# CRITICAL: Never commit these files - they contain sensitive credentials!
# Keystores (production and local development)
keystores/
*.jks
*.keystore
KEYSTORE_INFO.txt
# Gradle properties with secrets
gradle.properties
# ProGuard/R8 mapping files
# (Keep for debugging, but don't commit - can be large)
app/build/outputs/mapping/
**/mapping.txt
# Release build outputs (optional - uncomment if you want to exclude)
# app/build/outputs/apk/release/
# app/build/outputs/bundle/release/
templates/gradle.properties.template
# Template for local development signing configuration
# Copy this to gradle.properties (gitignored) and fill in values
# Path to your LOCAL development keystore (NOT production!)
SIGNING_KEY_STORE_PATH=/path/to/keystores/local-dev-release.jks
# Local development keystore credentials
SIGNING_KEY_ALIAS=local-dev
SIGNING_STORE_PASSWORD=your-local-dev-password
SIGNING_KEY_PASSWORD=your-local-dev-password
#===============================================================================
# IMPORTANT SECURITY NOTES:
#===============================================================================
# 1. This is for LOCAL testing of release builds ONLY
# 2. NEVER use production keystore locally
# 3. Production keystore lives ONLY in CI/CD (GitHub Secrets)
# 4. Each developer should have their own unique local keystore
# 5. Never commit gradle.properties to version control
#
# To generate your local development keystore, run:
# /devtools:android-release-setup
#
# The skill will generate both keystores and configure everything for you.
templates/KEYSTORE_INFO.txt.template
Production Keystore Information
===============================
CRITICAL SECURITY WARNING:
- This file contains PRODUCTION signing credentials
- NEVER commit this file to version control
- NEVER share this file with anyone
- Store these credentials in a secure password manager
- Back up this keystore to multiple secure locations
- Loss of this keystore means you CANNOT update your app on Google Play!
Keystore Details:
-----------------
Location: keystores/production-release.jks
Alias: {KEY_ALIAS}
Store Password: {STORE_PASSWORD}
Key Password: {KEY_PASSWORD}
Created: {CREATION_DATE}
Validity: {VALIDITY_DAYS} days (~27 years)
Distinguished Name:
-------------------
{DISTINGUISHED_NAME}
GitHub Secrets Setup:
---------------------
For CI/CD deployment, add these secrets to your GitHub repository:
(Repository Settings → Secrets and variables → Actions → New repository secret)
1. SIGNING_KEY_STORE_BASE64
Value: Run this command and copy the output:
For Linux/Mac:
base64 -w 0 keystores/production-release.jks
For Windows (PowerShell):
[Convert]::ToBase64String([IO.File]::ReadAllBytes('keystores\production-release.jks'))
2. SIGNING_KEY_ALIAS
Value: {KEY_ALIAS}
3. SIGNING_STORE_PASSWORD
Value: {STORE_PASSWORD}
4. SIGNING_KEY_PASSWORD
Value: {KEY_PASSWORD}
Backup Instructions:
--------------------
1. Store this file in a secure password manager (1Password, Bitwarden, etc.)
2. Back up the keystore file (production-release.jks) to:
- Secure cloud storage (encrypted)
- Offline secure location (USB drive, safe)
- Company secure vault (if applicable)
3. Document the backup locations in your company's secure documentation
Security Best Practices:
------------------------
✓ Production keystore ONLY in CI/CD environment (GitHub Secrets)
✓ Never store production keystore on developer machines
✓ Use local development keystore for testing (different file)
✓ Each developer has their own unique local keystore
✓ Rotate service accounts periodically (keystore stays the same)
✓ Monitor GitHub Actions logs for unauthorized access attempts
Next Steps:
-----------
1. Store these credentials securely (password manager + backups)
2. Add GitHub Secrets for CI/CD deployment
3. Use android-playstore-publishing skill to generate GitHub workflow
4. Never commit this file or the keystore to git (.gitignore configured)
Support:
--------
If you lose access to this keystore:
- You CANNOT update your existing app on Google Play
- You will need to publish as a completely new app (new package name)
- All existing users will need to uninstall and reinstall
- This is why backups are CRITICAL!
templates/proguard-rules.pro
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in the Android SDK.
#===============================================================================
# DEBUGGING
#===============================================================================
# Keep line numbers for debugging stack traces
-keepattributes SourceFile,LineNumberTable
# Hide the original source file name
-renamesourcefileattribute SourceFile
#===============================================================================
# KOTLIN & ANDROID ESSENTIALS
#===============================================================================
# Keep Kotlin metadata
-keepattributes *Annotation*
# Keep data classes and their fields (Kotlin serialization)
-keepclassmembers class * {
@kotlinx.serialization.SerialName <fields>;
}
# Keep Parcelables
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# Keep custom views
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# Keep native methods
-keepclasseswithmembernames class * {
native <methods>;
}
# Keep enum classes
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#===============================================================================
# COMMON LIBRARY RULES
#===============================================================================
# Add rules for libraries your project uses below
# --- Gson ---
# Uncomment if using Gson
# -keepattributes Signature
# -keepattributes *Annotation*
# -dontwarn sun.misc.**
# -keep class * implements com.google.gson.TypeAdapter
# -keep class * implements com.google.gson.TypeAdapterFactory
# -keep class * implements com.google.gson.JsonSerializer
# -keep class * implements com.google.gson.JsonDeserializer
# -keepclassmembers,allowobfuscation class * {
# @com.google.gson.annotations.SerializedName <fields>;
# }
# --- Retrofit 2 ---
# Uncomment if using Retrofit
# -dontwarn retrofit2.**
# -keep class retrofit2.** { *; }
# -keepattributes Signature
# -keepattributes Exceptions
# -keepclasseswithmembers class * {
# @retrofit2.http.* <methods>;
# }
# --- OkHttp3 ---
# Uncomment if using OkHttp
# -dontwarn okhttp3.**
# -dontwarn okio.**
# -keep class okhttp3.** { *; }
# -keep interface okhttp3.** { *; }
# --- Room ---
# Uncomment if using Room
# -keep class * extends androidx.room.RoomDatabase
# -keep @androidx.room.Entity class *
# -dontwarn androidx.room.paging.**
# --- Glide ---
# Uncomment if using Glide
# -keep public class * implements com.bumptech.glide.module.GlideModule
# -keep class * extends com.bumptech.glide.module.AppGlideModule {
# <init>(...);
# }
# -keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
# **[] $VALUES;
# public *;
# }
#===============================================================================
# PROJECT-SPECIFIC RULES
#===============================================================================
# Add your project-specific keep rules below
templates/signing-config.gradle.kts
// Android Release Build Signing Configuration
// This configuration supports dual-source credentials:
// 1. Environment variables (CI/CD priority)
// 2. gradle.properties (local development fallback)
signingConfigs {
create("release") {
// Priority: environment variables (CI/CD) > gradle.properties (local dev)
val keystorePath = System.getenv("SIGNING_KEY_STORE_PATH")
?: project.findProperty("SIGNING_KEY_STORE_PATH")?.toString()
val storePass = System.getenv("SIGNING_STORE_PASSWORD")
?: project.findProperty("SIGNING_STORE_PASSWORD")?.toString()
val alias = System.getenv("SIGNING_KEY_ALIAS")
?: project.findProperty("SIGNING_KEY_ALIAS")?.toString()
val keyPass = System.getenv("SIGNING_KEY_PASSWORD")
?: project.findProperty("SIGNING_KEY_PASSWORD")?.toString()
if (keystorePath != null && storePass != null && alias != null && keyPass != null) {
storeFile = file(keystorePath)
storePassword = storePass
keyAlias = alias
keyPassword = keyPass
}
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
// Validate signing config only when building release variants
tasks.matching { it.name.contains("Release") }.configureEach {
doFirst {
val releaseConfig = android.signingConfigs.getByName("release")
if (releaseConfig.storeFile == null) {
throw GradleException(
"""
Release signing not configured!
For CI/CD: Set environment variables:
- SIGNING_KEY_STORE_PATH
- SIGNING_STORE_PASSWORD
- SIGNING_KEY_ALIAS
- SIGNING_KEY_PASSWORD
For local development: Add to ~/.gradle/gradle.properties:
SIGNING_KEY_STORE_PATH=/path/to/local-dev-release.jks
SIGNING_STORE_PASSWORD=your-password
SIGNING_KEY_ALIAS=local-dev
SIGNING_KEY_PASSWORD=your-password
See gradle.properties.template for more details.
""".trimIndent()
)
}
}
}