krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v2.1: Hutch/Models/Builds.swift · raw
1import Foundation
2
3// MARK: - Enums
4
5/// Status of a build job.
6enum JobStatus: String, Codable, Sendable {
7 case pending = "PENDING"
8 case queued = "QUEUED"
9 case running = "RUNNING"
10 case success = "SUCCESS"
11 case failed = "FAILED"
12 case cancelled = "CANCELLED"
13 case timeout = "TIMEOUT"
14
15 /// Whether the job can be cancelled.
16 var isCancellable: Bool {
17 switch self {
18 case .pending, .queued, .running: true
19 default: false
20 }
21 }
22}
23
24/// Status of a single build task within a job.
25enum TaskStatus: String, Codable, Sendable {
26 case pending = "PENDING"
27 case running = "RUNNING"
28 case success = "SUCCESS"
29 case failed = "FAILED"
30 case skipped = "SKIPPED"
31}
32
33// MARK: - Build Task
34
35/// A single task within a build job.
36struct BuildTask: Codable, Sendable, Identifiable {
37 private(set) var ordinal: Int?
38 let name: String
39 let status: TaskStatus
40 let log: BuildLog?
41
42 var id: String {
43 if let ordinal {
44 return "\(ordinal):\(name)"
45 }
46 return [name, log?.fullURL, status.rawValue]
47 .compactMap { $0 }
48 .joined(separator: "::")
49 }
50
51 var logCacheKey: String {
52 id
53 }
54
55 func withOrdinal(_ ordinal: Int) -> BuildTask {
56 var task = self
57 task.ordinal = ordinal
58 return task
59 }
60
61 private enum CodingKeys: String, CodingKey {
62 case name, status, log
63 }
64}
65
66// MARK: - Job Summary (for list view)
67
68/// Lightweight job model matching the fields returned by the jobs list query.
69struct JobSummary: Codable, Sendable, Identifiable, Hashable {
70 let id: Int
71 let created: Date
72 let updated: Date
73 let status: JobStatus
74 let note: String?
75 let tags: [String]
76 let visibility: Visibility?
77 let image: String?
78 let tasks: [JobTaskSummary]
79
80 /// Number of completed (success) tasks.
81 var completedTaskCount: Int {
82 tasks.filter { $0.status == .success }.count
83 }
84
85 /// Display label: note if available, otherwise tags joined.
86 var displayLabel: String {
87 if let note, !note.isEmpty {
88 return note
89 }
90 if !tags.isEmpty {
91 return tags.joined(separator: ", ")
92 }
93 return "Job #\(id)"
94 }
95}
96
97/// Minimal task info for the list query.
98struct JobTaskSummary: Codable, Sendable, Hashable {
99 let name: String
100 let status: TaskStatus
101}
102
103// MARK: - Job Detail (for detail view)
104
105/// Full job model with all fields for the detail view.
106struct JobDetail: Codable, Sendable {
107 let id: Int
108 let created: Date
109 let updated: Date
110 let status: JobStatus
111 let note: String?
112 let tags: [String]
113 let visibility: Visibility?
114 let image: String?
115 let manifest: String?
116 var tasks: [BuildTask]
117 let log: BuildLog?
118 let owner: Entity
119}
120
121/// The log associated with a build job.
122struct BuildLog: Codable, Sendable {
123 let fullURL: String
124}
125
126// MARK: - Job Group
127
128/// A group of related build jobs.
129struct JobGroup: Codable, Sendable, Identifiable {
130 let id: Int
131 let created: Date
132 let note: String?
133 let jobs: [JobSummary]
134}