5. CI/CD & Build Pipeline
CI/CD Pipeline Health
Build Automation80 / 100
Automated Testing in CI/CD0 / 100
Code Signing Security30 / 100
Deployment Process40 / 100
5.1 Build Configuration
Status: ✅Pass
Findings:
- Flutter version pinned:
.fvmrcfile exists and pins Flutter to version 3.24.5 - FVM used for version management:
codemagic.yamlusesflutter: fvmwhich respects.fvmrc - CocoaPods version: Set to
default(not pinned to specific version) - SDK constraint: Allows Flutter 3.x (
>=3.0.0 <4.0.0) compatible with 3.24.5 - Build number calculation: Uses
PROJECT_BUILD_NUMBER + 100offset (not automatic store API lookup) - Xcode version: Pinned to 16.1
- Workflow structure: Well-organized with reusable script anchors (
&set_key_properties,&setup_pods, etc.)
Evidence:
.fvmrc: Defines Flutter 3.24.5 for the projectcodemagic.yamlline 16, 149:flutter: fvm(uses FVM which respects.fvmrc)codemagic.yamlline 18, 151:cocoapods: default(not pinned to specific version)codemagic.yamlline 17, 150:xcode: 16.1(pinned)pubspec.yamlSDK constraint:>=3.0.0 <4.0.0(compatible with 3.24.5)- Build scripts use
$(($PROJECT_BUILD_NUMBER + 100))for version code calculation codemagic.yaml: Uses YAML anchors for reusable scripts (lines 26, 37, 41, 45, 49, 63, 67, 71, 75, 79, 83, 94)
Risk Level: Low Risk
Recommendation:
- Immediate actions:
- Pin CocoaPods version explicitly (e.g.,
1.15.2) for reproducibility - Document Flutter version in README or build documentation
- Short-term:
- Plan incremental upgrades (e.g., current → latest 3.x → 4.0 when stable) aligned with dependency migrations
- Test Flutter upgrades in staging environment before production
- Resolve deprecated dependencies before major Flutter upgrades
- Use automatic build number from store APIs instead of offset calculation
5.2 Code Signing & Certificates
Status: ❌Fail
Findings:
- Critical: Sensitive signing credentials stored directly in repository
- Critical:
android/key.propertiescontains hardcoded passwords and keystore pathstorePassword=kZeLOMmMZN2o7EqTGfwA(hardcoded in repository)keyPassword=kZeLOMmMZN2o7EqTGfwA(hardcoded in repository)storeFile=/Users/thomascornet/Studioprojects/supertank/android-assets/supertank.keystore.jks(hardcoded path)
- Android keystore file (
supertank.keystore.jks) inandroid-assets/directory - Apple Sign In private key (
AuthKey_9ZW5QT9Y35 (1).p8) inios-assets/directory - Push certificate passwords in
ios-assets/ios_push_certificate_pass.rtfand.txt - Android signing configuration:
- Uses encrypted environment variables (
FCI_KEYSTORE,FCI_KEYSTORE_PASSWORD,FCI_KEY_PASSWORD,FCI_KEY_ALIAS) in CI/CD - Creates
key.propertiesfile dynamically from environment variables during build (good practice) - Both staging and production workflows include Android signing setup
- iOS signing configuration:
- Uses App Store Connect credentials from environment variables
- Credentials:
APP_STORE_CONNECT_PRIVATE_KEY,APP_STORE_CONNECT_KEY_IDENTIFIER,APP_STORE_CONNECT_ISSUER_ID - Uses
app-store-connect fetch-signing-filesto fetch certificates and profiles - Keychain setup and certificate management in build scripts
- Build number management:
- Uses
PROJECT_BUILD_NUMBER + 100offset calculation (not automatic store API lookup) - Version name extracted from Git tag (e.g.,
prod_1.20.0→1.20.0) - Potential for build number conflicts if not managed carefully
- Certificate management issues:
- No centralized certificate management
- Certificates and keys stored in multiple locations
- Sensitive files in repository despite encrypted variables in CI/CD
- Hardcoded passwords in
key.propertiesfile (critical security risk)
Evidence:
android/key.properties: Contains hardcoded passwords and keystore path (lines 1-4)storePassword=kZeLOMmMZN2o7EqTGfwAkeyPassword=kZeLOMmMZN2o7EqTGfwAkeyAlias=key0storeFile=/Users/thomascornet/Studioprojects/supertank/android-assets/supertank.keystore.jks
codemagic.yaml:- Android signing: Encrypted environment variables for keystore credentials (lines 26-36)
- Script
set_key_properties: Createskey.propertiesfrom encrypted variables (good practice) - iOS signing: Environment variables for App Store Connect credentials (lines 131-134, 231-234)
- Scripts:
setup_keychain,setup_certificates,add_certificates,setup_provisioning_profiles - Build number:
$(($PROJECT_BUILD_NUMBER + 100))(lines 56, 62, 101, 108, 169, 175, 199, 206) android-assets/supertank.keystore.jks: Android signing keystore in repositoryios-assets/AuthKey_9ZW5QT9Y35 (1).p8: Apple Sign In private key in repositoryios-assets/ios_push_certificate_pass.rtfand.txt: Push certificate passwords in repositoryandroid/app/build.gradlelines 19-23, 69-74: Referenceskey.propertiesfor signing config
Risk Level: Critical Risk
Recommendation:
- Immediate actions:
- Remove
android/key.propertiesfrom repository (contains hardcoded passwords) - Remove all sensitive signing files from repository (after backing up to secure location)
- Move signing credentials to Codemagic secrets management or secure cloud storage
- Add sensitive directories to
.gitignore:android-assets/,ios-assets/,android/key.properties - Rotate all exposed credentials (keystores, passwords, private keys)
- Short-term:
- Ensure
key.propertiesis only created from environment variables in CI/CD - Consider using Codemagic's App Store Connect integration instead of environment variables
- Implement centralized certificate management
5.3 Automated Testing in CI/CD
Status: ❌Fail
Findings:
- No automated tests in CI/CD pipeline:
codemagic.yamldoes not include test execution steps - No test files found: No test files (
*test*.dart) found in repository - Builds can succeed even with broken code
- Missing quality gates in build process
- No linting or static analysis steps in CI/CD
Evidence:
codemagic.yaml:- Workflow scripts (
supertank-prod,supertank-staging) do not includeflutter testcommands - No test execution steps in build scripts
- No test failure gates in build pipeline
- Scripts focus on dependency setup, signing, and building only
- No linting or static analysis steps visible
- No test files found in repository (glob search for
*test*.dartreturned 0 results)
Risk Level: High Risk
Recommendation:
- Immediate actions:
- Add test execution steps to Codemagic workflows
- Create initial test suite (unit tests, widget tests)
- Fail builds if critical tests fail
- Short-term:
- Run integration tests against staging environment in CI/CD
- Add linting and static analysis steps (
flutter analyze) - Add code coverage reporting
- Set up test coverage thresholds
5.4 Deployment Process
Status: ⚠️Warning
Findings:
- Separate tag-based deployment: Uses different Git tag patterns for staging and production (
staging_*vsprod_*) - Suboptimal tag management: Separate tags make it difficult to track which version is in staging vs production
- No clear promotion path: No mechanism to promote same artifact from staging to production
- Tag-based versioning: Version name extracted from tag (e.g.,
prod_1.20.0→ version1.20.0) - Build number offset: Uses
PROJECT_BUILD_NUMBER + 100calculation instead of automatic store API lookup - GitFlow workflow: Makes it hard to track pending changes and current state (see section 2.1)
- Multiple long-lived branches: Create complexity and merge conflicts
- Difficult to identify deployed code: Hard to determine what code is currently deployed in each environment
- Workflow naming: Uses
supertank-prodandsupertank-stagingworkflow names - Staging release notes: Hardcoded release notes in staging workflow (lines 182-191)
- SQLite header clearing: Custom script to clear SQLite headers (lines 83-93) - workaround for build issues
Evidence:
codemagic.yaml:- Separate workflows:
supertank-prodandsupertank-staging - Tag patterns:
prod_*for production (line 23),staging_*for staging (line 156) - Version extraction from tag:
IN="$FCI_TAG"; arrIN=(${IN//_/ }); VERSION_NAME=${arrIN[1]}(lines 52-54, 97-99, 165-167, 194-196) - Build number:
$(($PROJECT_BUILD_NUMBER + 100))(lines 56, 62, 101, 108, 169, 175, 199, 206) - Separate bundle IDs for staging (
com.supertank.supertank.staging) and production (com.supertank.supertank) - Different entry points:
lib/main_staging.dart(staging) vslib/main_prod.dart(production) - Staging workflow includes hardcoded release notes (lines 182-191)
- Custom SQLite header clearing script (lines 83-93) - workaround for build issues
- GitFlow branching model in use (based on section 2.1 findings)
Risk Level: Medium Risk
Recommendation:
- Immediate actions:
- Migrate from GitFlow to trunk-based development workflow
- Implement single tag approach: tag once, deploy to staging, then promote same tag to production after approval
- Finish and merge all hanging changes from feature branches
- Short-term:
- Implement deployment promotion pipeline: staging → production using same build artifact
- Simplify branching: main/master as primary branch, short-lived feature branches
- Add deployment notifications
- Remove hardcoded release notes, use dynamic release notes from Git commits or changelog
- Investigate and fix SQLite header issue to remove workaround script