Skip to content

Commit 6fbe139

Browse files
committed
refactor(installer): remove dead runCustomInstall and runInteractiveInstall; migrate tests to Plan/Apply
Both functions were unreachable from production code — runInstall now goes entirely through Plan() → Apply(). Deleted 165 lines of dead code. Migrated all 6 test call sites: - TestRunCustomInstall_IncludesCasksInSelectedPkgs: deleted (covered by TestRunInstall_DryRunRemoteConfig which already asserts SelectedPkgs via runInstall) - TestRunInteractiveInstall_HardFailOnBrew: renamed and rewritten to call runInstall - 4 TestRunCustomInstall_* tests: rewritten to call Plan()+Apply(NopReporter{}); PackagesOnly:true added where tests override HOME and are not testing git config
1 parent d2a3e98 commit 6fbe139

2 files changed

Lines changed: 30 additions & 216 deletions

File tree

internal/installer/installer.go

Lines changed: 0 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -209,171 +209,6 @@ func checkDependencies(opts *config.InstallOptions, st *config.InstallState) err
209209
return nil
210210
}
211211

212-
func runCustomInstall(opts *config.InstallOptions, st *config.InstallState) error {
213-
ui.Info(fmt.Sprintf("Custom config: @%s/%s", st.RemoteConfig.Username, st.RemoteConfig.Slug))
214-
215-
if len(st.RemoteConfig.Taps) > 0 {
216-
ui.Info(fmt.Sprintf("Adding %d taps, installing %d packages...", len(st.RemoteConfig.Taps), len(st.RemoteConfig.Packages)))
217-
} else {
218-
ui.Info(fmt.Sprintf("Installing %d packages...", len(st.RemoteConfig.Packages)))
219-
}
220-
fmt.Println()
221-
222-
formulaeCount := len(st.RemoteConfig.Packages)
223-
caskCount := len(st.RemoteConfig.Casks)
224-
npmCount := len(st.RemoteConfig.Npm)
225-
totalPackages := formulaeCount + caskCount + npmCount
226-
227-
minutes := estimateInstallMinutes(formulaeCount, caskCount, npmCount)
228-
ui.Info(fmt.Sprintf("Estimated install time: ~%d min for %d packages", minutes, totalPackages))
229-
fmt.Println()
230-
231-
printPackageList("CLI tools", st.RemoteConfig.Packages)
232-
printPackageList("Apps", st.RemoteConfig.Casks)
233-
printPackageList("npm", st.RemoteConfig.Npm)
234-
fmt.Println()
235-
236-
if !opts.Silent && !opts.DryRun {
237-
proceed, err := ui.Confirm("Install these packages?", true)
238-
if err != nil {
239-
return err
240-
}
241-
if !proceed {
242-
return ErrUserCancelled
243-
}
244-
fmt.Println()
245-
}
246-
247-
if len(st.RemoteConfig.Taps) > 0 {
248-
if err := brew.InstallTaps(st.RemoteConfig.Taps, opts.DryRun); err != nil {
249-
ui.Warn(fmt.Sprintf("Some taps failed: %v", err))
250-
}
251-
fmt.Println()
252-
}
253-
254-
st.SelectedPkgs = make(map[string]bool)
255-
for _, pkg := range st.RemoteConfig.Packages {
256-
st.SelectedPkgs[pkg.Name] = true
257-
}
258-
for _, cask := range st.RemoteConfig.Casks {
259-
st.SelectedPkgs[cask.Name] = true
260-
}
261-
262-
if err := stepInstallPackages(opts, st); err != nil {
263-
return err
264-
}
265-
266-
var softErrs []error
267-
268-
if len(st.RemoteConfig.Npm) > 0 {
269-
if err := stepInstallNpmWithRetry(opts, st); err != nil {
270-
ui.Error(fmt.Sprintf("npm package installation failed: %v", err))
271-
softErrs = append(softErrs, fmt.Errorf("npm: %w", err))
272-
}
273-
}
274-
275-
if st.RemoteConfig.DotfilesRepo != "" {
276-
opts.DotfilesURL = st.RemoteConfig.DotfilesRepo
277-
}
278-
279-
if err := stepShell(opts, st); err != nil {
280-
ui.Error(fmt.Sprintf("Shell setup failed: %v", err))
281-
softErrs = append(softErrs, fmt.Errorf("shell: %w", err))
282-
}
283-
284-
if err := stepDotfiles(opts, st); err != nil {
285-
ui.Error(fmt.Sprintf("Dotfiles setup failed: %v", err))
286-
softErrs = append(softErrs, fmt.Errorf("dotfiles: %w", err))
287-
}
288-
289-
// If dotfiles were applied, .zshrc is managed by dotfiles.
290-
// If no dotfiles, stepShell already handled brew shellenv.
291-
292-
if len(st.RemoteConfig.MacOSPrefs) > 0 {
293-
st.SnapshotMacOS = st.RemoteConfig.MacOSPrefs
294-
if err := stepRestoreMacOS(opts, st); err != nil {
295-
ui.Error(fmt.Sprintf("macOS configuration failed: %v", err))
296-
softErrs = append(softErrs, fmt.Errorf("macos: %w", err))
297-
}
298-
} else {
299-
if err := stepMacOS(opts, st); err != nil {
300-
ui.Error(fmt.Sprintf("macOS configuration failed: %v", err))
301-
softErrs = append(softErrs, fmt.Errorf("macos: %w", err))
302-
}
303-
}
304-
305-
if err := stepPostInstall(opts, st); err != nil {
306-
ui.Error(fmt.Sprintf("Post-install script failed: %v", err))
307-
softErrs = append(softErrs, fmt.Errorf("post-install: %w", err))
308-
}
309-
310-
fmt.Println()
311-
ui.Header("Installation Complete!")
312-
fmt.Println()
313-
ui.Success("OpenBoot has successfully configured your Mac.")
314-
fmt.Println()
315-
316-
if len(softErrs) > 0 {
317-
fmt.Println()
318-
ui.Warn(fmt.Sprintf("%d setup step(s) had errors — check the output above for details.", len(softErrs)))
319-
return errors.Join(softErrs...)
320-
}
321-
return nil
322-
}
323-
324-
func runInteractiveInstall(opts *config.InstallOptions, st *config.InstallState) error {
325-
if !opts.PackagesOnly {
326-
if err := stepGitConfig(opts, st); err != nil {
327-
return err
328-
}
329-
}
330-
331-
if err := stepPresetSelection(opts, st); err != nil {
332-
return err
333-
}
334-
335-
if err := stepPackageCustomization(opts, st); err != nil {
336-
return err
337-
}
338-
339-
if err := stepInstallPackages(opts, st); err != nil {
340-
return err
341-
}
342-
343-
var softErrs []error
344-
345-
if err := stepInstallNpmWithRetry(opts, st); err != nil {
346-
ui.Error(fmt.Sprintf("npm package installation failed: %v", err))
347-
softErrs = append(softErrs, fmt.Errorf("npm: %w", err))
348-
}
349-
350-
if !opts.PackagesOnly {
351-
if err := stepShell(opts, st); err != nil {
352-
ui.Error(fmt.Sprintf("Shell setup failed: %v", err))
353-
softErrs = append(softErrs, fmt.Errorf("shell: %w", err))
354-
}
355-
356-
if err := stepDotfiles(opts, st); err != nil {
357-
ui.Error(fmt.Sprintf("Dotfiles setup failed: %v", err))
358-
softErrs = append(softErrs, fmt.Errorf("dotfiles: %w", err))
359-
}
360-
361-
if err := stepMacOS(opts, st); err != nil {
362-
ui.Error(fmt.Sprintf("macOS configuration failed: %v", err))
363-
softErrs = append(softErrs, fmt.Errorf("macos: %w", err))
364-
}
365-
}
366-
367-
showCompletion(opts, st)
368-
369-
if len(softErrs) > 0 {
370-
fmt.Println()
371-
ui.Warn(fmt.Sprintf("%d setup step(s) had errors — check the output above for details.", len(softErrs)))
372-
return errors.Join(softErrs...)
373-
}
374-
return nil
375-
}
376-
377212
func RunFromSnapshot(cfg *config.Config) error {
378213
opts := cfg.ToInstallOptions()
379214
st := cfg.ToInstallState()

internal/installer/installer_test.go

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -129,36 +129,6 @@ func TestCheckDependencies_DryRunSkipsEverything(t *testing.T) {
129129
assert.NoError(t, err)
130130
}
131131

132-
// TestRunCustomInstall_IncludesCasksInSelectedPkgs verifies that GUI apps (casks)
133-
// from remote config are added to SelectedPkgs so they get installed.
134-
// Regression test for: https://github.com/openbootdotdev/openboot/issues/17
135-
func TestRunCustomInstall_IncludesCasksInSelectedPkgs(t *testing.T) {
136-
tmpDir := t.TempDir()
137-
t.Setenv("HOME", tmpDir)
138-
139-
cfg := &config.Config{
140-
DryRun: true,
141-
Shell: "skip",
142-
Macos: "skip",
143-
RemoteConfig: &config.RemoteConfig{
144-
Username: "testuser",
145-
Slug: "testconfig",
146-
Packages: config.PackageEntryList{{Name: "git"}, {Name: "curl"}},
147-
Casks: config.PackageEntryList{{Name: "visual-studio-code"}, {Name: "firefox"}},
148-
},
149-
}
150-
151-
opts := cfg.ToInstallOptions()
152-
st := cfg.ToInstallState()
153-
err := runCustomInstall(opts, st)
154-
assert.NoError(t, err)
155-
156-
// Verify both packages and casks are in SelectedPkgs
157-
assert.Contains(t, st.SelectedPkgs, "git", "CLI package should be in SelectedPkgs")
158-
assert.Contains(t, st.SelectedPkgs, "curl", "CLI package should be in SelectedPkgs")
159-
assert.Contains(t, st.SelectedPkgs, "visual-studio-code", "GUI app (cask) should be in SelectedPkgs")
160-
assert.Contains(t, st.SelectedPkgs, "firefox", "GUI app (cask) should be in SelectedPkgs")
161-
}
162132

163133
func TestRunInstall_DryRunRemoteConfig(t *testing.T) {
164134
cfg := &config.Config{
@@ -464,7 +434,7 @@ func TestInstallState_OnlySuccessfulPackagesMarked(t *testing.T) {
464434
assert.False(t, loaded.isFormulaInstalled("ripgrep"), "ripgrep should not appear in persisted state")
465435
}
466436

467-
func TestRunInteractiveInstall_HardFailOnBrew(t *testing.T) {
437+
func TestRunInstall_PackagesOnly_DryRun(t *testing.T) {
468438
tmpDir := t.TempDir()
469439
t.Setenv("HOME", tmpDir)
470440

@@ -477,7 +447,7 @@ func TestRunInteractiveInstall_HardFailOnBrew(t *testing.T) {
477447

478448
opts := cfg.ToInstallOptions()
479449
st := cfg.ToInstallState()
480-
err := runInteractiveInstall(opts, st)
450+
err := runInstall(opts, st)
481451
assert.NoError(t, err)
482452
}
483453

@@ -500,15 +470,16 @@ func TestRunFromSnapshot_SoftFailuresReturnError(t *testing.T) {
500470
assert.NoError(t, err)
501471
}
502472

503-
func TestRunCustomInstall_RunsShellDotfilesMacOS(t *testing.T) {
473+
func TestApply_RemoteConfig_RunsShellDotfilesMacOS(t *testing.T) {
504474
tmpDir := t.TempDir()
505475
t.Setenv("HOME", tmpDir)
506476
t.Setenv("OPENBOOT_DOTFILES", "")
507477

508478
cfg := &config.Config{
509-
DryRun: true,
510-
Shell: "skip",
511-
Macos: "skip",
479+
DryRun: true,
480+
PackagesOnly: true,
481+
Shell: "skip",
482+
Macos: "skip",
512483
RemoteConfig: &config.RemoteConfig{
513484
Username: "testuser",
514485
Slug: "default",
@@ -518,11 +489,13 @@ func TestRunCustomInstall_RunsShellDotfilesMacOS(t *testing.T) {
518489

519490
opts := cfg.ToInstallOptions()
520491
st := cfg.ToInstallState()
521-
err := runCustomInstall(opts, st)
492+
plan, err := Plan(opts, st)
493+
require.NoError(t, err)
494+
err = Apply(plan, NopReporter{})
522495
assert.NoError(t, err)
523496
}
524497

525-
func TestRunCustomInstall_DotfilesRepoPopulatesDotfilesURL(t *testing.T) {
498+
func TestPlan_RemoteConfig_DotfilesRepoPopulatesDotfilesURL(t *testing.T) {
526499
tmpDir := t.TempDir()
527500
t.Setenv("HOME", tmpDir)
528501

@@ -541,19 +514,20 @@ func TestRunCustomInstall_DotfilesRepoPopulatesDotfilesURL(t *testing.T) {
541514

542515
opts := cfg.ToInstallOptions()
543516
st := cfg.ToInstallState()
544-
err := runCustomInstall(opts, st)
545-
assert.NoError(t, err)
546-
assert.Equal(t, "https://github.com/testuser/dotfiles", opts.DotfilesURL)
517+
plan, err := Plan(opts, st)
518+
require.NoError(t, err)
519+
assert.Equal(t, "https://github.com/testuser/dotfiles", plan.DotfilesURL)
547520
}
548521

549-
func TestRunCustomInstall_DotfilesFallsBackToDefault(t *testing.T) {
522+
func TestApply_RemoteConfig_DotfilesFallsBackToDefault(t *testing.T) {
550523
tmpDir := t.TempDir()
551524
t.Setenv("HOME", tmpDir)
552525

553526
cfg := &config.Config{
554-
DryRun: true,
555-
Shell: "skip",
556-
Macos: "skip",
527+
DryRun: true,
528+
PackagesOnly: true,
529+
Shell: "skip",
530+
Macos: "skip",
557531
RemoteConfig: &config.RemoteConfig{
558532
Username: "testuser",
559533
Slug: "default",
@@ -564,7 +538,9 @@ func TestRunCustomInstall_DotfilesFallsBackToDefault(t *testing.T) {
564538

565539
opts := cfg.ToInstallOptions()
566540
st := cfg.ToInstallState()
567-
err := runCustomInstall(opts, st)
541+
plan, err := Plan(opts, st)
542+
require.NoError(t, err)
543+
err = Apply(plan, NopReporter{})
568544
assert.NoError(t, err, "should succeed using default dotfiles template")
569545
}
570546

@@ -820,15 +796,16 @@ func TestReconcileNpmWithSystem_EmptyState(t *testing.T) {
820796
assert.Equal(t, 0, removed)
821797
}
822798

823-
func TestRunCustomInstall_WithPostInstallScript(t *testing.T) {
799+
func TestApply_RemoteConfig_WithPostInstallScript(t *testing.T) {
824800
tmpDir := t.TempDir()
825801
t.Setenv("HOME", tmpDir)
826802
t.Setenv("OPENBOOT_DOTFILES", "")
827803

828804
cfg := &config.Config{
829-
DryRun: true,
830-
Shell: "skip",
831-
Macos: "skip",
805+
DryRun: true,
806+
PackagesOnly: true,
807+
Shell: "skip",
808+
Macos: "skip",
832809
RemoteConfig: &config.RemoteConfig{
833810
Username: "testuser",
834811
Slug: "default",
@@ -839,6 +816,8 @@ func TestRunCustomInstall_WithPostInstallScript(t *testing.T) {
839816

840817
opts := cfg.ToInstallOptions()
841818
st := cfg.ToInstallState()
842-
err := runCustomInstall(opts, st)
819+
plan, err := Plan(opts, st)
820+
require.NoError(t, err)
821+
err = Apply(plan, NopReporter{})
843822
assert.NoError(t, err)
844823
}

0 commit comments

Comments
 (0)