diff --git a/Package.resolved b/Package.resolved index d1aabdfd4..a3aaa7b29 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "040dd2e2c8649defb737f900e4032d270935f0af91ebf4a87d64391ecd4ea40b", + "originHash" : "1b173b9865bdf3b1fc4452aff048f169490a36552511ac607718cab6143f161d", "pins" : [ { "identity" : "async-http-client", @@ -22,28 +22,46 @@ { "identity" : "dns", "kind" : "remoteSourceControl", - "location" : "https://github.com/Bouke/DNS.git", + "location" : "https://github.com/Bouke/DNS", "state" : { "revision" : "78bbd1589890a90b202d11d5f9e1297050cf0eb2", "version" : "1.2.0" } }, { - "identity" : "dnsclient", + "identity" : "grpc-swift", "kind" : "remoteSourceControl", - "location" : "https://github.com/orlandos-nl/DNSClient.git", + "location" : "https://github.com/grpc/grpc-swift.git", "state" : { - "revision" : "551fbddbf4fa728d4cd86f6a5208fe4f925f0549", + "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", + "identity" : "grpc-swift-protobuf", "kind" : "remoteSourceControl", - "location" : "https://github.com/grpc/grpc-swift.git", + "location" : "https://github.com/grpc/grpc-swift-protobuf.git", "state" : { - "revision" : "a56a157218877ef3e9625f7e1f7b2cb7e46ead1b", - "version" : "1.26.1" + "revision" : "19153231a03c2fda1f4ea60da1b92a2cb9c011d8", + "version" : "2.2.0" } }, { @@ -60,8 +78,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-argument-parser.git", "state" : { - "revision" : "309a47b2b1d9b5e991f36961c983ecec72275be3", - "version" : "1.6.1" + "revision" : "c5d11a805e765f52ba34ec7284bd4fcd6ba68615", + "version" : "1.7.0" } }, { @@ -159,8 +177,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-log.git", "state" : { - "revision" : "ce592ae52f982c847a4efc0dd881cc9eb32d29f2", - "version" : "1.6.4" + "revision" : "bbd81b6725ae874c69e9b8c8804d462356b55523", + "version" : "1.10.1" } }, { @@ -222,8 +240,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-protobuf.git", "state" : { - "revision" : "102a647b573f60f73afdce5613a51d71349fe507", - "version" : "1.30.0" + "revision" : "86970144a0b86068c81ff48ee29b3f97cae0b879", + "version" : "1.36.0" } }, { @@ -240,8 +258,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-system.git", "state" : { - "revision" : "890830fff1a577dc83134890c7984020c5f6b43b", - "version" : "1.6.2" + "revision" : "7c6ad0fc39d0763e0b699210e4124afd5041c5df", + "version" : "1.6.4" } }, { diff --git a/Package.swift b/Package.swift index 3a24b7971..d7c2db77a 100644 --- a/Package.swift +++ b/Package.swift @@ -47,16 +47,17 @@ 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.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/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/swift-server/async-http-client.git", from: "1.20.1"), .package(url: "https://github.com/swiftlang/swift-docc-plugin.git", from: "1.1.0"), ], @@ -111,10 +112,14 @@ 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", ] ), @@ -133,7 +138,9 @@ let package = Package( .product(name: "ContainerizationExtras", package: "containerization"), .product(name: "ContainerizationOS", package: "containerization"), .product(name: "ContainerizationEXT4", package: "containerization"), - .product(name: "GRPC", package: "grpc-swift"), + .product(name: "GRPCCore", package: "grpc-swift-2"), + .product(name: "GRPCNIOTransportHTTP2", package: "grpc-swift-nio-transport"), + .product(name: "GRPCProtobuf", package: "grpc-swift-protobuf"), .product(name: "Logging", package: "swift-log"), "ContainerAPIService", "ContainerAPIClient", @@ -300,7 +307,9 @@ let package = Package( dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), .product(name: "Logging", package: "swift-log"), - .product(name: "GRPC", package: "grpc-swift"), + .product(name: "GRPCCore", package: "grpc-swift-2"), + .product(name: "GRPCNIOTransportHTTP2", package: "grpc-swift-nio-transport"), + .product(name: "GRPCProtobuf", package: "grpc-swift-protobuf"), .product(name: "Containerization", package: "containerization"), "ContainerLog", "ContainerPlugin", @@ -427,7 +436,6 @@ 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 2ae284d8b..488440999 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 + @$(SWIFT) build --product protoc-gen-grpc-swift-2 .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 \ + --plugin=protoc-gen-grpc-swift=$(BUILD_BIN_DIR)/protoc-gen-grpc-swift-2 \ --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 e90a23832..b052b1042 100644 --- a/Sources/ContainerBuild/BuildAPI+Extensions.swift +++ b/Sources/ContainerBuild/BuildAPI+Extensions.swift @@ -24,10 +24,6 @@ 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 c258f22f3..7b4fc4400 100644 --- a/Sources/ContainerBuild/BuildFSSync.swift +++ b/Sources/ContainerBuild/BuildFSSync.swift @@ -20,7 +20,7 @@ import ContainerizationArchive import ContainerizationOCI import CryptoKit import Foundation -import GRPC +import GRPCCore actor BuildFSSync: BuildPipelineHandler { let contextDir: URL diff --git a/Sources/ContainerBuild/BuildImageResolver.swift b/Sources/ContainerBuild/BuildImageResolver.swift index 049598296..c2b8c50d4 100644 --- a/Sources/ContainerBuild/BuildImageResolver.swift +++ b/Sources/ContainerBuild/BuildImageResolver.swift @@ -18,7 +18,7 @@ import ContainerAPIClient import Containerization import ContainerizationOCI import Foundation -import GRPC +import GRPCCore import Logging import TerminalProgress diff --git a/Sources/ContainerBuild/BuildPipelineHandler.swift b/Sources/ContainerBuild/BuildPipelineHandler.swift index a74fc56ec..143d42ebf 100644 --- a/Sources/ContainerBuild/BuildPipelineHandler.swift +++ b/Sources/ContainerBuild/BuildPipelineHandler.swift @@ -15,7 +15,7 @@ //===----------------------------------------------------------------------===// import Foundation -import GRPC +import GRPCCore import NIO protocol BuildPipelineHandler: Sendable { @@ -35,10 +35,10 @@ public actor BuildPipeline { ] } - public func run( + public func run( sender: AsyncStream.Continuation, - receiver: GRPCAsyncResponseStream - ) async throws { + receiver: S + ) async throws where S.Element == ServerStream { 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 7b46fac76..e6cb1cbce 100644 --- a/Sources/ContainerBuild/BuildRemoteContentProxy.swift +++ b/Sources/ContainerBuild/BuildRemoteContentProxy.swift @@ -19,7 +19,7 @@ import Containerization import ContainerizationArchive import ContainerizationOCI import Foundation -import GRPC +import GRPCCore struct BuildRemoteContentProxy: BuildPipelineHandler { let local: ContentStore diff --git a/Sources/ContainerBuild/BuildStdio.swift b/Sources/ContainerBuild/BuildStdio.swift index 8df54ba70..324294802 100644 --- a/Sources/ContainerBuild/BuildStdio.swift +++ b/Sources/ContainerBuild/BuildStdio.swift @@ -16,7 +16,7 @@ import ContainerizationOS import Foundation -import GRPC +import GRPCCore import NIO actor BuildStdio: BuildPipelineHandler { diff --git a/Sources/ContainerBuild/Builder.grpc.swift b/Sources/ContainerBuild/Builder.grpc.swift index 5c39eff26..d0bdd9729 100644 --- a/Sources/ContainerBuild/Builder.grpc.swift +++ b/Sources/ContainerBuild/Builder.grpc.swift @@ -14,868 +14,1206 @@ // limitations under the License. //===----------------------------------------------------------------------===// -// // DO NOT EDIT. // swift-format-ignore-file +// swiftlint:disable all // -// Generated by the protocol buffer compiler. +// Generated by the gRPC Swift generator plugin for the protocol buffer compiler. // Source: Builder.proto // -import GRPC -import NIO -import NIOConcurrencyHelpers -import SwiftProtobuf - - -/// 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 } - - 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 +// For information on using the generated types, please see the documentation: +// https://github.com/grpc/grpc-swift + +import GRPCCore +import GRPCProtobuf + +// MARK: - com.apple.container.build.v1.Builder + +/// 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 + ] + } } -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() ?? [] - ) - } +@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") } -@available(*, deprecated) -extension Com_Apple_Container_Build_V1_BuilderClient: @unchecked Sendable {} - -@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 } } - } - - /// 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 - } -} +// MARK: com.apple.container.build.v1.Builder (server) + +@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 + + /// 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 + } -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 - } -} + /// 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 + } -/// 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 } - - 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 + /// 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 + } } -@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 var interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? { - return nil - } - - 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() ?? [] - ) - } +// 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 + ) + } + ) + } } -@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() ?? [] - ) - } - - 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() ?? [] - ) - } - - 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() ?? [] - ) - } - - 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() ?? [] - ) - } -} +// 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) + } -@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? - - public init( - channel: GRPCChannel, - defaultCallOptions: CallOptions = CallOptions(), - interceptors: Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol? = nil - ) { - self.channel = channel - self.defaultCallOptions = defaultCallOptions - self.interceptors = interceptors - } + 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) + } } -public protocol Com_Apple_Container_Build_V1_BuilderClientInterceptorFactoryProtocol: Sendable { - - /// - Returns: Interceptors to use when invoking 'createBuild'. - func makeCreateBuildInterceptors() -> [ClientInterceptor] +// 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: [:] + ) + } - /// - Returns: Interceptors to use when invoking 'performBuild'. - func makePerformBuildInterceptors() -> [ClientInterceptor] + 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 [:] + } + ) + } - /// - Returns: Interceptors to use when invoking 'info'. - func makeInfoInterceptors() -> [ClientInterceptor] + 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 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 - ) - } -} +// MARK: com.apple.container.build.v1.Builder (client) + +@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 + + /// 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 + + /// 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 + } -/// 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 + /// 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 + ) + } + } } -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 +// 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 + ) } - } -} -/// 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 -} + /// 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 + ) + } -@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 + /// 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 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] +// 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 + ) + } - /// - Returns: Interceptors to use when handling 'info'. - /// Defaults to calling `self.makeInterceptors()`. - func makeInfoInterceptors() -> [ServerInterceptor] -} + /// 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 + ) + } -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 - ) - } -} + /// 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 + ) + } +} \ No newline at end of file diff --git a/Sources/ContainerBuild/Builder.pb.swift b/Sources/ContainerBuild/Builder.pb.swift index 5d3402561..6b6c11653 100644 --- a/Sources/ContainerBuild/Builder.pb.swift +++ b/Sources/ContainerBuild/Builder.pb.swift @@ -24,7 +24,11 @@ // 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 @@ -213,7 +217,7 @@ public struct Com_Apple_Container_Build_V1_ClientStream: @unchecked Sendable { /// A unique ID for the build. public var buildID: String { - get {return _storage._buildID} + get {_storage._buildID} set {_uniqueStorage()._buildID = newValue} } @@ -314,7 +318,7 @@ public struct Com_Apple_Container_Build_V1_RunComplete: Sendable { public init() {} } -public struct Com_Apple_Container_Build_V1_BuildTransfer: @unchecked Sendable { +public struct Com_Apple_Container_Build_V1_BuildTransfer: 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. @@ -328,21 +332,21 @@ public struct Com_Apple_Container_Build_V1_BuildTransfer: @unchecked Sendable { /// The absolute path to the source from the server perspective. public var source: String { - get {return _source ?? String()} + get {_source ?? String()} set {_source = newValue} } /// Returns true if `source` has been explicitly set. - public var hasSource: Bool {return self._source != nil} + public var hasSource: Bool {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 {return _destination ?? String()} + get {_destination ?? String()} set {_destination = newValue} } /// Returns true if `destination` has been explicitly set. - public var hasDestination: Bool {return self._destination != nil} + public var hasDestination: Bool {self._destination != nil} /// Clears the value of `destination`. Subsequent reads from it will return its default value. public mutating func clearDestination() {self._destination = nil} @@ -366,7 +370,7 @@ public struct Com_Apple_Container_Build_V1_BuildTransfer: @unchecked Sendable { fileprivate var _destination: String? = nil } -public struct Com_Apple_Container_Build_V1_ImageTransfer: @unchecked Sendable { +public struct Com_Apple_Container_Build_V1_ImageTransfer: 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. @@ -383,11 +387,11 @@ public struct Com_Apple_Container_Build_V1_ImageTransfer: @unchecked Sendable { /// The descriptor for the image content. public var descriptor: Com_Apple_Container_Build_V1_Descriptor { - get {return _descriptor ?? Com_Apple_Container_Build_V1_Descriptor()} + get {_descriptor ?? Com_Apple_Container_Build_V1_Descriptor()} set {_descriptor = newValue} } /// Returns true if `descriptor` has been explicitly set. - public var hasDescriptor: Bool {return self._descriptor != nil} + public var hasDescriptor: Bool {self._descriptor != nil} /// Clears the value of `descriptor`. Subsequent reads from it will return its default value. public mutating func clearDescriptor() {self._descriptor = nil} @@ -414,7 +418,7 @@ public struct Com_Apple_Container_Build_V1_ServerStream: @unchecked Sendable { /// A unique ID for the build. public var buildID: String { - get {return _storage._buildID} + get {_storage._buildID} set {_uniqueStorage()._buildID = newValue} } @@ -481,7 +485,7 @@ public struct Com_Apple_Container_Build_V1_ServerStream: @unchecked Sendable { fileprivate var _storage = _StorageClass.defaultInstance } -public struct Com_Apple_Container_Build_V1_IO: @unchecked Sendable { +public struct Com_Apple_Container_Build_V1_IO: 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. @@ -551,11 +555,11 @@ public struct Com_Apple_Container_Build_V1_Descriptor: Sendable { public var annotations: Dictionary = [:] public var platform: Com_Apple_Container_Build_V1_Platform { - get {return _platform ?? Com_Apple_Container_Build_V1_Platform()} + get {_platform ?? Com_Apple_Container_Build_V1_Platform()} set {_platform = newValue} } /// Returns true if `platform` has been explicitly set. - public var hasPlatform: Bool {return self._platform != nil} + public var hasPlatform: Bool {self._platform != nil} /// Clears the value of `platform`. Subsequent reads from it will return its default value. public mutating func clearPlatform() {self._platform = nil} @@ -571,25 +575,15 @@ 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 = [ - 0: .same(proto: "INTO"), - 1: .same(proto: "OUTOF"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0INTO\0\u{1}OUTOF\0") } extension Com_Apple_Container_Build_V1_Stdio: SwiftProtobuf._ProtoNameProviding { - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 0: .same(proto: "STDIN"), - 1: .same(proto: "STDOUT"), - 2: .same(proto: "STDERR"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0STDIN\0\u{1}STDOUT\0\u{1}STDERR\0") } extension Com_Apple_Container_Build_V1_BuildErrorType: SwiftProtobuf._ProtoNameProviding { - public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 0: .same(proto: "BUILD_FAILED"), - 1: .same(proto: "INTERNAL"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0BUILD_FAILED\0\u{1}INTERNAL\0") } extension Com_Apple_Container_Build_V1_InfoRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { @@ -632,13 +626,7 @@ 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 = [ - 1: .standard(proto: "stage_name"), - 2: .same(proto: "tag"), - 3: .same(proto: "metadata"), - 4: .standard(proto: "build_args"), - 5: .same(proto: "debug"), - ] + 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 mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -688,10 +676,7 @@ 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 = [ - 1: .standard(proto: "build_id"), - 2: .same(proto: "metadata"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}build_id\0\u{1}metadata\0") public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -726,13 +711,7 @@ 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 = [ - 1: .standard(proto: "build_id"), - 2: .same(proto: "signal"), - 3: .same(proto: "command"), - 4: .standard(proto: "build_transfer"), - 5: .standard(proto: "image_transfer"), - ] + 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") fileprivate class _StorageClass { var _buildID: String = String() @@ -876,9 +855,7 @@ 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 = [ - 1: .same(proto: "signal"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}signal\0") public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -908,10 +885,7 @@ 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 = [ - 1: .same(proto: "id"), - 2: .same(proto: "command"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}id\0\u{1}command\0") public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -946,9 +920,7 @@ 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 = [ - 1: .same(proto: "id"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}id\0") public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -978,16 +950,7 @@ 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 = [ - 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 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 mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1056,15 +1019,7 @@ 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 = [ - 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 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 mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1128,14 +1083,7 @@ 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 = [ - 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"), - ] + 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") fileprivate class _StorageClass { var _buildID: String = String() @@ -1296,10 +1244,7 @@ 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 = [ - 1: .same(proto: "type"), - 2: .same(proto: "data"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}type\0\u{1}data\0") public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1334,10 +1279,7 @@ 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 = [ - 1: .same(proto: "type"), - 2: .same(proto: "message"), - ] + public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}type\0\u{1}message\0") public mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1372,13 +1314,7 @@ 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 = [ - 1: .same(proto: "architecture"), - 2: .same(proto: "os"), - 3: .standard(proto: "os_version"), - 4: .standard(proto: "os_features"), - 5: .same(proto: "variant"), - ] + 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 mutating func decodeMessage(decoder: inout D) throws { while let fieldNumber = try decoder.nextFieldNumber() { @@ -1428,14 +1364,7 @@ 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 = [ - 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 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 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 e069e39d0..1db86bac2 100644 --- a/Sources/ContainerBuild/Builder.swift +++ b/Sources/ContainerBuild/Builder.swift @@ -19,58 +19,72 @@ import Containerization import ContainerizationOCI import ContainerizationOS import Foundation -import GRPC +import GRPCCore +import GRPCNIOTransportHTTP2 +import Logging import NIO +import NIOCore import NIOHPACK import NIOHTTP2 +import NIOPosix public struct Builder: Sendable { public static let builderContainerId = "buildkit" - let client: BuilderClientProtocol - let clientAsync: BuilderClientAsyncProtocol + let client: Com_Apple_Container_Build_V1_Builder.Client + let grpcClient: GRPCClient let group: EventLoopGroup let builderShimSocket: FileHandle - let channel: GRPCChannel + let clientTask: Task + let logger: Logger - public init(socket: FileHandle, group: EventLoopGroup) throws { + public init(socket: FileHandle, group: EventLoopGroup, logger: Logger) throws { try socket.setSendBufSize(4 << 20) try socket.setRecvBufSize(2 << 20) - 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) + + 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 ) - config.callStartBehavior = .fastFailure - config.httpMaxFrameSize = 8 << 10 - config.maximumReceiveMessageLength = 512 << 20 - config.httpTargetWindowSize = 16 << 10 - - let channel = ClientConnection(configuration: config) - self.channel = channel - self.clientAsync = BuilderClientAsync(channel: channel) - self.client = BuilderClient(channel: channel) + + let grpcClient = GRPCClient(transport: transport) + self.grpcClient = grpcClient + self.client = Com_Apple_Container_Build_V1_Builder.Client(wrapping: grpcClient) self.group = group self.builderShimSocket = socket - } - - public func info() throws -> InfoResponse { - let resp = self.client.info(InfoRequest(), callOptions: CallOptions()) - return try resp.response.wait() + 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() async throws -> InfoResponse { - let opts = CallOptions(timeLimit: .timeout(.seconds(30))) - return try await self.clientAsync.info(InfoRequest(), callOptions: opts) + var opts = CallOptions.defaults + opts.timeout = .seconds(30) + return try await self.client.info(InfoRequest(), options: opts) } // TODO @@ -119,12 +133,23 @@ public struct Builder: Sendable { } } - let respStream = self.clientAsync.performBuild(reqStream, callOptions: try CallOptions(config)) let pipeline = try await BuildPipeline(config) do { - try await pipeline.run(sender: continuation, receiver: respStream) + 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) + } + ) } catch Error.buildComplete { - _ = channel.close() + self.grpcClient.beginGracefulShutdown() + self.clientTask.cancel() try await group.shutdownGracefully() return } @@ -289,64 +314,60 @@ public struct Builder: Sendable { self.pull = pull } } -} - -extension Builder { - enum Error: Swift.Error, CustomStringConvertible { - case invalidContinuation - case buildComplete - case invalidExport(String, String) - var description: String { - switch self { - case .invalidContinuation: - return "continuation could not created" - case .buildComplete: - return "build completed" - case .invalidExport(let exp, let reason): - return "export entry \(exp) is invalid: \(reason)" - } - } - } -} + 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") -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), - ] for tag in config.tags { - headers.append(("tag", tag)) + metadata.addString(tag, forKey: "tag") } for platform in config.platforms { - headers.append(("platforms", platform.description)) + metadata.addString(platform.description, forKey: "platforms") } if config.noCache { - headers.append(("no-cache", "")) + metadata.addString("", forKey: "no-cache") } for label in config.labels { - headers.append(("labels", label)) + metadata.addString(label, forKey: "labels") } for buildArg in config.buildArgs { - headers.append(("build-args", buildArg)) + metadata.addString(buildArg, forKey: "build-args") } for output in config.exports { - headers.append(("outputs", try output.stringValue)) + metadata.addString(try output.stringValue, forKey: "outputs") } for cacheIn in config.cacheIn { - headers.append(("cache-in", cacheIn)) + metadata.addString(cacheIn, forKey: "cache-in") } for cacheOut in config.cacheOut { - headers.append(("cache-out", cacheOut)) + metadata.addString(cacheOut, forKey: "cache-out") } - self.init( - customMetadata: HPACKHeaders(headers) - ) + return metadata + } +} + +extension Builder { + enum Error: Swift.Error, CustomStringConvertible { + case invalidContinuation + case buildComplete + case invalidExport(String, String) + + var description: String { + switch self { + case .invalidContinuation: + return "continuation could not created" + case .buildComplete: + return "build completed" + case .invalidExport(let exp, let reason): + return "export entry \(exp) is invalid: \(reason)" + } + } } } @@ -392,3 +413,49 @@ 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 372ad00fb..417673997 100644 --- a/Sources/ContainerCommands/BuildCommand.swift +++ b/Sources/ContainerCommands/BuildCommand.swift @@ -162,7 +162,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) + let b = try Builder(socket: fh, group: threadGroup, logger: log) // 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 695419794..ffcd9179e 100644 --- a/Sources/ContainerLog/StderrLogHandler.swift +++ b/Sources/ContainerLog/StderrLogHandler.swift @@ -46,31 +46,42 @@ public struct StderrLogHandler: LogHandler { let data: Data switch logLevel { case .debug, .trace: - let timestamp = ISO8601DateFormatter().string(from: Date()) + let timestamp = isoTimestamp() if let metadata, !metadata.isEmpty { data = - "\(timestamp) \(message.description): \(metadata.description)" + "\(timestamp) \(message.description): \(metadata.description)\n" .data(using: .utf8) ?? Data() } else { data = - "\(timestamp) \(message.description)" + "\(timestamp) \(message.description)\n" .data(using: .utf8) ?? Data() } default: if let metadata, !metadata.isEmpty { data = - "\(message.description): \(metadata.description)" + "\(message.description): \(metadata.description)\n" .data(using: .utf8) ?? Data() } else { data = - message.description + "\(message.description)\n" .data(using: .utf8) ?? Data() } } - // Use a single write call for atomicity - var output = data - output.append("\n".data(using: .utf8)!) - FileHandle.standardError.write(output) + 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) } } diff --git a/scripts/install-hawkeye.sh b/scripts/install-hawkeye.sh index f6e7c467f..6c7381b37 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.1.0 + export VERSION=v6.5.1 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