# Codemagic CI/CD for Timbre (Flutter). # The repo root IS the Flutter project, so scripts run from the app directory # with no `working_directory` override. Two workflows: Android (Linux) and # iOS (mac). Docs: https://docs.codemagic.io/yaml/yaml-getting-started/ definitions: # Shared quality gate — anchored per-step (YAML can't splice a list into a # list, only reference individual map items). Toolchain is pinned inline in # each workflow to Flutter 3.44.8 / Dart 3.12.2 (the local dev version); # change to `stable` for the latest, or bump when you upgrade. scripts: - &flutter_version name: Flutter version script: flutter --version - &get_deps name: Get dependencies script: flutter pub get - &analyze name: Analyze script: flutter analyze - &unit_tests name: Unit tests script: | mkdir -p test-results flutter test --machine --coverage > test-results/flutter.json test_report: test-results/flutter.json workflows: # --------------------------------------------------------------------------- android: name: Android (APK + AAB) # mac_mini_m1 is the free-tier / most widely available instance and builds # Android fine. If your plan includes Linux, `linux_x2` is cheaper/faster # for Android-only builds. instance_type: mac_mini_m1 max_build_duration: 60 environment: flutter: 3.44.8 java: 17 # Uncomment once you add a keystore to Codemagic (Teams → Code signing # identities → Android) and reference its group here to sign releases. # groups: # - android_keystore # CM_KEYSTORE, CM_KEYSTORE_PASSWORD, CM_KEY_ALIAS, CM_KEY_PASSWORD cache: cache_paths: - $HOME/.pub-cache - $HOME/.gradle/caches # triggering: # events: [push, tag] # branch_patterns: # - pattern: main # include: true scripts: - *flutter_version - *get_deps - *analyze - *unit_tests # NOTE: android/app/build.gradle.kts currently signs `release` with the # DEBUG key (Flutter template default), so these build & install but are # not upload-ready. To ship: add a real signingConfig backed by # key.properties / the CI env vars above — this step then needs no change. - name: Build APK (release) script: flutter build apk --release - name: Build App Bundle (release) script: flutter build appbundle --release artifacts: - build/app/outputs/flutter-apk/*.apk - build/app/outputs/bundle/**/*.aab - build/app/outputs/**/mapping.txt - flutter_drive.log # publishing: # email: # recipients: # - you@conversionpath.com # notify: # success: true # failure: true # # google_play: # # credentials: $GCLOUD_SERVICE_ACCOUNT_CREDENTIALS # # track: internal # --------------------------------------------------------------------------- ios: name: iOS (TestFlight) instance_type: mac_mini_m1 max_build_duration: 60 # Reference NAME of the App Store Connect API key integration you added in # Codemagic (Teams → Integrations → App Store Connect). Replace the value # below with whatever you named it there. integrations: app_store_connect: Troglodyte environment: flutter: 3.44.8 java: 17 # NOTE: intentionally NO `ios_signing` block. That block triggers # Codemagic's *automatic* signing during build initialization, which only # FETCHES existing certs/profiles and fails the build up front ("No # matching profiles found") on a fresh account that has none yet. Instead # we sign fully manually in the scripts below, where we can create the # cert + profile on first run. The `integrations.app_store_connect` above # still injects the ASC API-key env vars the app-store-connect CLI uses. vars: # The app's numeric Apple ID (App Store Connect → your app → App # Information → General → Apple ID). Used to auto-bump the build number # so TestFlight never rejects a duplicate. Fill in after you create the # app record in App Store Connect. (Until then the build number falls # back to 1 — fine for the very first upload.) APP_STORE_APPLE_ID: 6796333279 cache: cache_paths: - $HOME/.pub-cache - $HOME/.gradle/caches scripts: - *flutter_version - *get_deps - *analyze - *unit_tests - name: Initialize keychain # Manual signing: create the build keychain ourselves (the removed # ios_signing block used to do this automatically). script: keychain initialize - name: Fetch signing files # fetch-signing-files --create mints the Apple Distribution cert + the # App Store provisioning profile via the ASC API key and downloads them. # --create also registers the Bundle ID if it isn't already. On the # first build this creates everything; later builds reuse it. script: | app-store-connect fetch-signing-files "com.troglodyte.timbre" \ --type IOS_APP_STORE \ --create - name: Add certificates to keychain # Load the freshly fetched distribution cert into the build keychain. script: keychain add-certificates - name: Set up code signing # Applies the profile to the Xcode project and writes # ~/export_options.plist (= /Users/builder/export_options.plist) that # the build step reads. script: xcode-project use-profiles - name: Build signed IPA script: | BUILD_NUMBER=$(app-store-connect get-latest-testflight-build-number "$APP_STORE_APPLE_ID" 2>/dev/null || echo 0) flutter build ipa --release \ --build-number=$(( BUILD_NUMBER + 1 )) \ --export-options-plist=/Users/builder/export_options.plist artifacts: - build/ios/ipa/*.ipa publishing: app_store_connect: auth: integration submit_to_testflight: true # Internal testers automatically receive every build once Apple finishes # processing (no Beta App Review). To also push to a named group, # uncomment and match the group name from App Store Connect → TestFlight: # beta_groups: # - Internal Testers