Migrating from Codemagic
BuildMagic reads codemagic.yaml directly. Point it at your repository and your existing pipeline runs — you do not rename the file, rewrite your scripts, or restructure your project.
What to do
- Add the application. Connect GitHub or GitLab, pick the repository and choose the project type. The project directory is detected automatically, including inside a monorepo.
- Copy your variables. This is the step people forget. Codemagic holds your variable groups; BuildMagic starts empty. Recreate them under app → Settings → Environment, keeping the group names your
codemagic.yamlreferences. - Set up signing. Either upload the certificates, profiles and keystores you already have, or connect an App Store Connect API key and let BuildMagic issue them. See Code Signing.
- Select the Android keystore for the app under Settings → Code Signing, along with the Google Play service account if you publish there.
- Run a build. Variables your configuration reads but that are not set yet are reported before the build starts, so a missing one is named up front.
What carries over unchanged
workflows, withname,instance_typeandmax_build_durationscripts— each named step becomes a build step, running in order and stopping the build on a non-zero exitenvironment.varsandenvironment.groups, matched by group nameartifacts, including**globs and absolute paths such as/tmp/xcodebuild_logs/*.logpublishing.app_store_connectandpublishing.google_playtriggering.branch_patterns
Where a file declares one workflow per platform, instance_type decides which runs: anything starting with mac or osx selects an iOS build machine, anything starting with linux selects a container.
Conventions BuildMagic matches
These are the details that make a configuration written for Codemagic behave the same here.
- Scripts start at the repository root. A step that says
cd apps/mobileresolves against the clone directory, not against the detected project directory, so the path does not resolve twice. CM_PROJECT_PATHdefaults to.socd $CM_PROJECT_PATHis harmless at the repository root.- The keystore is a file at
CM_KEYSTORE_PATH, in place before the first step runs. The usualstoreFile=$CM_KEYSTORE_PATHin a generatedkey.propertiesworks as written. - Expo projects are prebuilt automatically when
ios/andandroid/are not committed. - iOS build numbers come from App Store Connect, so uploads are not rejected for reusing one. See automatic build numbers.
What is different
| Area | Difference |
|---|---|
| Codemagic CLI tools | keychain, xcode-project and app-store-connect are not available. Rewrite those steps, or drop them and let BuildMagic handle signing, build numbers and publishing through its own settings — which is usually fewer lines than the originals. |
xcode: version pin | Read but not applied: builds use the Xcode in the machine image, currently 26.4.1. The build reports the mismatch in its first lines so a failure caused by the version gap is recognisable. If your project needs a specific version, tell us — the image is ours to change. The same applies to cocoapods, node, java and ruby; flutter is honoured through FVM. |
| Android version codes | Not incremented automatically. iOS build numbers are; the Google Play equivalent is not implemented yet, so manage versionCode in your project or a script. |
| Variable scope | Variable groups belong to a single application rather than to the team, so two apps can hold different values under the same name without shadowing each other. |
Failures worth recognising
These come up often enough on a first migration to be worth naming.
| What you see | What it usually is |
|---|---|
Gradle: Cannot convert '' to File | A variable the configuration expands into a file is not set. The build lists the missing names before it starts — check that line first. |
Malformed root json from processReleaseGoogleServices | GOOGLE_SERVICES_JSON is missing, so the decode step wrote an empty file. Add it under the app's Environment tab. |
Expo: the module expo is not installed | Dependencies were installed somewhere other than the app. A repository whose root holds an unrelated npm project is the usual cause; the app is installed in its own directory when it carries its own lockfile. |
npm ci can only install packages when ... in sync | The lockfile has drifted from package.json. The build falls back to a resolving install and continues, but it is no longer reproducible — commit an updated lockfile. |
| A compiler error deep inside a dependency | Check the first lines of the build for a version mismatch. A project that pins xcode: usually pins it because another version miscompiles something. |
For iOS, the full xcodebuild log is collected with the artifacts, so a failure can be examined after the build machine is gone.
Keeping both files
BuildMagic looks for buildmagic.yaml first and codemagic.yaml second, so you can add a buildmagic.yaml to try something different while leaving the original in place. There is also Ignore repository config in the app's settings, which runs the default pipeline instead — useful for comparing your pipeline against ours, or when the committed file belongs to a CI service you are still running in parallel.
You can also edit the configuration from the dashboard without committing anything: Settings → buildmagic.yaml creates a local override, and discarding it returns to the repository file.