Last Updated: 2026-02-13 Total Scripts: 17 Categories: Setup (4) | iOS Deployment (3) | iOS Setup (2) | Verification (3) | Utilities (5)
- Overview
- Setup Scripts
- iOS Deployment Scripts
- iOS Setup Scripts
- Verification Scripts
- Utility Scripts
- Common Tasks
- Troubleshooting
This directory contains 17 bash scripts for project setup, deployment, and verification.
Script Categories:
setup/
├── setup-project.sh (565 lines) - Master orchestrator
├── customizer.sh (566 lines) - Package name customization
├── firebase-setup.sh (469 lines) - Firebase project setup
└── keystore-manager.sh (1,356 lines) - Keystore & secrets management
ios-deployment/
├── deploy_firebase.sh - iOS Firebase deployment
├── deploy_testflight.sh - iOS TestFlight deployment
└── deploy_appstore.sh - iOS App Store deployment
ios-setup/
├── setup_ios_complete.sh (518 lines) - Complete iOS setup wizard
└── setup_apn_key.sh - APN key configuration
verification/
├── verify_ios_deployment.sh (365 lines, 70+ checks)
├── verify_apn_setup.sh - APN verification
└── check_ios_version.sh - Version sanitization display
utilities/
├── check_environment.sh - Environment validation
├── check_file_env_keys.sh - Environment file validation
├── check-commit-signing.sh - Git commit signing check
├── ensure_base64.sh - Base64 encoding helper
└── fix-detekt-permissions.sh - Detekt config permissions fix
Purpose: Master orchestration script for complete project setup
Usage:
./setup-project.shWhat it does:
-
Validates Prerequisites:
- Checks for:
git,gh(GitHub CLI),firebase,keytool,openssl,python3 - Verifies: Git repository initialized, clean working directory
- Checks for:
-
Collects User Inputs:
- Package names (Android, iOS)
- Organization info (name, department, city, country)
- Firebase project info
- Keystore passwords
-
Orchestrates Setup:
- Runs
customizer.shto update package names - Runs
firebase-setup.shto create Firebase projects - Runs
keystore-manager.shto generate keystores - Runs iOS setup (if user confirms)
- Runs
-
Generates Documentation:
- Creates
PROJECT_SETUP_INFO.txtwith all configuration details - Saves to project root
- Creates
Interactive Prompts:
- Android package name
- iOS bundle identifier
- Organization details
- Firebase configuration
- iOS setup confirmation
Output:
- Updated package names across project
- Firebase projects configured
- Keystores generated
- Secrets encoded for GitHub Actions
PROJECT_SETUP_INFO.txtdocumentation
Line Count: 565 lines
Purpose: Update package names and namespaces throughout the project
Usage:
./customizer.shWhat it does:
-
Collects Package Info:
- Android package name (e.g.,
com.example.app) - iOS bundle identifier (e.g.,
com.example.app)
- Android package name (e.g.,
-
Updates Android Configuration:
build.gradle.kts:namespace,applicationIdfastlane-config/project_config.rb: ANDROID hash
-
Updates iOS Configuration:
- Xcode project:
PRODUCT_BUNDLE_IDENTIFIER fastlane-config/project_config.rb: IOS hash- Preserves
IOS_SHAREDsection (critical!)
- Xcode project:
-
Creates google-services.json:
- Generates template with 4 variants:
release,debug,demo,demo.debug
- Placeholder app IDs (will be updated by
firebase-setup.sh)
- Generates template with 4 variants:
-
Updates libs.versions.toml:
androidPackageNamespaceversion
firebase-setup.sh after this to populate real Firebase app IDs
Interactive: Yes (prompts for package names)
Line Count: 566 lines
Purpose: Create Firebase projects and register Android/iOS apps
Usage:
./firebase-setup.shWhat it does:
-
Creates Firebase Project:
- Project ID from Android package name
- Adds Firebase Admin SDK
-
Registers Apps (2 Android + 1 iOS):
- Android Prod:
{package}.prod(SHA-1 certificate) - Android Demo:
{package}.demo.debug(SHA-1 certificate) - iOS:
{bundle_id}(no SHA required)
- Android Prod:
-
Downloads Configurations:
google-services.jsonfor each Android appGoogleService-Info.plistfor iOS
-
Merges Configurations:
- Uses Python script to merge 2 Android configs into 4-variant
google-services.json - Optimization: Only 2 apps registered in Firebase (saves quota), but 4 variants in config
- Uses Python script to merge 2 Android configs into 4-variant
-
Saves to Correct Locations:
cmp-android/google-services.jsoncmp-ios/GoogleService-Info.plist
Prerequisites:
firebaseCLI installed and logged inpython3installed- Android keystore exists (for SHA-1 certificate)
Variant Mapping:
Firebase App → Config Variant
---------------------------------------------
{package}.prod → release, prod
{package}.demo.debug → debug, demo, demo.debug
Interactive: Yes (project name, confirmation)
Line Count: 469 lines
Purpose: Complete keystore and secrets management tool
Usage:
./keystore-manager.sh <command>Commands:
Generate ORIGINAL and UPLOAD keystores
./keystore-manager.sh generateWhat it does:
- Validates
keytoolandopensslinstalled - Loads configuration from
secrets.env(or prompts for input) - Generates ORIGINAL keystore:
- File:
keystores/{package}_original.keystore - Used for app signing
- File:
- Generates UPLOAD keystore:
- File:
keystores/{package}_upload.keystore - Used for Play Console (Play App Signing)
- File:
- Extracts certificates and keys
- Saves configuration to
secrets.env
Interactive: Yes (if no secrets.env)
Encode all secrets in secrets/ directory to base64
./keystore-manager.sh encode-secretsWhat it does:
- Scans
secrets/directory for files - Encodes each file to base64
- Updates
secrets.envwith encoded file secrets
File-to-Secret Mapping:
FILE_TO_SECRET_MAP["firebaseAppDistributionServiceCredentialsFile.json"]="FIREBASECREDS"
FILE_TO_SECRET_MAP["google-services.json"]="GOOGLESERVICES"
FILE_TO_SECRET_MAP["playStorePublishServiceCredentialsFile.json"]="PLAYSTORECREDS"
FILE_TO_SECRET_MAP["AuthKey.p8"]="APPSTORE_AUTH_KEY"
FILE_TO_SECRET_MAP["match_ci_key"]="MATCH_SSH_PRIVATE_KEY"Synchronize all secrets to secrets.env
./keystore-manager.sh syncWhat it does:
- Parse
shared_keys.envfor iOS string secrets - Encode
secrets/*files to base64 - Update
secrets.envwith all platform secrets - Add Desktop signing placeholders
- Validate result (format, required secrets, base64)
Output Artifacts:
- Updated
secrets.env(all platform secrets unified) secrets.env.backup(safety backup)
Use cases:
- After iOS setup (automatic via
setup_ios_complete.sh) - After adding new files to
secrets/directory - After updating
shared_keys.env - To refresh/validate secrets.env
Features:
- Creates backup before modification
- Preserves existing secrets if source files missing
- Idempotent: safe to run multiple times
- Validates format and base64 encoding
View current secrets (files + environment variables)
./keystore-manager.sh viewWhat it does:
- Lists all files in
secrets/directory - Displays selected environment variables from
secrets.env - Shows keystore info (aliases, validity)
Add secrets to GitHub repository (requires gh CLI)
./keystore-manager.sh add [--repo owner/repo] [--env environment]What it does:
- Encodes all secrets to base64
- Uses GitHub CLI to set repository secrets:
gh secret set SECRET_NAME --body "$base64_value"
- Optionally targets specific environment
Prerequisites: gh auth login (GitHub CLI authenticated)
List all secrets in GitHub repository
./keystore-manager.sh list [--repo owner/repo]Uses: gh secret list
Delete a specific secret from GitHub
./keystore-manager.sh delete [--repo owner/repo] [--name SECRET_NAME]Interactive: Prompts for secret name if not provided
Delete ALL secrets from GitHub repository
./keystore-manager.sh delete-all [--repo owner/repo]Configuration File: secrets.env
Example:
# Company & Organization
COMPANY_NAME="Mifos Initiative"
DEPARTMENT="Mobile Development"
ORGANIZATION="Mifos"
CITY="San Francisco"
STATE="CA"
COUNTRY="US"
# Keystore Configuration
VALIDITY=10000
KEYALG=RSA
KEYSIZE=2048
# Keystore Credentials
ORIGINAL_KEYSTORE_PASSWORD="xxx"
ORIGINAL_KEYSTORE_ALIAS="xxx"
ORIGINAL_KEYSTORE_ALIAS_PASSWORD="xxx"
UPLOAD_KEYSTORE_PASSWORD="xxx"
UPLOAD_KEYSTORE_ALIAS="xxx"
UPLOAD_KEYSTORE_ALIAS_PASSWORD="xxx"Line Count: 1,356 lines (largest script)
Purpose: Deploy iOS app to Firebase App Distribution
Usage:
./scripts/deploy_firebase.shWhat it does:
- Loads secrets from
secrets/shared_keys.env - Calls Fastlane lane:
bundle exec fastlane ios deploy_on_firebase - Displays success message
Prerequisites:
secrets/shared_keys.envexists (created bysetup_ios_complete.sh)- Fastlane installed
- CocoaPods installed
Output: IPA uploaded to Firebase App Distribution
Purpose: Deploy iOS app to TestFlight
Usage:
./scripts/deploy_testflight.shWhat it does:
- Loads secrets from
secrets/shared_keys.env - Calls Fastlane lane:
bundle exec fastlane ios beta - Displays success message
Prerequisites: Same as deploy_firebase.sh
Output: IPA uploaded to TestFlight
Purpose: Deploy iOS app to App Store
Usage:
./scripts/deploy_appstore.shWhat it does:
- Double Confirmation:
- First confirmation: "Deploy to App Store? (y/n)"
- Second confirmation: "This is PRODUCTION. Are you ABSOLUTELY sure? (yes/no)"
- Requires typing "yes" (not just "y")
- Loads secrets from
secrets/shared_keys.env - Calls Fastlane lane:
bundle exec fastlane ios release - Displays success message
- Production deployment
- Double confirmation required
- Never bypass this script
Prerequisites: Same as deploy_firebase.sh
Output: IPA submitted to App Store for review
Purpose: Complete iOS deployment setup wizard
Usage:
./scripts/setup_ios_complete.shWhat it does:
-
Validates Prerequisites:
- Checks:
openssl,ssh-keygen,ghCLI, Xcode Command Line Tools
- Checks:
-
Collects Configuration:
- Team Information:
- Apple Developer Team ID
- Bundle Identifier
- App Store Connect API:
- Key ID
- Issuer ID
- Private Key (.p8 file path)
- Fastlane Match:
- Git repository URL
- Git branch
- Passphrase
- Team Information:
-
Generates SSH Key for Match:
- Creates
secrets/match_ci_key(private key) - Creates
secrets/match_ci_key.pub(public key) - Instructions to add public key to Match repository deploy keys
- Creates
-
Generates Secrets File:
- Creates
secrets/shared_keys.envwith all configuration:TEAM_ID="xxx" APPSTORE_KEY_ID="xxx" APPSTORE_ISSUER_ID="xxx" APPSTORE_KEY_PATH="./secrets/AuthKey.p8" MATCH_GIT_URL="[email protected]:org/repo.git" MATCH_GIT_BRANCH="master" MATCH_SSH_KEY_PATH="./secrets/match_ci_key" MATCH_PASSWORD="xxx"
- Creates
-
Copies App Store Connect Key:
- Copies
.p8file tosecrets/AuthKey.p8
- Copies
-
Verifies Configuration:
- Runs
verify_ios_deployment.sh(70+ checks)
- Runs
-
Displays Next Steps:
- Add SSH public key to Match repository
- Run
fastlane matchto generate certificates - Test deployment with
deploy_firebase.sh
Interactive: Extensive (prompts for all configuration)
Line Count: 518 lines
Output:
secrets/shared_keys.envsecrets/match_ci_key(SSH private key)secrets/match_ci_key.pub(SSH public key)secrets/AuthKey.p8(App Store Connect API key)
Purpose: Configure Apple Push Notification (APN) key
Usage:
./scripts/setup_apn_key.shWhat it does:
- Prompts for APN Key ID
- Prompts for APN .p8 file path
- Copies APN key to
secrets/ - Updates
secrets/shared_keys.envwith APN configuration - Verifies setup with
verify_apn_setup.sh
When needed:
- If app uses push notifications
- Optional for apps without notifications
Purpose: Comprehensive validation of iOS deployment configuration
Usage:
./scripts/verify_ios_deployment.shWhat it does:
70+ Checks across 10 categories:
-
Prerequisites (7 checks):
- Ruby installed
- Bundler installed
- Fastlane installed
- CocoaPods installed
- Xcode Command Line Tools
- Git installed
- OpenSSL installed
-
Fastlane Configuration (8 checks):
GemfileexistsFastfileexists- iOS platform defined in Fastfile
- Required lanes exist (
beta,release,deploy_on_firebase) - Plugins installed (
firebase_app_distribution,increment_build_number)
-
Project Structure (6 checks):
- Xcode project exists
- Workspace exists
- Shared module exists
- Podfile exists
- Info.plist exists
-
App Store Connect API (4 checks):
APPSTORE_KEY_IDsetAPPSTORE_ISSUER_IDsetAPPSTORE_KEY_PATHset.p8file exists at path
-
Fastlane Match (6 checks):
MATCH_GIT_URLsetMATCH_GIT_BRANCHsetMATCH_SSH_KEY_PATHset- SSH private key exists
MATCH_PASSWORDset- SSH key has correct permissions (600)
-
Firebase Configuration (5 checks):
GoogleService-Info.plistexists- Firebase service credentials exist
- Firebase app ID configured
- Firebase tester groups configured
-
Code Signing (10 checks):
- Team ID set
- Bundle identifier set
- Provisioning profile name format
- Match type configured
- SSH config for Match repository
- Can connect to Match repository
- Certificates exist in Match repository
-
Build Configuration (8 checks):
- Scheme exists
- Build settings valid
- Code signing identity set
- Provisioning profile set
- Development team set
- Version number set
- Build number set
-
Deployment Readiness (6 checks):
- Can build debug
- Can build release (dry run)
- Can access App Store Connect API
- Can fetch Match certificates (dry run)
- Firebase credentials valid
-
Security (5 checks):
- Secrets directory exists
- Secret files have correct permissions
- No secrets committed to Git
- SSH key not world-readable
.p8file not world-readable
Output:
- ✅ All checks passed → "iOS deployment configuration is READY"
- ❌ Some checks failed → Detailed error messages with fixes
Line Count: 365 lines
Exit Codes:
0: All checks passed1: One or more checks failed
Purpose: Verify Apple Push Notification setup
Usage:
./scripts/verify_apn_setup.shWhat it does:
- Checks
APN_KEY_IDinsecrets/shared_keys.env - Checks APN
.p8file exists - Validates file permissions
- Verifies key format
Output:
- ✅ APN setup valid
- ❌ Missing configuration or invalid key
Purpose: Display version handling and sanitization explanation
Usage:
./scripts/check_ios_version.shWhat it does:
- Reads current version from
version.txt(generated by Gradle) - Shows version formats:
Gradle Version: 2026.1.1-beta.0.9+abc123 Firebase Version: 2026.1.1-beta.0.9 App Store Version: 2026.1.9 - Explains sanitization logic:
- Why: App Store requires
MAJOR.MINOR.PATCHformat - How: Extract year, month, commit count
- Result:
YYYY.M.{commitCount}
- Why: App Store requires
- Shows Fastlane code that performs sanitization (from Fastfile:383-429)
Educational Output:
- Version comparison table
- Sanitization explanation
- Code snippet from Fastfile
Purpose: Validate development environment prerequisites
Usage:
./scripts/check_environment.shWhat it does:
- Checks for required tools:
- Git
- Java (version 17+)
- Gradle
- Ruby
- Bundler
- CocoaPods (if macOS)
- Firebase CLI
- GitHub CLI (
gh)
- Displays versions
- Reports missing tools
Output:
- ✅ All prerequisites met
⚠️ Missing tools (with installation instructions)
Purpose: Validate environment variable files
Usage:
./scripts/check_file_env_keys.sh <file.env>What it does:
- Reads
.envfile - Checks for required keys
- Validates format (KEY=VALUE)
- Detects multiline blocks
- Reports missing or malformed entries
Use cases:
- Validate
secrets.envafter manual edits - Check
secrets/shared_keys.envformat
Purpose: Check if Git commits are GPG-signed
Usage:
./scripts/check-commit-signing.shWhat it does:
- Checks Git configuration for GPG signing
- Verifies GPG key exists
- Validates signing setup
- Provides setup instructions if not configured
Output:
- ✅ Commit signing configured
- ℹ️ Setup instructions
Purpose: Helper to encode files to base64
Usage:
./scripts/ensure_base64.sh <file>What it does:
- Encodes file to base64
- Handles platform differences (macOS vs Linux)
- Outputs to stdout or file
Use cases:
- Manually encode secrets for GitHub Actions
- Quick base64 encoding
Purpose: Fix Detekt configuration file permissions
Usage:
./scripts/fix-detekt-permissions.shWhat it does:
- Finds Detekt config files (
detekt.yml,detekt-config.yml) - Sets correct permissions (644)
- Fixes "Permission denied" errors
When needed:
- After cloning repository
- If Detekt fails with permission errors
# Complete setup (interactive)
./setup-project.sh
# OR step-by-step:
# 1. Customize package names
./customizer.sh
# 2. Setup Firebase
./firebase-setup.sh
# 3. Generate keystores
./keystore-manager.sh generate
# 4. Encode secrets for GitHub Actions
./keystore-manager.sh encode-secrets
# 5. Add secrets to GitHub (requires gh CLI)
./keystore-manager.sh add
# 6. Setup iOS (if needed)
./scripts/setup_ios_complete.sh# Deploy to Firebase
./scripts/deploy_firebase.sh
# Deploy to TestFlight
./scripts/deploy_testflight.sh
# Deploy to App Store (double confirmation required)
./scripts/deploy_appstore.sh# Synchronize all secrets to secrets.env (recommended)
./keystore-manager.sh sync
# View current secrets
./keystore-manager.sh view
# Encode all secrets
./keystore-manager.sh encode-secrets
# Add secrets to GitHub
./keystore-manager.sh add
# List GitHub secrets
./keystore-manager.sh list
# Delete a secret
./keystore-manager.sh delete --name SECRET_NAME
# Delete all secrets (with confirmation)
./keystore-manager.sh delete-all# Check environment prerequisites
./scripts/check_environment.sh
# Verify iOS deployment setup
./scripts/verify_ios_deployment.sh
# Check version sanitization
./scripts/check_ios_version.sh
# Validate environment file
./scripts/check_file_env_keys.sh secrets.envCause: Missing prerequisite tools
Fix:
# Check what's missing
./scripts/check_environment.sh
# Install missing tools (macOS)
brew install git gh firebase-cliCause: Script requires interactive input
Fix:
- Run script in terminal (not via IDE)
- Provide valid package name (e.g.,
com.example.app)
Cause: Not logged into Firebase CLI
Fix:
firebase loginCause: Missing keytool or openssl
Fix:
# Check if Java is installed
java -version
# Install if missing (macOS)
brew install openjdk@17
# Check OpenSSL
openssl version
brew install openssl # if missingCause: GitHub CLI not authenticated
Fix:
gh auth login
gh auth status # Verify
# Then retry
./keystore-manager.sh addCause: Missing ssh-keygen
Fix:
# macOS (should be installed by default)
xcode-select --install
# Verify
ssh-keygen -VCause: SSH public key not added to repository
Fix:
- Get public key:
cat secrets/match_ci_key.pub
- Go to Match repository → Settings → Deploy keys
- Add public key with write access
Cause: secrets/shared_keys.env missing
Fix:
# Run iOS setup wizard
./scripts/setup_ios_complete.sh
# OR manually create secrets/shared_keys.envCause: Incomplete iOS setup
Fix:
- Read failure messages carefully
- Each check has specific fix instructions
- Re-run setup wizard if needed:
./scripts/setup_ios_complete.sh
Cause: Gradle version not compatible with App Store
Fix:
- Fastlane automatically sanitizes versions
- Check with:
./scripts/check_ios_version.sh - See Version Handling Guide
Need more help?