Support for Test Analytics API

This commit is contained in:
Aaron Sky 2022-06-06 20:06:56 -04:00
parent 5316ba12a7
commit 868d5dd50f
5 changed files with 180 additions and 3 deletions

View File

@ -7,8 +7,7 @@ A Swift library and client for the Buildkite REST and GraphQL APIs.
```swift
import Buildkite
let client = BuildkiteClient()
client.token = "..."
let client = BuildkiteClient(token: "...")
let response = try await client.send(.pipelines(in: "buildkite"))
let pipelines = response.content
@ -17,7 +16,7 @@ print(pipelines)
## Usage
[Getting Started](./Sources/Buildkite/Documentation.docc/Articles/GettingStarted.md)
[Getting Started](./Sources/Buildkite/Buildkite.docc/Articles/GettingStarted.md)
## References

View File

@ -26,6 +26,7 @@ The entire publicly documented REST API surface is supported by this package.
- ``Organization/Resources``
- ``Pipeline/Resources``
- ``Team/Resources``
- ``TestAnalytics/Resources``
- ``User/Resources``
- ``Followable``
- ``Resource``

View File

@ -0,0 +1,62 @@
//
// Trace.swift
// Buildkite
//
// Created by Aaron Sky on 6/5/22.
// Copyright © 2022 Aaron Sky. All rights reserved.
//
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
public struct Trace: Codable, Equatable, Identifiable {
/// a unique identifier for this test result
public var id: UUID
/// a group or topic for the test
///
/// - `Student.isEnrolled()`
public var scope: String?
/// a name or description for the test
///
/// - `Manager.isEnrolled()`
/// - `returns_boolean`
public var name: String?
/// a unique identifier for the test. If your test runner supports it, use the identifier needed to rerun this test
///
/// - `Manager.isEnrolled#returns_boolean`
public var identifier: String?
/// the file and line number where the test originates, separated by a colon (:)
///
/// - `./tests/Manager/isEnrolled.js:32`
public var location: String?
/// the file where the test originates
///
/// - `./tests/Manager/isEnrolled.js`
public var fileName: String?
/// the outcome of the test, e.g. `"passed"`, `"failed"`, `"skipped"`, or `"unknown"``
public var result: String?
/// if applicable, a short summary of why the test failed
///
/// - `Expected Boolean, got Object`
public var failureReason: String?
/// History object
public var history: Span
public struct Span: Codable, Equatable {
/// A section category for this span, e.g. `"http"`, `"sql"`, `"sleep"`, or `"annotation"`
public var section: String
/// A monotonically increasing number
public var startAt: TimeInterval?
/// A monotonically increasing number
public var endAt: TimeInterval?
/// How long the span took to run
public var duration: TimeInterval?
/// Any information related to this span
public var detail: [String: String] = [:]
/// array of span objects
public var children: [Span] = []
}
}

View File

@ -0,0 +1,79 @@
//
// TestAnalyticsUpload.swift
// Buildkite
//
// Created by Aaron Sky on 6/5/22.
// Copyright © 2022 Aaron Sky. All rights reserved.
//
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
public enum TestAnalytics {
/// Resources for requesting information about your organization's Buildkite agents.
public enum Resources {}
}
extension TestAnalytics.Resources {
/// Get metrics about agents active with the current organization.
public struct Upload: Resource {
public struct Body: Encodable {
public var format: String
public var environment: Environment
public var data: [Trace]
public struct Environment: Encodable {
public var ci: String
public var key: String
public var number: String?
public var jobId: String?
public var branch: String?
public var commitSha: String?
public var message: String?
public var url: String?
}
private enum CodingKeys: String, CodingKey {
case format
case environment = "runEnv"
case data
}
}
public struct Content: Codable, Equatable {
public var id: UUID
public var runId: UUID
public var queued: Int
public var skipped: Int
public var errors: [String]
public var runUrl: URL
}
public var version: APIVersion {
APIVersion.TestAnalytics.v1
}
public let path = "upload"
/// body of the request
public var body: Body
public init(
body: Body
) {
self.body = body
}
}
}
extension Resource where Self == TestAnalytics.Resources.Upload {
/// Get an object with properties describing Buildkite
///
/// Returns meta information about Buildkite.
public static func uploadTestAnalytics(_ data: [Trace], environment: Self.Body.Environment) -> Self {
Self(body: .init(format: "json", environment: environment, data: data))
}
}

View File

@ -0,0 +1,36 @@
//
// TestAnalyticsUploadTests.swift
// Buildkite
//
// Created by Aaron Sky on 6/6/22.
// Copyright © 2022 Aaron Sky. All rights reserved.
//
import Foundation
import XCTest
@testable import Buildkite
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
class TestAnalyticsUpload: XCTestCase {
func testTestAnalyticsUpload() async throws {
typealias Resource = TestAnalytics.Resources.Upload
let traces: [Trace] = [
.init(id: .init(), history: .init(section: "http")),
.init(id: .init(), history: .init(section: "http")),
.init(id: .init(), history: .init(section: "http")),
]
let expected = Resource.Content(id: .init(), runId: .init(), queued: 0, skipped: 0, errors: [], runUrl: .init())
let context = try MockContext(content: expected)
let response = try await context.client.send(
.uploadTestAnalytics(traces, environment: .init(ci: "buildkite", key: "test"))
)
XCTAssertEqual(expected, response.content)
}
}