メインコンテンツへスキップ

Bitbucket PipelinesでiOSアプリをビルド・デプロイ

ホスト型のmacOSランナーを使わずに、Bitbucket PipelinesからiOSアプリのビルド、署名、TestFlightへの配信を実現。Linuxステップからのクラウドビルド、またはセルフホストのMacから実行可能です。

Bitbucket PipelinesによるiOSアプリのビルドとTestFlightへの配信

Bitbucket Pipelines cannot build an iOS app on its hosted runners, because every step runs in a Linux container and Xcode only runs on macOS. You have two working options: register your own Mac as a self-hosted Bitbucket runner, or keep the step on Linux and hand the iOS compile, signing, and TestFlight upload to a cloud build service. This guide shows both, with complete bitbucket-pipelines.yml Capacitor アプリ用のファイル

もしチームがすでにcodeのレビュー、Jira連携、デプロイのためにBitbucketを活用しているなら、iOSのためだけに別のCIツールを導入する必要はありません。パイプラインはBitbucketに置いたまま、Macが必要な部分だけを切り離せばよいのです。

Bitbucket PipelinesでiOSビルドが失敗する理由

Bitbucket Pipelinesは、AtlassianのLinuxインフラ上で、選択したDockerイメージ(node:22, cimg/androidなど)を使用して各ステップを実行します。これは、 bun install、ユニットテスト、リンター、さらにはAndroidのフルビルドには適しています。しかし、iOSでは限界があります:

  • xcodebuild, codesign、iOSのSDKはmacOS上にしか存在しません。
  • Appleのライセンスにより、macOSはApple製ハードウェア上でのみ実行が許可されているため、署名済みのアプリを作成できるLinuxイメージは存在しません。 .ipa.
  • 2026年4月28日以降、App Store ConnectはXcode 26およびiOS 26 SDKでビルドされていないuploadを拒否するため、使用するMacは常に最新の状態に保つ必要があります。詳細は Appleによる Capacitor アプリ向けのXcode 26要件.

BitbucketはLinux、Windows、macOSでのセルフホスト型ランナーをサポートしています。Atlassianは自社ランナーで実行されるステップに対してビルド時間の課金は行いませんが、ハードウェア費用とメンテナンスコストが発生します。

3つの選択肢

オプション iOSビルドの実行場所 管理対象 適したユースケース
セルフホスト型macOSランナー 所有しているMac miniまたはレンタルMac macOS、Xcode、キーチェーン、証明書、ディスク容量、稼働時間 すでにMacを所有しており、運用担当者がいるチーム
モバイル専用のセカンドCI 他ベンダーのMac 2つのパイプライン、2組のシークレットとトリガー モバイル専用のCIを別途導入したいチーム
Linuxステップから呼び出すクラウドビルド Capgo BuildのMacフリート 1回のCLI呼び出しと少数のセキュアな変数 Bitbucketを唯一のCIとして使い続けたいCapacitorチーム

本ガイドの残りの部分では、1番目と3番目のオプションについて詳しく解説します。各プラットフォームの全体像については、以下をご覧ください。 iOSアプリ向けCI/CDプラットフォームの比較.

オプション1: Capgo Buildを使用してLinuxステップからiOSをビルドする

Capgo のビルド Capgoが管理するMac上でCapacitorアプリをコンパイルおよび署名します。Bitbucketのステップでは、Linux上で得意とする依存関係のインストール、Webレイヤーのビルド、実行をそのまま行います。 cap sync iosその後、CapgoのCLIが、準備されたネイティブプロジェクト(Webソースのcodeや node_modules), Xcode ビルドを実行して証明書で署名し、その結果を TestFlight に upload できます。ログは Bitbucket のステップにストリーム出力され、ビルドに失敗するとコマンドが非ゼロで終了するため、iOS ビルドの失敗がそのままパイプラインの失敗として扱われます。

Runner がプロジェクトを Capgo に push するため、Capgo が Bitbucket リポジトリへのアクセス権を持つ必要はありません。認可が必要なリポジトリ接続や、承認が必要な OAuth アプリも存在しません。

前提条件

  • ローカルでビルドする Capacitor アプリ (Capacitor 8 には Node.js 22 以降が必要)
  • チームの管理者権限を持つ Apple Developer Program メンバーシップ
  • Capgo アカウントと、upload 権限を持つ API キー
  • Capgo に登録済みのアプリ: bunx @capgo/cli@latest app add

