# macOS build providers Builder supports GitHub Actions, Codemagic, and Bitrise for IPA builds and simulator sessions. GitHub remains the default: existing `builder.json` files and `builder ios build` / `builder ios share` commands continue to use it. Your source repository stays on GitHub regardless of the compute provider. ## Stay logged into all three ```sh builder auth github builder auth codemagic builder auth bitrise builder auth status ``` GitHub keeps its browser/device-code login. Codemagic and Bitrise prompt for a personal API token with hidden input (paste once, then press Enter), validate it against the provider, and save it. Create a token in [Codemagic's account settings](https://docs.codemagic.io/rest-api/codemagic-rest-api/) or [Bitrise's personal access token settings](https://docs.bitrise.io/en/bitrise-ci/api/authenticating-with-the-bitrise-api). Each login has its own credential entry. Logging in does not change the default provider or remove any other login. `auth status` reports local availability; it does not check token expiry remotely. Tokens use the system keychain where available. As with the existing GitHub login, Linux/headless systems and unavailable keychains use separate credential files in the user config directory, with mode 0600 on Unix. Tokens are never written to `builder.json` or the generated CI files. For automation, pipe a token to `builder auth codemagic --token-stdin` or `builder auth bitrise --token-stdin`, or set `CODEMAGIC_API_TOKEN` / `BITRISE_API_TOKEN` in the environment. Environment tokens override saved tokens. Avoid putting tokens in command arguments or shell history. ```sh builder auth logout codemagic # removes only the saved Codemagic login builder auth logout bitrise builder auth logout # existing behavior: removes the GitHub login ``` Logout cannot unset environment variables in your shell. Unset an environment token separately if you want to stop using it. ## Configure a project Start with the [step-by-step app creation and repository connection guide](provider-setup.md). It includes dashboard links, API-token instructions, app-ID lookup, YAML selection, and a first unsigned build. Login and repository authorization are separate steps. Initialize GitHub as usual, then add the other providers: ```sh builder init builder init --provider codemagic --app-id YOUR_CODEMAGIC_APP_ID --branch main builder init --provider bitrise --app-id YOUR_BITRISE_APP_SLUG --branch main ``` Each provider must already have an app connected to this same GitHub repository, including read access to private repositories. `--branch` is the committed branch that supplies CI configuration; it need not be your current branch. Your Git credentials must allow snapshot pushes (`git push` must work). Builder's GitHub API login does not configure Git's credential helper. The new setup commands preserve existing project/provider settings and create: - `codemagic.yaml` for Codemagic - `bitrise.yml` for Bitrise - `.builder/ci/runner.sh`, shared by the two providers Commit these files to the configured branch before building. App sources come from the current working-tree snapshot, including uncommitted and untracked files except those excluded by `.gitignore`. The runner fetches the full snapshot ref and verifies its expected commit SHA. Workflow and runner-script changes take effect after committing them to the configured branch. Setup refuses to overwrite unrelated CI files. If you already have provider YAML, merge the `ios-build` and `ios-share` workflows from the templates in `internal/workflow/templates/`, copy `runner.sh` to `.builder/ci/`, and add the provider configuration below manually. Re-running setup replaces files carrying the `Generated by ios-builder` marker; preserve custom edits before doing so. If the selected provider has custom workflow names in `builder.json`, rerunning setup preserves those names and all CI files. Merge runner/workflow updates manually in that case; `--app-id`, `--branch`, and `--set-default` still apply. ### Codemagic Use a personal account and a YAML-configured app. Create an environment group named `builder` accessible to that app; add `BUILDER=1` if you only need unsigned builds. Store any signing/MobAI secrets in that group. The generated workflows use `mac_mini_m2`, the machine eligible for personal free minutes, and have no automatic push triggers. ### Bitrise Use a Hobby app connected to your repository. Enable **configuration from the repository** so Bitrise loads the committed `bitrise.yml`; dashboard-only YAML will not pick up these files. Select a macOS Xcode stack in the app settings. The workflow requests `g2.mac.medium`. Disable any automatically generated push triggers if you only want builds explicitly started by Builder. Add secrets in the app's Secrets settings. Keep the app's total build timeout at 90 minutes or less; IPA/script limits are also included in the generated workflow. Unsigned IPAs are stored as generic `.ipa.zip` artifacts to avoid Bitrise's installable-app metadata checks; Builder downloads and validates the unchanged IPA bytes and saves them with the usual `.ipa` extension. ## Choose where to build ```sh builder ios build # GitHub unless explicitly configured otherwise builder ios build --provider codemagic builder ios build --provider bitrise --unsigned builder ios build --provider github # explicit override ``` Provider selection is: command flag, then the selected build profile's `provider` (see the README's Build Profiles section), then `builder.json`'s `provider`, then `github`. Adding or logging into a provider does not change the default. To change it, edit `provider`, or pass `--set-default` when configuring a provider. ```json { "project": "MyApp", "platform": "ios", "provider": "github", "github": { "owner": "me", "repo": "my-app" }, "codemagic": { "app_id": "YOUR_CODEMAGIC_APP_ID", "branch": "main", "build_workflow": "ios-build", "share_workflow": "ios-share" }, "bitrise": { "app_id": "YOUR_BITRISE_APP_SLUG", "branch": "main", "build_workflow": "ios-build", "share_workflow": "ios-share" }, "ios": { "path": "ios", "scheme": "MyApp", "configuration": "Debug" } } ``` Native, Flutter, React Native/Expo, and KMP use the same framework settings as GitHub builds. A pinned `flutter.version` installs that SDK; `kmp.jdkVersion` selects the major JDK version. Provider caches and setup costs differ, so the same build may consume different minutes on each provider. ### Signing See [step-by-step signing and MobAI secret setup](provider-secrets.md). `builder signing setup` uploads signing secrets to **GitHub** only, and prints the three names and the values to paste on every run. For Codemagic/Bitrise, take them from that output and set these secrets there yourself, one set per distribution (`` is `DEVELOPMENT`, `AD_HOC`, `STORE` or `ENTERPRISE`; a build reads the set its profile's `distribution` names; a build without a profile and with `ios.signing: true` reads the unsuffixed legacy names): - `IOS_CERTIFICATE_`: base64-encoded `.p12` - `IOS_CERTIFICATE_PASSWORD_`: the `.p12` password (required; only the unsuffixed legacy one can be empty) - `IOS_PROVISIONING_PROFILE_`: base64-encoded `.mobileprovision` Build with a profile whose `distribution` names the set (`signing setup` writes one). `--unsigned` disables signing for a particular build. The runner installs a temporary signing keychain and removes it on exit. The CSR and P12 commands remain usable for all providers. ## Simulator sessions First [create a MobAI key and add it to each provider](provider-secrets.md#3-create-the-mobai-api-key). ```sh builder ios share --provider codemagic builder ios share --provider bitrise --duration 20m builder ios cancel --provider bitrise --run-id RUN_SLUG ``` Set `MOBAI_API_KEY` as a secret on the chosen provider. Any MobAI account will do, as for GitHub sharing. For the new providers, `ios share` returns **submitted** and a workflow URL. The simulator appears under MobAI's CI Devices once its build and bridge start; acceptance by the CI service does not establish readiness. Inspect the workflow URL for setup/build/bridge failures. Existing GitHub sharing retains its waiting behavior. The remote job outlives the CLI and consumes minutes until released, idle, cancelled, or timed out. Workflows on these free plans are capped at 90 minutes including setup and compilation. `--duration` controls idle time only (maximum 60 minutes for these providers), so it does not guarantee that much usable time. The CLI prints an explicit cancellation command. `ios cancel` confirms the run has stopped; it does not affect another provider's runs. Submitted simulator sessions retain their source ref while queued/running. After the run finishes, use the cleanup command printed by the CLI, for example: ```sh git push origin --delete refs/ios-builder/jobs/BUILD_ID ``` IPA builds on the new providers clean up their refs after terminal state/cancellation is confirmed. If dispatch returns an ambiguous error, or cancellation cannot be confirmed, Builder preserves the ref and reports the run/dashboard to inspect. It never automatically retries dispatch or starts a duplicate run on a different provider. Explicit request/access rejections (such as an invalid app ID or denied access) clean up the snapshot immediately. Timeouts and other uncertain dispatch outcomes still retain it. Transient API read failures (network errors, malformed responses, HTTP 408/429 and 5xx) receive up to three retries with exponential backoff. Builder honors `Retry-After` and the command deadline. Persistent failures still stop the command and attempt to cancel a running build. Bitrise artifact retrieval happens after completion, so an artifact API failure does not trigger cancellation of a completed run. Bitrise cancellation reserves time for the abort request even if its preliminary status check is unavailable or rate-limited. ## Free allowances Use one account at each provider and check each account's eligibility and billing settings. The approximate 800-minute target is not a guaranteed combined quota: | Provider | Published free allowance | | --- | --- | | [GitHub Actions](https://docs.github.com/en/billing/concepts/product-billing/github-actions) | GitHub Free includes 2,000 metered minutes for private repositories; macOS accounting differs from Linux. Standard runners for public repositories are free. | | [Codemagic](https://docs.codemagic.io/billing/pricing/) | 500 macOS M2 minutes/month on personal accounts; Teams do not receive them. | | [Bitrise](https://bitrise.io/pricing) | Hobby includes 300 credits/month, one private app; actual minutes depend on the machine's credit rate. | Allowances belong to accounts, so builds outside Builder also consume them. Switch providers explicitly when you want to use another allowance. Builder does not aggregate billing or enforce a zero-spend cap. Disable paid overages or set appropriate spending limits in each provider's billing settings if free usage is your requirement. Rates and plans can change; consult the linked pages.