detached 7d997b9

fix(phases): add error handling for phase registration

- RegisterPhase now returns error for nil phases and duplicates
- main.go checks all RegisterPhase calls for errors
- prevents silent failures during phase setup
commit
7d997b9bba45c985f3bcf07d1a37bc818184501f
author
bnema · · 2025-10-26 11:23 UTC
parent
2436595
signature
unsigned
2 files · +30 -9
M cmd/archup-installer/main.go +17 -8
@@ -60,14 +60,23 @@ func main() {
6060 orchestrator := phases.NewOrchestrator(cfg, config.DefaultLogPath)
6161
6262 // Register all phases with logger
63- orchestrator.RegisterPhase(phases.NewBootstrapPhase(cfg, log))
64- orchestrator.RegisterPhase(phases.NewPreflightPhase(cfg, log))
65- orchestrator.RegisterPhase(phases.NewPartitioningPhase(cfg, log))
66- orchestrator.RegisterPhase(phases.NewBaseInstallPhase(cfg, log))
67- orchestrator.RegisterPhase(phases.NewConfigPhase(cfg, log))
68- orchestrator.RegisterPhase(phases.NewBootPhase(cfg, log))
69- orchestrator.RegisterPhase(phases.NewReposPhase(cfg, log))
70- orchestrator.RegisterPhase(phases.NewPostInstallPhase(cfg, log))
63+ phasesToRegister := []phases.Phase{
64+ phases.NewBootstrapPhase(cfg, log),
65+ phases.NewPreflightPhase(cfg, log),
66+ phases.NewPartitioningPhase(cfg, log),
67+ phases.NewBaseInstallPhase(cfg, log),
68+ phases.NewConfigPhase(cfg, log),
69+ phases.NewBootPhase(cfg, log),
70+ phases.NewReposPhase(cfg, log),
71+ phases.NewPostInstallPhase(cfg, log),
72+ }
73+
74+ for _, phase := range phasesToRegister {
75+ if err := orchestrator.RegisterPhase(phase); err != nil {
76+ fmt.Fprintf(os.Stderr, "Failed to register phase: %v\n", err)
77+ os.Exit(1)
78+ }
79+ }
7180
7281 // Create UI model
7382 model := ui.NewModel(orchestrator, cfg, version)
@@ -60,14 +60,23 @@ func main() {
60 orchestrator := phases.NewOrchestrator(cfg, config.DefaultLogPath)60 orchestrator := phases.NewOrchestrator(cfg, config.DefaultLogPath)
61 61
62 // Register all phases with logger62 // Register all phases with logger
63- orchestrator.RegisterPhase(phases.NewBootstrapPhase(cfg, log))63+ phasesToRegister := []phases.Phase{
64- orchestrator.RegisterPhase(phases.NewPreflightPhase(cfg, log))64+ phases.NewBootstrapPhase(cfg, log),
65- orchestrator.RegisterPhase(phases.NewPartitioningPhase(cfg, log))65+ phases.NewPreflightPhase(cfg, log),
66- orchestrator.RegisterPhase(phases.NewBaseInstallPhase(cfg, log))66+ phases.NewPartitioningPhase(cfg, log),
67- orchestrator.RegisterPhase(phases.NewConfigPhase(cfg, log))67+ phases.NewBaseInstallPhase(cfg, log),
68- orchestrator.RegisterPhase(phases.NewBootPhase(cfg, log))68+ phases.NewConfigPhase(cfg, log),
69- orchestrator.RegisterPhase(phases.NewReposPhase(cfg, log))69+ phases.NewBootPhase(cfg, log),
70- orchestrator.RegisterPhase(phases.NewPostInstallPhase(cfg, log))70+ phases.NewReposPhase(cfg, log),
71+ phases.NewPostInstallPhase(cfg, log),
72+ }
73+
74+ for _, phase := range phasesToRegister {
75+ if err := orchestrator.RegisterPhase(phase); err != nil {
76+ fmt.Fprintf(os.Stderr, "Failed to register phase: %v\n", err)
77+ os.Exit(1)
78+ }
79+ }
71 80
72 // Create UI model81 // Create UI model
73 model := ui.NewModel(orchestrator, cfg, version)82 model := ui.NewModel(orchestrator, cfg, version)
M internal/phases/orchestrator.go +13 -1
@@ -27,8 +27,20 @@ func NewOrchestrator(cfg *config.Config, logPath string) *Orchestrator {
2727 }
2828
2929 // RegisterPhase adds a phase to the execution sequence
30-func (o *Orchestrator) RegisterPhase(phase Phase) {
30+func (o *Orchestrator) RegisterPhase(phase Phase) error {
31+ if phase == nil {
32+ return fmt.Errorf("cannot register nil phase")
33+ }
34+
35+ // Check for duplicate phase names
36+ for _, p := range o.phases {
37+ if p.Name() == phase.Name() {
38+ return fmt.Errorf("phase %s already registered", phase.Name())
39+ }
40+ }
41+
3142 o.phases = append(o.phases, phase)
43+ return nil
3244 }
3345
3446 // Phases returns all registered phases
@@ -27,8 +27,20 @@ func NewOrchestrator(cfg *config.Config, logPath string) *Orchestrator {
27 }27 }
28 28
29 // RegisterPhase adds a phase to the execution sequence29 // RegisterPhase adds a phase to the execution sequence
30-func (o *Orchestrator) RegisterPhase(phase Phase) {30+func (o *Orchestrator) RegisterPhase(phase Phase) error {
31+ if phase == nil {
32+ return fmt.Errorf("cannot register nil phase")
33+ }
34+
35+ // Check for duplicate phase names
36+ for _, p := range o.phases {
37+ if p.Name() == phase.Name() {
38+ return fmt.Errorf("phase %s already registered", phase.Name())
39+ }
40+ }
41+
31 o.phases = append(o.phases, phase)42 o.phases = append(o.phases, phase)
43+ return nil
32 }44 }
33 45
34 // Phases returns all registered phases46 // Phases returns all registered phases

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 0

    ↑↓ moveenter openesc close