Files
Vetting/internal/model/model.go
T
josh f79fe0f0db
CI / Lint + build + test (push) Successful in 1m26s
Release / release (push) Successful in 6m47s
ui: GitHub-Actions-style detail page, sub-steps, mini-tile run-view
Reshapes the detail page into a run-view: hybrid horizontal pipeline
+ expanded active-step pane with sub-steps, a per-step log pane with
line-numbered permalinks and client-side search, and a runs-history
sidebar that navigates via ?run=N. Default step is server-picked
(running → failed → Reporting) so the operator lands on the thing
that's moving.

Adds a sub_steps table + SSE topic (substep-{run}-{stage}-{ordinal})
so per-disk and per-pass work (SMART, CPUStress CPU/RAM, Storage,
GPU) is visible in the UI instead of buried in stage summary JSON.
Agent emits sub-step reports from existing per-iteration loops.

Dashboard tiles become a mini run-view with a 9-dot step strip so
the operator reads run health across the whole grid at a glance.
Register page gets the same card shell + button styling.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 19:00:11 -04:00

127 lines
3.1 KiB
Go

package model
import "time"
type Host struct {
ID int64
Name string
MAC string
WoLBroadcastIP string
WoLPort int
ExpectedSpecYAML string
PDUConfigJSON string
IPMIConfigJSON string
Notes string
CreatedAt time.Time
UpdatedAt time.Time
LastSeenAt *time.Time // host-mode agent heartbeat; nil = never seen
}
type RunState string
const (
StateRegistered RunState = "Registered"
StateQueued RunState = "Queued"
StateWaitingWoL RunState = "WaitingWoL"
StateWaitingReboot RunState = "WaitingReboot"
StateBooting RunState = "Booting"
StateInventoryCheck RunState = "InventoryCheck"
StateSpecValidate RunState = "SpecValidate"
StateSMART RunState = "SMART"
StateCPUStress RunState = "CPUStress"
StateStorage RunState = "Storage"
StateNetwork RunState = "Network"
StateGPU RunState = "GPU"
StatePSU RunState = "PSU"
StateReporting RunState = "Reporting"
StateCompleted RunState = "Completed"
StateFailed RunState = "Failed"
StateFailedHolding RunState = "FailedHolding"
StateReleased RunState = "Released"
StateCancelled RunState = "Cancelled"
)
func (s RunState) IsTerminal() bool {
switch s {
case StateCompleted, StateFailed, StateFailedHolding, StateReleased, StateCancelled:
return true
}
return false
}
type Run struct {
ID int64
HostID int64
State RunState
Result string
FailedStage string
NextBootTarget string
AgentTokenHash string
StartedAt time.Time
CompletedAt *time.Time
ReportPath string
HoldIP string
OverrideFlagsJSON string
NonDestructive bool
}
type StageState string
const (
StagePending StageState = "pending"
StageRunning StageState = "running"
StagePassed StageState = "passed"
StageFailed StageState = "failed"
StageSkipped StageState = "skipped"
)
type Stage struct {
ID int64
RunID int64
Name string
Ordinal int
State StageState
StartedAt *time.Time
CompletedAt *time.Time
SummaryJSON string
}
// SubStep is a finer-grained unit within a Stage, authored by the agent.
// Not every stage has sub-steps; those that do (CPUStress, SMART per-disk,
// Storage per-disk, GPU per-device) surface them so the UI can render a
// GitHub-Actions-style collapsible list. Sub-steps share the StageState
// enum with Stage; Ordinal is 0-based within StageName for a given RunID
// and is how the UI and SSE events key each row.
type SubStep struct {
ID int64
RunID int64
StageName string
Ordinal int
Name string
State StageState
StartedAt *time.Time
CompletedAt *time.Time
SummaryJSON string
}
type Measurement struct {
ID int64
RunID int64
StageID *int64
TS time.Time
Kind string
Key string
Value float64
Unit string
}
type SpecDiff struct {
ID int64
RunID int64
Field string
Expected string
Actual string
Severity string // critical|warning|info
Ignored bool
}