diff options
| author | Christian Cleberg <[email protected]> | 2026-03-17 23:19:43 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-03-17 23:19:43 -0500 |
| commit | 32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5 (patch) | |
| tree | ee36d421d704e508d5617d803b4c8cbdb4804fe1 /Hutch/Models/Builds.swift | |
| parent | 8f2057c53e9009c2529c9c4849c914666c0e4b40 (diff) | |
| download | hutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.tar.gz hutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.tar.bz2 hutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.zip | |
v1.0
Diffstat (limited to 'Hutch/Models/Builds.swift')
| -rw-r--r-- | Hutch/Models/Builds.swift | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/Hutch/Models/Builds.swift b/Hutch/Models/Builds.swift new file mode 100644 index 0000000..6694c35 --- /dev/null +++ b/Hutch/Models/Builds.swift @@ -0,0 +1,111 @@ +import Foundation + +// MARK: - Enums + +/// Status of a build job. +enum JobStatus: String, Codable, Sendable { + case pending = "PENDING" + case queued = "QUEUED" + case running = "RUNNING" + case success = "SUCCESS" + case failed = "FAILED" + case cancelled = "CANCELLED" + case timeout = "TIMEOUT" + + /// Whether the job can be cancelled. + var isCancellable: Bool { + switch self { + case .pending, .queued, .running: true + default: false + } + } +} + +/// Status of a single build task within a job. +enum TaskStatus: String, Codable, Sendable { + case pending = "PENDING" + case running = "RUNNING" + case success = "SUCCESS" + case failed = "FAILED" + case skipped = "SKIPPED" +} + +// MARK: - Build Task + +/// A single task within a build job. +struct BuildTask: Codable, Sendable, Identifiable { + var id: String { name } + let name: String + let status: TaskStatus + let log: BuildLog? +} + +// MARK: - Job Summary (for list view) + +/// Lightweight job model matching the fields returned by the jobs list query. +struct JobSummary: Codable, Sendable, Identifiable, Hashable { + let id: Int + let created: Date + let updated: Date + let status: JobStatus + let note: String? + let tags: [String] + let visibility: Visibility? + let image: String? + let tasks: [JobTaskSummary] + + /// Number of completed (success) tasks. + var completedTaskCount: Int { + tasks.filter { $0.status == .success }.count + } + + /// Display label: note if available, otherwise tags joined. + var displayLabel: String { + if let note, !note.isEmpty { + return note + } + if !tags.isEmpty { + return tags.joined(separator: ", ") + } + return "Job #\(id)" + } +} + +/// Minimal task info for the list query. +struct JobTaskSummary: Codable, Sendable, Hashable { + let name: String + let status: TaskStatus +} + +// MARK: - Job Detail (for detail view) + +/// Full job model with all fields for the detail view. +struct JobDetail: Codable, Sendable { + let id: Int + let created: Date + let updated: Date + let status: JobStatus + let note: String? + let tags: [String] + let visibility: Visibility? + let image: String? + let manifest: String? + let tasks: [BuildTask] + let log: BuildLog? + let owner: Entity +} + +/// The log associated with a build job. +struct BuildLog: Codable, Sendable { + let fullURL: String +} + +// MARK: - Job Group + +/// A group of related build jobs. +struct JobGroup: Codable, Sendable, Identifiable { + let id: Int + let created: Date + let note: String? + let jobs: [JobSummary] +} |
