WWDC Quick Look 💓 By SwiftGGTeam
Deep dive into Xcode Cloud for teams

Deep dive into Xcode Cloud for teams

元の動画を見る

ハイライト

Xcode Cloud は、Webhook および App Store Connect API を通じてチームの既存のツールと統合し、Swift Package Manager の依存関係管理、カスタム スクリプト、権限制御と連携して、CI/CD プロセスをチームの既存の開発ワークフローに統合します。

主要内容

あなたのチームは Xcode Cloud を使用していますが、ビルド情報と問題トラッカーは別のものです。開発者はビルド ステータスを手動で確認する必要があり、ビルド製品はあちこちに散らばっており、コード スタイルには統一された制約がありません。

(01:34) セッションでは Food Truck プロジェクトを使用して、チームの完全な開発プロセスに Xcode Cloud を組み込む方法をデモンストレーションしました。

問題トラッカーとの統合

(01:46) チームは課題トラッカーを使用してタスクを管理していますが、ビルド情報は特定のチケットに関連付けられていません。解決策は、Swift on Server サービスを構築し、Xcode Cloud の Webhook を受信し、対応する問題の下にビルド結果のコメントを自動的に追加することです。

プロセスは次のとおりです。

  1. Xcode Cloudのビルドが完了したら、Webhookをチームサーバーに送信します。
  2. サーバーはコミットメッセージを解析し、問題番号を抽出します。
  3. Xcode Cloud API を呼び出してビルドの詳細と問題リストを取得します
  4. コメントのコンテンツを作成し、問題トラッカー API を呼び出して公開します。

(03:01) Xcode Cloud API は App Store Connect API の一部です。 App Store Connect API の認証トークンをすでに持っている場合は、Xcode Cloud データに直接アクセスできます。

主要なエンドポイント:

  • CiBuildRuns:ビルドの作成、キャンセル、クエリ
  • CiBuildActions: ビルドアクションの詳細を取得します
  • CiArtifacts: ビルド製品のダウンロード リンクを取得します。

(04:00) App Store Connect ドキュメントから OpenAPI 仕様をダウンロードし、OpenAPI Generator を使用して Swift クライアントを自動的に生成します。

# 下载 OpenAPI 规范后
openapi-generator generate -i app_store_connect_api.json \
  -g swift -o xcodecloud-client

生成されたクライアントは、Webhook サーバー プロジェクトに依存関係として直接導入できる Swift パッケージです。

(05:24) App Store Connect で Webhook を設定します。 [製品設定] > [Webhook] に移動し、サーバー URL を入力します。各ビルドが完了すると、Xcode Cloud はこのアドレスに POST リクエストを送信します。

Webhook ペイロードには、ビルド ID、アクション リスト、実行ステータス、その他の情報が含まれます。 Vapor フレームワークで処理:

import Vapor

struct WebhookPayload: Content {
    let buildRun: CiBuildRun
    let actions: [CiBuildAction]
}

func routes(_ app: Application) throws {
    app.post("webhook") { req async throws in
        let payload = try req.content.decode(WebhookPayload.self)
        // 解析 commit message 中的 issue 编号
        // 调用 API 获取构建问题
        // 发布评论到 issue tracker
        return HTTPStatus.ok
    }
}

依存関係の管理

(08:25) Xcode Cloud は Swift Package Manager をネイティブにサポートしています。パブリック パッケージには追加の構成は必要ありませんが、プライベート パッケージには構成アクセス権限が必要です。

CocoaPods や Carthage などのサードパーティの依存関係マネージャーも、カスタム スクリプトを介して Xcode Cloud で利用できます。具体的な設定方法については、Xcode のドキュメントを参照してください。

ビルドが完了したら、Xcode の [レポート ナビゲーター] > [クラウド] タブでビルド ログを表示します。 Xcode Cloud は、Swift パッケージの依存関係を自動的に解析してダウンロードします。

コードの品質チェック

(09:50) SwiftLint を使用して静的コード分析を行い、カスタム スクリプトを通じて Xcode Cloud に統合します。

#!/bin/bash
# ci_scripts/post_clone.sh

# 安装 SwiftLint
brew install swiftlint

# 在代码仓库目录运行检查
swiftlint lint --path "$CI_WORKSPACE"

キーポイント:

  • post_cloneコードが複製された後にスクリプトが実行されます
  • CI_WORKSPACE環境変数はコード リポジトリ ディレクトリを指します
  • スクリプトの実行場所はci_scriptsディレクトリ。作業ディレクトリを明示的に指定する必要があります
  • SwiftLint は違反の数と重大度を出力します。

(11:27) 最初の統合中に多数の違反が発見される可能性があります。ワークフローは一時的に無効にすることができ、修復して有効にする前に、チームでコードの仕様を話し合って決定します。

ワークフロー権限制御

(12:13) チームが拡大するにつれて、メンバーが誤ってワークフロー構成を変更しないようにする必要があります。 Xcode Cloud は、ワークフロー編集権限の制限をサポートしています。

  • ワークフローを右クリック > 編集の制限
  • 管理者、アカウント所有者、アプリ管理者のみが制限を設定および削除できます
  • 制限されたワークフローにはキーアイコンが表示されます
  • ロックされたワークフローには鍵のアイコンが表示され、通常のメンバーは編集できません

複数の開始条件

(13:22) ワークフローには複数の開始条件を設定できるため、維持する必要があるワークフローの数が減ります。

たとえば、同じテストとアーカイブのワークフローを次のようにトリガーできます。

  • メインブランチに変更があります
  • リリースブランチに変更があります
  • メインブランチのスケジュールされたビルド

3 つの個別のワークフローを作成する必要はなく、1 つのワークフローに 3 つの開始条件を追加するだけです。

