diff --git a/.gitignore b/.gitignore
index 4a519ee..5cd0309 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
.DS_Store
/.build
-/Example/.build
+/.vscode
+/Examples/.build
/Packages
/*.xcodeproj
xcuserdata/
+Package.resolved
diff --git a/.swift-format.json b/.swift-format.json
new file mode 100644
index 0000000..f83fc91
--- /dev/null
+++ b/.swift-format.json
@@ -0,0 +1,56 @@
+{
+ "fileScopedDeclarationPrivacy": {
+ "accessLevel": "private"
+ },
+ "indentation": {
+ "spaces": 4
+ },
+ "indentConditionalCompilationBlocks": false,
+ "indentSwitchCaseLabels": false,
+ "lineBreakAroundMultilineExpressionChainComponents": true,
+ "lineBreakBeforeControlFlowKeywords": false,
+ "lineBreakBeforeEachArgument": true,
+ "lineBreakBeforeEachGenericRequirement": false,
+ "lineLength": 120,
+ "maximumBlankLines": 1,
+ "prioritizeKeepingFunctionOutputTogether": true,
+ "respectsExistingLineBreaks": true,
+ "rules": {
+ "AllPublicDeclarationsHaveDocumentation": false,
+ "AlwaysUseLowerCamelCase": true,
+ "AmbiguousTrailingClosureOverload": true,
+ "BeginDocumentationCommentWithOneLineSummary": false,
+ "DoNotUseSemicolons": true,
+ "DontRepeatTypeInStaticProperties": true,
+ "FileScopedDeclarationPrivacy": true,
+ "FullyIndirectEnum": true,
+ "GroupNumericLiterals": true,
+ "IdentifiersMustBeASCII": true,
+ "NeverForceUnwrap": false,
+ "NeverUseForceTry": false,
+ "NeverUseImplicitlyUnwrappedOptionals": false,
+ "NoAccessLevelOnExtensionDeclaration": true,
+ "NoBlockComments": true,
+ "NoCasesWithOnlyFallthrough": true,
+ "NoEmptyTrailingClosureParentheses": true,
+ "NoLabelsInCasePatterns": true,
+ "NoLeadingUnderscores": false,
+ "NoParensAroundConditions": true,
+ "NoVoidReturnOnFunctionSignature": true,
+ "OneCasePerLine": true,
+ "OneVariableDeclarationPerLine": true,
+ "OnlyOneTrailingClosureArgument": true,
+ "OrderedImports": true,
+ "ReturnVoidInsteadOfEmptyTuple": true,
+ "UseEarlyExits": true,
+ "UseLetInEveryBoundCaseVariable": true,
+ "UseShorthandTypeNames": true,
+ "UseSingleLinePropertyGetter": true,
+ "UseSynthesizedInitializer": true,
+ "UseTripleSlashForDocumentationComments": true,
+ "UseWhereClausesInForLoops": true,
+ "ValidateDocumentationComments": true
+ },
+ "tabWidth": 8,
+ "version": 1
+}
diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
index 706eede..919434a 100644
--- a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
+++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
+ location = "self:">
diff --git a/Examples/graphql/GraphQLExample.swift b/Examples/graphql/GraphQLExample.swift
new file mode 100644
index 0000000..9ffe641
--- /dev/null
+++ b/Examples/graphql/GraphQLExample.swift
@@ -0,0 +1,69 @@
+//
+// main.swift
+// graphql
+//
+// Created by Aaron Sky on 5/5/20.
+//
+
+#if compiler(>=5.5.2) && canImport(_Concurrency)
+
+import Foundation
+import Combine
+import Buildkite
+
+struct MyPipeline: Codable {
+ var organization: Organization?
+
+ struct Organization: Codable {
+ var pipelines: Pipelines
+
+ struct Pipelines: Codable {
+ var edges: [PipelineEdge]
+
+ struct PipelineEdge: Codable {
+ var node: Pipeline
+
+ struct Pipeline: Codable {
+ var name: String
+ var uuid: UUID
+ }
+ }
+ }
+ }
+}
+
+@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *)
+@main struct GraphQLExample {
+ static func main() async {
+ let client = BuildkiteClient()
+ client.token = "..."
+
+ let query = """
+ query MyPipelines($first: Int!) {
+ organization(slug: "buildkite") {
+ pipelines(first: $first) {
+ edges {
+ node {
+ name
+ uuid
+ }
+ }
+ }
+ }
+ }
+ """
+
+ do {
+ let pipelines = try await client.sendQuery(GraphQL(
+ rawQuery: query,
+ variables: ["first": 30]
+ ))
+ print(pipelines)
+ } catch {
+ print(error)
+ exit(1)
+ }
+ }
+}
+
+#endif
diff --git a/Examples/graphql/main.swift b/Examples/graphql/main.swift
deleted file mode 100644
index a0c657b..0000000
--- a/Examples/graphql/main.swift
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// main.swift
-// graphql
-//
-// Created by Aaron Sky on 5/5/20.
-//
-
-import Foundation
-import Combine
-import Buildkite
-
-let client = BuildkiteClient()
-client.token = "..."
-
-let query = """
-query MyPipelines($first: Int!) {
- organization(slug: "buildkite") {
- pipelines(first: $first) {
- edges {
- node {
- name
- uuid
- }
- }
- }
- }
-}
-"""
-
-struct MyPipeline: Codable {
- var organization: Organization?
-
- struct Organization: Codable {
- var pipelines: Pipelines
-
- struct Pipelines: Codable {
- var edges: [PipelineEdge]
-
- struct PipelineEdge: Codable {
- var node: Pipeline
-
- struct Pipeline: Codable {
- var name: String
- var uuid: UUID
- }
- }
- }
- }
-}
-
-client.sendQuery(GraphQL(rawQuery: query, variables: ["first": 30])) { result in
- do {
- let pipelines = try result.get()
- print(pipelines)
- exit(0)
- } catch {
- print(error)
- exit(1)
- }
-}
-
-RunLoop.main.run()
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..74c8d27
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+SWIFT_FORMAT_BIN := swift format
+GIT_REPO_TOPLEVEL := $(shell git rev-parse --show-toplevel)
+SWIFT_FORMAT_CONFIG_FILE := $(GIT_REPO_TOPLEVEL)/.swift-format.json
+
+format:
+ $(SWIFT_FORMAT_BIN) \
+ --configuration $(SWIFT_FORMAT_CONFIG_FILE) \
+ --ignore-unparsable-files \
+ --in-place \
+ --recursive \
+ $(GIT_REPO_TOPLEVEL)/Package.swift $(GIT_REPO_TOPLEVEL)/Sources $(GIT_REPO_TOPLEVEL)/Tests
+
+lint:
+ $(SWIFT_FORMAT_BIN) lint \
+ --configuration $(SWIFT_FORMAT_CONFIG_FILE) \
+ --ignore-unparsable-files \
+ --recursive \
+ $(GIT_REPO_TOPLEVEL)/Package.swift $(GIT_REPO_TOPLEVEL)/Sources $(GIT_REPO_TOPLEVEL)/Tests
+
+test:
+ swift test --parallel --enable-code-coverage
+
+coverage: test
+ xcrun llvm-cov export \
+ -format=lcov \
+ -instr-profile=.build/arm64-apple-macosx/debug/codecov/default.profdata \
+ .build/arm64-apple-macosx/debug/BuildkitePackageTests.xctest/Contents/MacOS/BuildkitePackageTests \
+ > lcov.info
+
+.PHONY: format lint test coverage
diff --git a/Package.swift b/Package.swift
index 7ed40c6..3b64a58 100644
--- a/Package.swift
+++ b/Package.swift
@@ -8,12 +8,13 @@ let package = Package(
.iOS(.v10),
.macOS(.v10_12),
.tvOS(.v10),
- .watchOS(.v3)
+ .watchOS(.v3),
],
products: [
.library(
name: "Buildkite",
- targets: ["Buildkite"])
+ targets: ["Buildkite"]
+ )
],
targets: [
.target(
@@ -34,6 +35,13 @@ let package = Package(
.testTarget(
name: "BuildkiteTests",
dependencies: ["Buildkite"]
- )
+ ),
]
)
+
+#if swift(>=5.6)
+// Add the documentation compiler plugin if possible
+package.dependencies.append(
+ .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0")
+)
+#endif
diff --git a/Sources/Buildkite/Buildkite.docc/Buildkite.md b/Sources/Buildkite/Buildkite.docc/Buildkite.md
index b6c3362..da98d35 100644
--- a/Sources/Buildkite/Buildkite.docc/Buildkite.md
+++ b/Sources/Buildkite/Buildkite.docc/Buildkite.md
@@ -22,6 +22,7 @@ The entire publicly documented REST API surface is supported by this package.
- ``Build/Resources``
- ``Emoji/Resources``
- ``Job/Resources``
+- ``Meta/Resources``
- ``Organization/Resources``
- ``Pipeline/Resources``
- ``Team/Resources``
@@ -50,6 +51,7 @@ The entire publicly documented REST API surface is supported by this package.
- ``Build``
- ``Emoji``
- ``Job``
+- ``Meta``
- ``Organization``
- ``Pipeline``
- ``Team``
diff --git a/Sources/Buildkite/BuildkiteClient.swift b/Sources/Buildkite/BuildkiteClient.swift
index 35bf593..364a23c 100644
--- a/Sources/Buildkite/BuildkiteClient.swift
+++ b/Sources/Buildkite/BuildkiteClient.swift
@@ -47,12 +47,17 @@ public final class BuildkiteClient {
/// - Parameters:
/// - configuration: Configures supported API versions and the access token. Uses the latest supported API versions by default. See ``token`` for setting the client access token if using the default configuration.
/// - transport: Transport layer used for API communication. Uses the shared URLSession by default.
- public init(configuration: Configuration = .default, transport: Transport = URLSession.shared) {
+ public init(
+ configuration: Configuration = .default,
+ transport: Transport = URLSession.shared
+ ) {
self.configuration = configuration
self.transport = transport
}
- private func handleContentfulResponse(completion: @escaping (Result, Error>) -> Void) -> Transport.Completion {
+ private func handleContentfulResponse(
+ completion: @escaping (Result, Error>) -> Void
+ ) -> Transport.Completion {
return { [weak self] result in
guard let self = self else {
return
@@ -72,7 +77,9 @@ public final class BuildkiteClient {
}
}
- private func handleEmptyResponse(completion: @escaping (Result, Error>) -> Void) -> Transport.Completion {
+ private func handleEmptyResponse(
+ completion: @escaping (Result, Error>) -> Void
+ ) -> Transport.Completion {
return { [weak self] result in
guard let self = self else {
return
@@ -91,14 +98,16 @@ public final class BuildkiteClient {
private func checkResponseForIssues(_ response: URLResponse, data: Data? = nil) throws {
guard let httpResponse = response as? HTTPURLResponse,
- let statusCode = StatusCode(rawValue: httpResponse.statusCode) else {
- throw ResponseError.incompatibleResponse(response)
- }
+ let statusCode = StatusCode(rawValue: httpResponse.statusCode)
+ else {
+ throw ResponseError.incompatibleResponse(response)
+ }
if !statusCode.isSuccess {
guard let data = data,
- let errorIntermediary = try? decoder.decode(BuildkiteError.Intermediary.self, from: data) else {
- throw statusCode
- }
+ let errorIntermediary = try? decoder.decode(BuildkiteError.Intermediary.self, from: data)
+ else {
+ throw statusCode
+ }
throw BuildkiteError(statusCode: statusCode, intermediary: errorIntermediary)
}
}
@@ -106,12 +115,13 @@ public final class BuildkiteClient {
// MARK: - Closure API
-public extension BuildkiteClient {
+extension BuildkiteClient {
/// Performs the given resource asynchronously, then calls a handler upon completion.
/// - Parameters:
/// - resource:A resource.
/// - completion:The completion handler to call when the operation has completed. This handler is called on whatever queue the transport layer is implemented to use. You should generally assume this is happening on a global background queue, such as the case when using the shared URLSession.
- func send(_ resource: R, completion: @escaping (Result, Error>) -> Void) where R: Resource, R.Content: Decodable {
+ public func send(_ resource: R, completion: @escaping (Result, Error>) -> Void)
+ where R: Resource, R.Content: Decodable {
do {
let request = try URLRequest(resource, configuration: configuration)
transport.send(request: request, completion: handleContentfulResponse(completion: completion))
@@ -125,7 +135,11 @@ public extension BuildkiteClient {
/// - resource:A resource.
/// - pageOptions: Page options to perform pagination.
/// - completion:The completion handler to call when the operation has completed. This handler is called on whatever queue the transport layer is implemented to use. You should generally assume this is happening on a global background queue, such as the case when using the shared URLSession.
- func send(_ resource: R, pageOptions: PageOptions? = nil, completion: @escaping (Result, Error>) -> Void) where R: PaginatedResource {
+ public func send(
+ _ resource: R,
+ pageOptions: PageOptions? = nil,
+ completion: @escaping (Result, Error>) -> Void
+ ) where R: PaginatedResource {
do {
let request = try URLRequest(resource, configuration: configuration, pageOptions: pageOptions)
transport.send(request: request, completion: handleContentfulResponse(completion: completion))
@@ -138,7 +152,8 @@ public extension BuildkiteClient {
/// - Parameters:
/// - resource:A resource.
/// - completion:The completion handler to call when the operation has completed. This handler is called on whatever queue the transport layer is implemented to use. You should generally assume this is happening on a global background queue, such as the case when using the shared URLSession.
- func send(_ resource: R, completion: @escaping (Result, Error>) -> Void) where R: Resource, R.Body: Encodable, R.Content: Decodable {
+ public func send(_ resource: R, completion: @escaping (Result, Error>) -> Void)
+ where R: Resource, R.Body: Encodable, R.Content: Decodable {
do {
let request = try URLRequest(resource, configuration: configuration, encoder: encoder)
transport.send(request: request, completion: handleContentfulResponse(completion: completion))
@@ -152,9 +167,18 @@ public extension BuildkiteClient {
/// - resource:A resource.
/// - pageOptions: Page options to perform pagination.
/// - completion:The completion handler to call when the operation has completed. This handler is called on whatever queue the transport layer is implemented to use. You should generally assume this is happening on a global background queue, such as the case when using the shared URLSession.
- func send(_ resource: R, pageOptions: PageOptions? = nil, completion: @escaping (Result, Error>) -> Void) where R: PaginatedResource, R.Body: Encodable {
+ public func send(
+ _ resource: R,
+ pageOptions: PageOptions? = nil,
+ completion: @escaping (Result, Error>) -> Void
+ ) where R: PaginatedResource, R.Body: Encodable {
do {
- let request = try URLRequest(resource, configuration: configuration, encoder: encoder, pageOptions: pageOptions)
+ let request = try URLRequest(
+ resource,
+ configuration: configuration,
+ encoder: encoder,
+ pageOptions: pageOptions
+ )
transport.send(request: request, completion: handleContentfulResponse(completion: completion))
} catch {
completion(.failure(error))
@@ -165,7 +189,8 @@ public extension BuildkiteClient {
/// - Parameters:
/// - resource:A resource.
/// - completion:The completion handler to call when the operation has completed. This handler is called on whatever queue the transport layer is implemented to use. You should generally assume this is happening on a global background queue, such as the case when using the shared URLSession.
- func send(_ resource: R, completion: @escaping (Result, Error>) -> Void) where R: Resource, R.Content == Void {
+ public func send(_ resource: R, completion: @escaping (Result, Error>) -> Void)
+ where R: Resource, R.Content == Void {
do {
let request = try URLRequest(resource, configuration: configuration)
transport.send(request: request, completion: handleEmptyResponse(completion: completion))
@@ -178,7 +203,8 @@ public extension BuildkiteClient {
/// - Parameters:
/// - resource:A resource.
/// - completion:The completion handler to call when the operation has completed. This handler is called on whatever queue the transport layer is implemented to use. You should generally assume this is happening on a global background queue, such as the case when using the shared URLSession.
- func send(_ resource: R, completion: @escaping (Result, Error>) -> Void) where R: Resource, R.Body: Encodable, R.Content == Void {
+ public func send(_ resource: R, completion: @escaping (Result, Error>) -> Void)
+ where R: Resource, R.Body: Encodable, R.Content == Void {
do {
let request = try URLRequest(resource, configuration: configuration, encoder: encoder)
transport.send(request: request, completion: handleEmptyResponse(completion: completion))
@@ -191,7 +217,7 @@ public extension BuildkiteClient {
/// - Parameters:
/// - resource:A resource.
/// - completion:The completion handler to call when the operation has completed. This handler is called on whatever queue the transport layer is implemented to use. You should generally assume this is happening on a global background queue, such as the case when using the shared URLSession.
- func sendQuery(_ resource: GraphQL, completion: @escaping (Result) -> Void) {
+ public func sendQuery(_ resource: GraphQL, completion: @escaping (Result) -> Void) {
send(resource) { result in
do {
switch (try result.get()).content {
@@ -213,20 +239,21 @@ public extension BuildkiteClient {
import Combine
@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *)
-public extension BuildkiteClient {
+extension BuildkiteClient {
/// Performs the given resource and publishes the response asynchronously.
/// - Parameter resource: A resource.
/// - Returns: The publisher publishes the response when the operation completes, or terminates if the operation fails with an error.
- func sendPublisher(_ resource: R) -> AnyPublisher, Error> where R: Resource, R.Content: Decodable {
+ public func sendPublisher(_ resource: R) -> AnyPublisher, Error>
+ where R: Resource, R.Content: Decodable {
Result { try URLRequest(resource, configuration: configuration) }
- .publisher
- .flatMap(transport.sendPublisher)
- .tryMap {
- try self.checkResponseForIssues($0.response, data: $0.data)
- let content = try self.decoder.decode(R.Content.self, from: $0.data)
- return Response(content: content, response: $0.response)
- }
- .eraseToAnyPublisher()
+ .publisher
+ .flatMap(transport.sendPublisher)
+ .tryMap {
+ try self.checkResponseForIssues($0.response, data: $0.data)
+ let content = try self.decoder.decode(R.Content.self, from: $0.data)
+ return Response(content: content, response: $0.response)
+ }
+ .eraseToAnyPublisher()
}
/// Performs the given resource and publishes the response asynchronously.
@@ -234,31 +261,35 @@ public extension BuildkiteClient {
/// - resource: A resource.
/// - pageOptions: Page options to perform pagination.
/// - Returns: The publisher publishes the response when the operation completes, or terminates if the operation fails with an error.
- func sendPublisher(_ resource: R, pageOptions: PageOptions? = nil) -> AnyPublisher, Error> where R: PaginatedResource {
+ public func sendPublisher(
+ _ resource: R,
+ pageOptions: PageOptions? = nil
+ ) -> AnyPublisher, Error> where R: PaginatedResource {
Result { try URLRequest(resource, configuration: configuration, pageOptions: pageOptions) }
- .publisher
- .flatMap(transport.sendPublisher)
- .tryMap {
- try self.checkResponseForIssues($0.response, data: $0.data)
- let content = try self.decoder.decode(R.Content.self, from: $0.data)
- return Response(content: content, response: $0.response)
- }
- .eraseToAnyPublisher()
+ .publisher
+ .flatMap(transport.sendPublisher)
+ .tryMap {
+ try self.checkResponseForIssues($0.response, data: $0.data)
+ let content = try self.decoder.decode(R.Content.self, from: $0.data)
+ return Response(content: content, response: $0.response)
+ }
+ .eraseToAnyPublisher()
}
/// Performs the given resource and publishes the response asynchronously.
/// - Parameter resource: A resource.
/// - Returns: The publisher publishes the response when the operation completes, or terminates if the operation fails with an error.
- func sendPublisher(_ resource: R) -> AnyPublisher, Error> where R: Resource, R.Body: Encodable, R.Content: Decodable {
+ public func sendPublisher(_ resource: R) -> AnyPublisher, Error>
+ where R: Resource, R.Body: Encodable, R.Content: Decodable {
Result { try URLRequest(resource, configuration: configuration, encoder: encoder) }
- .publisher
- .flatMap(transport.sendPublisher)
- .tryMap {
- try self.checkResponseForIssues($0.response, data: $0.data)
- let content = try self.decoder.decode(R.Content.self, from: $0.data)
- return Response(content: content, response: $0.response)
- }
- .eraseToAnyPublisher()
+ .publisher
+ .flatMap(transport.sendPublisher)
+ .tryMap {
+ try self.checkResponseForIssues($0.response, data: $0.data)
+ let content = try self.decoder.decode(R.Content.self, from: $0.data)
+ return Response(content: content, response: $0.response)
+ }
+ .eraseToAnyPublisher()
}
/// Performs the given resource and publishes the response asynchronously.
@@ -266,50 +297,55 @@ public extension BuildkiteClient {
/// - resource: A resource.
/// - pageOptions: Page options to perform pagination.
/// - Returns: The publisher publishes the response when the operation completes, or terminates if the operation fails with an error.
- func sendPublisher(_ resource: R, pageOptions: PageOptions? = nil) -> AnyPublisher, Error> where R: PaginatedResource, R.Body: Encodable {
+ public func sendPublisher(
+ _ resource: R,
+ pageOptions: PageOptions? = nil
+ ) -> AnyPublisher, Error> where R: PaginatedResource, R.Body: Encodable {
Result { try URLRequest(resource, configuration: configuration, encoder: encoder, pageOptions: pageOptions) }
- .publisher
- .flatMap(transport.sendPublisher)
- .tryMap {
- try self.checkResponseForIssues($0.response, data: $0.data)
- let content = try self.decoder.decode(R.Content.self, from: $0.data)
- return Response(content: content, response: $0.response)
- }
- .eraseToAnyPublisher()
+ .publisher
+ .flatMap(transport.sendPublisher)
+ .tryMap {
+ try self.checkResponseForIssues($0.response, data: $0.data)
+ let content = try self.decoder.decode(R.Content.self, from: $0.data)
+ return Response(content: content, response: $0.response)
+ }
+ .eraseToAnyPublisher()
}
/// Performs the given resource and publishes the response asynchronously.
/// - Parameter resource: A resource.
/// - Returns: The publisher publishes the response when the operation completes, or terminates if the operation fails with an error.
- func sendPublisher(_ resource: R) -> AnyPublisher, Error> where R: Resource, R.Content == Void {
+ public func sendPublisher(_ resource: R) -> AnyPublisher, Error>
+ where R: Resource, R.Content == Void {
Result { try URLRequest(resource, configuration: configuration) }
- .publisher
- .flatMap(transport.sendPublisher)
- .tryMap {
- try self.checkResponseForIssues($0.response)
- return Response(content: (), response: $0.response)
- }
- .eraseToAnyPublisher()
+ .publisher
+ .flatMap(transport.sendPublisher)
+ .tryMap {
+ try self.checkResponseForIssues($0.response)
+ return Response(content: (), response: $0.response)
+ }
+ .eraseToAnyPublisher()
}
/// Performs the given resource and publishes the response asynchronously.
/// - Parameter resource: A resource.
/// - Returns: The publisher publishes the response when the operation completes, or terminates if the operation fails with an error.
- func sendPublisher(_ resource: R) -> AnyPublisher, Error> where R: Resource, R.Body: Encodable, R.Content == Void {
+ public func sendPublisher(_ resource: R) -> AnyPublisher, Error>
+ where R: Resource, R.Body: Encodable, R.Content == Void {
Result { try URLRequest(resource, configuration: configuration, encoder: encoder) }
- .publisher
- .flatMap(transport.sendPublisher)
- .tryMap {
- try self.checkResponseForIssues($0.response)
- return Response(content: (), response: $0.response)
- }
- .eraseToAnyPublisher()
+ .publisher
+ .flatMap(transport.sendPublisher)
+ .tryMap {
+ try self.checkResponseForIssues($0.response)
+ return Response(content: (), response: $0.response)
+ }
+ .eraseToAnyPublisher()
}
/// Performs the given GraphQL query or mutation and publishes the content asynchronously.
/// - Parameter resource: A resource.
/// - Returns: The publisher publishes the content when the operation completes, or terminates if the operation fails with an error.
- func sendQueryPublisher(_ resource: GraphQL) -> AnyPublisher {
+ public func sendQueryPublisher(_ resource: GraphQL) -> AnyPublisher {
sendPublisher(resource)
.map(\.content)
.tryMap { try $0.get() }
@@ -323,11 +359,11 @@ public extension BuildkiteClient {
// MARK: - Async/Await API
@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *)
-public extension BuildkiteClient {
+extension BuildkiteClient {
/// Performs the given resource asynchronously.
/// - Parameter resource: A resource.
/// - Returns: A response containing the content of the response body, as well as other information about the HTTP operation.
- func send(_ resource: R) async throws -> Response where R: Resource, R.Content: Decodable {
+ public func send(_ resource: R) async throws -> Response where R: Resource, R.Content: Decodable {
let request = try URLRequest(resource, configuration: configuration)
let (data, response) = try await transport.send(request: request)
try checkResponseForIssues(response, data: data)
@@ -340,7 +376,8 @@ public extension BuildkiteClient {
/// - resource: A resource.
/// - pageOptions: Page options to perform pagination.
/// - Returns: A response containing the content of the response body, as well as other information about the HTTP operation.
- func send(_ resource: R, pageOptions: PageOptions? = nil) async throws -> Response where R: PaginatedResource {
+ public func send(_ resource: R, pageOptions: PageOptions? = nil) async throws -> Response
+ where R: PaginatedResource {
let request = try URLRequest(resource, configuration: configuration, pageOptions: pageOptions)
let (data, response) = try await transport.send(request: request)
try checkResponseForIssues(response, data: data)
@@ -351,7 +388,8 @@ public extension BuildkiteClient {
/// Performs the given resource asynchronously.
/// - Parameter resource: A resource.
/// - Returns: A response containing the content of the response body, as well as other information about the HTTP operation.
- func send(_ resource: R) async throws -> Response where R: Resource, R.Body: Encodable, R.Content: Decodable {
+ public func send(_ resource: R) async throws -> Response
+ where R: Resource, R.Body: Encodable, R.Content: Decodable {
let request = try URLRequest(resource, configuration: configuration, encoder: encoder)
let (data, response) = try await transport.send(request: request)
try checkResponseForIssues(response, data: data)
@@ -364,7 +402,8 @@ public extension BuildkiteClient {
/// - resource: A resource.
/// - pageOptions: Page options to perform pagination.
/// - Returns: A response containing the content of the response body, as well as other information about the HTTP operation.
- func send(_ resource: R, pageOptions: PageOptions? = nil) async throws -> Response where R: PaginatedResource, R.Body: Encodable {
+ public func send(_ resource: R, pageOptions: PageOptions? = nil) async throws -> Response
+ where R: PaginatedResource, R.Body: Encodable {
let request = try URLRequest(resource, configuration: configuration, encoder: encoder, pageOptions: pageOptions)
let (data, response) = try await transport.send(request: request)
@@ -376,7 +415,7 @@ public extension BuildkiteClient {
/// Performs the given resource asynchronously.
/// - Parameter resource: A resource.
/// - Returns: A response containing the content of the response body, as well as other information about the HTTP operation.
- func send(_ resource: R) async throws -> Response where R: Resource, R.Content == Void {
+ public func send(_ resource: R) async throws -> Response where R: Resource, R.Content == Void {
let request = try URLRequest(resource, configuration: configuration)
let (data, response) = try await transport.send(request: request)
try checkResponseForIssues(response, data: data)
@@ -386,7 +425,8 @@ public extension BuildkiteClient {
/// Performs the given resource asynchronously.
/// - Parameter resource: A resource.
/// - Returns: A response containing information about the HTTP operation, and no content.
- func send(_ resource: R) async throws -> Response where R: Resource, R.Body: Encodable, R.Content == Void {
+ public func send(_ resource: R) async throws -> Response
+ where R: Resource, R.Body: Encodable, R.Content == Void {
let request = try URLRequest(resource, configuration: configuration, encoder: encoder)
let (data, response) = try await transport.send(request: request)
try checkResponseForIssues(response, data: data)
@@ -397,7 +437,7 @@ public extension BuildkiteClient {
/// - Parameter resource: A resource.
/// - Returns: Content of the resolved GraphQL operation.
/// - Throws: An error either of type ``BuildkiteError`` or ``GraphQL/Errors``.
- func sendQuery(_ resource: GraphQL) async throws -> T {
+ public func sendQuery(_ resource: GraphQL) async throws -> T {
let response = try await send(resource)
return try response.content.get()
}
diff --git a/Sources/Buildkite/Models/Job.swift b/Sources/Buildkite/Models/Job.swift
index bd85e40..75e1e8a 100644
--- a/Sources/Buildkite/Models/Job.swift
+++ b/Sources/Buildkite/Models/Job.swift
@@ -25,7 +25,9 @@ public enum Job: Codable, Equatable {
case trigger
}
- public init(from decoder: Decoder) throws {
+ public init(
+ from decoder: Decoder
+ ) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(Unassociated.self, forKey: .type)
switch type {
diff --git a/Sources/Buildkite/Models/Meta.swift b/Sources/Buildkite/Models/Meta.swift
new file mode 100644
index 0000000..d2f97ff
--- /dev/null
+++ b/Sources/Buildkite/Models/Meta.swift
@@ -0,0 +1,29 @@
+//
+// Meta.swift
+// Buildkite
+//
+// Created by Aaron Sky on 5/29/22.
+// Copyright © 2022 Aaron Sky. All rights reserved.
+//
+
+import Foundation
+
+#if canImport(FoundationNetworking)
+import FoundationNetworking
+#endif
+
+public struct Meta: Codable, Equatable {
+ /// A list of IP addresses in CIDR notation that Buildkite uses to
+ /// send outbound traffic such as webhooks and commit statuses.
+ /// These are subject to change from time to time.
+ ///
+ /// Buildkite recommends checking for new addresses daily, and
+ /// will try to advertise new addresses for at least 7 days
+ /// before they are used.
+ public var webhookIPRanges: [String]
+
+ private enum CodingKeys: String, CodingKey {
+ // This corresponds to the key "webhook_ips" from the Buildkite payload.
+ case webhookIPRanges = "webhookIps"
+ }
+}
diff --git a/Sources/Buildkite/Models/Pipeline.swift b/Sources/Buildkite/Models/Pipeline.swift
index 88915bc..c5dce68 100644
--- a/Sources/Buildkite/Models/Pipeline.swift
+++ b/Sources/Buildkite/Models/Pipeline.swift
@@ -93,7 +93,9 @@ extension Pipeline {
case trigger
}
- public init(from decoder: Decoder) throws {
+ public init(
+ from decoder: Decoder
+ ) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(Unassociated.self, forKey: .type)
switch type {
diff --git a/Sources/Buildkite/Networking/APIVersion.swift b/Sources/Buildkite/Networking/APIVersion.swift
index 9586551..50d88ad 100644
--- a/Sources/Buildkite/Networking/APIVersion.swift
+++ b/Sources/Buildkite/Networking/APIVersion.swift
@@ -26,7 +26,10 @@ public struct APIVersion: Equatable {
public let baseURL: URL
public let version: String
- init(baseURL: URL, version: String) {
+ init(
+ baseURL: URL,
+ version: String
+ ) {
self.baseURL = baseURL
self.version = version
}
diff --git a/Sources/Buildkite/Networking/Configuration.swift b/Sources/Buildkite/Networking/Configuration.swift
index 01c0235..a97bb8c 100644
--- a/Sources/Buildkite/Networking/Configuration.swift
+++ b/Sources/Buildkite/Networking/Configuration.swift
@@ -18,11 +18,16 @@ public struct Configuration {
public var graphQLVersion: APIVersion
public static var `default`: Configuration {
- .init(version: APIVersion.REST.v2,
- graphQLVersion: APIVersion.GraphQL.v1)
+ .init(
+ version: APIVersion.REST.v2,
+ graphQLVersion: APIVersion.GraphQL.v1
+ )
}
- public init(version: APIVersion = APIVersion.REST.v2, graphQLVersion: APIVersion = APIVersion.GraphQL.v1) {
+ public init(
+ version: APIVersion = APIVersion.REST.v2,
+ graphQLVersion: APIVersion = APIVersion.GraphQL.v1
+ ) {
self.version = version
self.graphQLVersion = graphQLVersion
}
diff --git a/Sources/Buildkite/Networking/Formatters.swift b/Sources/Buildkite/Networking/Formatters.swift
index cd9dbc8..63e0850 100644
--- a/Sources/Buildkite/Networking/Formatters.swift
+++ b/Sources/Buildkite/Networking/Formatters.swift
@@ -49,7 +49,12 @@ enum Formatters {
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
guard let date = dateIfPossible(fromISO8601: dateString) else {
- throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: container.codingPath, debugDescription: "Expected date string to be ISO8601-formatted."))
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: container.codingPath,
+ debugDescription: "Expected date string to be ISO8601-formatted."
+ )
+ )
}
return date
}
diff --git a/Sources/Buildkite/Networking/JSONValue.swift b/Sources/Buildkite/Networking/JSONValue.swift
index d251e16..f34a102 100644
--- a/Sources/Buildkite/Networking/JSONValue.swift
+++ b/Sources/Buildkite/Networking/JSONValue.swift
@@ -24,12 +24,12 @@ public enum JSONValue {
indirect case object([String: JSONValue])
}
-public extension JSONValue {
- subscript(dynamicMember key: JSONValue) -> JSONValue? {
+extension JSONValue {
+ public subscript(dynamicMember key: JSONValue) -> JSONValue? {
self[key]
}
- subscript(_ key: JSONValue) -> JSONValue? {
+ public subscript(_ key: JSONValue) -> JSONValue? {
if case let .number(key) = key {
return self[Int(key)]
} else if case let .string(key) = key {
@@ -38,14 +38,14 @@ public extension JSONValue {
return nil
}
- subscript(_ index: Int) -> JSONValue? {
+ public subscript(_ index: Int) -> JSONValue? {
guard case let .array(array) = self else {
return nil
}
return array[index]
}
- subscript(_ key: String) -> JSONValue? {
+ public subscript(_ key: String) -> JSONValue? {
guard case let .object(object) = self else {
return nil
}
@@ -76,7 +76,9 @@ extension JSONValue: Encodable {
}
extension JSONValue: Decodable {
- public init(from decoder: Decoder) throws {
+ public init(
+ from decoder: Decoder
+ ) throws {
let singleValueContainer = try decoder.singleValueContainer()
if singleValueContainer.decodeNil() {
@@ -94,49 +96,64 @@ extension JSONValue: Decodable {
} else {
throw DecodingError.dataCorruptedError(
in: singleValueContainer,
- debugDescription: "invalid JSON structure or the input was not JSON")
+ debugDescription: "invalid JSON structure or the input was not JSON"
+ )
}
}
}
extension JSONValue: ExpressibleByNilLiteral {
- public init(nilLiteral: Void) {
+ public init(
+ nilLiteral: Void
+ ) {
self = .null
}
}
extension JSONValue: ExpressibleByBooleanLiteral {
- public init(booleanLiteral value: BooleanLiteralType) {
+ public init(
+ booleanLiteral value: BooleanLiteralType
+ ) {
self = .bool(value)
}
}
extension JSONValue: ExpressibleByIntegerLiteral {
- public init(integerLiteral value: IntegerLiteralType) {
+ public init(
+ integerLiteral value: IntegerLiteralType
+ ) {
self = .number(Double(value))
}
}
extension JSONValue: ExpressibleByFloatLiteral {
- public init(floatLiteral value: FloatLiteralType) {
+ public init(
+ floatLiteral value: FloatLiteralType
+ ) {
self = .number(value)
}
}
extension JSONValue: ExpressibleByStringLiteral {
- public init(stringLiteral value: StringLiteralType) {
+ public init(
+ stringLiteral value: StringLiteralType
+ ) {
self = .string(value)
}
}
extension JSONValue: ExpressibleByArrayLiteral {
- public init(arrayLiteral elements: JSONValue...) {
+ public init(
+ arrayLiteral elements: JSONValue...
+ ) {
self = .array(elements)
}
}
extension JSONValue: ExpressibleByDictionaryLiteral {
- public init(dictionaryLiteral elements: (String, JSONValue)...) {
+ public init(
+ dictionaryLiteral elements: (String, JSONValue)...
+ ) {
self = .object(Dictionary(uniqueKeysWithValues: elements))
}
}
diff --git a/Sources/Buildkite/Networking/Pagination.swift b/Sources/Buildkite/Networking/Pagination.swift
index c380560..f01e78c 100644
--- a/Sources/Buildkite/Networking/Pagination.swift
+++ b/Sources/Buildkite/Networking/Pagination.swift
@@ -18,13 +18,16 @@ public struct Page {
public var firstPage: Int?
public var lastPage: Int?
- init?(for header: String) {
+ init?(
+ for header: String
+ ) {
guard !header.isEmpty else {
return nil
}
for link in header.split(separator: ",") {
- let segments = link
+ let segments =
+ link
.trimmingCharacters(in: .whitespacesAndNewlines)
.split(separator: ";")
guard
@@ -36,8 +39,9 @@ public struct Page {
let url = URLComponents(string: String(urlString.dropFirst().dropLast())),
let pageString = url.queryItems?.first(where: { $0.name == "page" })?.value,
- let page = Int(pageString) else {
- continue
+ let page = Int(pageString)
+ else {
+ continue
}
for segment in segments.dropFirst() {
@@ -62,7 +66,10 @@ public struct PageOptions {
public var page: Int
public var perPage: Int
- public init(page: Int, perPage: Int) {
+ public init(
+ page: Int,
+ perPage: Int
+ ) {
self.page = page
self.perPage = perPage
}
@@ -71,8 +78,9 @@ public struct PageOptions {
extension URLRequest {
mutating func appendPageOptions(_ options: PageOptions) {
guard let url = self.url,
- var components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
- return
+ var components = URLComponents(url: url, resolvingAgainstBaseURL: true)
+ else {
+ return
}
var queryItems = components.queryItems ?? []
queryItems.append(pageOptions: options)
@@ -81,8 +89,8 @@ extension URLRequest {
}
}
-private extension Array where Element == URLQueryItem {
- mutating func append(pageOptions: PageOptions) {
+extension Array where Element == URLQueryItem {
+ fileprivate mutating func append(pageOptions: PageOptions) {
append(URLQueryItem(name: "page", value: String(pageOptions.page)))
append(URLQueryItem(name: "per_page", value: String(pageOptions.perPage)))
}
diff --git a/Sources/Buildkite/Networking/Resource.swift b/Sources/Buildkite/Networking/Resource.swift
index 0d4bb6c..76b9832 100644
--- a/Sources/Buildkite/Networking/Resource.swift
+++ b/Sources/Buildkite/Networking/Resource.swift
@@ -43,11 +43,16 @@ extension Resource where Body == Void {
public protocol PaginatedResource: Resource where Content: Decodable {}
extension URLRequest {
- init(_ resource: R, configuration: Configuration) throws {
+ init(
+ _ resource: R,
+ configuration: Configuration
+ ) throws {
let version = resource.version
- guard version == configuration.version
- || version == configuration.graphQLVersion else {
- throw ResourceError.incompatibleVersion(version)
+ guard
+ version == configuration.version
+ || version == configuration.graphQLVersion
+ else {
+ throw ResourceError.incompatibleVersion(version)
}
let url = version.url(for: resource.path)
@@ -58,19 +63,32 @@ extension URLRequest {
self = request
}
- init(_ resource: R, configuration: Configuration, encoder: JSONEncoder) throws where R.Body: Encodable {
+ init(
+ _ resource: R,
+ configuration: Configuration,
+ encoder: JSONEncoder
+ ) throws where R.Body: Encodable {
try self.init(resource, configuration: configuration)
httpBody = try encoder.encode(resource.body)
}
- init(_ resource: R, configuration: Configuration, pageOptions: PageOptions? = nil) throws {
+ init(
+ _ resource: R,
+ configuration: Configuration,
+ pageOptions: PageOptions? = nil
+ ) throws {
try self.init(resource, configuration: configuration)
if let options = pageOptions {
appendPageOptions(options)
}
}
- init(_ resource: R, configuration: Configuration, encoder: JSONEncoder, pageOptions: PageOptions? = nil) throws where R.Body: Encodable {
+ init(
+ _ resource: R,
+ configuration: Configuration,
+ encoder: JSONEncoder,
+ pageOptions: PageOptions? = nil
+ ) throws where R.Body: Encodable {
try self.init(resource, configuration: configuration, encoder: encoder)
if let options = pageOptions {
appendPageOptions(options)
diff --git a/Sources/Buildkite/Networking/Response.swift b/Sources/Buildkite/Networking/Response.swift
index d6eb7e5..388e57f 100644
--- a/Sources/Buildkite/Networking/Response.swift
+++ b/Sources/Buildkite/Networking/Response.swift
@@ -17,7 +17,10 @@ public struct Response {
public let response: URLResponse
public let page: Page?
- init(content: T, response: URLResponse) {
+ init(
+ content: T,
+ response: URLResponse
+ ) {
self.content = content
self.response = response
if let response = response as? HTTPURLResponse, let link = response.allHeaderFields["Link"] as? String {
@@ -37,7 +40,10 @@ public struct BuildkiteError: Error {
public var message: String
public var errors: [String]
- init(statusCode: StatusCode, intermediary: Intermediary) {
+ init(
+ statusCode: StatusCode,
+ intermediary: Intermediary
+ ) {
self.statusCode = statusCode
self.message = intermediary.message ?? ""
self.errors = intermediary.errors ?? []
diff --git a/Sources/Buildkite/Networking/Transport.swift b/Sources/Buildkite/Networking/Transport.swift
index 8f16135..7eea91d 100644
--- a/Sources/Buildkite/Networking/Transport.swift
+++ b/Sources/Buildkite/Networking/Transport.swift
@@ -26,15 +26,15 @@ public protocol Transport {
func send(request: URLRequest, completion: @escaping Completion)
-#if canImport(Combine)
+ #if canImport(Combine)
@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *)
func sendPublisher(request: URLRequest) -> AnyPublisher