gitbay/Builds/BuildModels.swift

v1.6.0
gitbay-ios/gitbay/Builds/BuildModels.swift history · blame · raw

71 lines · 2163 bytes

 1import Foundation
 2import SwiftUI
 3
 4/// One row of `build list`.
 5nonisolated struct Build: Decodable, Sendable, Hashable, Identifiable {
 6    let number: Int64
 7    let job: String
 8    let status: String
 9    let sha: String
10    let ref: String
11    let createdAt: Date
12    let finishedAt: Date?
13    /// The built commit's subject, which `build list` resolves since
14    /// gitbay v1.33.0. Absent when the commit is gone.
15    let subject: String?
16
17    enum CodingKeys: String, CodingKey {
18        case number, job, status, sha, ref, subject
19        case createdAt = "created_at"
20        case finishedAt = "finished_at"
21    }
22
23    var id: Int64 { number }
24    var shortSHA: String { String(sha.prefix(10)) }
25    /// What a row leads with. A sha alone does not say what was built
26    /// (krz/gitbay#241).
27    var title: String {
28        if let subject, !subject.isEmpty { return "#\(number) \(subject)" }
29        return "#\(number) \(shortSHA)"
30    }
31}
32
33/// `build jobs` — what a trigger can name. A repo with no CI config has
34/// none, which is an empty state rather than an error.
35nonisolated struct CIJob: Decodable, Sendable, Hashable, Identifiable {
36    let name: String
37    let schedule: String?
38    let tags: String?
39
40    var id: String { name }
41
42    /// Why this job runs, in the words the server uses.
43    var trigger: String {
44        if let schedule, !schedule.isEmpty { return "schedule \(schedule)" }
45        if let tags, !tags.isEmpty { return "tags \(tags)" }
46        return "on push"
47    }
48}
49
50extension Build {
51    /// The list row and the detail header must agree on what a status
52    /// looks like; the strings come from the registry.
53    var statusIcon: String {
54        switch status {
55        case "success": "checkmark.circle.fill"
56        case "failure", "error": "xmark.circle.fill"
57        case "running": "circle.dotted"
58        case "queued", "pending": "clock"
59        default: "questionmark.circle"
60        }
61    }
62
63    var statusColor: Color {
64        switch status {
65        case "success": .gbOK
66        case "failure", "error": .gbBad
67        case "running", "queued", "pending": .gbWarn
68        default: .secondary
69        }
70    }
71}