gitbay/Builds/BuildModels.swift
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}