From 32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Tue, 17 Mar 2026 23:19:43 -0500 Subject: v1.0 --- Hutch/Models/Builds.swift | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 Hutch/Models/Builds.swift (limited to 'Hutch/Models/Builds.swift') 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] +} -- cgit v1.2.3