Skip to content

Commit aee0983

Browse files
authored
Merge pull request #22 from ametel01/fix/11-inject-input-into-confirm-apply
Inject input into confirmApply instead of hardcoding os.Stdin
2 parents da56566 + e0135b9 commit aee0983

4 files changed

Lines changed: 39 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changed
1111
- `State.Tool()` now returns `(ToolState, bool)` by value instead of a pointer to a copy, making copy semantics explicit and eliminating a potential mutation footgun.
12+
- `confirmApply` now reads from an injected `io.Reader` instead of hardcoding `os.Stdin`, improving testability and enabling non-interactive integrations.
1213

1314
### Fixed
1415
- The standalone installer now surfaces `mkdir -p` failures directly instead of suppressing the error and failing later with weaker diagnostics.

cmd/atb/install.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ func newInstallCmd() *cobra.Command {
99
Use: "install",
1010
Short: "Install selected tools",
1111
RunE: func(cmd *cobra.Command, _ []string) error {
12-
return runInstall(cmd.Context(), cmd.OutOrStdout(), cmd.ErrOrStderr(), yes)
12+
return runInstall(cmd.Context(), cmd.InOrStdin(), cmd.OutOrStdout(), cmd.ErrOrStderr(), yes)
1313
},
1414
}
1515

cmd/atb/runtime.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"errors"
77
"fmt"
88
"io"
9-
"os"
109
"os/exec"
1110
"runtime"
1211
"slices"
@@ -71,7 +70,7 @@ func (liveVerifier) Check(ctx context.Context, tool catalog.Tool) (verify.Verify
7170
return result, nil
7271
}
7372

74-
func runInstall(ctx context.Context, stdout, stderr io.Writer, yes bool) error {
73+
func runInstall(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, yes bool) error {
7574
installCtx, err := prepareInstall(stderr, yes)
7675
if err != nil {
7776
return err
@@ -110,7 +109,7 @@ func runInstall(ctx context.Context, stdout, stderr io.Writer, yes bool) error {
110109
return wrapError("execute install plan", err)
111110
}
112111

113-
if err := applyShellWorkflow(stdout, yes, &installCtx.stateData, installCtx.selected); err != nil {
112+
if err := applyShellWorkflow(stdin, stdout, yes, &installCtx.stateData, installCtx.selected); err != nil {
114113
return wrapError("apply shell workflow", err)
115114
}
116115

@@ -427,7 +426,7 @@ func runUninstall(ctx context.Context, stdout, stderr io.Writer, toolIDs []strin
427426
return nil
428427
}
429428

430-
func applyShellWorkflow(stdout io.Writer, yes bool, st *state.State, tools []catalog.Tool) error {
429+
func applyShellWorkflow(stdin io.Reader, stdout io.Writer, yes bool, st *state.State, tools []catalog.Tool) error {
431430
suggestions := shell.Suggestions(tools)
432431
if len(suggestions) == 0 {
433432
return nil
@@ -440,7 +439,7 @@ func applyShellWorkflow(stdout io.Writer, yes bool, st *state.State, tools []cat
440439
return nil
441440
}
442441

443-
apply, err := confirmApply(stdout)
442+
apply, err := confirmApply(stdin, stdout)
444443
if err != nil {
445444
return wrapError("confirm shell hook application", err)
446445
}
@@ -454,12 +453,12 @@ func applyShellWorkflow(stdout io.Writer, yes bool, st *state.State, tools []cat
454453
return wrapError("apply shell hook suggestions", shell.ApplyConfirmedSuggestions(suggestions, st))
455454
}
456455

457-
func confirmApply(stdout io.Writer) (bool, error) {
456+
func confirmApply(stdin io.Reader, stdout io.Writer) (bool, error) {
458457
if _, err := fmt.Fprint(stdout, "Apply shell hook suggestions now? [y/N]: "); err != nil {
459458
return false, wrapError("write shell hook prompt", err)
460459
}
461460

462-
reader := bufio.NewReader(os.Stdin)
461+
reader := bufio.NewReader(stdin)
463462
answer, err := reader.ReadString('\n')
464463
if err != nil {
465464
return false, fmt.Errorf("read shell hook confirmation: %w", err)

cmd/atb/runtime_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,37 @@ func TestFinishInstallPersistsStateWithNormalTargets(t *testing.T) {
220220
}
221221
}
222222

223+
func TestConfirmApplyFromInjectedInput(t *testing.T) {
224+
t.Parallel()
225+
226+
tests := []struct {
227+
name string
228+
input string
229+
want bool
230+
}{
231+
{"yes", "y\n", true},
232+
{"YES", "YES\n", true},
233+
{"no", "n\n", false},
234+
{"empty", "\n", false},
235+
}
236+
237+
for _, tt := range tests {
238+
t.Run(tt.name, func(t *testing.T) {
239+
t.Parallel()
240+
241+
var stdout bytes.Buffer
242+
got, err := confirmApply(strings.NewReader(tt.input), &stdout)
243+
if err != nil {
244+
t.Fatalf("confirmApply() error = %v", err)
245+
}
246+
247+
if got != tt.want {
248+
t.Fatalf("confirmApply() = %v, want %v", got, tt.want)
249+
}
250+
})
251+
}
252+
}
253+
223254
func TestResolveStoredTargets(t *testing.T) {
224255
t.Parallel()
225256

0 commit comments

Comments
 (0)