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.
code_magic_new (App Manager role) added
to Codemagic team settings → Apple Developer Portal integration.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).
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 |
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 Store → Generate.
Do not download. Codemagic fetches it via the App Store Connect API on the next build.
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"
codemagic.io → Applications → Add application.
code_magic_new integration).mahmoudholding/<project>.On the new app's Workflow Editor page, click Switch to YAML configuration. This:
codemagic.yaml from the repo.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.Open a PR with these three changes.
codemagic.yamlCopy the staging-internal-testing workflow from
roomy-mobile/codemagic.yaml and change:
bundle_identifier: com.<product>.app.stagingENDPOINT URL →
https://api.github.com/repos/mahmoudholding/<project>/issues/$CM_PULL_REQUEST_NUMBER/commentsapp_store_connect: code_magic_new (team-scoped, reusable).xcode-project use-profiles --archive-method=app-store --code-signing-setup-verbose-logging as-is.ios/Runner.xcodeproj/project.pbxprojsed -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.
ios/Runner/Info.plistAdd 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.
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.
If Apple's API propagation never seems to land (rare but happens), bypass the API-driven profile fetch:
Apple Developer Portal → the new profile → Download the
.mobileprovision.
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).
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>
Remove the xcode-project use-profiles script step (it's only for
API-mode signing).
| 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