From f8ba57ebd2e4070d02f96f2a0469a0afd163849e Mon Sep 17 00:00:00 2001 From: Eric Ernst Date: Wed, 18 Mar 2026 01:33:21 -0700 Subject: [PATCH] Revert "Update builder API to use grpc-swift-2. (#1309)" (#1324) This reverts commit 50900938c48788aa6c68fa4cd13aad6dc2b2721e, restoring the grpc-swift-1 based builder API while preserving build secrets and hidden docker dir support added in a00ec5c. Signed-off-by: Eric Ernst --- Package.resolved | 60 +- Package.swift | 24 +- Protobuf.Makefile | 4 +- .../ContainerBuild/BuildAPI+Extensions.swift | 4 + Sources/ContainerBuild/BuildFSSync.swift | 2 +- .../ContainerBuild/BuildImageResolver.swift | 2 +- .../ContainerBuild/BuildPipelineHandler.swift | 8 +- .../BuildRemoteContentProxy.swift | 2 +- Sources/ContainerBuild/BuildStdio.swift | 2 +- Sources/ContainerBuild/Builder.grpc.swift | 1996 +++++++---------- Sources/ContainerBuild/Builder.pb.swift | 137 +- Sources/ContainerBuild/Builder.swift | 229 +- Sources/ContainerCommands/BuildCommand.swift | 2 +- Sources/ContainerLog/StderrLogHandler.swift | 29 +- scripts/install-hawkeye.sh | 2 +- 15 files changed, 1068 insertions(+), 1435 deletions(-) diff --git a/Package.resolved b/Package.resolved index a3aaa7b2..d1aabdfd 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "1b173b9865bdf3b1fc4452aff048f169490a36552511ac607718cab6143f161d", + "originHash" : "040dd2e2c8649defb737f900e4032d270935f0af91ebf4a87d64391ecd4ea40b", "pins" : [ { "identity" : "async-http-client", @@ -22,46 +22,28 @@ { "identity" : "dns", "kind" : "remoteSourceControl", - "location" : "https://github.com/Bouke/DNS", + "location" : "https://github.com/Bouke/DNS.git", "state" : { "revision" : "78bbd1589890a90b202d11d5f9e1297050cf0eb2", "version" : "1.2.0" } }, + { + "identity" : "dnsclient", + "kind" : "remoteSourceControl", + "location" : "https://github.com/orlandos-nl/DNSClient.git", + "state" : { + "revision" : "551fbddbf4fa728d4cd86f6a5208fe4f925f0549", + "version" : "2.4.4" + } + }, { "identity" : "grpc-swift", "kind" : "remoteSourceControl", "location" : "https://github.com/grpc/grpc-swift.git", "state" : { - "revision" : "ac715c584bb1e2e5cdfb7684ccb46fab8dafc641", - "version" : "1.27.4" - } - }, - { - "identity" : "grpc-swift-2", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-swift-2.git", - "state" : { - "revision" : "f28854bc760a116e053fdfc4a48a9428c34625c0", - "version" : "2.3.0" - } - }, - { - "identity" : "grpc-swift-nio-transport", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-swift-nio-transport.git", - "state" : { - "revision" : "f37e0c2d293cea668b11e10e1fb1c24cb40781ff", - "version" : "2.4.4" - } - }, - { - "identity" : "grpc-swift-protobuf", - "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-swift-protobuf.git", - "state" : { - "revision" : "19153231a03c2fda1f4ea60da1b92a2cb9c011d8", - "version" : "2.2.0" + "revision" : "a56a157218877ef3e9625f7e1f7b2cb7e46ead1b", + "version" : "1.26.1" } }, { @@ -78,8 +60,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-argument-parser.git", "state" : { - "revision" : "c5d11a805e765f52ba34ec7284bd4fcd6ba68615", - "version" : "1.7.0" + "revision" : "309a47b2b1d9b5e991f36961c983ecec72275be3", + "version" : "1.6.1" } }, { @@ -177,8 +159,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-log.git", "state" : { - "revision" : "bbd81b6725ae874c69e9b8c8804d462356b55523", - "version" : "1.10.1" + "revision" : "ce592ae52f982c847a4efc0dd881cc9eb32d29f2", + "version" : "1.6.4" } }, { @@ -240,8 +222,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-protobuf.git", "state" : { - "revision" : "86970144a0b86068c81ff48ee29b3f97cae0b879", - "version" : "1.36.0" + "revision" : "102a647b573f60f73afdce5613a51d71349fe507", + "version" : "1.30.0" } }, { @@ -258,8 +240,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-system.git", "state" : { - "revision" : "7c6ad0fc39d0763e0b699210e4124afd5041c5df", - "version" : "1.6.4" + "revision" : "890830fff1a577dc83134890c7984020c5f6b43b", + "version" : "1.6.2" } }, { diff --git a/Package.swift b/Package.swift index 7229a2bd..a18f52a3 100644 --- a/Package.swift +++ b/Package.swift @@ -47,17 +47,16 @@ let package = Package( .library(name: "TerminalProgress", targets: ["TerminalProgress"]), ], dependencies: [ + .package(url: "https://github.com/Bouke/DNS.git", from: "1.2.0"), .package(url: "https://github.com/apple/containerization.git", exact: Version(stringLiteral: scVersion)), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0"), .package(url: "https://github.com/apple/swift-collections.git", from: "1.2.0"), .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"), .package(url: "https://github.com/apple/swift-nio.git", from: "2.80.0"), - .package(url: "https://github.com/apple/swift-protobuf.git", from: "1.36.0"), - .package(url: "https://github.com/apple/swift-system.git", from: "1.6.4"), - .package(url: "https://github.com/Bouke/DNS.git", from: "1.2.0"), - .package(url: "https://github.com/grpc/grpc-swift-2.git", from: "2.3.0"), - .package(url: "https://github.com/grpc/grpc-swift-nio-transport.git", from: "2.4.4"), - .package(url: "https://github.com/grpc/grpc-swift-protobuf.git", from: "2.2.0"), + .package(url: "https://github.com/apple/swift-protobuf.git", from: "1.29.0"), + .package(url: "https://github.com/apple/swift-system.git", from: "1.4.0"), + .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.26.0"), + .package(url: "https://github.com/orlandos-nl/DNSClient.git", from: "2.4.1"), .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.20.1"), .package(url: "https://github.com/swiftlang/swift-docc-plugin.git", from: "1.1.0"), ], @@ -112,14 +111,10 @@ let package = Package( dependencies: [ .product(name: "Logging", package: "swift-log"), .product(name: "NIO", package: "swift-nio"), - .product(name: "NIOPosix", package: "swift-nio"), .product(name: "Containerization", package: "containerization"), .product(name: "ContainerizationArchive", package: "containerization"), .product(name: "ContainerizationOCI", package: "containerization"), .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "GRPCCore", package: "grpc-swift-2"), - .product(name: "GRPCNIOTransportHTTP2", package: "grpc-swift-nio-transport"), - .product(name: "GRPCProtobuf", package: "grpc-swift-protobuf"), "ContainerAPIClient", ] ), @@ -138,9 +133,7 @@ let package = Package( .product(name: "ContainerizationExtras", package: "containerization"), .product(name: "ContainerizationOS", package: "containerization"), .product(name: "ContainerizationEXT4", package: "containerization"), - .product(name: "GRPCCore", package: "grpc-swift-2"), - .product(name: "GRPCNIOTransportHTTP2", package: "grpc-swift-nio-transport"), - .product(name: "GRPCProtobuf", package: "grpc-swift-protobuf"), + .product(name: "GRPC", package: "grpc-swift"), .product(name: "Logging", package: "swift-log"), "ContainerAPIService", "ContainerAPIClient", @@ -307,9 +300,7 @@ let package = Package( dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), .product(name: "Logging", package: "swift-log"), - .product(name: "GRPCCore", package: "grpc-swift-2"), - .product(name: "GRPCNIOTransportHTTP2", package: "grpc-swift-nio-transport"), - .product(name: "GRPCProtobuf", package: "grpc-swift-protobuf"), + .product(name: "GRPC", package: "grpc-swift"), .product(name: "Containerization", package: "containerization"), "ContainerLog", "ContainerPlugin", @@ -436,6 +427,7 @@ let package = Package( dependencies: [ .product(name: "NIOCore", package: "swift-nio"), .product(name: "NIOPosix", package: "swift-nio"), + .product(name: "DNSClient", package: "DNSClient"), .product(name: "DNS", package: "DNS"), .product(name: "Logging", package: "swift-log"), .product(name: "ContainerizationOS", package: "containerization"), diff --git a/Protobuf.Makefile b/Protobuf.Makefile index 48844099..2ae284d8 100644 --- a/Protobuf.Makefile +++ b/Protobuf.Makefile @@ -37,7 +37,7 @@ $(PROTOC): .PHONY: protoc-gen-swift protoc-gen-swift: @$(SWIFT) build --product protoc-gen-swift - @$(SWIFT) build --product protoc-gen-grpc-swift-2 + @$(SWIFT) build --product protoc-gen-grpc-swift .PHONY: protos protos: $(PROTOC) protoc-gen-swift @@ -47,7 +47,7 @@ protos: $(PROTOC) protoc-gen-swift cd $(LOCAL_DIR) && git clone --branch $(BUILDER_SHIM_VERSION) --depth 1 $(BUILDER_SHIM_REPO); \ fi @$(PROTOC) $(LOCAL_DIR)/container-builder-shim/pkg/api/Builder.proto \ - --plugin=protoc-gen-grpc-swift=$(BUILD_BIN_DIR)/protoc-gen-grpc-swift-2 \ + --plugin=protoc-gen-grpc-swift=$(BUILD_BIN_DIR)/protoc-gen-grpc-swift \ --plugin=protoc-gen-swift=$(BUILD_BIN_DIR)/protoc-gen-swift \ --proto_path=$(LOCAL_DIR)/container-builder-shim/pkg/api \ --grpc-swift_out="Sources/ContainerBuild" \ diff --git a/Sources/ContainerBuild/BuildAPI+Extensions.swift b/Sources/ContainerBuild/BuildAPI+Extensions.swift index b052b104..e90a2383 100644 --- a/Sources/ContainerBuild/BuildAPI+Extensions.swift +++ b/Sources/ContainerBuild/BuildAPI+Extensions.swift @@ -24,6 +24,10 @@ public typealias ClientStream = Com_Apple_Container_Build_V1_ClientStream public typealias ServerStream = Com_Apple_Container_Build_V1_ServerStream public typealias ImageTransfer = Com_Apple_Container_Build_V1_ImageTransfer public typealias BuildTransfer = Com_Apple_Container_Build_V1_BuildTransfer +public typealias BuilderClient = Com_Apple_Container_Build_V1_BuilderNIOClient +public typealias BuilderClientAsync = Com_Apple_Container_Build_V1_BuilderAsyncClient +public typealias BuilderClientProtocol = Com_Apple_Container_Build_V1_BuilderClientProtocol +public typealias BuilderClientAsyncProtocol = Com_Apple_Container_Build_V1_BuilderAsyncClient extension BuildTransfer { func stage() -> String? { diff --git a/Sources/ContainerBuild/BuildFSSync.swift b/Sources/ContainerBuild/BuildFSSync.swift index 7b4fc440..c258f22f 100644 --- a/Sources/ContainerBuild/BuildFSSync.swift +++ b/Sources/ContainerBuild/BuildFSSync.swift @@ -20,7 +20,7 @@ import ContainerizationArchive import ContainerizationOCI import CryptoKit import Foundation -import GRPCCore +import GRPC actor BuildFSSync: BuildPipelineHandler { let contextDir: URL diff --git a/Sources/ContainerBuild/BuildImageResolver.swift b/Sources/ContainerBuild/BuildImageResolver.swift index c2b8c50d..04959829 100644 --- a/Sources/ContainerBuild/BuildImageResolver.swift +++ b/Sources/ContainerBuild/BuildImageResolver.swift @@ -18,7 +18,7 @@ import ContainerAPIClient import Containerization import ContainerizationOCI import Foundation -import GRPCCore +import GRPC import Logging import TerminalProgress diff --git a/Sources/ContainerBuild/BuildPipelineHandler.swift b/Sources/ContainerBuild/BuildPipelineHandler.swift index 143d42eb..a74fc56e 100644 --- a/Sources/ContainerBuild/BuildPipelineHandler.swift +++ b/Sources/ContainerBuild/BuildPipelineHandler.swift @@ -15,7 +15,7 @@ //===----------------------------------------------------------------------===// import Foundation -import GRPCCore +import GRPC import NIO protocol BuildPipelineHandler: Sendable { @@ -35,10 +35,10 @@ public actor BuildPipeline { ] } - public func run( + public func run( sender: AsyncStream.Continuation, - receiver: S - ) async throws where S.Element == ServerStream { + receiver: GRPCAsyncResponseStream + ) async throws { defer { sender.finish() } try await untilFirstError { group in for try await packet in receiver { diff --git a/Sources/ContainerBuild/BuildRemoteContentProxy.swift b/Sources/ContainerBuild/BuildRemoteContentProxy.swift index e6cb1cbc..7b46fac7 100644 --- a/Sources/ContainerBuild/BuildRemoteContentProxy.swift +++ b/Sources/ContainerBuild/BuildRemoteContentProxy.swift @@ -19,7 +19,7 @@ import Containerization import ContainerizationArchive import ContainerizationOCI import Foundation -import GRPCCore +import GRPC struct BuildRemoteContentProxy: BuildPipelineHandler { let local: ContentStore diff --git a/Sources/ContainerBuild/BuildStdio.swift b/Sources/ContainerBuild/BuildStdio.swift index 32429480..8df54ba7 100644 --- a/Sources/ContainerBuild/BuildStdio.swift +++ b/Sources/ContainerBuild/BuildStdio.swift @@ -16,7 +16,7 @@ import ContainerizationOS import Foundation -import GRPCCore +import GRPC import NIO actor BuildStdio: BuildPipelineHandler { diff --git a/Sources/ContainerBuild/Builder.grpc.swift b/Sources/ContainerBuild/Builder.grpc.swift index d0bdd972..5c39eff2 100644 --- a/Sources/ContainerBuild/Builder.grpc.swift +++ b/Sources/ContainerBuild/Builder.grpc.swift @@ -14,1206 +14,868 @@ // limitations under the License. //===----------------------------------------------------------------------===// +// // DO NOT EDIT. // swift-format-ignore-file -// swiftlint:disable all // -// Generated by the gRPC Swift generator plugin for the protocol buffer compiler. +// Generated by the protocol buffer compiler. // Source: Builder.proto // -// For information on using the generated types, please see the documentation: -// https://github.com/grpc/grpc-swift +import GRPC +import NIO +import NIOConcurrencyHelpers +import SwiftProtobuf -import GRPCCore -import GRPCProtobuf -// MARK: - com.apple.container.build.v1.Builder +/// Builder service implements APIs for performing an image build with +/// Container image builder agent. +/// +/// To perform a build: +/// +/// 1. CreateBuild to create a new build +/// 2. StartBuild to start the build execution where client and server +/// both have a stream for exchanging data during the build. +/// +/// The client may send: +/// a) signal packet to signal to the build process (e.g. SIGINT) +/// +/// b) command packet for executing a command in the build file on the +/// server +/// NOTE: the server will need to switch on the command to determine the +/// type of command to execute (e.g. RUN, ENV, etc.) +/// +/// c) transfer build data either to or from the server +/// - INTO direction is for sending build data to the server at specific +/// location (e.g. COPY) +/// - OUTOF direction is for copying build data from the server to be +/// used in subsequent build stages +/// +/// d) transfer image content data either to or from the server +/// - INTO direction is for sending inherited image content data to the +/// server's local content store +/// - OUTOF direction is for copying successfully built OCI image from +/// the server to the client +/// +/// The server may send: +/// a) stdio packet for the build progress +/// +/// b) build error indicating unsuccessful build +/// +/// c) command complete packet indicating a command has finished executing +/// +/// d) handle transfer build data either to or from the client +/// +/// e) handle transfer image content data either to or from the client +/// +/// +/// NOTE: The build data and image content data transfer is ALWAYS initiated +/// by the client. +/// +/// Sequence for transferring from the client to the server: +/// 1. client send a BuildTransfer/ImageTransfer request with ID, direction +/// of 'INTO', +/// destination path, and first chunk of data +/// 2. server starts to receive the data and stream to a temporary file +/// 3. client continues to send all chunks of data until last chunk, which +/// client will +/// send with 'complete' set to true +/// 4. server continues to receive until the last chunk with 'complete' set +/// to true, +/// server will finish writing the last chunk and un-archive the +/// temporary file to the destination path +/// 5. server completes the transfer by sending a last +/// BuildTransfer/ImageTransfer with +/// 'complete' set to true +/// 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' +/// set to true +/// before proceeding with the rest of the commands +/// +/// Sequence for transferring from the server to the client: +/// 1. client send a BuildTransfer/ImageTransfer request with ID, direction +/// of 'OUTOF', +/// source path, and empty data +/// 2. server archives the data at source path, and starts to send chunks to +/// the client +/// 3. server continues to send all chunks until last chunk, which server +/// will send with +/// 'complete' set to true +/// 4. client starts to receive the data and stream to a temporary file +/// 5. client continues to receive until the last chunk with 'complete' set +/// to true, +/// client will finish writing last chunk and un-archive the temporary +/// file to the destination path +/// 6. client MAY choose to send one last BuildTransfer/ImageTransfer with +/// 'complete' +/// set to true, but NOT required. +/// +/// +/// NOTE: the client should close the send stream once it has finished +/// receiving the build output or abandon the current build due to error. +/// Server should keep the stream open until it receives the EOF that client +/// has closed the stream, which the server should then close its send stream. +/// +/// Usage: instantiate `Com_Apple_Container_Build_V1_BuilderClient`, then call methods of this protocol to make API calls. +public protocol Com_Apple_Container_Build_V1_BuilderClientProtocol: GRPCClient { + var serviceName: String { get } + var interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? { get } -/// Namespace containing generated types for the "com.apple.container.build.v1.Builder" service. -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -public enum Com_Apple_Container_Build_V1_Builder: Sendable { - /// Service descriptor for the "com.apple.container.build.v1.Builder" service. - public static let descriptor = GRPCCore.ServiceDescriptor(fullyQualifiedService: "com.apple.container.build.v1.Builder") - /// Namespace for method metadata. - public enum Method: Sendable { - /// Namespace for "CreateBuild" metadata. - public enum CreateBuild: Sendable { - /// Request type for "CreateBuild". - public typealias Input = Com_Apple_Container_Build_V1_CreateBuildRequest - /// Response type for "CreateBuild". - public typealias Output = Com_Apple_Container_Build_V1_CreateBuildResponse - /// Descriptor for "CreateBuild". - public static let descriptor = GRPCCore.MethodDescriptor( - service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "com.apple.container.build.v1.Builder"), - method: "CreateBuild", - type: .unary - ) - } - /// Namespace for "PerformBuild" metadata. - public enum PerformBuild: Sendable { - /// Request type for "PerformBuild". - public typealias Input = Com_Apple_Container_Build_V1_ClientStream - /// Response type for "PerformBuild". - public typealias Output = Com_Apple_Container_Build_V1_ServerStream - /// Descriptor for "PerformBuild". - public static let descriptor = GRPCCore.MethodDescriptor( - service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "com.apple.container.build.v1.Builder"), - method: "PerformBuild", - type: .bidirectionalStreaming - ) - } - /// Namespace for "Info" metadata. - public enum Info: Sendable { - /// Request type for "Info". - public typealias Input = Com_Apple_Container_Build_V1_InfoRequest - /// Response type for "Info". - public typealias Output = Com_Apple_Container_Build_V1_InfoResponse - /// Descriptor for "Info". - public static let descriptor = GRPCCore.MethodDescriptor( - service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "com.apple.container.build.v1.Builder"), - method: "Info", - type: .unary - ) - } - /// Descriptors for all methods in the "com.apple.container.build.v1.Builder" service. - public static let descriptors: [GRPCCore.MethodDescriptor] = [ - CreateBuild.descriptor, - PerformBuild.descriptor, - Info.descriptor - ] - } + func createBuild( + _ request: Com_Apple_Container_Build_V1_CreateBuildRequest, + callOptions: CallOptions? + ) -> UnaryCall + + func performBuild( + callOptions: CallOptions?, + handler: @escaping (Com_Apple_Container_Build_V1_ServerStream) -> Void + ) -> BidirectionalStreamingCall + + func info( + _ request: Com_Apple_Container_Build_V1_InfoRequest, + callOptions: CallOptions? + ) -> UnaryCall } -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -extension GRPCCore.ServiceDescriptor { - /// Service descriptor for the "com.apple.container.build.v1.Builder" service. - public static let com_apple_container_build_v1_Builder = GRPCCore.ServiceDescriptor(fullyQualifiedService: "com.apple.container.build.v1.Builder") +extension Com_Apple_Container_Build_V1_BuilderClientProtocol { + public var serviceName: String { + return "com.apple.container.build.v1.Builder" + } + + /// Create a build request. + /// + /// - Parameters: + /// - request: Request to send to CreateBuild. + /// - callOptions: Call options. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + public func createBuild( + _ request: Com_Apple_Container_Build_V1_CreateBuildRequest, + callOptions: CallOptions? = nil + ) -> UnaryCall { + return self.makeUnaryCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.createBuild.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeCreateBuildInterceptors() ?? [] + ) + } + + /// Perform the build. + /// Executes the entire build sequence with attaching input/output + /// to handling data exchange with the server during the build. + /// + /// Callers should use the `send` method on the returned object to send messages + /// to the server. The caller should send an `.end` after the final message has been sent. + /// + /// - Parameters: + /// - callOptions: Call options. + /// - handler: A closure called when each response is received from the server. + /// - Returns: A `ClientStreamingCall` with futures for the metadata and status. + public func performBuild( + callOptions: CallOptions? = nil, + handler: @escaping (Com_Apple_Container_Build_V1_ServerStream) -> Void + ) -> BidirectionalStreamingCall { + return self.makeBidirectionalStreamingCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.performBuild.path, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makePerformBuildInterceptors() ?? [], + handler: handler + ) + } + + /// Unary call to Info + /// + /// - Parameters: + /// - request: Request to send to Info. + /// - callOptions: Call options. + /// - Returns: A `UnaryCall` with futures for the metadata, status and response. + public func info( + _ request: Com_Apple_Container_Build_V1_InfoRequest, + callOptions: CallOptions? = nil + ) -> UnaryCall { + return self.makeUnaryCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.info.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeInfoInterceptors() ?? [] + ) + } } -// MARK: com.apple.container.build.v1.Builder (server) +@available(*, deprecated) +extension Com_Apple_Container_Build_V1_BuilderClient: @unchecked Sendable {} -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -extension Com_Apple_Container_Build_V1_Builder { - /// Streaming variant of the service protocol for the "com.apple.container.build.v1.Builder" service. - /// - /// This protocol is the lowest-level of the service protocols generated for this service - /// giving you the most flexibility over the implementation of your service. This comes at - /// the cost of more verbose and less strict APIs. Each RPC requires you to implement it in - /// terms of a request stream and response stream. Where only a single request or response - /// message is expected, you are responsible for enforcing this invariant is maintained. - /// - /// Where possible, prefer using the stricter, less-verbose ``ServiceProtocol`` - /// or ``SimpleServiceProtocol`` instead. - /// - /// > Source IDL Documentation: - /// > - /// > Builder service implements APIs for performing an image build with - /// > Container image builder agent. - /// > - /// > To perform a build: - /// > - /// > 1. CreateBuild to create a new build - /// > 2. StartBuild to start the build execution where client and server - /// > both have a stream for exchanging data during the build. - /// > - /// > The client may send: - /// > a) signal packet to signal to the build process (e.g. SIGINT) - /// > - /// > b) command packet for executing a command in the build file on the - /// > server - /// > NOTE: the server will need to switch on the command to determine the - /// > type of command to execute (e.g. RUN, ENV, etc.) - /// > - /// > c) transfer build data either to or from the server - /// > - INTO direction is for sending build data to the server at specific - /// > location (e.g. COPY) - /// > - OUTOF direction is for copying build data from the server to be - /// > used in subsequent build stages - /// > - /// > d) transfer image content data either to or from the server - /// > - INTO direction is for sending inherited image content data to the - /// > server's local content store - /// > - OUTOF direction is for copying successfully built OCI image from - /// > the server to the client - /// > - /// > The server may send: - /// > a) stdio packet for the build progress - /// > - /// > b) build error indicating unsuccessful build - /// > - /// > c) command complete packet indicating a command has finished executing - /// > - /// > d) handle transfer build data either to or from the client - /// > - /// > e) handle transfer image content data either to or from the client - /// > - /// > - /// > NOTE: The build data and image content data transfer is ALWAYS initiated - /// > by the client. - /// > - /// > Sequence for transferring from the client to the server: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'INTO', - /// > destination path, and first chunk of data - /// > 2. server starts to receive the data and stream to a temporary file - /// > 3. client continues to send all chunks of data until last chunk, which - /// > client will - /// > send with 'complete' set to true - /// > 4. server continues to receive until the last chunk with 'complete' set - /// > to true, - /// > server will finish writing the last chunk and un-archive the - /// > temporary file to the destination path - /// > 5. server completes the transfer by sending a last - /// > BuildTransfer/ImageTransfer with - /// > 'complete' set to true - /// > 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' - /// > set to true - /// > before proceeding with the rest of the commands - /// > - /// > Sequence for transferring from the server to the client: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'OUTOF', - /// > source path, and empty data - /// > 2. server archives the data at source path, and starts to send chunks to - /// > the client - /// > 3. server continues to send all chunks until last chunk, which server - /// > will send with - /// > 'complete' set to true - /// > 4. client starts to receive the data and stream to a temporary file - /// > 5. client continues to receive until the last chunk with 'complete' set - /// > to true, - /// > client will finish writing last chunk and un-archive the temporary - /// > file to the destination path - /// > 6. client MAY choose to send one last BuildTransfer/ImageTransfer with - /// > 'complete' - /// > set to true, but NOT required. - /// > - /// > - /// > NOTE: the client should close the send stream once it has finished - /// > receiving the build output or abandon the current build due to error. - /// > Server should keep the stream open until it receives the EOF that client - /// > has closed the stream, which the server should then close its send stream. - public protocol StreamingServiceProtocol: GRPCCore.RegistrableRPCService { - /// Handle the "CreateBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Create a build request. - /// - /// - Parameters: - /// - request: A streaming request of `Com_Apple_Container_Build_V1_CreateBuildRequest` messages. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - /// - Returns: A streaming response of `Com_Apple_Container_Build_V1_CreateBuildResponse` messages. - func createBuild( - request: GRPCCore.StreamingServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.StreamingServerResponse +@available(*, deprecated, renamed: "Com_Apple_Container_Build_V1_BuilderNIOClient") +public final class Com_Apple_Container_Build_V1_BuilderClient: Com_Apple_Container_Build_V1_BuilderClientProtocol { + private let lock = Lock() + private var _defaultCallOptions: CallOptions + private var _interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? + public let channel: GRPCChannel + public var defaultCallOptions: CallOptions { + get { self.lock.withLock { return self._defaultCallOptions } } + set { self.lock.withLockVoid { self._defaultCallOptions = newValue } } + } + public var interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? { + get { self.lock.withLock { return self._interceptors } } + set { self.lock.withLockVoid { self._interceptors = newValue } } + } - /// Handle the "PerformBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Perform the build. - /// > Executes the entire build sequence with attaching input/output - /// > to handling data exchange with the server during the build. - /// - /// - Parameters: - /// - request: A streaming request of `Com_Apple_Container_Build_V1_ClientStream` messages. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - /// - Returns: A streaming response of `Com_Apple_Container_Build_V1_ServerStream` messages. - func performBuild( - request: GRPCCore.StreamingServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.StreamingServerResponse - - /// Handle the "Info" method. - /// - /// - Parameters: - /// - request: A streaming request of `Com_Apple_Container_Build_V1_InfoRequest` messages. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - /// - Returns: A streaming response of `Com_Apple_Container_Build_V1_InfoResponse` messages. - func info( - request: GRPCCore.StreamingServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.StreamingServerResponse - } - - /// Service protocol for the "com.apple.container.build.v1.Builder" service. - /// - /// This protocol is higher level than ``StreamingServiceProtocol`` but lower level than - /// the ``SimpleServiceProtocol``, it provides access to request and response metadata and - /// trailing response metadata. If you don't need these then consider using - /// the ``SimpleServiceProtocol``. If you need fine grained control over your RPCs then - /// use ``StreamingServiceProtocol``. - /// - /// > Source IDL Documentation: - /// > - /// > Builder service implements APIs for performing an image build with - /// > Container image builder agent. - /// > - /// > To perform a build: - /// > - /// > 1. CreateBuild to create a new build - /// > 2. StartBuild to start the build execution where client and server - /// > both have a stream for exchanging data during the build. - /// > - /// > The client may send: - /// > a) signal packet to signal to the build process (e.g. SIGINT) - /// > - /// > b) command packet for executing a command in the build file on the - /// > server - /// > NOTE: the server will need to switch on the command to determine the - /// > type of command to execute (e.g. RUN, ENV, etc.) - /// > - /// > c) transfer build data either to or from the server - /// > - INTO direction is for sending build data to the server at specific - /// > location (e.g. COPY) - /// > - OUTOF direction is for copying build data from the server to be - /// > used in subsequent build stages - /// > - /// > d) transfer image content data either to or from the server - /// > - INTO direction is for sending inherited image content data to the - /// > server's local content store - /// > - OUTOF direction is for copying successfully built OCI image from - /// > the server to the client - /// > - /// > The server may send: - /// > a) stdio packet for the build progress - /// > - /// > b) build error indicating unsuccessful build - /// > - /// > c) command complete packet indicating a command has finished executing - /// > - /// > d) handle transfer build data either to or from the client - /// > - /// > e) handle transfer image content data either to or from the client - /// > - /// > - /// > NOTE: The build data and image content data transfer is ALWAYS initiated - /// > by the client. - /// > - /// > Sequence for transferring from the client to the server: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'INTO', - /// > destination path, and first chunk of data - /// > 2. server starts to receive the data and stream to a temporary file - /// > 3. client continues to send all chunks of data until last chunk, which - /// > client will - /// > send with 'complete' set to true - /// > 4. server continues to receive until the last chunk with 'complete' set - /// > to true, - /// > server will finish writing the last chunk and un-archive the - /// > temporary file to the destination path - /// > 5. server completes the transfer by sending a last - /// > BuildTransfer/ImageTransfer with - /// > 'complete' set to true - /// > 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' - /// > set to true - /// > before proceeding with the rest of the commands - /// > - /// > Sequence for transferring from the server to the client: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'OUTOF', - /// > source path, and empty data - /// > 2. server archives the data at source path, and starts to send chunks to - /// > the client - /// > 3. server continues to send all chunks until last chunk, which server - /// > will send with - /// > 'complete' set to true - /// > 4. client starts to receive the data and stream to a temporary file - /// > 5. client continues to receive until the last chunk with 'complete' set - /// > to true, - /// > client will finish writing last chunk and un-archive the temporary - /// > file to the destination path - /// > 6. client MAY choose to send one last BuildTransfer/ImageTransfer with - /// > 'complete' - /// > set to true, but NOT required. - /// > - /// > - /// > NOTE: the client should close the send stream once it has finished - /// > receiving the build output or abandon the current build due to error. - /// > Server should keep the stream open until it receives the EOF that client - /// > has closed the stream, which the server should then close its send stream. - public protocol ServiceProtocol: Com_Apple_Container_Build_V1_Builder.StreamingServiceProtocol { - /// Handle the "CreateBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Create a build request. - /// - /// - Parameters: - /// - request: A request containing a single `Com_Apple_Container_Build_V1_CreateBuildRequest` message. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - /// - Returns: A response containing a single `Com_Apple_Container_Build_V1_CreateBuildResponse` message. - func createBuild( - request: GRPCCore.ServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.ServerResponse - - /// Handle the "PerformBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Perform the build. - /// > Executes the entire build sequence with attaching input/output - /// > to handling data exchange with the server during the build. - /// - /// - Parameters: - /// - request: A streaming request of `Com_Apple_Container_Build_V1_ClientStream` messages. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - /// - Returns: A streaming response of `Com_Apple_Container_Build_V1_ServerStream` messages. - func performBuild( - request: GRPCCore.StreamingServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.StreamingServerResponse - - /// Handle the "Info" method. - /// - /// - Parameters: - /// - request: A request containing a single `Com_Apple_Container_Build_V1_InfoRequest` message. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - /// - Returns: A response containing a single `Com_Apple_Container_Build_V1_InfoResponse` message. - func info( - request: GRPCCore.ServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.ServerResponse - } - - /// Simple service protocol for the "com.apple.container.build.v1.Builder" service. - /// - /// This is the highest level protocol for the service. The API is the easiest to use but - /// doesn't provide access to request or response metadata. If you need access to these - /// then use ``ServiceProtocol`` instead. - /// - /// > Source IDL Documentation: - /// > - /// > Builder service implements APIs for performing an image build with - /// > Container image builder agent. - /// > - /// > To perform a build: - /// > - /// > 1. CreateBuild to create a new build - /// > 2. StartBuild to start the build execution where client and server - /// > both have a stream for exchanging data during the build. - /// > - /// > The client may send: - /// > a) signal packet to signal to the build process (e.g. SIGINT) - /// > - /// > b) command packet for executing a command in the build file on the - /// > server - /// > NOTE: the server will need to switch on the command to determine the - /// > type of command to execute (e.g. RUN, ENV, etc.) - /// > - /// > c) transfer build data either to or from the server - /// > - INTO direction is for sending build data to the server at specific - /// > location (e.g. COPY) - /// > - OUTOF direction is for copying build data from the server to be - /// > used in subsequent build stages - /// > - /// > d) transfer image content data either to or from the server - /// > - INTO direction is for sending inherited image content data to the - /// > server's local content store - /// > - OUTOF direction is for copying successfully built OCI image from - /// > the server to the client - /// > - /// > The server may send: - /// > a) stdio packet for the build progress - /// > - /// > b) build error indicating unsuccessful build - /// > - /// > c) command complete packet indicating a command has finished executing - /// > - /// > d) handle transfer build data either to or from the client - /// > - /// > e) handle transfer image content data either to or from the client - /// > - /// > - /// > NOTE: The build data and image content data transfer is ALWAYS initiated - /// > by the client. - /// > - /// > Sequence for transferring from the client to the server: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'INTO', - /// > destination path, and first chunk of data - /// > 2. server starts to receive the data and stream to a temporary file - /// > 3. client continues to send all chunks of data until last chunk, which - /// > client will - /// > send with 'complete' set to true - /// > 4. server continues to receive until the last chunk with 'complete' set - /// > to true, - /// > server will finish writing the last chunk and un-archive the - /// > temporary file to the destination path - /// > 5. server completes the transfer by sending a last - /// > BuildTransfer/ImageTransfer with - /// > 'complete' set to true - /// > 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' - /// > set to true - /// > before proceeding with the rest of the commands - /// > - /// > Sequence for transferring from the server to the client: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'OUTOF', - /// > source path, and empty data - /// > 2. server archives the data at source path, and starts to send chunks to - /// > the client - /// > 3. server continues to send all chunks until last chunk, which server - /// > will send with - /// > 'complete' set to true - /// > 4. client starts to receive the data and stream to a temporary file - /// > 5. client continues to receive until the last chunk with 'complete' set - /// > to true, - /// > client will finish writing last chunk and un-archive the temporary - /// > file to the destination path - /// > 6. client MAY choose to send one last BuildTransfer/ImageTransfer with - /// > 'complete' - /// > set to true, but NOT required. - /// > - /// > - /// > NOTE: the client should close the send stream once it has finished - /// > receiving the build output or abandon the current build due to error. - /// > Server should keep the stream open until it receives the EOF that client - /// > has closed the stream, which the server should then close its send stream. - public protocol SimpleServiceProtocol: Com_Apple_Container_Build_V1_Builder.ServiceProtocol { - /// Handle the "CreateBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Create a build request. - /// - /// - Parameters: - /// - request: A `Com_Apple_Container_Build_V1_CreateBuildRequest` message. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - /// - Returns: A `Com_Apple_Container_Build_V1_CreateBuildResponse` to respond with. - func createBuild( - request: Com_Apple_Container_Build_V1_CreateBuildRequest, - context: GRPCCore.ServerContext - ) async throws -> Com_Apple_Container_Build_V1_CreateBuildResponse - - /// Handle the "PerformBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Perform the build. - /// > Executes the entire build sequence with attaching input/output - /// > to handling data exchange with the server during the build. - /// - /// - Parameters: - /// - request: A stream of `Com_Apple_Container_Build_V1_ClientStream` messages. - /// - response: A response stream of `Com_Apple_Container_Build_V1_ServerStream` messages. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - func performBuild( - request: GRPCCore.RPCAsyncSequence, - response: GRPCCore.RPCWriter, - context: GRPCCore.ServerContext - ) async throws - - /// Handle the "Info" method. - /// - /// - Parameters: - /// - request: A `Com_Apple_Container_Build_V1_InfoRequest` message. - /// - context: Context providing information about the RPC. - /// - Throws: Any error which occurred during the processing of the request. Thrown errors - /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted - /// to an internal error. - /// - Returns: A `Com_Apple_Container_Build_V1_InfoResponse` to respond with. - func info( - request: Com_Apple_Container_Build_V1_InfoRequest, - context: GRPCCore.ServerContext - ) async throws -> Com_Apple_Container_Build_V1_InfoResponse - } + /// Creates a client for the com.apple.container.build.v1.Builder service. + /// + /// - Parameters: + /// - channel: `GRPCChannel` to the service host. + /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. + /// - interceptors: A factory providing interceptors for each RPC. + public init( + channel: GRPCChannel, + defaultCallOptions: CallOptions = CallOptions(), + interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? = nil + ) { + self.channel = channel + self._defaultCallOptions = defaultCallOptions + self._interceptors = interceptors + } } -// Default implementation of 'registerMethods(with:)'. -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -extension Com_Apple_Container_Build_V1_Builder.StreamingServiceProtocol { - public func registerMethods(with router: inout GRPCCore.RPCRouter) where Transport: GRPCCore.ServerTransport { - router.registerHandler( - forMethod: Com_Apple_Container_Build_V1_Builder.Method.CreateBuild.descriptor, - deserializer: GRPCProtobuf.ProtobufDeserializer(), - serializer: GRPCProtobuf.ProtobufSerializer(), - handler: { request, context in - try await self.createBuild( - request: request, - context: context - ) - } - ) - router.registerHandler( - forMethod: Com_Apple_Container_Build_V1_Builder.Method.PerformBuild.descriptor, - deserializer: GRPCProtobuf.ProtobufDeserializer(), - serializer: GRPCProtobuf.ProtobufSerializer(), - handler: { request, context in - try await self.performBuild( - request: request, - context: context - ) - } - ) - router.registerHandler( - forMethod: Com_Apple_Container_Build_V1_Builder.Method.Info.descriptor, - deserializer: GRPCProtobuf.ProtobufDeserializer(), - serializer: GRPCProtobuf.ProtobufSerializer(), - handler: { request, context in - try await self.info( - request: request, - context: context - ) - } - ) - } +public struct Com_Apple_Container_Build_V1_BuilderNIOClient: Com_Apple_Container_Build_V1_BuilderClientProtocol { + public var channel: GRPCChannel + public var defaultCallOptions: CallOptions + public var interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? + + /// Creates a client for the com.apple.container.build.v1.Builder service. + /// + /// - Parameters: + /// - channel: `GRPCChannel` to the service host. + /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. + /// - interceptors: A factory providing interceptors for each RPC. + public init( + channel: GRPCChannel, + defaultCallOptions: CallOptions = CallOptions(), + interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? = nil + ) { + self.channel = channel + self.defaultCallOptions = defaultCallOptions + self.interceptors = interceptors + } } -// Default implementation of streaming methods from 'StreamingServiceProtocol'. -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -extension Com_Apple_Container_Build_V1_Builder.ServiceProtocol { - public func createBuild( - request: GRPCCore.StreamingServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.StreamingServerResponse { - let response = try await self.createBuild( - request: GRPCCore.ServerRequest(stream: request), - context: context - ) - return GRPCCore.StreamingServerResponse(single: response) - } +/// Builder service implements APIs for performing an image build with +/// Container image builder agent. +/// +/// To perform a build: +/// +/// 1. CreateBuild to create a new build +/// 2. StartBuild to start the build execution where client and server +/// both have a stream for exchanging data during the build. +/// +/// The client may send: +/// a) signal packet to signal to the build process (e.g. SIGINT) +/// +/// b) command packet for executing a command in the build file on the +/// server +/// NOTE: the server will need to switch on the command to determine the +/// type of command to execute (e.g. RUN, ENV, etc.) +/// +/// c) transfer build data either to or from the server +/// - INTO direction is for sending build data to the server at specific +/// location (e.g. COPY) +/// - OUTOF direction is for copying build data from the server to be +/// used in subsequent build stages +/// +/// d) transfer image content data either to or from the server +/// - INTO direction is for sending inherited image content data to the +/// server's local content store +/// - OUTOF direction is for copying successfully built OCI image from +/// the server to the client +/// +/// The server may send: +/// a) stdio packet for the build progress +/// +/// b) build error indicating unsuccessful build +/// +/// c) command complete packet indicating a command has finished executing +/// +/// d) handle transfer build data either to or from the client +/// +/// e) handle transfer image content data either to or from the client +/// +/// +/// NOTE: The build data and image content data transfer is ALWAYS initiated +/// by the client. +/// +/// Sequence for transferring from the client to the server: +/// 1. client send a BuildTransfer/ImageTransfer request with ID, direction +/// of 'INTO', +/// destination path, and first chunk of data +/// 2. server starts to receive the data and stream to a temporary file +/// 3. client continues to send all chunks of data until last chunk, which +/// client will +/// send with 'complete' set to true +/// 4. server continues to receive until the last chunk with 'complete' set +/// to true, +/// server will finish writing the last chunk and un-archive the +/// temporary file to the destination path +/// 5. server completes the transfer by sending a last +/// BuildTransfer/ImageTransfer with +/// 'complete' set to true +/// 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' +/// set to true +/// before proceeding with the rest of the commands +/// +/// Sequence for transferring from the server to the client: +/// 1. client send a BuildTransfer/ImageTransfer request with ID, direction +/// of 'OUTOF', +/// source path, and empty data +/// 2. server archives the data at source path, and starts to send chunks to +/// the client +/// 3. server continues to send all chunks until last chunk, which server +/// will send with +/// 'complete' set to true +/// 4. client starts to receive the data and stream to a temporary file +/// 5. client continues to receive until the last chunk with 'complete' set +/// to true, +/// client will finish writing last chunk and un-archive the temporary +/// file to the destination path +/// 6. client MAY choose to send one last BuildTransfer/ImageTransfer with +/// 'complete' +/// set to true, but NOT required. +/// +/// +/// NOTE: the client should close the send stream once it has finished +/// receiving the build output or abandon the current build due to error. +/// Server should keep the stream open until it receives the EOF that client +/// has closed the stream, which the server should then close its send stream. +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +public protocol Com_Apple_Container_Build_V1_BuilderAsyncClientProtocol: GRPCClient { + static var serviceDescriptor: GRPCServiceDescriptor { get } + var interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? { get } - public func info( - request: GRPCCore.StreamingServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.StreamingServerResponse { - let response = try await self.info( - request: GRPCCore.ServerRequest(stream: request), - context: context - ) - return GRPCCore.StreamingServerResponse(single: response) - } + func makeCreateBuildCall( + _ request: Com_Apple_Container_Build_V1_CreateBuildRequest, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall + + func makePerformBuildCall( + callOptions: CallOptions? + ) -> GRPCAsyncBidirectionalStreamingCall + + func makeInfoCall( + _ request: Com_Apple_Container_Build_V1_InfoRequest, + callOptions: CallOptions? + ) -> GRPCAsyncUnaryCall } -// Default implementation of methods from 'ServiceProtocol'. -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -extension Com_Apple_Container_Build_V1_Builder.SimpleServiceProtocol { - public func createBuild( - request: GRPCCore.ServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.ServerResponse { - return GRPCCore.ServerResponse( - message: try await self.createBuild( - request: request.message, - context: context - ), - metadata: [:] - ) - } +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension Com_Apple_Container_Build_V1_BuilderAsyncClientProtocol { + public static var serviceDescriptor: GRPCServiceDescriptor { + return Com_Apple_Container_Build_V1_BuilderClientMetadata.serviceDescriptor + } - public func performBuild( - request: GRPCCore.StreamingServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.StreamingServerResponse { - return GRPCCore.StreamingServerResponse( - metadata: [:], - producer: { writer in - try await self.performBuild( - request: request.messages, - response: writer, - context: context - ) - return [:] - } - ) - } + public var interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? { + return nil + } - public func info( - request: GRPCCore.ServerRequest, - context: GRPCCore.ServerContext - ) async throws -> GRPCCore.ServerResponse { - return GRPCCore.ServerResponse( - message: try await self.info( - request: request.message, - context: context - ), - metadata: [:] - ) - } + public func makeCreateBuildCall( + _ request: Com_Apple_Container_Build_V1_CreateBuildRequest, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.createBuild.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeCreateBuildInterceptors() ?? [] + ) + } + + public func makePerformBuildCall( + callOptions: CallOptions? = nil + ) -> GRPCAsyncBidirectionalStreamingCall { + return self.makeAsyncBidirectionalStreamingCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.performBuild.path, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makePerformBuildInterceptors() ?? [] + ) + } + + public func makeInfoCall( + _ request: Com_Apple_Container_Build_V1_InfoRequest, + callOptions: CallOptions? = nil + ) -> GRPCAsyncUnaryCall { + return self.makeAsyncUnaryCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.info.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeInfoInterceptors() ?? [] + ) + } } -// MARK: com.apple.container.build.v1.Builder (client) +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension Com_Apple_Container_Build_V1_BuilderAsyncClientProtocol { + public func createBuild( + _ request: Com_Apple_Container_Build_V1_CreateBuildRequest, + callOptions: CallOptions? = nil + ) async throws -> Com_Apple_Container_Build_V1_CreateBuildResponse { + return try await self.performAsyncUnaryCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.createBuild.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeCreateBuildInterceptors() ?? [] + ) + } -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -extension Com_Apple_Container_Build_V1_Builder { - /// Generated client protocol for the "com.apple.container.build.v1.Builder" service. - /// - /// You don't need to implement this protocol directly, use the generated - /// implementation, ``Client``. - /// - /// > Source IDL Documentation: - /// > - /// > Builder service implements APIs for performing an image build with - /// > Container image builder agent. - /// > - /// > To perform a build: - /// > - /// > 1. CreateBuild to create a new build - /// > 2. StartBuild to start the build execution where client and server - /// > both have a stream for exchanging data during the build. - /// > - /// > The client may send: - /// > a) signal packet to signal to the build process (e.g. SIGINT) - /// > - /// > b) command packet for executing a command in the build file on the - /// > server - /// > NOTE: the server will need to switch on the command to determine the - /// > type of command to execute (e.g. RUN, ENV, etc.) - /// > - /// > c) transfer build data either to or from the server - /// > - INTO direction is for sending build data to the server at specific - /// > location (e.g. COPY) - /// > - OUTOF direction is for copying build data from the server to be - /// > used in subsequent build stages - /// > - /// > d) transfer image content data either to or from the server - /// > - INTO direction is for sending inherited image content data to the - /// > server's local content store - /// > - OUTOF direction is for copying successfully built OCI image from - /// > the server to the client - /// > - /// > The server may send: - /// > a) stdio packet for the build progress - /// > - /// > b) build error indicating unsuccessful build - /// > - /// > c) command complete packet indicating a command has finished executing - /// > - /// > d) handle transfer build data either to or from the client - /// > - /// > e) handle transfer image content data either to or from the client - /// > - /// > - /// > NOTE: The build data and image content data transfer is ALWAYS initiated - /// > by the client. - /// > - /// > Sequence for transferring from the client to the server: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'INTO', - /// > destination path, and first chunk of data - /// > 2. server starts to receive the data and stream to a temporary file - /// > 3. client continues to send all chunks of data until last chunk, which - /// > client will - /// > send with 'complete' set to true - /// > 4. server continues to receive until the last chunk with 'complete' set - /// > to true, - /// > server will finish writing the last chunk and un-archive the - /// > temporary file to the destination path - /// > 5. server completes the transfer by sending a last - /// > BuildTransfer/ImageTransfer with - /// > 'complete' set to true - /// > 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' - /// > set to true - /// > before proceeding with the rest of the commands - /// > - /// > Sequence for transferring from the server to the client: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'OUTOF', - /// > source path, and empty data - /// > 2. server archives the data at source path, and starts to send chunks to - /// > the client - /// > 3. server continues to send all chunks until last chunk, which server - /// > will send with - /// > 'complete' set to true - /// > 4. client starts to receive the data and stream to a temporary file - /// > 5. client continues to receive until the last chunk with 'complete' set - /// > to true, - /// > client will finish writing last chunk and un-archive the temporary - /// > file to the destination path - /// > 6. client MAY choose to send one last BuildTransfer/ImageTransfer with - /// > 'complete' - /// > set to true, but NOT required. - /// > - /// > - /// > NOTE: the client should close the send stream once it has finished - /// > receiving the build output or abandon the current build due to error. - /// > Server should keep the stream open until it receives the EOF that client - /// > has closed the stream, which the server should then close its send stream. - public protocol ClientProtocol: Sendable { - /// Call the "CreateBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Create a build request. - /// - /// - Parameters: - /// - request: A request containing a single `Com_Apple_Container_Build_V1_CreateBuildRequest` message. - /// - serializer: A serializer for `Com_Apple_Container_Build_V1_CreateBuildRequest` messages. - /// - deserializer: A deserializer for `Com_Apple_Container_Build_V1_CreateBuildResponse` messages. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - func createBuild( - request: GRPCCore.ClientRequest, - serializer: some GRPCCore.MessageSerializer, - deserializer: some GRPCCore.MessageDeserializer, - options: GRPCCore.CallOptions, - onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result - ) async throws -> Result where Result: Sendable + public func performBuild( + _ requests: RequestStream, + callOptions: CallOptions? = nil + ) -> GRPCAsyncResponseStream where RequestStream: Sequence, RequestStream.Element == Com_Apple_Container_Build_V1_ClientStream { + return self.performAsyncBidirectionalStreamingCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.performBuild.path, + requests: requests, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makePerformBuildInterceptors() ?? [] + ) + } - /// Call the "PerformBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Perform the build. - /// > Executes the entire build sequence with attaching input/output - /// > to handling data exchange with the server during the build. - /// - /// - Parameters: - /// - request: A streaming request producing `Com_Apple_Container_Build_V1_ClientStream` messages. - /// - serializer: A serializer for `Com_Apple_Container_Build_V1_ClientStream` messages. - /// - deserializer: A deserializer for `Com_Apple_Container_Build_V1_ServerStream` messages. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - func performBuild( - request: GRPCCore.StreamingClientRequest, - serializer: some GRPCCore.MessageSerializer, - deserializer: some GRPCCore.MessageDeserializer, - options: GRPCCore.CallOptions, - onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result - ) async throws -> Result where Result: Sendable + public func performBuild( + _ requests: RequestStream, + callOptions: CallOptions? = nil + ) -> GRPCAsyncResponseStream where RequestStream: AsyncSequence & Sendable, RequestStream.Element == Com_Apple_Container_Build_V1_ClientStream { + return self.performAsyncBidirectionalStreamingCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.performBuild.path, + requests: requests, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makePerformBuildInterceptors() ?? [] + ) + } - /// Call the "Info" method. - /// - /// - Parameters: - /// - request: A request containing a single `Com_Apple_Container_Build_V1_InfoRequest` message. - /// - serializer: A serializer for `Com_Apple_Container_Build_V1_InfoRequest` messages. - /// - deserializer: A deserializer for `Com_Apple_Container_Build_V1_InfoResponse` messages. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - func info( - request: GRPCCore.ClientRequest, - serializer: some GRPCCore.MessageSerializer, - deserializer: some GRPCCore.MessageDeserializer, - options: GRPCCore.CallOptions, - onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result - ) async throws -> Result where Result: Sendable - } - - /// Generated client for the "com.apple.container.build.v1.Builder" service. - /// - /// The ``Client`` provides an implementation of ``ClientProtocol`` which wraps - /// a `GRPCCore.GRPCCClient`. The underlying `GRPCClient` provides the long-lived - /// means of communication with the remote peer. - /// - /// > Source IDL Documentation: - /// > - /// > Builder service implements APIs for performing an image build with - /// > Container image builder agent. - /// > - /// > To perform a build: - /// > - /// > 1. CreateBuild to create a new build - /// > 2. StartBuild to start the build execution where client and server - /// > both have a stream for exchanging data during the build. - /// > - /// > The client may send: - /// > a) signal packet to signal to the build process (e.g. SIGINT) - /// > - /// > b) command packet for executing a command in the build file on the - /// > server - /// > NOTE: the server will need to switch on the command to determine the - /// > type of command to execute (e.g. RUN, ENV, etc.) - /// > - /// > c) transfer build data either to or from the server - /// > - INTO direction is for sending build data to the server at specific - /// > location (e.g. COPY) - /// > - OUTOF direction is for copying build data from the server to be - /// > used in subsequent build stages - /// > - /// > d) transfer image content data either to or from the server - /// > - INTO direction is for sending inherited image content data to the - /// > server's local content store - /// > - OUTOF direction is for copying successfully built OCI image from - /// > the server to the client - /// > - /// > The server may send: - /// > a) stdio packet for the build progress - /// > - /// > b) build error indicating unsuccessful build - /// > - /// > c) command complete packet indicating a command has finished executing - /// > - /// > d) handle transfer build data either to or from the client - /// > - /// > e) handle transfer image content data either to or from the client - /// > - /// > - /// > NOTE: The build data and image content data transfer is ALWAYS initiated - /// > by the client. - /// > - /// > Sequence for transferring from the client to the server: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'INTO', - /// > destination path, and first chunk of data - /// > 2. server starts to receive the data and stream to a temporary file - /// > 3. client continues to send all chunks of data until last chunk, which - /// > client will - /// > send with 'complete' set to true - /// > 4. server continues to receive until the last chunk with 'complete' set - /// > to true, - /// > server will finish writing the last chunk and un-archive the - /// > temporary file to the destination path - /// > 5. server completes the transfer by sending a last - /// > BuildTransfer/ImageTransfer with - /// > 'complete' set to true - /// > 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' - /// > set to true - /// > before proceeding with the rest of the commands - /// > - /// > Sequence for transferring from the server to the client: - /// > 1. client send a BuildTransfer/ImageTransfer request with ID, direction - /// > of 'OUTOF', - /// > source path, and empty data - /// > 2. server archives the data at source path, and starts to send chunks to - /// > the client - /// > 3. server continues to send all chunks until last chunk, which server - /// > will send with - /// > 'complete' set to true - /// > 4. client starts to receive the data and stream to a temporary file - /// > 5. client continues to receive until the last chunk with 'complete' set - /// > to true, - /// > client will finish writing last chunk and un-archive the temporary - /// > file to the destination path - /// > 6. client MAY choose to send one last BuildTransfer/ImageTransfer with - /// > 'complete' - /// > set to true, but NOT required. - /// > - /// > - /// > NOTE: the client should close the send stream once it has finished - /// > receiving the build output or abandon the current build due to error. - /// > Server should keep the stream open until it receives the EOF that client - /// > has closed the stream, which the server should then close its send stream. - public struct Client: ClientProtocol where Transport: GRPCCore.ClientTransport { - private let client: GRPCCore.GRPCClient - - /// Creates a new client wrapping the provided `GRPCCore.GRPCClient`. - /// - /// - Parameters: - /// - client: A `GRPCCore.GRPCClient` providing a communication channel to the service. - public init(wrapping client: GRPCCore.GRPCClient) { - self.client = client - } - - /// Call the "CreateBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Create a build request. - /// - /// - Parameters: - /// - request: A request containing a single `Com_Apple_Container_Build_V1_CreateBuildRequest` message. - /// - serializer: A serializer for `Com_Apple_Container_Build_V1_CreateBuildRequest` messages. - /// - deserializer: A deserializer for `Com_Apple_Container_Build_V1_CreateBuildResponse` messages. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func createBuild( - request: GRPCCore.ClientRequest, - serializer: some GRPCCore.MessageSerializer, - deserializer: some GRPCCore.MessageDeserializer, - options: GRPCCore.CallOptions = .defaults, - onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in - try response.message - } - ) async throws -> Result where Result: Sendable { - try await self.client.unary( - request: request, - descriptor: Com_Apple_Container_Build_V1_Builder.Method.CreateBuild.descriptor, - serializer: serializer, - deserializer: deserializer, - options: options, - onResponse: handleResponse - ) - } - - /// Call the "PerformBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Perform the build. - /// > Executes the entire build sequence with attaching input/output - /// > to handling data exchange with the server during the build. - /// - /// - Parameters: - /// - request: A streaming request producing `Com_Apple_Container_Build_V1_ClientStream` messages. - /// - serializer: A serializer for `Com_Apple_Container_Build_V1_ClientStream` messages. - /// - deserializer: A deserializer for `Com_Apple_Container_Build_V1_ServerStream` messages. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func performBuild( - request: GRPCCore.StreamingClientRequest, - serializer: some GRPCCore.MessageSerializer, - deserializer: some GRPCCore.MessageDeserializer, - options: GRPCCore.CallOptions = .defaults, - onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result - ) async throws -> Result where Result: Sendable { - try await self.client.bidirectionalStreaming( - request: request, - descriptor: Com_Apple_Container_Build_V1_Builder.Method.PerformBuild.descriptor, - serializer: serializer, - deserializer: deserializer, - options: options, - onResponse: handleResponse - ) - } - - /// Call the "Info" method. - /// - /// - Parameters: - /// - request: A request containing a single `Com_Apple_Container_Build_V1_InfoRequest` message. - /// - serializer: A serializer for `Com_Apple_Container_Build_V1_InfoRequest` messages. - /// - deserializer: A deserializer for `Com_Apple_Container_Build_V1_InfoResponse` messages. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func info( - request: GRPCCore.ClientRequest, - serializer: some GRPCCore.MessageSerializer, - deserializer: some GRPCCore.MessageDeserializer, - options: GRPCCore.CallOptions = .defaults, - onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in - try response.message - } - ) async throws -> Result where Result: Sendable { - try await self.client.unary( - request: request, - descriptor: Com_Apple_Container_Build_V1_Builder.Method.Info.descriptor, - serializer: serializer, - deserializer: deserializer, - options: options, - onResponse: handleResponse - ) - } - } + public func info( + _ request: Com_Apple_Container_Build_V1_InfoRequest, + callOptions: CallOptions? = nil + ) async throws -> Com_Apple_Container_Build_V1_InfoResponse { + return try await self.performAsyncUnaryCall( + path: Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.info.path, + request: request, + callOptions: callOptions ?? self.defaultCallOptions, + interceptors: self.interceptors?.makeInfoInterceptors() ?? [] + ) + } } -// Helpers providing default arguments to 'ClientProtocol' methods. -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -extension Com_Apple_Container_Build_V1_Builder.ClientProtocol { - /// Call the "CreateBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Create a build request. - /// - /// - Parameters: - /// - request: A request containing a single `Com_Apple_Container_Build_V1_CreateBuildRequest` message. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func createBuild( - request: GRPCCore.ClientRequest, - options: GRPCCore.CallOptions = .defaults, - onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in - try response.message - } - ) async throws -> Result where Result: Sendable { - try await self.createBuild( - request: request, - serializer: GRPCProtobuf.ProtobufSerializer(), - deserializer: GRPCProtobuf.ProtobufDeserializer(), - options: options, - onResponse: handleResponse - ) - } +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +public struct Com_Apple_Container_Build_V1_BuilderAsyncClient: Com_Apple_Container_Build_V1_BuilderAsyncClientProtocol { + public var channel: GRPCChannel + public var defaultCallOptions: CallOptions + public var interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? - /// Call the "PerformBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Perform the build. - /// > Executes the entire build sequence with attaching input/output - /// > to handling data exchange with the server during the build. - /// - /// - Parameters: - /// - request: A streaming request producing `Com_Apple_Container_Build_V1_ClientStream` messages. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func performBuild( - request: GRPCCore.StreamingClientRequest, - options: GRPCCore.CallOptions = .defaults, - onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result - ) async throws -> Result where Result: Sendable { - try await self.performBuild( - request: request, - serializer: GRPCProtobuf.ProtobufSerializer(), - deserializer: GRPCProtobuf.ProtobufDeserializer(), - options: options, - onResponse: handleResponse - ) - } - - /// Call the "Info" method. - /// - /// - Parameters: - /// - request: A request containing a single `Com_Apple_Container_Build_V1_InfoRequest` message. - /// - options: Options to apply to this RPC. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func info( - request: GRPCCore.ClientRequest, - options: GRPCCore.CallOptions = .defaults, - onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in - try response.message - } - ) async throws -> Result where Result: Sendable { - try await self.info( - request: request, - serializer: GRPCProtobuf.ProtobufSerializer(), - deserializer: GRPCProtobuf.ProtobufDeserializer(), - options: options, - onResponse: handleResponse - ) - } + public init( + channel: GRPCChannel, + defaultCallOptions: CallOptions = CallOptions(), + interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? = nil + ) { + self.channel = channel + self.defaultCallOptions = defaultCallOptions + self.interceptors = interceptors + } } -// Helpers providing sugared APIs for 'ClientProtocol' methods. -@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) -extension Com_Apple_Container_Build_V1_Builder.ClientProtocol { - /// Call the "CreateBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Create a build request. - /// - /// - Parameters: - /// - message: request message to send. - /// - metadata: Additional metadata to send, defaults to empty. - /// - options: Options to apply to this RPC, defaults to `.defaults`. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func createBuild( - _ message: Com_Apple_Container_Build_V1_CreateBuildRequest, - metadata: GRPCCore.Metadata = [:], - options: GRPCCore.CallOptions = .defaults, - onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in - try response.message - } - ) async throws -> Result where Result: Sendable { - let request = GRPCCore.ClientRequest( - message: message, - metadata: metadata - ) - return try await self.createBuild( - request: request, - options: options, - onResponse: handleResponse - ) - } +public protocol Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol: Sendable { - /// Call the "PerformBuild" method. - /// - /// > Source IDL Documentation: - /// > - /// > Perform the build. - /// > Executes the entire build sequence with attaching input/output - /// > to handling data exchange with the server during the build. - /// - /// - Parameters: - /// - metadata: Additional metadata to send, defaults to empty. - /// - options: Options to apply to this RPC, defaults to `.defaults`. - /// - producer: A closure producing request messages to send to the server. The request - /// stream is closed when the closure returns. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func performBuild( - metadata: GRPCCore.Metadata = [:], - options: GRPCCore.CallOptions = .defaults, - requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter) async throws -> Void, - onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result - ) async throws -> Result where Result: Sendable { - let request = GRPCCore.StreamingClientRequest( - metadata: metadata, - producer: producer - ) - return try await self.performBuild( - request: request, - options: options, - onResponse: handleResponse - ) - } + /// - Returns: Interceptors to use when invoking 'createBuild'. + func makeCreateBuildInterceptors() -> [ClientInterceptor] - /// Call the "Info" method. - /// - /// - Parameters: - /// - message: request message to send. - /// - metadata: Additional metadata to send, defaults to empty. - /// - options: Options to apply to this RPC, defaults to `.defaults`. - /// - handleResponse: A closure which handles the response, the result of which is - /// returned to the caller. Returning from the closure will cancel the RPC if it - /// hasn't already finished. - /// - Returns: The result of `handleResponse`. - public func info( - _ message: Com_Apple_Container_Build_V1_InfoRequest, - metadata: GRPCCore.Metadata = [:], - options: GRPCCore.CallOptions = .defaults, - onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in - try response.message - } - ) async throws -> Result where Result: Sendable { - let request = GRPCCore.ClientRequest( - message: message, - metadata: metadata - ) - return try await self.info( - request: request, - options: options, - onResponse: handleResponse - ) + /// - Returns: Interceptors to use when invoking 'performBuild'. + func makePerformBuildInterceptors() -> [ClientInterceptor] + + /// - Returns: Interceptors to use when invoking 'info'. + func makeInfoInterceptors() -> [ClientInterceptor] +} + +public enum Com_Apple_Container_Build_V1_BuilderClientMetadata { + public static let serviceDescriptor = GRPCServiceDescriptor( + name: "Builder", + fullName: "com.apple.container.build.v1.Builder", + methods: [ + Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.createBuild, + Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.performBuild, + Com_Apple_Container_Build_V1_BuilderClientMetadata.Methods.info, + ] + ) + + public enum Methods { + public static let createBuild = GRPCMethodDescriptor( + name: "CreateBuild", + path: "/com.apple.container.build.v1.Builder/CreateBuild", + type: GRPCCallType.unary + ) + + public static let performBuild = GRPCMethodDescriptor( + name: "PerformBuild", + path: "/com.apple.container.build.v1.Builder/PerformBuild", + type: GRPCCallType.bidirectionalStreaming + ) + + public static let info = GRPCMethodDescriptor( + name: "Info", + path: "/com.apple.container.build.v1.Builder/Info", + type: GRPCCallType.unary + ) + } +} + +/// Builder service implements APIs for performing an image build with +/// Container image builder agent. +/// +/// To perform a build: +/// +/// 1. CreateBuild to create a new build +/// 2. StartBuild to start the build execution where client and server +/// both have a stream for exchanging data during the build. +/// +/// The client may send: +/// a) signal packet to signal to the build process (e.g. SIGINT) +/// +/// b) command packet for executing a command in the build file on the +/// server +/// NOTE: the server will need to switch on the command to determine the +/// type of command to execute (e.g. RUN, ENV, etc.) +/// +/// c) transfer build data either to or from the server +/// - INTO direction is for sending build data to the server at specific +/// location (e.g. COPY) +/// - OUTOF direction is for copying build data from the server to be +/// used in subsequent build stages +/// +/// d) transfer image content data either to or from the server +/// - INTO direction is for sending inherited image content data to the +/// server's local content store +/// - OUTOF direction is for copying successfully built OCI image from +/// the server to the client +/// +/// The server may send: +/// a) stdio packet for the build progress +/// +/// b) build error indicating unsuccessful build +/// +/// c) command complete packet indicating a command has finished executing +/// +/// d) handle transfer build data either to or from the client +/// +/// e) handle transfer image content data either to or from the client +/// +/// +/// NOTE: The build data and image content data transfer is ALWAYS initiated +/// by the client. +/// +/// Sequence for transferring from the client to the server: +/// 1. client send a BuildTransfer/ImageTransfer request with ID, direction +/// of 'INTO', +/// destination path, and first chunk of data +/// 2. server starts to receive the data and stream to a temporary file +/// 3. client continues to send all chunks of data until last chunk, which +/// client will +/// send with 'complete' set to true +/// 4. server continues to receive until the last chunk with 'complete' set +/// to true, +/// server will finish writing the last chunk and un-archive the +/// temporary file to the destination path +/// 5. server completes the transfer by sending a last +/// BuildTransfer/ImageTransfer with +/// 'complete' set to true +/// 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' +/// set to true +/// before proceeding with the rest of the commands +/// +/// Sequence for transferring from the server to the client: +/// 1. client send a BuildTransfer/ImageTransfer request with ID, direction +/// of 'OUTOF', +/// source path, and empty data +/// 2. server archives the data at source path, and starts to send chunks to +/// the client +/// 3. server continues to send all chunks until last chunk, which server +/// will send with +/// 'complete' set to true +/// 4. client starts to receive the data and stream to a temporary file +/// 5. client continues to receive until the last chunk with 'complete' set +/// to true, +/// client will finish writing last chunk and un-archive the temporary +/// file to the destination path +/// 6. client MAY choose to send one last BuildTransfer/ImageTransfer with +/// 'complete' +/// set to true, but NOT required. +/// +/// +/// NOTE: the client should close the send stream once it has finished +/// receiving the build output or abandon the current build due to error. +/// Server should keep the stream open until it receives the EOF that client +/// has closed the stream, which the server should then close its send stream. +/// +/// To build a server, implement a class that conforms to this protocol. +public protocol Com_Apple_Container_Build_V1_BuilderProvider: CallHandlerProvider { + var interceptors: Com_Apple_Container_Build_V1_BuilderServerInterceptorFactoryProtocol? { get } + + /// Create a build request. + func createBuild(request: Com_Apple_Container_Build_V1_CreateBuildRequest, context: StatusOnlyCallContext) -> EventLoopFuture + + /// Perform the build. + /// Executes the entire build sequence with attaching input/output + /// to handling data exchange with the server during the build. + func performBuild(context: StreamingResponseCallContext) -> EventLoopFuture<(StreamEvent) -> Void> + + func info(request: Com_Apple_Container_Build_V1_InfoRequest, context: StatusOnlyCallContext) -> EventLoopFuture +} + +extension Com_Apple_Container_Build_V1_BuilderProvider { + public var serviceName: Substring { + return Com_Apple_Container_Build_V1_BuilderServerMetadata.serviceDescriptor.fullName[...] + } + + /// Determines, calls and returns the appropriate request handler, depending on the request's method. + /// Returns nil for methods not handled by this service. + public func handle( + method name: Substring, + context: CallHandlerContext + ) -> GRPCServerHandlerProtocol? { + switch name { + case "CreateBuild": + return UnaryServerHandler( + context: context, + requestDeserializer: ProtobufDeserializer(), + responseSerializer: ProtobufSerializer(), + interceptors: self.interceptors?.makeCreateBuildInterceptors() ?? [], + userFunction: self.createBuild(request:context:) + ) + + case "PerformBuild": + return BidirectionalStreamingServerHandler( + context: context, + requestDeserializer: ProtobufDeserializer(), + responseSerializer: ProtobufSerializer(), + interceptors: self.interceptors?.makePerformBuildInterceptors() ?? [], + observerFactory: self.performBuild(context:) + ) + + case "Info": + return UnaryServerHandler( + context: context, + requestDeserializer: ProtobufDeserializer(), + responseSerializer: ProtobufSerializer(), + interceptors: self.interceptors?.makeInfoInterceptors() ?? [], + userFunction: self.info(request:context:) + ) + + default: + return nil } -} \ No newline at end of file + } +} + +/// Builder service implements APIs for performing an image build with +/// Container image builder agent. +/// +/// To perform a build: +/// +/// 1. CreateBuild to create a new build +/// 2. StartBuild to start the build execution where client and server +/// both have a stream for exchanging data during the build. +/// +/// The client may send: +/// a) signal packet to signal to the build process (e.g. SIGINT) +/// +/// b) command packet for executing a command in the build file on the +/// server +/// NOTE: the server will need to switch on the command to determine the +/// type of command to execute (e.g. RUN, ENV, etc.) +/// +/// c) transfer build data either to or from the server +/// - INTO direction is for sending build data to the server at specific +/// location (e.g. COPY) +/// - OUTOF direction is for copying build data from the server to be +/// used in subsequent build stages +/// +/// d) transfer image content data either to or from the server +/// - INTO direction is for sending inherited image content data to the +/// server's local content store +/// - OUTOF direction is for copying successfully built OCI image from +/// the server to the client +/// +/// The server may send: +/// a) stdio packet for the build progress +/// +/// b) build error indicating unsuccessful build +/// +/// c) command complete packet indicating a command has finished executing +/// +/// d) handle transfer build data either to or from the client +/// +/// e) handle transfer image content data either to or from the client +/// +/// +/// NOTE: The build data and image content data transfer is ALWAYS initiated +/// by the client. +/// +/// Sequence for transferring from the client to the server: +/// 1. client send a BuildTransfer/ImageTransfer request with ID, direction +/// of 'INTO', +/// destination path, and first chunk of data +/// 2. server starts to receive the data and stream to a temporary file +/// 3. client continues to send all chunks of data until last chunk, which +/// client will +/// send with 'complete' set to true +/// 4. server continues to receive until the last chunk with 'complete' set +/// to true, +/// server will finish writing the last chunk and un-archive the +/// temporary file to the destination path +/// 5. server completes the transfer by sending a last +/// BuildTransfer/ImageTransfer with +/// 'complete' set to true +/// 6. client waits for the last BuildTransfer/ImageTransfer with 'complete' +/// set to true +/// before proceeding with the rest of the commands +/// +/// Sequence for transferring from the server to the client: +/// 1. client send a BuildTransfer/ImageTransfer request with ID, direction +/// of 'OUTOF', +/// source path, and empty data +/// 2. server archives the data at source path, and starts to send chunks to +/// the client +/// 3. server continues to send all chunks until last chunk, which server +/// will send with +/// 'complete' set to true +/// 4. client starts to receive the data and stream to a temporary file +/// 5. client continues to receive until the last chunk with 'complete' set +/// to true, +/// client will finish writing last chunk and un-archive the temporary +/// file to the destination path +/// 6. client MAY choose to send one last BuildTransfer/ImageTransfer with +/// 'complete' +/// set to true, but NOT required. +/// +/// +/// NOTE: the client should close the send stream once it has finished +/// receiving the build output or abandon the current build due to error. +/// Server should keep the stream open until it receives the EOF that client +/// has closed the stream, which the server should then close its send stream. +/// +/// To implement a server, implement an object which conforms to this protocol. +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +public protocol Com_Apple_Container_Build_V1_BuilderAsyncProvider: CallHandlerProvider, Sendable { + static var serviceDescriptor: GRPCServiceDescriptor { get } + var interceptors: Com_Apple_Container_Build_V1_BuilderServerInterceptorFactoryProtocol? { get } + + /// Create a build request. + func createBuild( + request: Com_Apple_Container_Build_V1_CreateBuildRequest, + context: GRPCAsyncServerCallContext + ) async throws -> Com_Apple_Container_Build_V1_CreateBuildResponse + + /// Perform the build. + /// Executes the entire build sequence with attaching input/output + /// to handling data exchange with the server during the build. + func performBuild( + requestStream: GRPCAsyncRequestStream, + responseStream: GRPCAsyncResponseStreamWriter, + context: GRPCAsyncServerCallContext + ) async throws + + func info( + request: Com_Apple_Container_Build_V1_InfoRequest, + context: GRPCAsyncServerCallContext + ) async throws -> Com_Apple_Container_Build_V1_InfoResponse +} + +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +extension Com_Apple_Container_Build_V1_BuilderAsyncProvider { + public static var serviceDescriptor: GRPCServiceDescriptor { + return Com_Apple_Container_Build_V1_BuilderServerMetadata.serviceDescriptor + } + + public var serviceName: Substring { + return Com_Apple_Container_Build_V1_BuilderServerMetadata.serviceDescriptor.fullName[...] + } + + public var interceptors: Com_Apple_Container_Build_V1_BuilderServerInterceptorFactoryProtocol? { + return nil + } + + public func handle( + method name: Substring, + context: CallHandlerContext + ) -> GRPCServerHandlerProtocol? { + switch name { + case "CreateBuild": + return GRPCAsyncServerHandler( + context: context, + requestDeserializer: ProtobufDeserializer(), + responseSerializer: ProtobufSerializer(), + interceptors: self.interceptors?.makeCreateBuildInterceptors() ?? [], + wrapping: { try await self.createBuild(request: $0, context: $1) } + ) + + case "PerformBuild": + return GRPCAsyncServerHandler( + context: context, + requestDeserializer: ProtobufDeserializer(), + responseSerializer: ProtobufSerializer(), + interceptors: self.interceptors?.makePerformBuildInterceptors() ?? [], + wrapping: { try await self.performBuild(requestStream: $0, responseStream: $1, context: $2) } + ) + + case "Info": + return GRPCAsyncServerHandler( + context: context, + requestDeserializer: ProtobufDeserializer(), + responseSerializer: ProtobufSerializer(), + interceptors: self.interceptors?.makeInfoInterceptors() ?? [], + wrapping: { try await self.info(request: $0, context: $1) } + ) + + default: + return nil + } + } +} + +public protocol Com_Apple_Container_Build_V1_BuilderServerInterceptorFactoryProtocol: Sendable { + + /// - Returns: Interceptors to use when handling 'createBuild'. + /// Defaults to calling `self.makeInterceptors()`. + func makeCreateBuildInterceptors() -> [ServerInterceptor] + + /// - Returns: Interceptors to use when handling 'performBuild'. + /// Defaults to calling `self.makeInterceptors()`. + func makePerformBuildInterceptors() -> [ServerInterceptor] + + /// - Returns: Interceptors to use when handling 'info'. + /// Defaults to calling `self.makeInterceptors()`. + func makeInfoInterceptors() -> [ServerInterceptor] +} + +public enum Com_Apple_Container_Build_V1_BuilderServerMetadata { + public static let serviceDescriptor = GRPCServiceDescriptor( + name: "Builder", + fullName: "com.apple.container.build.v1.Builder", + methods: [ + Com_Apple_Container_Build_V1_BuilderServerMetadata.Methods.createBuild, + Com_Apple_Container_Build_V1_BuilderServerMetadata.Methods.performBuild, + Com_Apple_Container_Build_V1_BuilderServerMetadata.Methods.info, + ] + ) + + public enum Methods { + public static let createBuild = GRPCMethodDescriptor( + name: "CreateBuild", + path: "/com.apple.container.build.v1.Builder/CreateBuild", + type: GRPCCallType.unary + ) + + public static let performBuild = GRPCMethodDescriptor( + name: "PerformBuild", + path: "/com.apple.container.build.v1.Builder/PerformBuild", + type: GRPCCallType.bidirectionalStreaming + ) + + public static let info = GRPCMethodDescriptor( + name: "Info", + path: "/com.apple.container.build.v1.Builder/Info", + type: GRPCCallType.unary + ) + } +} diff --git a/Sources/ContainerBuild/Builder.pb.swift b/Sources/ContainerBuild/Builder.pb.swift index 6b6c1165..5d340256 100644 --- a/Sources/ContainerBuild/Builder.pb.swift +++ b/Sources/ContainerBuild/Builder.pb.swift @@ -24,11 +24,7 @@ // For information on using the generated types, please see the documentation: // https://github.com/apple/swift-protobuf/ -#if canImport(FoundationEssentials) -import FoundationEssentials -#else import Foundation -#endif import SwiftProtobuf // If the compiler emits an error on this type, it is because this file @@ -217,7 +213,7 @@ public struct Com_Apple_Container_Build_V1_ClientStream: @unchecked Sendable { /// A unique ID for the build. public var buildID: String { - get {_storage._buildID} + get {return _storage._buildID} set {_uniqueStorage()._buildID = newValue} } @@ -318,7 +314,7 @@ public struct Com_Apple_Container_Build_V1_RunComplete: Sendable { public init() {} } -public struct Com_Apple_Container_Build_V1_BuildTransfer: Sendable { +public struct Com_Apple_Container_Build_V1_BuildTransfer: @unchecked Sendable { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -332,21 +328,21 @@ public struct Com_Apple_Container_Build_V1_BuildTransfer: Sendable { /// The absolute path to the source from the server perspective. public var source: String { - get {_source ?? String()} + get {return _source ?? String()} set {_source = newValue} } /// Returns true if `source` has been explicitly set. - public var hasSource: Bool {self._source != nil} + public var hasSource: Bool {return self._source != nil} /// Clears the value of `source`. Subsequent reads from it will return its default value. public mutating func clearSource() {self._source = nil} /// The absolute path for the destination from the server perspective. public var destination: String { - get {_destination ?? String()} + get {return _destination ?? String()} set {_destination = newValue} } /// Returns true if `destination` has been explicitly set. - public var hasDestination: Bool {self._destination != nil} + public var hasDestination: Bool {return self._destination != nil} /// Clears the value of `destination`. Subsequent reads from it will return its default value. public mutating func clearDestination() {self._destination = nil} @@ -370,7 +366,7 @@ public struct Com_Apple_Container_Build_V1_BuildTransfer: Sendable { fileprivate var _destination: String? = nil } -public struct Com_Apple_Container_Build_V1_ImageTransfer: Sendable { +public struct Com_Apple_Container_Build_V1_ImageTransfer: @unchecked Sendable { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -387,11 +383,11 @@ public struct Com_Apple_Container_Build_V1_ImageTransfer: Sendable { /// The descriptor for the image content. public var descriptor: Com_Apple_Container_Build_V1_Descriptor { - get {_descriptor ?? Com_Apple_Container_Build_V1_Descriptor()} + get {return _descriptor ?? Com_Apple_Container_Build_V1_Descriptor()} set {_descriptor = newValue} } /// Returns true if `descriptor` has been explicitly set. - public var hasDescriptor: Bool {self._descriptor != nil} + public var hasDescriptor: Bool {return self._descriptor != nil} /// Clears the value of `descriptor`. Subsequent reads from it will return its default value. public mutating func clearDescriptor() {self._descriptor = nil} @@ -418,7 +414,7 @@ public struct Com_Apple_Container_Build_V1_ServerStream: @unchecked Sendable { /// A unique ID for the build. public var buildID: String { - get {_storage._buildID} + get {return _storage._buildID} set {_uniqueStorage()._buildID = newValue} } @@ -485,7 +481,7 @@ public struct Com_Apple_Container_Build_V1_ServerStream: @unchecked Sendable { fileprivate var _storage = _StorageClass.defaultInstance } -public struct Com_Apple_Container_Build_V1_IO: Sendable { +public struct Com_Apple_Container_Build_V1_IO: @unchecked Sendable { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. @@ -555,11 +551,11 @@ public struct Com_Apple_Container_Build_V1_Descriptor: Sendable { public var annotations: Dictionary = [:] public var platform: Com_Apple_Container_Build_V1_Platform { - get {_platform ?? Com_Apple_Container_Build_V1_Platform()} + get {return _platform ?? Com_Apple_Container_Build_V1_Platform()} set {_platform = newValue} } /// Returns true if `platform` has been explicitly set. - public var hasPlatform: Bool {self._platform != nil} + public var hasPlatform: Bool {return self._platform != nil} /// Clears the value of `platform`. Subsequent reads from it will return its default value. public mutating func clearPlatform() {self._platform = nil} @@ -575,15 +571,25 @@ public struct Com_Apple_Container_Build_V1_Descriptor: Sendable { fileprivate let _protobuf_package = "com.apple.container.build.v1" extension Com_Apple_Container_Build_V1_TransferDirection: SwiftProtobuf._ProtoNameProviding { - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0INTO\0\u{1}OUTOF\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "INTO"), + 1: .same(proto: "OUTOF"), + ] } extension Com_Apple_Container_Build_V1_Stdio: SwiftProtobuf._ProtoNameProviding { - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0STDIN\0\u{1}STDOUT\0\u{1}STDERR\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "STDIN"), + 1: .same(proto: "STDOUT"), + 2: .same(proto: "STDERR"), + ] } extension Com_Apple_Container_Build_V1_BuildErrorType: SwiftProtobuf._ProtoNameProviding { - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0BUILD_FAILED\0\u{1}INTERNAL\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "BUILD_FAILED"), + 1: .same(proto: "INTERNAL"), + ] } extension Com_Apple_Container_Build_V1_InfoRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { @@ -626,7 +632,13 @@ extension Com_Apple_Container_Build_V1_InfoResponse: SwiftProtobuf.Message, Swif extension Com_Apple_Container_Build_V1_CreateBuildRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".CreateBuildRequest" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}stage_name\0\u{1}tag\0\u{1}metadata\0\u{3}build_args\0\u{1}debug\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "stage_name"), + 2: .same(proto: "tag"), + 3: .same(proto: "metadata"), + 4: .standard(proto: "build_args"), + 5: .same(proto: "debug"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -676,7 +688,10 @@ extension Com_Apple_Container_Build_V1_CreateBuildRequest: SwiftProtobuf.Message extension Com_Apple_Container_Build_V1_CreateBuildResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".CreateBuildResponse" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}build_id\0\u{1}metadata\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "build_id"), + 2: .same(proto: "metadata"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -711,7 +726,13 @@ extension Com_Apple_Container_Build_V1_CreateBuildResponse: SwiftProtobuf.Messag extension Com_Apple_Container_Build_V1_ClientStream: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".ClientStream" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}build_id\0\u{1}signal\0\u{1}command\0\u{3}build_transfer\0\u{3}image_transfer\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "build_id"), + 2: .same(proto: "signal"), + 3: .same(proto: "command"), + 4: .standard(proto: "build_transfer"), + 5: .standard(proto: "image_transfer"), + ] fileprivate class _StorageClass { var _buildID: String = String() @@ -855,7 +876,9 @@ extension Com_Apple_Container_Build_V1_ClientStream: SwiftProtobuf.Message, Swif extension Com_Apple_Container_Build_V1_Signal: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".Signal" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}signal\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "signal"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -885,7 +908,10 @@ extension Com_Apple_Container_Build_V1_Signal: SwiftProtobuf.Message, SwiftProto extension Com_Apple_Container_Build_V1_Run: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".Run" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}id\0\u{1}command\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + 2: .same(proto: "command"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -920,7 +946,9 @@ extension Com_Apple_Container_Build_V1_Run: SwiftProtobuf.Message, SwiftProtobuf extension Com_Apple_Container_Build_V1_RunComplete: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".RunComplete" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}id\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -950,7 +978,16 @@ extension Com_Apple_Container_Build_V1_RunComplete: SwiftProtobuf.Message, Swift extension Com_Apple_Container_Build_V1_BuildTransfer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".BuildTransfer" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}id\0\u{1}direction\0\u{1}source\0\u{1}destination\0\u{1}data\0\u{1}complete\0\u{3}is_directory\0\u{1}metadata\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + 2: .same(proto: "direction"), + 3: .same(proto: "source"), + 4: .same(proto: "destination"), + 5: .same(proto: "data"), + 6: .same(proto: "complete"), + 7: .standard(proto: "is_directory"), + 8: .same(proto: "metadata"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1019,7 +1056,15 @@ extension Com_Apple_Container_Build_V1_BuildTransfer: SwiftProtobuf.Message, Swi extension Com_Apple_Container_Build_V1_ImageTransfer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".ImageTransfer" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}id\0\u{1}direction\0\u{1}tag\0\u{1}descriptor\0\u{1}data\0\u{1}complete\0\u{1}metadata\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + 2: .same(proto: "direction"), + 3: .same(proto: "tag"), + 4: .same(proto: "descriptor"), + 5: .same(proto: "data"), + 6: .same(proto: "complete"), + 7: .same(proto: "metadata"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1083,7 +1128,14 @@ extension Com_Apple_Container_Build_V1_ImageTransfer: SwiftProtobuf.Message, Swi extension Com_Apple_Container_Build_V1_ServerStream: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".ServerStream" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}build_id\0\u{1}io\0\u{3}build_error\0\u{3}command_complete\0\u{3}build_transfer\0\u{3}image_transfer\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "build_id"), + 2: .same(proto: "io"), + 3: .standard(proto: "build_error"), + 4: .standard(proto: "command_complete"), + 5: .standard(proto: "build_transfer"), + 6: .standard(proto: "image_transfer"), + ] fileprivate class _StorageClass { var _buildID: String = String() @@ -1244,7 +1296,10 @@ extension Com_Apple_Container_Build_V1_ServerStream: SwiftProtobuf.Message, Swif extension Com_Apple_Container_Build_V1_IO: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".IO" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}type\0\u{1}data\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "type"), + 2: .same(proto: "data"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1279,7 +1334,10 @@ extension Com_Apple_Container_Build_V1_IO: SwiftProtobuf.Message, SwiftProtobuf. extension Com_Apple_Container_Build_V1_BuildError: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".BuildError" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}type\0\u{1}message\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "type"), + 2: .same(proto: "message"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1314,7 +1372,13 @@ extension Com_Apple_Container_Build_V1_BuildError: SwiftProtobuf.Message, SwiftP extension Com_Apple_Container_Build_V1_Platform: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".Platform" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}architecture\0\u{1}os\0\u{3}os_version\0\u{3}os_features\0\u{1}variant\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "architecture"), + 2: .same(proto: "os"), + 3: .standard(proto: "os_version"), + 4: .standard(proto: "os_features"), + 5: .same(proto: "variant"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1364,7 +1428,14 @@ extension Com_Apple_Container_Build_V1_Platform: SwiftProtobuf.Message, SwiftPro extension Com_Apple_Container_Build_V1_Descriptor: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".Descriptor" - public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}media_type\0\u{1}digest\0\u{1}size\0\u{1}urls\0\u{1}annotations\0\u{1}platform\0") + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "media_type"), + 2: .same(proto: "digest"), + 3: .same(proto: "size"), + 4: .same(proto: "urls"), + 5: .same(proto: "annotations"), + 6: .same(proto: "platform"), + ] public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { diff --git a/Sources/ContainerBuild/Builder.swift b/Sources/ContainerBuild/Builder.swift index be1b21f0..4c605c41 100644 --- a/Sources/ContainerBuild/Builder.swift +++ b/Sources/ContainerBuild/Builder.swift @@ -19,72 +19,58 @@ import Containerization import ContainerizationOCI import ContainerizationOS import Foundation -import GRPCCore -import GRPCNIOTransportHTTP2 -import Logging +import GRPC import NIO -import NIOCore import NIOHPACK import NIOHTTP2 -import NIOPosix public struct Builder: Sendable { public static let builderContainerId = "buildkit" - let client: Com_Apple_Container_Build_V1_Builder.Client - let grpcClient: GRPCClient + let client: BuilderClientProtocol + let clientAsync: BuilderClientAsyncProtocol let group: EventLoopGroup let builderShimSocket: FileHandle - let clientTask: Task - let logger: Logger + let channel: GRPCChannel - public init(socket: FileHandle, group: EventLoopGroup, logger: Logger) throws { + public init(socket: FileHandle, group: EventLoopGroup) throws { try socket.setSendBufSize(4 << 20) try socket.setRecvBufSize(2 << 20) - - let channel = try ClientBootstrap(group: group) - .channelInitializer { channel in - channel.eventLoop.makeCompletedFuture(withResultOf: { - try channel.pipeline.syncOperations.addHandler(HTTP2ConnectBufferingHandler()) - }) - } - .withConnectedSocket(socket.fileDescriptor) - .wait() - - let transport = HTTP2ClientTransport.WrappedChannel.wrapping( - channel: channel + var config = ClientConnection.Configuration.default( + target: .connectedSocket(socket.fileDescriptor), + eventLoopGroup: group ) + config.connectionIdleTimeout = TimeAmount(.seconds(600)) + config.connectionKeepalive = .init( + interval: TimeAmount(.seconds(600)), + timeout: TimeAmount(.seconds(500)), + permitWithoutCalls: true + ) + config.connectionBackoff = .init( + initialBackoff: TimeInterval(1), + maximumBackoff: TimeInterval(10) + ) + config.callStartBehavior = .fastFailure + config.httpMaxFrameSize = 8 << 10 + config.maximumReceiveMessageLength = 512 << 20 + config.httpTargetWindowSize = 16 << 10 - let grpcClient = GRPCClient(transport: transport) - self.grpcClient = grpcClient - self.client = Com_Apple_Container_Build_V1_Builder.Client(wrapping: grpcClient) + let channel = ClientConnection(configuration: config) + self.channel = channel + self.clientAsync = BuilderClientAsync(channel: channel) + self.client = BuilderClient(channel: channel) self.group = group self.builderShimSocket = socket - self.logger = logger + } - // Start the client connection loop in a background task - self.clientTask = Task { - do { - try await grpcClient.runConnections() - } catch is CancellationError { - // Expected during graceful shutdown - re-throw - throw CancellationError() - } catch let error as RPCError where error.code == .unavailable { - // Connection closed - this is expected when the container stops - logger.debug("gRPC connection closed: \(error)") - throw error - } catch { - // Log unexpected connection errors - logger.error("gRPC client connection error: \(error)") - throw error - } - } + public func info() throws -> InfoResponse { + let resp = self.client.info(InfoRequest(), callOptions: CallOptions()) + return try resp.response.wait() } public func info() async throws -> InfoResponse { - var opts = CallOptions.defaults - opts.timeout = .seconds(30) - return try await self.client.info(InfoRequest(), options: opts) + let opts = CallOptions(timeLimit: .timeout(.seconds(30))) + return try await self.clientAsync.info(InfoRequest(), callOptions: opts) } // TODO @@ -133,23 +119,12 @@ public struct Builder: Sendable { } } + let respStream = self.clientAsync.performBuild(reqStream, callOptions: try CallOptions(config)) let pipeline = try await BuildPipeline(config) do { - try await self.client.performBuild( - metadata: try Self.buildMetadata(config), - options: .defaults, - requestProducer: { writer in - for await message in reqStream { - try await writer.write(message) - } - }, - onResponse: { response in - try await pipeline.run(sender: continuation, receiver: response.messages) - } - ) + try await pipeline.run(sender: continuation, receiver: respStream) } catch Error.buildComplete { - self.grpcClient.beginGracefulShutdown() - self.clientTask.cancel() + _ = channel.close() try await group.shutdownGracefully() return } @@ -320,48 +295,6 @@ public struct Builder: Sendable { self.pull = pull } } - - static func buildMetadata(_ config: BuildConfig) throws -> Metadata { - var metadata = Metadata() - metadata.addString(config.buildID, forKey: "build-id") - metadata.addString(URL(filePath: config.contextDir).path(percentEncoded: false), forKey: "context") - metadata.addString(config.dockerfile.base64EncodedString(), forKey: "dockerfile") - metadata.addString(config.terminal != nil ? "tty" : "plain", forKey: "progress") - metadata.addString(config.target, forKey: "target") - - if let hiddenDockerDir = config.hiddenDockerDir { - metadata.addString(hiddenDockerDir, forKey: "hidden-docker-dir") - } - for tag in config.tags { - metadata.addString(tag, forKey: "tag") - } - for platform in config.platforms { - metadata.addString(platform.description, forKey: "platforms") - } - if config.noCache { - metadata.addString("", forKey: "no-cache") - } - for label in config.labels { - metadata.addString(label, forKey: "labels") - } - for buildArg in config.buildArgs { - metadata.addString(buildArg, forKey: "build-args") - } - for (id, data) in config.secrets { - metadata.addString(id + "=" + data.base64EncodedString(), forKey: "secrets") - } - for output in config.exports { - metadata.addString(try output.stringValue, forKey: "outputs") - } - for cacheIn in config.cacheIn { - metadata.addString(cacheIn, forKey: "cache-in") - } - for cacheOut in config.cacheOut { - metadata.addString(cacheOut, forKey: "cache-out") - } - - return metadata - } } extension Builder { @@ -383,6 +316,52 @@ extension Builder { } } +extension CallOptions { + public init(_ config: Builder.BuildConfig) throws { + var headers: [(String, String)] = [ + ("build-id", config.buildID), + ("context", URL(filePath: config.contextDir).path(percentEncoded: false)), + ("dockerfile", config.dockerfile.base64EncodedString()), + ("progress", config.terminal != nil ? "tty" : "plain"), + ("target", config.target), + ] + if let hiddenDockerDir = config.hiddenDockerDir { + headers.append(("hidden-docker-dir", hiddenDockerDir)) + } + for tag in config.tags { + headers.append(("tag", tag)) + } + for platform in config.platforms { + headers.append(("platforms", platform.description)) + } + if config.noCache { + headers.append(("no-cache", "")) + } + for label in config.labels { + headers.append(("labels", label)) + } + for buildArg in config.buildArgs { + headers.append(("build-args", buildArg)) + } + for (id, data) in config.secrets { + headers.append(("secrets", id + "=" + data.base64EncodedString())) + } + for output in config.exports { + headers.append(("outputs", try output.stringValue)) + } + for cacheIn in config.cacheIn { + headers.append(("cache-in", cacheIn)) + } + for cacheOut in config.cacheOut { + headers.append(("cache-out", cacheOut)) + } + + self.init( + customMetadata: HPACKHeaders(headers) + ) + } +} + extension FileHandle { @discardableResult func setSendBufSize(_ bytes: Int) throws -> Int { @@ -425,49 +404,3 @@ extension FileHandle { } } } - -/// Buffers incoming bytes until the full gRPC HTTP/2 pipeline is configured, then replays them. -/// -/// See the equivalent in Containerization/Vminitd.swift for a full explanation. -private final class HTTP2ConnectBufferingHandler: ChannelDuplexHandler, RemovableChannelHandler { - typealias InboundIn = ByteBuffer - typealias InboundOut = ByteBuffer - typealias OutboundIn = ByteBuffer - typealias OutboundOut = ByteBuffer - - private var removalScheduled = false - private var bufferedReads: [NIOAny] = [] - - func channelRead(context: ChannelHandlerContext, data: NIOAny) { - bufferedReads.append(data) - } - - func channelReadComplete(context: ChannelHandlerContext) {} - - func flush(context: ChannelHandlerContext) { - if !removalScheduled { - removalScheduled = true - context.eventLoop.assumeIsolatedUnsafeUnchecked().execute { - context.pipeline.syncOperations.removeHandler(self, promise: nil) - } - } - context.flush() - } - - func removeHandler(context: ChannelHandlerContext, removalToken: ChannelHandlerContext.RemovalToken) { - var didRead = false - while !bufferedReads.isEmpty { - context.fireChannelRead(bufferedReads.removeFirst()) - didRead = true - } - if didRead { - context.fireChannelReadComplete() - } - context.leavePipeline(removalToken: removalToken) - } - - func channelInactive(context: ChannelHandlerContext) { - bufferedReads.removeAll() - context.fireChannelInactive() - } -} diff --git a/Sources/ContainerCommands/BuildCommand.swift b/Sources/ContainerCommands/BuildCommand.swift index 4ed22bd9..b8f633b9 100644 --- a/Sources/ContainerCommands/BuildCommand.swift +++ b/Sources/ContainerCommands/BuildCommand.swift @@ -176,7 +176,7 @@ extension Application { let fh = try await client.dial(id: "buildkit", port: vsockPort) let threadGroup: MultiThreadedEventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount) - let b = try Builder(socket: fh, group: threadGroup, logger: log) + let b = try Builder(socket: fh, group: threadGroup) // If this call succeeds, then BuildKit is running. let _ = try await b.info() diff --git a/Sources/ContainerLog/StderrLogHandler.swift b/Sources/ContainerLog/StderrLogHandler.swift index ffcd9179..69541979 100644 --- a/Sources/ContainerLog/StderrLogHandler.swift +++ b/Sources/ContainerLog/StderrLogHandler.swift @@ -46,42 +46,31 @@ public struct StderrLogHandler: LogHandler { let data: Data switch logLevel { case .debug, .trace: - let timestamp = isoTimestamp() + let timestamp = ISO8601DateFormatter().string(from: Date()) if let metadata, !metadata.isEmpty { data = - "\(timestamp) \(message.description): \(metadata.description)\n" + "\(timestamp) \(message.description): \(metadata.description)" .data(using: .utf8) ?? Data() } else { data = - "\(timestamp) \(message.description)\n" + "\(timestamp) \(message.description)" .data(using: .utf8) ?? Data() } default: if let metadata, !metadata.isEmpty { data = - "\(message.description): \(metadata.description)\n" + "\(message.description): \(metadata.description)" .data(using: .utf8) ?? Data() } else { data = - "\(message.description)\n" + message.description .data(using: .utf8) ?? Data() } } - FileHandle.standardError.write(data) - } - - private func isoTimestamp() -> String { - let date = Date() - var time = time_t(date.timeIntervalSince1970) - var ms = Int(date.timeIntervalSince1970 * 1000) % 1000 - if ms < 0 { ms += 1000 } - var tm = tm() - gmtime_r(&time, &tm) - let buf = withUnsafeTemporaryAllocation(of: CChar.self, capacity: 32) { ptr -> String in - strftime(ptr.baseAddress!, 32, "%Y-%m-%dT%H:%M:%S", &tm) - return String(cString: ptr.baseAddress!) - } - return String(format: "%@.%03dZ", buf, ms) + // Use a single write call for atomicity + var output = data + output.append("\n".data(using: .utf8)!) + FileHandle.standardError.write(output) } } diff --git a/scripts/install-hawkeye.sh b/scripts/install-hawkeye.sh index 6c7381b3..f6e7c467 100755 --- a/scripts/install-hawkeye.sh +++ b/scripts/install-hawkeye.sh @@ -17,6 +17,6 @@ if command -v .local/bin/hawkeye >/dev/null 2>&1; then echo "hawkeye already installed" else echo "Installing hawkeye" - export VERSION=v6.5.1 + export VERSION=v6.1.0 curl --proto '=https' --tlsv1.2 -LsSf https://github.com/korandoru/hawkeye/releases/download/${VERSION}/hawkeye-installer.sh | CARGO_HOME=.local sh -s -- --no-modify-path fi