詳細

Webhook サービスの実装

(05:55) 完全な Webhook 処理フロー:

import Vapor

// 定义 Webhook payload 结构
struct XcodeCloudWebhook: Content {
    let buildRun: CiBuildRun
    let actions: [CiBuildActionResponse]
}

// 扩展 API 客户端获取构建问题
extension CiBuildActionsAPI {
    func getIssues(for actionId: String) async throws -> [CiIssue] {
        let response = try await ciBuildActionsActionsIdIssuesGet(
            id: actionId
        )
        return response.data
    }
}

// Vapor 路由处理
func routes(_ app: Application) throws {
    app.post("webhook") { req async throws -> HTTPStatus in
        let payload = try req.content.decode(XcodeCloudWebhook.self)
        
        // 只处理已完成的构建
        guard payload.buildRun.attributes?.status == .complete else {
            return .ok
        }
        
        // 从 commit message 提取 issue 编号
        let commitMessage = payload.buildRun.attributes?.commitMessage ?? ""
        guard let issueId = extractIssueId(from: commitMessage) else {
            return .ok
        }
        
        // 构造评论内容
        var comment = "Build #\(payload.buildRun.attributes?.number ?? 0)\n"
        comment += "Commit: \(payload.buildRun.attributes?.commitHash ?? "")\n"
        comment += "Author: \(payload.buildRun.attributes?.commitAuthor ?? "")\n"
        
        // 获取每个 action 的问题
        for action in payload.actions {
            let issues = try await req.application.ciAPI.getIssues(for: action.id)
            for issue in issues {
                comment += "- [\(issue.attributes?.issueType ?? "")] \(issue.attributes?.message ?? "")\n"
            }
        }
        
        // 发布到 issue tracker
        try await postComment(to: issueId, content: comment, on: req)
        
        return .ok
    }
}

キーポイント:

  • Webhook ペイロードには、ビルドとアクションに関する完全な情報が含まれています
  • API拡張機能を通じて各アクションの質問リストを取得します
  • コメントにはビルド番号、コミットハッシュ、作成者および問題の詳細が含まれます
  • サービスは、App Store Connect で構成された Webhook URL にデプロイされます

App Store Connect API 認定

(03:08) App Store Connect API と同じ認証方法を使用して Xcode Cloud API にアクセスします。

  1. App Store Connect > ユーザーとアクセス > キーで API キーを生成します
  2. 秘密鍵ファイル (.p8) をダウンロードします。
  3. JWT を使用して認証トークンを生成する
import JWT

struct AppStoreConnectToken {
    let keyId: String
    let issuerId: String
    let privateKey: String
    
    func generate() throws -> String {
        let signer = JWTSigner.es256(privateKey: privateKey)
        let claims = AppStoreConnectClaims(
            iss: issuerId,
            iat: Date(),
            exp: Date().addingTimeInterval(1200)
        )
        let jwt = JWT(claims: claims)
        return try signer.sign(jwt, kid: JWKIdentifier(string: keyId))
    }
}

キーポイント:

  • App Store Connect API と Xcode Cloud API の両方に同じトークンが使用されます
  • トークンは最大 20 分間有効です
  • 秘密キー ファイルは一度だけダウンロードできるため、適切に保管する必要があります

カスタムスクリプトのタイミング

Xcode Cloud は、各アクションの複数の段階でカスタム スクリプトを実行します。

スクリプト名実行時間
pre_cloneコードリポジトリを複製する前に
post_cloneコードリポジトリのクローンを作成した後
pre_buildビルドが始まる前に
post_buildビルドが完了したら
pre_testテストが始まる前に
post_testテストが完了したら
pre_archiveアーカイブを開始する前に
post_archiveアーカイブが完了したら
pre_xcodebuildxcodebuild 実行前
post_xcodebuildxcodebuild 実行後

スクリプトはプロジェクトに配置されますci_scriptsディレクトリには、実行権限を追加する必要があります。

重要ポイント

  • やるべきこと: Xcode Cloud Webhook サービスをセットアップし、ビルドと問題トラッカーを自動的に関連付けます

  • 実行する価値がある理由: 開発者はビルド ステータスを手動で確認する必要がなく、問題ページにはビルド結果と問題リストが直接表示されます。

  • 開始方法: Vapor を使用して Swift on Server サービスを構築し、Webhook URL を構成し、コミット メッセージ内の課題番号を解析します。

  • 対処方法: OpenAPI Generator を使用して App Store Connect API クライアントを自動的に生成します

  • 実行する価値がある理由: API リクエスト コードの手動メンテナンスを回避し、タイプ セーフティを確保し、API の更新後にのみ再生成します。

  • 開始方法: ドキュメントから OpenAPI 仕様をダウンロードし、ジェネレーターを実行して Swift パッケージを生成し、依存関係としてプロジェクトに導入します。

  • やるべきこと: コード スタイル チェックのために SwiftLint を Xcode Cloud に統合する

  • 実行する価値がある理由: チームのコーディング スタイルの一貫性を保ち、コード レビューではなく CI フェーズで問題を発見します。

  • 開始方法: 作成するci_scripts/post_clone.shチームの仕様に従って構成された SwiftLint をインストールして実行する.swiftlint.yml

  • やるべきこと: チームの階層型ワークフロー権限管理を確立する

  • 実行する価値がある理由: メンバーが重要なワークフロー構成を誤って変更するのを防ぎます。リリース ワークフローは管理者のみが編集できます。

  • 開始方法: 主要なワークフローを右クリックし、[編集の制限] を選択します。通常のメンバーは引き続き手動でビルドをトリガーできます

関連セッション

コメント

GitHub Issues · utterances