ローカルマシンでの初回セットアップ

初回のみ onboarding を実行します。iOS の場合、配布用証明書と provisioning profile を作成または再利用し、App Store Connect の API キーを求められます:

bunx @capgo/cli@latest login
bunx @capgo/cli@latest build init --platform ios

手元に Mac がない場合でも、ブラウザを使用して証明書署名要求(CSR)を作成できます。詳細は iOS証明書ジェネレーター、または Capgo Build を使えば Windows から iOS アプリをビルドできます.

CIを触る前に、まずはローカル環境で一度ビルドを実行しましょう。最初のビルドのデバッグをCI上で行うのは効率が悪いためです。

bun run build
bunx cap sync ios
bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release

Bitbucket用の認証情報をエクスポートする

CLI を使用すると、認証情報をローカルマシンに保持できます。これらをBitbucketに移行するには、dotenvファイルにエクスポートしてください:

bunx @capgo/cli@latest build credentials manage --appId com.example.app --platform ios
# choose "Export to .env" in the menu

これにより、次が書き込まれます: .env.capgo.com.example.app.ios モード付き 0600。これには以下のキーが含まれます:

変数 コンテンツ
BUILD_CERTIFICATE_BASE64 のBase64形式 .p12 配布用証明書
P12_PASSWORD 証明書のパスワード(設定がない場合は空)
CAPGO_IOS_PROVISIONING_MAP_BASE64 CLI によって生成された Provisioning profile マッピング
APPLE_KEY_ID App Store Connect API キーID
APPLE_ISSUER_ID App Store Connect issuer ID
APPLE_KEY_CONTENT 〜のBase64 .p8 API キー
APP_STORE_CONNECT_TEAM_ID あなたのApple Team ID

各行を次の形式で追加 セキュアな Bitbucketの変数として リポジトリ設定 > Pipelines > Repository variables、さらに CAPGO_TOKEN にはご自身のCapgo APIキーを指定します。セキュア変数はログでマスクされ、UIから読み戻すことはできません。

APIを使う場合は、このループで一括作成できます。パイプライン変数の書き込みスコープを持つBitbucket APIトークンを使用します:

WORKSPACE=my-team
REPO=my-app
ENV_FILE=.env.capgo.com.example.app.ios

grep -v '^#' "$ENV_FILE" | grep '=' | while IFS= read -r line; do
  key="${line%%=*}"
  value="${line#*=}"
  value="${value%\"}"; value="${value#\"}"
  jq -n --arg k "$key" --arg v "$value" '{key:$k, value:$v, secured:true}' |
    curl -s -u "$BB_EMAIL:$BB_API_TOKEN" \
      -H 'Content-Type: application/json' \
      -X POST --data @- \
      "https://api.bitbucket.org/2.0/repositories/$WORKSPACE/$REPO/pipelines_config/variables" > /dev/null
  echo "created $key"
done

rm "$ENV_FILE"

後でファイルを削除して、追加してください .env.capgo.* まで .gitignore. 平文の署名用マテリアルが含まれています。

本番環境の認証情報には、リポジトリ変数ではなく、 デプロイメント変数(deployment variables)の 使用を検討してください。これらはデプロイ環境ごとにスコープが設定されており(例: Production)、Premiumプランではその環境へのアクセスを管理者や特定のブランチに制限できます。

パイプラインファイル

Bitbucketはリポジトリ変数とデプロイメント変数を環境変数として注入するため、Capgo CLI はマッピングなしでこれらを取得できます。このファイルは、プッシュのたびにテストを実行し、オンデマンドでiOSのad hocビルドを作成し、バージョンタグが打たれた際にTestFlightへ配信します。

# bitbucket-pipelines.yml
image: node:22

definitions:
  caches:
    bun: ~/.bun/install/cache

