Closed3

Azure Pipeline で `Xcode@5` を使用せずに iOS アプリの ビルドと TestFlight 配信を行う YAML

Kazunori KimuraKazunori Kimura

Azure Pipeline には Xcode@5 という Xcode でビルドを行うタスクが用意されているが、コードの署名に問題があるようで Keychain access groups が適切に登録されない問題につまづいた。

Keychain access groups が適切に登録されないと、MSAL を使用して Azure ActiveDIrectory B2C で認証する際にトークンを Keychain に保存できずに以下のエラーが発生していた。

操作を完了できませんでした。(OSStatusエラー-34018)

Kazunori KimuraKazunori Kimura

Xcode@5 の代わりに CmdLine@2 を使用して xcodebuild でアーカイブの作成と ipa ファイルのエクスポートを行ったところ、きちんと Keychain access groups が登録された。

備忘録も兼ねて YAML の内容を貼り付けておく

Kazunori KimuraKazunori Kimura
trigger:
- develop

pool:
  vmImage: 'macos-13' # macos-latest は罠, 12 とか使う

# Pipelines > Library > Variable group に DEPLOYMENT_KEYS を定義
# 以下の変数を定義
# - APP_STORE_CONNECT_USER_NAME: App Store Connect のユーザー名
# - APP_STORE_CONNECT_USER_PASSWORD: アプリ用パスワード
# - CERTIFICATE_PASSWORD: 証明書のパスワード
# - PROVISIONING_PROFILE: ProvisioningProfile のファイル名
# - XCODE_PROJECT_NAME: プロジェクト名
variables:
- group: DEPLOYMENT_KEYS

steps:
# 証明書のインストール
# Pipelines > Library > Secure files にアップロードしておく
- task: InstallAppleCertificate@2
  inputs:
    certSecureFile: "Certificate.p12"
    certPwd: "$(CERTIFICATE_PASSWORD)"
    keychain: "temp"
    deleteCert: true

# プロビジョニングプロファイルのインストール
# Pipelines > Library > Secure files にアップロードしておく
- task: InstallAppleProvisioningProfile@1
  inputs:
    provisioningProfileLocation: "secureFiles"
    provProfileSecureFile: "$(PROVISIONING_PROFILE)"
    removeProfile: true

# ビルド番号を更新
# YYYY.md.HM (例: 2024.425.1545)
- task: CmdLine@2
  displayName: "Updating the Build Number"
  inputs:
    script: "xcrun agvtool new-version `date +%Y.%m%d.%H%M`"

# Staging 設定ファイルのダウンロード
# Pipelines > Library > Secure files にアップロードしておく
- task: DownloadSecureFile@1
  name: stagingConfiguration
  displayName: "Download Configuration File"
  inputs:
    secureFile: "Staging.Secret.xcconfig"

# 設定ファイルの配置
- task: CopyFiles@2
  inputs:
    SourceFolder: '$(Agent.TempDirectory)'
    Contents: 'Staging.Secret.xcconfig'
    TargetFolder: "./$(XCODE_PROJECT_NAME)/Config/"
    OverWrite: true

# Firebaseの構成ファイルのダウンロード
# Pipelines > Library > Secure files にアップロードしておく
- task: DownloadSecureFile@1
  inputs:
    secureFile: "GoogleService-Info-staging.plist"

# Firebaseの構成ファイルの配置
- task: CopyFiles@2
  inputs:
    SourceFolder: '$(Agent.TempDirectory)'
    Contents: 'GoogleService-Info-staging.plist'
    TargetFolder: "./$(XCODE_PROJECT_NAME)/Config/"
    OverWrite: true

# exportOptionsPlistのダウンロード
# Pipelines > Library > Secure files にアップロードしておく
- task: DownloadSecureFile@1
  name: exportOptionsPlist
  displayName: "Download exportOptionsPlist File"
  inputs:
    secureFile: "exportOptionsPlist"

# --- ビルド ---
# clean, archive
- task: CmdLine@2
  displayName: "xcodebuild clean archive"
  inputs:
    script: |
      export DEVELOPER_DIR=/Applications/Xcode_15.2.app/Contents/Developer
      /usr/bin/xcodebuild -version
      /usr/bin/xcodebuild \
      -sdk iphoneos \
      -configuration Staging \
      -project $(Build.SourcesDirectory)/$(XCODE_PROJECT_NAME).xcodeproj \
      -scheme $(XCODE_PROJECT_NAME) \
      clean \
      archive \
      -archivePath $(agent.buildDirectory)/output/iphoneos/Staging/$(XCODE_PROJECT_NAME).xcarchive \
      -verbose \
      -skipPackagePluginValidation \
      CODE_SIGN_STYLE=Manual \
      CODE_SIGN_IDENTITY="$(APPLE_CERTIFICATE_SIGNING_IDENTITY)" \
      PROVISIONING_PROFILE_APP="$(APPLE_PROV_PROFILE_UUID)"
# export
- task: CmdLine@2
  displayName: "xcodebuild exportArchive"
  inputs:
    script: |
      export DEVELOPER_DIR=/Applications/Xcode_15.2.app/Contents/Developer
      /usr/bin/xcodebuild -version
      /usr/bin/xcodebuild \
      -exportArchive \
      -archivePath $(agent.buildDirectory)/output/iphoneos/Staging/$(XCODE_PROJECT_NAME).xcarchive \
      -exportPath $(agent.buildDirectory)/output/iphoneos/Staging/ \
      -exportOptionsPlist $(Agent.TempDirectory)/exportOptionsPlist

# ビルドログを公開フォルダにコピーする
- task: CopyFiles@2
  condition: succeededOrFailed()
  inputs:
    SourceFolder: "$(Agent.TempDirectory)"
    Contents: "**"
    TargetFolder: "$(Build.ArtifactStagingDirectory)/Log"
    OverWrite: true

# .ipaを公開フォルダにコピーする
# ビルドエラー時は空振りする
- task: CopyFiles@2
  condition: succeededOrFailed()
  inputs:
    SourceFolder: "$(agent.buildDirectory)/output/iphoneos/Staging"
    Contents: "**"
    TargetFolder: "$(build.artifactStagingDirectory)/Build"
    OverWrite: true

# 公開フォルダの内容をアーティファクトとして公開する
- task: PublishBuildArtifacts@1
  condition: succeededOrFailed()
  inputs:
    PathtoPublish: "$(Build.ArtifactStagingDirectory)"
    ArtifactName: "drop"
    publishLocation: "Container"

# .ipaをApp Storeにアップロード
- task: CmdLine@2
  displayName: "Distribute IPA file to TestFlight"
  inputs:
    script: |
      xcrun altool --upload-app \
      -f '$(agent.buildDirectory)/output/iphoneos/Staging/$(XCODE_PROJECT_NAME).ipa' \
      -t "ios" \
      -u '$(APP_STORE_CONNECT_USER_NAME)' \
      -p '$(APP_STORE_CONNECT_USER_PASSWORD)'
このスクラップは3ヶ月前にクローズされました