Athena — runbooks/codemagic-new-app-on-roomy-team.md

Runbook — Add a new app to Codemagic under the Roomy B.V Apple team

For shipping a new Flutter app to TestFlight from Codemagic, reusing the existing The Roomy App Codemagic workspace and the Roomy B.V Apple Developer team (team ID DWTXQWJP95).

This runbook was derived from the AuditPic Staging setup on 2026-05-17. Time to complete: ~20 minutes plus a 10-minute wait for Apple API propagation.


Prerequisites (one-off, already done for the team)

  • Apple Developer Program License Agreement accepted (Account Holder).
  • App Store Connect API key code_magic_new (App Manager role) added to Codemagic team settings → Apple Developer Portal integration.
  • An iOS Distribution certificate exists in the Apple Developer Portal under the Roomy B.V team — the same cert Roomy Mobile uses.

1. Apple side — 4 steps

1.1 Register the bundle ID identifier

developer.apple.com → Identifiers+App IDs → App → Explicit → e.g. com.<product>.app.staging. No capabilities yet unless the app needs them (Push, NFC, etc. — add later as required; a mismatch later causes the same kind of "no matching profile" error).

1.2 Create the App Store Connect record

appstoreconnect.apple.com → My Apps → + → New App.

| Field | Value | |-------|-------| | Platforms | iOS | | Name | e.g. AuditPic staging (≤30 chars, no emoji) | | Primary Language | Dutch or English (US) | | Bundle ID | the one from step 1.1 (must already be registered to appear in the dropdown) | | SKU | internal-only, e.g. <product>-staging-001 | | User Access | Full Access |

1.3 Create the App Store distribution provisioning profile

This is the step that bites — Codemagic's code_magic_new API key has App Manager role, which can read & use profiles but cannot create them. Manual per-app step.

developer.apple.com → Profiles+Distribution → App Store (iOS) → select the App ID from step 1.1 → attach the existing iOS Distribution certificate (same one Roomy Mobile uses) → name it <Product> Staging App StoreGenerate.

Do not download. Codemagic fetches it via the App Store Connect API on the next build.

1.4 Wait 5–10 min

Profile creation on the Apple Developer Portal takes a few minutes to propagate to the App Store Connect API endpoint that Codemagic queries. Skipping this wait causes the first build to fail with:

No matching profiles found for bundle identifier "<bundle>"
and distribution type "app_store"

2. Codemagic side — 2 steps

2.1 Add the application

codemagic.io → Applications → Add application.

  • Team: The Roomy App (gives access to the team's code_magic_new integration).
  • Repository: GitHub → pick mahmoudholding/<project>.
  • Project type: Flutter (via Workflow Editor).

2.2 Switch to YAML configuration

On the new app's Workflow Editor page, click Switch to YAML configuration. This:

  • Reads codemagic.yaml from the repo.
  • Registers a GitHub webhook for all events declared in the yaml (push, pull_request, tag) — but only if the OAuth scope at sign-in includes admin:repo_hook. If "Finish build setup" stays on the Applications page, the webhook didn't get installed; trigger the first build manually via "Start your first build" and add the webhook by hand later.

3. Repo side — one PR

Open a PR with these three changes.

3.1 codemagic.yaml

Copy the staging-internal-testing workflow from roomy-mobile/codemagic.yaml and change:

  • bundle_identifier: com.<product>.app.staging
  • The "Notify Claude on build failure" script's ENDPOINT URL → https://api.github.com/repos/mahmoudholding/<project>/issues/$CM_PULL_REQUEST_NUMBER/comments
  • Trim Firebase Crashlytics + Google Play + Slack sections if the new app doesn't have them wired up yet.
  • Keep app_store_connect: code_magic_new (team-scoped, reusable).
  • Keep xcode-project use-profiles --archive-method=app-store --code-signing-setup-verbose-logging as-is.

3.2 ios/Runner.xcodeproj/project.pbxproj

sed -i.bak 's|PRODUCT_BUNDLE_IDENTIFIER = <old.bundle.id>;|PRODUCT_BUNDLE_IDENTIFIER = com.<product>.app.staging;|g' ios/Runner.xcodeproj/project.pbxproj
sed -i.bak2 's|PRODUCT_BUNDLE_IDENTIFIER = <old.bundle.id>.RunnerTests;|PRODUCT_BUNDLE_IDENTIFIER = com.<product>.app.staging.RunnerTests;|g' ios/Runner.xcodeproj/project.pbxproj
rm ios/Runner.xcodeproj/project.pbxproj.bak ios/Runner.xcodeproj/project.pbxproj.bak2

Verify DEVELOPMENT_TEAM = DWTXQWJP95 in the same file. It usually already is.

3.3 ios/Runner/Info.plist

Add the encryption-export exemption so TestFlight uploads don't prompt per-build:

<key>ITSAppUsesNonExemptEncryption</key>
<false/>

Only safe if the app uses standard crypto only (AES, HMAC, TLS). If the app implements proprietary or non-standard algorithms, upload an ATF/CCATS classification instead and set this key to true.


4. Trigger the first build

Push the PR → merge → Codemagic auto-triggers a build (if the webhook got installed) or you trigger it manually via "Start your first build" → select workflow Staging (Internal) → branch main.

If the build fails with "No matching profiles found": wait another 5–10 minutes for Apple's API propagation and retry. If it persists, fall back to section 5 below.


5. Fallback — upload the profile to Codemagic directly

If Apple's API propagation never seems to land (rare but happens), bypass the API-driven profile fetch:

  1. Apple Developer Portal → the new profile → Download the .mobileprovision.

  2. Codemagic → workspace → Team settings → Code signing identities → iOS provisioning profiles → Add profile. Upload the file. Note the reference name (e.g. AuditPic_Staging_App_Store).

  3. In codemagic.yaml, replace the API-driven ios_signing block with a manual one:

    ios_signing:
      provisioning_profiles:
        - AuditPic_Staging_App_Store
      certificates:
        - <name of the iOS distribution cert already uploaded for Roomy>
    
  4. Remove the xcode-project use-profiles script step (it's only for API-mode signing).


Gotchas reference

| Symptom | Cause | Fix | |---------|-------|-----| | "Agreement Update" dialog blocks new app creation in App Store Connect | License agreement updated; only Account Holder can accept | Sign in as Account Holder at developer.apple.com → Agreements → Accept | | Bundle ID dropdown is empty in "New App" form | Identifier not registered in Apple Developer Portal yet | Step 1.1 first | | Codemagic app shows "Finish build setup" instead of "Start new build" | GitHub webhook didn't auto-install (OAuth scope) | Click "Switch to YAML configuration" or trigger first build manually | | Build fails: "No matching profiles found for bundle identifier" | Profile doesn't exist yet, or wrong distribution type, or Apple API propagation lag | Step 1.3, wait 5–10 min, or section 5 fallback | | Build fails: profile found but Xcode rejects it | DEVELOPMENT_TEAM in pbxproj doesn't match the team that owns the profile | Set DEVELOPMENT_TEAM = DWTXQWJP95 (Roomy B.V) | | TestFlight upload prompts for encryption export compliance every build | ITSAppUsesNonExemptEncryption missing from Info.plist | Step 3.3 | | flutter create --platforms=android leaves com.example.<name> package | Flutter scaffold default | Rename via sed on the Xcode project + Kotlin MainActivity.kt package; com.example.* is reserved by Apple/Google and won't ship |

Reacties

Nog geen reacties