pipelines:
  default:
    - step:
        name: Lint and test
        caches:
          - bun
        script:
          - curl -fsSL https://bun.sh/install | bash
          - export PATH="$HOME/.bun/bin:$PATH"
          - bun install --frozen-lockfile
          - bun run lint
          - bun run test

  tags:
    'v*':
      - step:
          name: Build iOS and upload to TestFlight
          deployment: Production
          caches:
            - bun
          script:
            - curl -fsSL https://bun.sh/install | bash
            - export PATH="$HOME/.bun/bin:$PATH"
            - bun install --frozen-lockfile
            - bun run build
            - bunx cap sync ios
            - >
              bunx @capgo/cli@latest build request com.example.app
              --platform ios
              --build-mode release
              --ios-distribution app_store

  custom:
    ios-adhoc:
      - step:
          name: Ad hoc iOS build for testers
          caches:
            - bun
          script:
            - curl -fsSL https://bun.sh/install | bash
            - export PATH="$HOME/.bun/bin:$PATH"
            - bun install --frozen-lockfile
            - bun run build
            - bunx cap sync ios
            - echo "$ADHOC_PROFILE_BASE64" | base64 --decode > adhoc.mobileprovision
            - >
              bunx @capgo/cli@latest build request com.example.app
              --platform ios
              --build-mode release
              --ios-distribution ad_hoc
              --ios-provisioning-profile ./adhoc.mobileprovision
              --output-upload
              --output-retention 2d
              --output-record /tmp/build.json
            - bunx @capgo/cli@latest build last-output --path /tmp/build.json --field outputUrl

重要な詳細事項:

  • このイメージは標準的なLinux node:22このファイルに macOS は不要です。
  • Linux 環境では、 cap sync ios Web アセットのコピーと native 設定の更新を行いますが、CocoaPods は実行できません。これは問題ありません。ビルドを実行する Mac 側で pods のインストールや Swift パッケージの解決が行われるためです。
  • Capgo は App Store Connect から最新のビルド番号を読み取ってインクリメントするため、「bundle version must be higher than the previously uploaded version」というエラーを回避できます。自分で管理する場合は、 --skip-build-number-bump このフラグを渡してください。
  • Ad Hoc ビルドには Ad Hoc プロビジョニングプロファイルが必要で、リストされたデバイスにのみインストールできます。セキュアな ADHOC_PROFILE_BASE64 変数として保存してください。また、 --ios-provisioning-profile フラグを使用すると、このビルドに限り環境から App Store プロファイルを上書きできます。テスターの UDID は、 iOS UDID 検索ツール.
  • CLI を特定のバージョンに固定してください(例: @capgo/cli@7.104.0)。パイプラインが安定したら、スプリントの途中で CLI リリースによって挙動が変わってしまうのを防げます。

カスタムパイプラインの実行は、 Pipelines > パイプラインの実行 > ios-adhoc から行います。最後のコマンドで、保持期間が過ぎると期限切れになるダウンロードリンクが表示されます。

TestFlight 前の手動承認

Bitbucketは以下をサポートしています: trigger: manual 各ステップで実行可能です。TestFlightへのアップロードごとに人の承認を挟みたい場合は、リリースをbuildステップと、承認待ちのuploadステップに分けてください:

  tags:
    'v*':
      - step:
          name: Test
          script:
            - curl -fsSL https://bun.sh/install | bash
            - export PATH="$HOME/.bun/bin:$PATH"
            - bun install --frozen-lockfile
            - bun run test
      - step:
          name: Ship iOS to TestFlight
          trigger: manual
          deployment: Production
          script:
            - curl -fsSL https://bun.sh/install | bash
            - export PATH="$HOME/.bun/bin:$PATH"
            - bun install --frozen-lockfile
            - bun run build
            - bunx cap sync ios
            - bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release

TestFlightへのアップロード後、そのままApp Reviewへ進めるようにするには、以下を追加します: --submit-to-store-review を使用して --store-release-name "$BITBUCKET_TAG"。ただし、事前にApp Store ConnectでApp Storeの掲載情報、スクリーンショット、コンプライアンスへの回答を完了させておく必要があります。

Androidも並行して追加する

AndroidのbuildはBitbucketのLinux runnerで直接実行できますが、Capgo Buildに送ることも可能です。これにより、両プラットフォームで同じ署名およびuploadフローを利用できます。また、 parallel ブロックで定義します:

  tags:
    'v*':
      - parallel:
          - step:
              name: iOS release
              script:
                - curl -fsSL https://bun.sh/install | bash
                - export PATH="$HOME/.bun/bin:$PATH"
                - bun install --frozen-lockfile && bun run build
                - bunx cap sync ios
                - bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release
          - step:
              name: Android release
              script:
                - curl -fsSL https://bun.sh/install | bash
                - export PATH="$HOME/.bun/bin:$PATH"
                - bun install --frozen-lockfile && bun run build
                - bunx cap sync android
                - bunx @capgo/cli@latest build request com.example.app --platform android --build-mode release --android-track internal

