2024 EssentialsDeveloper Tools
WWDC24 · 21 min · Essentials / Developer Tools
Extend your Xcode Cloud workflows
Discover how Xcode Cloud can adapt to your development needs. We’ll show you how to streamline your workflows, automate testing and distribution with start conditions, custom aliases, custom scripts, webhooks, and the App Store Connect API.
Watch at developer.apple.com ↗Chapters
Code shown on screen · 4 snippets
Custom Script
set -e
if [[ $CI_XCODEBUILD_ACTION == "test-without-building" && $CI_WORKFLOW_ID == "82D89C93-B69C-46B5-A794-A2BCFD3EE487" ]]
then
curl https://example.com/health --fail
fi App Store Connect API - Client Extension
extension Client {
func repoID(workflowID: String) async throws -> String {
return try await ciWorkflowsGetInstance(
path: .init(id: workflowID),
query: .init(include: [.repository])
).ok.body.json.data.relationships!.repository!.data!.id
}
func branchID(repoID: String, name: String) async throws -> String {
return try await scmRepositoriesGitReferencesGetToManyRelated(
path: .init(id: repoID)
)
.ok.body.json.data
.filter { $0.attributes!.kind == .BRANCH && $0.attributes!.name == name }
.first!.id
}
func startBuild(workflowID: String, gitReferenceID: String) async throws {
_ = try await ciBuildRunsCreateInstance(
body: .json(.init(
data: .init(
_type: .ciBuildRuns,
relationships: .init(
workflow: .init(data: .init(
_type: .ciWorkflows,
id: workflowID
)),
sourceBranchOrTag: .init(data: .init(
_type: .scmGitReferences,
id: gitReferenceID
))
)
)
))
).created
}
} App Store Connect API - Main Function
static func main() async throws {
let client = try Client(
serverURL: Servers.server1(),
configuration: .init(dateTranscoder: .iso8601WithFractionalSeconds),
transport: URLSessionTransport(),
middlewares: [AuthMiddleware(token: ProcessInfo.processInfo.environment["TOKEN"]!)]
)
let workflowID = "82D89C93-B69C-46B5-A794-A2BCFD3EE487"
let repoID = try await client.repoID(workflowID: workflowID)
let branchName = "main"
let branchID = try await client.branchID(repoID: repoID, name: branchName)
try await client.startBuild(workflowID: workflowID, gitReferenceID: branchID)
} Webhook Handler Implementation
struct WebhookPayload: Content {
let ciWorkflow: CiWorkflow
let ciBuildRun: CiBuildRun
struct CiWorkflow: Content {
let id: String
}
struct CiBuildRun: Content {
let id: String
let executionProgress: String
let completionStatus: String
}
}
func routes(_ app: Application) throws {
let deploymentService = ExampleDeploymentClient()
let workflowID = "82D89C93-B69C-46B5-A794-A2BCFD3EE487"
app.post("webhook") { req async throws -> HTTPStatus in
return HTTPStatus.ok
}
} Resources
Related sessions
-
22 min -
29 min -
17 min