---
description: Bitbucket Pipelines has no hosted macOS runners. Here's how to build, sign, and ship iOS apps from your Bitbucket pipeline using Capawesome Cloud and its CLI.
title: Build & Ship iOS Apps with Bitbucket Pipelines - Capawesome
image: https://capawesome.io/docs/assets/images/social/blog/build-and-deploy-ios-apps-with-bitbucket.png
---

[ Skip to content](#build-ship-ios-apps-with-bitbucket-pipelines) 

[ 🔐 Introducing the **Capacitor Vault** plugin — store secrets behind biometrics or a device passcode.](/blog/announcing-the-capacitor-vault-plugin/) 

* [  Formbricks ](/docs/plugins/formbricks/)
* [  Geocoder ](/docs/plugins/geocoder/)
* [  Google Sign-In ](/docs/plugins/google-sign-in/)
* [  Grafana Faro ](/docs/plugins/grafana-faro/)
* [  libSQL ](/docs/plugins/libsql/)
* [  Live Update ](/docs/plugins/live-update/)
* [  Managed Configurations ](/docs/plugins/managed-configurations/)
* [  Media Session ](/docs/plugins/media-session/)
* [  ML Kit ](/docs/plugins/mlkit/)
* [  Navigation Bar ](/docs/plugins/navigation-bar/)
* [  NFC ](/docs/plugins/nfc/)
* [  OAuth ](/docs/plugins/oauth/)
* [  Pedometer ](/docs/plugins/pedometer/)
* [  Photo Editor ](/docs/plugins/photo-editor/)
* [  PostHog ](/docs/plugins/posthog/)
* [  Printer ](/docs/plugins/printer/)
* [  Purchases ](/docs/plugins/purchases/)
* [  RealtimeKit ](/docs/plugins/realtimekit/)
* [  Screen Orientation ](/docs/plugins/screen-orientation/)
* [  Screenshot ](/docs/plugins/screenshot/)
* [  Secure Preferences ](/docs/plugins/secure-preferences/)
* [  Speech Recognition ](/docs/plugins/speech-recognition/)
* [  Speech Synthesis ](/docs/plugins/speech-synthesis/)
* [  Share Target ](/docs/plugins/share-target/)
* [  Square Mobile Payments ](/docs/plugins/square-mobile-payments/)
* [  SQLite ](/docs/plugins/sqlite/)
* [  Superwall ](/docs/plugins/superwall/)
* [  Torch ](/docs/plugins/torch/)
* [  Vault ](/docs/plugins/vault/)
* [  Wifi ](/docs/plugins/wifi/)
* [  Zip ](/docs/plugins/zip/)
* [  Cloud ](/docs/cloud/)
* [  Live Updates ](/docs/cloud/live-updates/)
* Advanced
* Integrations
* [  Native Builds ](/docs/cloud/native-builds/)
* [  Configuration ](/docs/cloud/native-builds/configuration/)
* [  Environments ](/docs/cloud/native-builds/environments/)
* Guides
* [  Sample Projects ](/docs/cloud/native-builds/sample-projects/)
* [  Troubleshooting ](/docs/cloud/native-builds/troubleshooting/)
* [  Automations ](/docs/cloud/automations/)
* [  Assist ](/docs/cloud/assist/)
* Account
* Organizations
* [  Organization and User Management ](/docs/cloud/organizations/memberships/)
* [  Single Sign-On (SSO) ](/docs/cloud/organizations/sso/)
* [  Teams ](/docs/cloud/organizations/teams/)
* [  Two-Factor Authentication ](/docs/cloud/organizations/two-factor-authentication/)
* [  Integrations ](/docs/cloud/integrations/)
* [  License Keys ](/docs/cloud/license-keys/)
* [  Webhooks ](/docs/cloud/webhooks/)
* [  Pricing ](https://capawesome.io/pricing/)
* [  FAQ ](/docs/cloud/faq/)
* [  Support ](/docs/cloud/support/)
* [  Contributing ](/docs/contributing/)
* [  LLMs ](/docs/llms/)
* [  Insiders ](/docs/insiders/)
* [  License ](https://capawesome.io/legal/eula/)
* [  Support ](/docs/insiders/support/)
* [  FAQ ](/docs/insiders/faq/)
* [  Blog ](/blog/)
* Categories

# Build & Ship iOS Apps with Bitbucket Pipelines[¶](#build-ship-ios-apps-with-bitbucket-pipelines "Permanent link")

Bitbucket Pipelines is a solid CI/CD home for your backend, your web app, and your tests. Then you try to build your iOS app and hit a wall: Atlassian's hosted runners are Linux containers, and there's no macOS image to pick. iOS builds need Xcode, and Xcode needs a Mac. This guide shows you how to close that gap — building, signing, and shipping iOS apps straight from your existing Bitbucket pipeline, without owning a single Mac.

[ ![Build and deploy your Capacitor app with Capawesome Cloud](../../assets/external/cloud.capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.69628c3f.png) ](https://capawesome.io/) 

This works whether your app is a native Swift or Objective-C project, a [Capacitor](https://capawesome.io/technologies/capacitor/) app, or a Cordova app. The build itself happens on real macOS hardware in the cloud — your Bitbucket pipeline just kicks it off.

## The Bitbucket + iOS Problem[¶](#the-bitbucket-ios-problem "Permanent link")

Bitbucket Pipelines runs every step inside a Docker container on Linux. That's perfect for `npm`, `gradle`, `pytest`, and most of what a team does day to day. It's also a hard stop for iOS: you can't run `xcodebuild` without macOS and Xcode, and Atlassian doesn't offer hosted macOS runners.

So teams that live in Bitbucket usually end up with their iOS build sitting _somewhere else_ — a Mac mini under a desk, or a second CI tool bolted on just for mobile. Now you're maintaining two pipelines, two sets of secrets, and two mental models for "how do we ship."

The goal is simple: keep Bitbucket as the place your team already pushes code, and make iOS builds a normal step in that pipeline.

## Your Options for macOS[¶](#your-options-for-macos "Permanent link")

There are three realistic ways to get a macOS build out of a Bitbucket-centric setup.

**1\. Run a self-hosted macOS runner.** Bitbucket supports self-hosted runners, so you can register a Mac and point your pipeline at it. It works — until the Mac needs an OS update, Xcode falls behind, a certificate expires in Keychain, or the machine simply goes offline on a Friday. You've traded a CI problem for an IT problem.

**2\. Add a separate mobile-only CI tool.** Wire up a second platform purely for the iOS build. This solves the macOS problem but splits your pipeline in two, with duplicated triggers, secrets, and notifications to keep in sync.

**3\. Trigger cloud macOS builds from Bitbucket.** Keep Bitbucket Pipelines as the orchestrator and hand the actual iOS build off to a cloud service running real Macs. One command in your existing pipeline; no hardware to babysit.

For most teams, the third option is the one worth recommending. You don't give up Bitbucket, you don't maintain a Mac, and the iOS build stays a first-class step next to everything else. That's what the rest of this guide walks through, using [Capawesome Cloud](https://capawesome.io/).

## How It Works[¶](#how-it-works "Permanent link")

The model is a clean split of responsibilities. Bitbucket Pipelines stays in charge of orchestration — running your lint, tests, and tagging logic, and deciding _when_ a build should happen. When it's time to build iOS, a single [Capawesome CLI](/docs/cloud/cli/) call hands the job to [Capawesome Cloud](https://capawesome.io/), which runs it on Apple Silicon M4 runners with current Xcode versions.

Because the build runs in the cloud, your `bitbucket-pipelines.yml` never needs a macOS image. It runs on the standard `node:20` container, installs the CLI, and triggers the build. The cloud handles cloning your repo, running the web build and native sync (for Capacitor and Cordova apps), compiling with Xcode, and signing the result.

It's worth saying plainly: this is not Capacitor-only. Capawesome Cloud builds **native iOS projects written in Swift or Objective-C** just as happily as it builds Capacitor or Cordova apps — the build type and signing flow are the same regardless of framework.

## One-Time Setup[¶](#one-time-setup "Permanent link")

You only need to do this once per app.

First, create an app in Capawesome Cloud. You can do it from the [console](https://console.cloud.capawesome.io) or from your terminal:

`[](#%5F%5Fcodelineno-0-1)npx @capawesome/cli apps:create
`

Next, connect your Bitbucket repository. In the console, open your app's **Git** page, choose **Bitbucket** as the provider, authorize access, and select the repository you want to build. This lets the cloud check out your code by Git reference.

Then upload your iOS signing assets. iOS code signing needs two things — a distribution certificate as a `.p12` file (which bundles the certificate and its private key) and a `.mobileprovision` provisioning profile. Upload them once on the app's **Certificates** page, give the certificate a name like `Production iOS`, and the cloud stores them as named, reusable objects. You reference them by name at build time instead of stuffing base64 blobs into CI variables. See the [iOS certificates guide](/docs/cloud/native-builds/certificates/) for the full walkthrough, including how to generate a `.p12` if you don't have one.

Finally, give your pipeline permission to talk to the cloud. Create a Capawesome Cloud API token, then add it as a [secured repository variable](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/) in Bitbucket under **Repository settings → Repository variables**:

* Name: `CAPAWESOME_CLOUD_TOKEN`
* Value: your token
* Check **Secured** so it's masked in logs

The CLI reads this variable automatically — you don't pass the token on the command line.

## Build iOS from Bitbucket Pipelines[¶](#build-ios-from-bitbucket-pipelines "Permanent link")

With setup done, building iOS is one step. Here's a `bitbucket-pipelines.yml` that builds an App Store binary every time you push to `main`:

`[](#%5F%5Fcodelineno-1-1)image: node:20
[](#%5F%5Fcodelineno-1-2)
[](#%5F%5Fcodelineno-1-3)pipelines:
[](#%5F%5Fcodelineno-1-4)  branches:
[](#%5F%5Fcodelineno-1-5)    main:
[](#%5F%5Fcodelineno-1-6)      - step:
[](#%5F%5Fcodelineno-1-7)          name: Build iOS app
[](#%5F%5Fcodelineno-1-8)          script:
[](#%5F%5Fcodelineno-1-9)            - npm install -g @capawesome/cli@latest
[](#%5F%5Fcodelineno-1-10)            - npx @capawesome/cli apps:builds:create --app-id 00000000-0000-0000-0000-000000000000 --platform ios --type app-store --certificate "Production iOS" --git-ref $BITBUCKET_COMMIT
`

A few things worth pointing out. The image is plain `node:20` — no macOS runner anywhere in this file. `$BITBUCKET_COMMIT` is a [built-in Bitbucket variable](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/), so the cloud builds the exact commit that triggered the pipeline. And `--certificate "Production iOS"` points at the signing assets you uploaded earlier, so the resulting `.ipa` comes out signed and ready.

The `--type` flag controls what kind of build you get. For iOS the supported values are `simulator`, `development`, `ad-hoc`, `app-store`, and `enterprise` — pick the one that matches where the build is headed.

## Ship to TestFlight & the App Store[¶](#ship-to-testflight-the-app-store "Permanent link")

Building is half the job. To get the binary in front of testers, add a **destination**. A destination holds your App Store Connect credentials and tells the cloud where to deliver a build.

Create one once with your App Store Connect API key:

`[](#%5F%5Fcodelineno-2-1)npx @capawesome/cli apps:destinations:create --app-id 00000000-0000-0000-0000-000000000000 --name "TestFlight" --platform ios
`

The command will prompt for the details it needs — your Apple Team ID, Issuer ID, and the API key file. With the destination in place, you can build and deploy in a single pipeline step by adding `--destination`:

`[](#%5F%5Fcodelineno-3-1)image: node:20
[](#%5F%5Fcodelineno-3-2)
[](#%5F%5Fcodelineno-3-3)pipelines:
[](#%5F%5Fcodelineno-3-4)  branches:
[](#%5F%5Fcodelineno-3-5)    main:
[](#%5F%5Fcodelineno-3-6)      - step:
[](#%5F%5Fcodelineno-3-7)          name: Build & deploy iOS to TestFlight
[](#%5F%5Fcodelineno-3-8)          script:
[](#%5F%5Fcodelineno-3-9)            - npm install -g @capawesome/cli@latest
[](#%5F%5Fcodelineno-3-10)            - npx @capawesome/cli apps:builds:create --app-id 00000000-0000-0000-0000-000000000000 --platform ios --type app-store --certificate "Production iOS" --destination "TestFlight" --git-ref $BITBUCKET_COMMIT
`

Now a push to `main` produces a signed build and uploads it to TestFlight without you opening Xcode. If you'd rather decouple the two — build on every push, but deploy only when you decide — you can promote an existing build to a destination on its own:

`[](#%5F%5Fcodelineno-4-1)npx @capawesome/cli apps:deployments:create --app-id 00000000-0000-0000-0000-000000000000 --build-number 42 --destination "TestFlight"
`

## Internal Builds & On-Device Testing[¶](#internal-builds-on-device-testing "Permanent link")

Not every build is for the App Store. For QA and stakeholder review, an `ad-hoc` or `development` build is faster — and Capawesome Cloud gives every build a QR code for over-the-air installs. A tester scans it and the app lands on their device in under a minute, with no review queue in the way.

A common pattern is a separate, manually triggered pipeline for internal builds. Bitbucket's [custom pipelines](https://support.atlassian.com/bitbucket-cloud/docs/pipeline-triggers/) let you run a step on demand from the Bitbucket UI:

`[](#%5F%5Fcodelineno-5-1)image: node:20
[](#%5F%5Fcodelineno-5-2)
[](#%5F%5Fcodelineno-5-3)pipelines:
[](#%5F%5Fcodelineno-5-4)  custom:
[](#%5F%5Fcodelineno-5-5)    internal-ios-build:
[](#%5F%5Fcodelineno-5-6)      - step:
[](#%5F%5Fcodelineno-5-7)          name: Build ad-hoc iOS app
[](#%5F%5Fcodelineno-5-8)          script:
[](#%5F%5Fcodelineno-5-9)            - npm install -g @capawesome/cli@latest
[](#%5F%5Fcodelineno-5-10)            - npx @capawesome/cli apps:builds:create --app-id 00000000-0000-0000-0000-000000000000 --platform ios --type ad-hoc --certificate "Production iOS" --git-ref $BITBUCKET_COMMIT
`

Run it whenever a stakeholder asks for "the latest," share the QR code, and skip the App Store round trip entirely.

## Why This Beats a Self-Hosted Mac[¶](#why-this-beats-a-self-hosted-mac "Permanent link")

Once it's running, the difference from babysitting a Mac mini is hard to overstate:

* **No hardware to maintain.** No machine to patch, no Keychain to unlock, no runner that drops offline overnight.
* **Xcode stays current.** New Xcode versions are typically available within days of Apple's release, so you're not blocked when a new iOS requires the latest SDK.
* **Signing is managed, not hacked.** Certificates and provisioning profiles are named objects you upload once — not base64 blobs juggled through CI variables.
* **Builds are quick.** Apple Silicon M4 runners turn most iOS builds around in a few minutes.

Your team keeps pushing to Bitbucket exactly as they do today. The iOS build just stops being the part of the pipeline that nobody wants to own.

## Get Started[¶](#get-started "Permanent link")

You can wire up your first cloud-built iOS pipeline today — no Mac, no credit card.

[Try Capawesome Cloud Free](https://capawesome.io)

## Conclusion[¶](#conclusion "Permanent link")

Bitbucket Pipelines doesn't do iOS on its own, but it doesn't have to. By keeping Bitbucket as your orchestrator and handing the macOS build off to [Capawesome Cloud](https://capawesome.io/) with a single CLI call, you get signed builds and TestFlight deployments from the pipeline your team already uses — without owning or maintaining a Mac. Whether you're shipping a native Swift app, a Capacitor app, or a Cordova app, the workflow is the same.

If you're curious how a specialized platform compares to wiring everything up yourself, our post on [why CI/CD specialization wins](/blog/ci-cd-for-capacitor-apps/) digs into the trade-offs. Got questions about your own setup? Join the [Capawesome Discord server](https://discord.gg/VCXxSVjefW), and subscribe to the [Capawesome newsletter](https://capawesome.io/newsletter) to catch new guides as they ship.

June 2, 2026 

 Back to top 