Androidのステップには以下が必要です: ANDROID_KEYSTORE_FILE, KEYSTORE_KEY_ALIAS, KEYSTORE_KEY_PASSWORD, KEYSTORE_STORE_PASSWORDや PLAY_CONFIG_JSON セキュア変数として。同じ方法でエクスポートするには: --platform android.

Native Build なしで Web のみの変更を配信

Capacitor アプリへのコミットのほとんどは、HTML、CSS、JavaScript しか変更しません。新しいバイナリは不要です。これを使えば Capgo Live Updates、Bitbucket のステップでストアビルドと OTA バンドルのどちらにするかを判断できます:

  branches:
    main:
      - step:
          name: Release (live update or native)
          script:
            - curl -fsSL https://bun.sh/install | bash
            - export PATH="$HOME/.bun/bin:$PATH"
            - bun install --frozen-lockfile
            - bun run build
            - |
              if bunx @capgo/cli@latest build needed com.example.app --channel production; then
                echo "No native change, shipping a live update"
                bunx @capgo/cli@latest bundle upload com.example.app --channel production
              else
                echo "Native change detected, building iOS"
                bunx cap sync ios
                bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release
              fi

build needed Native Build が不要な場合は code 0、必要な場合は 1 で終了します。ネイティブプラグインのバージョンを、チャンネルで稼働中のものと比較します。ただし、配下の手動編集は検知しません ios/そのため、これらのファイルが変更されたときはネイティブのパスも強制してください。パターン全体はこちらにあります。 live update か Native Build を自動選択.

オプション 2: セルフホストの macOS runner

すでに Mac を持っていれば、1 台を Bitbucket runner として登録し、自分で Xcode を実行できます。

runner を登録する

  1. Bitbucketで、 Repository settings > Runners を開き、 (または ワークスペース設定 > Workspace runners を共有するには) をクリックし runner を追加.
  2. 選択: MacOS を選択します をシステムとして指定します。Bitbucket に runner UUID と OAuth 認証情報を含む start コマンドが表示されます。
  3. Mac に、サポートされている JDK(runner は Java プログラムです)、Xcode 26、fastlane をインストールします。その後、start コマンドを貼り付けます。
  4. 再起動後も動作するように、runner を launch agent として実行し続けてください。

ステップでは、以下のラベルで runner を指定します:

pipelines:
  tags:
    'v*':
      - step:
          name: iOS build on our Mac
          runs-on:
            - self.hosted
            - macos
          script:
            - bun install --frozen-lockfile
            - bun run build
            - bunx cap sync ios
            - echo "$BUILD_CERTIFICATE_BASE64" | base64 --decode > dist.p12
            - echo "$PROFILE_BASE64" | base64 --decode > profile.mobileprovision
            - bundle exec fastlane ios beta

macOS runner はコンテナ内ではなく、ホスト上のユーザー環境で直接実行されます。Mac 自体に Bun と Ruby をインストールしてください。

最小構成の Fastfile

default_platform(:ios)

platform :ios do
  lane :beta do
    setup_ci(force: true)

    api_key = app_store_connect_api_key(
      key_id: ENV["APPLE_KEY_ID"],
      issuer_id: ENV["APPLE_ISSUER_ID"],
      key_content: ENV["APPLE_KEY_CONTENT"],
      is_key_content_base64: true
    )

    import_certificate(
      certificate_path: "dist.p12",
      certificate_password: ENV["P12_PASSWORD"],
      keychain_name: "fastlane_tmp_keychain",
      keychain_password: ""
    )
    install_provisioning_profile(path: "profile.mobileprovision")

    update_code_signing_settings(
      path: "ios/App/App.xcodeproj",
      use_automatic_signing: false,
      team_id: ENV["APP_STORE_CONNECT_TEAM_ID"],
      code_sign_identity: "Apple Distribution",
      profile_name: ENV["PROFILE_NAME"]
    )

    increment_build_number(
      xcodeproj: "ios/App/App.xcodeproj",
      build_number: latest_testflight_build_number(api_key: api_key) + 1
    )

    build_app(
      project: "ios/App/App.xcodeproj", # use workspace: "ios/App/App.xcworkspace" for CocoaPods projects
      scheme: "App",
      export_method: "app-store"
    )

    upload_to_testflight(api_key: api_key, skip_waiting_for_build_processing: true)
  end
end

新しい Capacitor 8 プロジェクトは Swift Package Manager を使用しているため、ビルドには App.xcodeproj. CocoaPodsを使用している古いプロジェクトのビルドには、 App.xcworkspace また、 pod install ランナーが必要です。当社の GitHub Actions iOSガイドでは、 各fastlane actionを詳しく解説しています。Bitbucketでもlaneは共通です。

サインアップ内容

アーカイブ作成は簡単です。セルフホストのMacを利用すれば、以下も可能になります:

  • Xcodeのアップグレード Appleが最小 SDK を引き上げた際も、期限前にテスト・対応できます。
  • Keychainの状態 ジョブがクラッシュすると一時的なkeychainが残ることがあり、次のジョブが誤ったアイデンティティを読み込んでしまいます。
  • 隔離環境の欠如 ジョブが同じディスク上で実行されるため、DerivedDataや古いアーカイブ、シミュレータでディスクが圧迫されます。
  • 一度に1つのビルドのみ Macを追加で購入しない限り、ランナーごとに制限されます。
  • 証明書とプロファイル これらは毎年期限が切れ、マシン上での更新作業が必要です。

チームですでにMacを管理しているなら許容範囲ですが、管理者がいない場合は、オプション1でこの問題を解消できます。

トラブルシューティング

症状 主な原因と解決策
CAPGO_TOKEN is not set 変数が不足しているか、デプロイ用の変数ですが、ステップに deployment: key.
ステップの動作条件 main ただし、タグには適用されません デプロイ変数は、そのデプロイ環境を宣言しているステップにのみ適用されます。
Provisioning profile doesn't match bundle ID プロファイルが別のApp ID用に作成されています。再実行して build init 再エクスポートしてください。
App Store Connect の認証に失敗しました Issuer IDまたはKey IDが間違っているか、キーが失効しています。App Store Connect > Users and Access > Integrations でキーを確認してください。
SDK バージョンのアップロードが拒否されました ビルドで使用されたXcodeが26より古いです。セルフホストのMacをアップグレードしてください。
セルフホストのステップが「Pending」のまま停止 Runnerがオフライン、またはラベルが一致しません self.hosted と macos.
errSecInternalComponent codesign 中 非対話型セッションではキーチェーンがロックされています。使用してください: setup_ci 証明書を一時的なキーチェーンにインポートします。
ビルドは成功しましたが、TestFlightに何も表示されません。 処理には数分かかり、輸出コンプライアンスの確認待ちになる場合があります。以下を追加してください: ITSAppUsesNonExemptEncryption まで Info.plist アプリが標準的な暗号化のみを使用している場合。

パイプライン失敗時のその他の修正方法は、こちらにあります: Capacitor の CI/CD パイプラインにおけるビルド失敗の修正方法 および Capgo Build トラブルシューティングガイドにあります.

どちらのオプションを選ぶべきか?

すでにハードウェアを所有している場合、Xcode環境を完全に制御する必要がある場合、または Capacitor アプリではないネイティブのSwiftターゲットをビルドする場合は、セルフホストのMacを選択してください。アプリが Capacitor アプリであり、チームのCI設定をBitbucketに集約したい場合は、Linuxステップからのクラウドビルドを選択してください。どちらの方法でも、ビルドロジックは以下に保持されます: bitbucket-pipelines.yml code の横に署名用の素材をセキュアな変数として置き、ネイティブの code が実際に変わったときだけ Native Build を実行してください。

Capacitor アプリ向けの Live Updates

Web レイヤーのバグが本番で発生したら、App Store の審査を何日も待たずに Capgo で修正を配信しましょう。ネイティブの変更は通常の審査フローに残したまま、ユーザーはバックグラウンドでアップデートを受け取れます。

最新のブログ記事

Capgoは、真にプロフェッショナルなモバイルアプリを作るために必要な最高のインサイトを提供します。