Skip to content

Commit bf633f6

Browse files
committed
chore: Cleanup
1 parent 36fb42e commit bf633f6

26 files changed

Lines changed: 605 additions & 349 deletions

.golangci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ linters:
109109
- linters:
110110
- dupl
111111
path: cli/flags/shared
112+
# BubbleTea's tea.Model expects value-receiver methods (Init/Update/View),
113+
# so Model and WelcomeModel in the TUI packages trip gocritic's hugeParam
114+
# check. Silence it for these packages only; hugeParam still runs everywhere else.
115+
- linters:
116+
- gocritic
117+
text: "hugeParam:"
118+
path: internal/cli/commands/catalog/tui/
112119
# Incrementally linting lines that are too long to ensure that
113120
# we don't have conflicts on every file in the codebase while
114121
# trying to get this merged in.

internal/cli/commands/catalog/catalog_redesign.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ import (
1414
"github.com/gruntwork-io/terragrunt/pkg/options"
1515
)
1616

17+
// urlChannelBufferSize is the buffer size for the discovery URL channel. It
18+
// absorbs short producer bursts from the two concurrent URL discoverers
19+
// without blocking them on a slow consumer.
20+
const urlChannelBufferSize = 10
21+
1722
// runRedesign is the entry point for the redesigned catalog experience.
1823
// It is invoked when the catalog-redesign experiment is enabled.
1924
//
@@ -27,11 +32,11 @@ func runRedesign(ctx context.Context, l log.Logger, opts *options.TerragruntOpti
2732
}
2833

2934
return redesign.RunRedesign(
30-
ctx, l, opts,
35+
ctx, l, opts, opts.Writers.ErrWriter,
3136
func(
3237
ctx context.Context, status redesign.StatusFunc, componentCh chan<- *redesign.ComponentEntry,
3338
) error {
34-
urlCh := make(chan string, 10) //nolint:mnd
39+
urlCh := make(chan string, urlChannelBufferSize)
3540

3641
g, gctx := errgroup.WithContext(ctx)
3742

internal/cli/commands/catalog/tui/keys.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ type DelegateKeyMap struct {
8080

8181
// ShortHelp returns additional short help entries. This satisfies the help.KeyMap interface and
8282
// is entirely optional.
83-
func (d DelegateKeyMap) ShortHelp() []key.Binding { //nolint:gocritic
83+
func (d DelegateKeyMap) ShortHelp() []key.Binding {
8484
return []key.Binding{
8585
d.Choose,
8686
d.Scaffold,
@@ -89,7 +89,7 @@ func (d DelegateKeyMap) ShortHelp() []key.Binding { //nolint:gocritic
8989

9090
// FullHelp returns additional full help entries. This satisfies the help.KeyMap interface and
9191
// is entirely optional.
92-
func (d DelegateKeyMap) FullHelp() [][]key.Binding { //nolint:gocritic
92+
func (d DelegateKeyMap) FullHelp() [][]key.Binding {
9393
return [][]key.Binding{
9494
{
9595
d.Choose,
@@ -143,7 +143,7 @@ type PagerKeyMap struct {
143143

144144
// ShortHelp returns keybindings to be shown in the mini help view. It's part
145145
// of the key.Map interface.
146-
func (keys PagerKeyMap) ShortHelp() []key.Binding { //nolint:gocritic
146+
func (keys PagerKeyMap) ShortHelp() []key.Binding {
147147
return []key.Binding{
148148
keys.Up,
149149
keys.Down,
@@ -160,7 +160,7 @@ func (keys PagerKeyMap) ShortHelp() []key.Binding { //nolint:gocritic
160160

161161
// FullHelp returns keybindings for the expanded help view. It's part of the
162162
// key.Map interface.
163-
func (keys PagerKeyMap) FullHelp() [][]key.Binding { //nolint:gocritic
163+
func (keys PagerKeyMap) FullHelp() [][]key.Binding {
164164
return [][]key.Binding{
165165
{keys.Up, keys.Down, keys.PageDown, keys.PageUp}, // first column
166166
{keys.Navigation, keys.NavigationBack, keys.Choose, keys.Scaffold}, // second column

internal/cli/commands/catalog/tui/model.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,6 @@ func NewModel(l log.Logger, opts *options.TerragruntOptions, svc catalog.Catalog
119119
}
120120

121121
// Init implements bubbletea.Model.Init
122-
func (m Model) Init() tea.Cmd { //nolint:gocritic
122+
func (m Model) Init() tea.Cmd {
123123
return m.buttonBar.Init()
124124
}

internal/cli/commands/catalog/tui/model_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
// the interact callback, and returns the final model once the program exits.
3030
// The program runs with a pipe for input, a buffer for output, and a fixed
3131
// terminal size so tests are deterministic.
32-
func runModel(t *testing.T, m tui.Model, width, height int, interact func(p *tea.Program)) tui.Model { //nolint:gocritic
32+
func runModel(t *testing.T, m tui.Model, width, height int, interact func(p *tea.Program)) tui.Model {
3333
t.Helper()
3434

3535
var out bytes.Buffer

internal/cli/commands/catalog/tui/redesign/copy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ type CopyCmd struct {
2424

2525
// copyResult records what the copy step did beyond the raw file copy, so the
2626
// TUI can surface an appropriate exit message to the user.
27-
type copyResult struct { //nolint:govet // field order favors readability over GC-scan bytes
28-
references ValuesReferences
27+
type copyResult struct {
2928
workingDir string
29+
references ValuesReferences
3030
valuesWritten bool
3131
valuesSkipped bool
3232
}

internal/cli/commands/catalog/tui/redesign/copy_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,82 @@ func TestCopyCmd_RefusesToOverwriteExistingFile(t *testing.T) {
142142
require.Error(t, err)
143143
assert.Contains(t, err.Error(), "already exists")
144144
}
145+
146+
func TestCopyCmd_RejectsNilComponent(t *testing.T) {
147+
t.Parallel()
148+
149+
opts := options.NewTerragruntOptions()
150+
opts.WorkingDir = t.TempDir()
151+
152+
err := redesign.NewCopyCmd(logger.CreateLogger(), opts, nil).Run()
153+
require.Error(t, err)
154+
assert.Contains(t, err.Error(), "nil component")
155+
}
156+
157+
func TestCopyCmd_RejectsEmptyWorkingDir(t *testing.T) {
158+
t.Parallel()
159+
160+
repoDir := helpers.TmpDirWOSymlinks(t)
161+
writeFile(t, filepath.Join(repoDir, "vpc", "terragrunt.hcl"), "# unit\n")
162+
163+
repo := newFakeRepo(t, repoDir)
164+
165+
components, err := redesign.NewComponentDiscovery().Discover(repo)
166+
require.NoError(t, err)
167+
require.Len(t, components, 1)
168+
169+
opts := options.NewTerragruntOptions()
170+
opts.WorkingDir = ""
171+
172+
err = redesign.NewCopyCmd(logger.CreateLogger(), opts, components[0]).Run()
173+
require.Error(t, err)
174+
assert.Contains(t, err.Error(), "empty working directory")
175+
}
176+
177+
func TestCopyCmd_FailsWhenSourceMissing(t *testing.T) {
178+
t.Parallel()
179+
180+
repoDir := helpers.TmpDirWOSymlinks(t)
181+
writeFile(t, filepath.Join(repoDir, "vpc", "terragrunt.hcl"), "# unit\n")
182+
183+
repo := newFakeRepo(t, repoDir)
184+
185+
components, err := redesign.NewComponentDiscovery().Discover(repo)
186+
require.NoError(t, err)
187+
require.Len(t, components, 1)
188+
189+
// Remove the source directory after discovery so the copy walk fails.
190+
require.NoError(t, os.RemoveAll(filepath.Join(repoDir, "vpc")))
191+
192+
opts := options.NewTerragruntOptions()
193+
opts.WorkingDir = t.TempDir()
194+
195+
err = redesign.NewCopyCmd(logger.CreateLogger(), opts, components[0]).Run()
196+
require.Error(t, err)
197+
}
198+
199+
func TestCopyCmd_SkipsSymlinks(t *testing.T) {
200+
t.Parallel()
201+
202+
repoDir := helpers.TmpDirWOSymlinks(t)
203+
writeFile(t, filepath.Join(repoDir, "vpc", "terragrunt.hcl"), "# unit\n")
204+
writeFile(t, filepath.Join(repoDir, "vpc", "real.txt"), "hello\n")
205+
206+
// Add a symlink inside the component; copyDir should skip it silently.
207+
require.NoError(t, os.Symlink("real.txt", filepath.Join(repoDir, "vpc", "link.txt")))
208+
209+
repo := newFakeRepo(t, repoDir)
210+
211+
components, err := redesign.NewComponentDiscovery().Discover(repo)
212+
require.NoError(t, err)
213+
require.Len(t, components, 1)
214+
215+
workingDir := t.TempDir()
216+
opts := options.NewTerragruntOptions()
217+
opts.WorkingDir = workingDir
218+
219+
require.NoError(t, redesign.NewCopyCmd(logger.CreateLogger(), opts, components[0]).Run())
220+
221+
assert.FileExists(t, filepath.Join(workingDir, "real.txt"))
222+
assert.NoFileExists(t, filepath.Join(workingDir, "link.txt"))
223+
}

internal/cli/commands/catalog/tui/redesign/delegate.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,22 @@ func newCatalogDelegate(keys *tui.DelegateKeyMap) catalogDelegate {
9898
}
9999

100100
// Height returns the delegate's preferred height (title + desc + meta + spacing).
101-
func (d catalogDelegate) Height() int { //nolint:gocritic // value receiver required by list.ItemDelegate interface
101+
func (d catalogDelegate) Height() int {
102102
return delegateHeight
103103
}
104104

105105
// Spacing returns the gap between items.
106-
func (d catalogDelegate) Spacing() int { //nolint:gocritic // value receiver required by list.ItemDelegate interface
106+
func (d catalogDelegate) Spacing() int {
107107
return 1
108108
}
109109

110110
// Update is a no-op; input is handled by the model.
111-
func (d catalogDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { //nolint:gocritic // value receiver required by list.ItemDelegate interface
111+
func (d catalogDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd {
112112
return nil
113113
}
114114

115115
// ShortHelp returns the delegate's short help bindings.
116-
func (d catalogDelegate) ShortHelp() []key.Binding { //nolint:gocritic // value receiver required by list.ItemDelegate interface
116+
func (d catalogDelegate) ShortHelp() []key.Binding {
117117
if d.shortHelp != nil {
118118
return d.shortHelp()
119119
}
@@ -122,7 +122,7 @@ func (d catalogDelegate) ShortHelp() []key.Binding { //nolint:gocritic // value
122122
}
123123

124124
// FullHelp returns the delegate's full help bindings.
125-
func (d catalogDelegate) FullHelp() [][]key.Binding { //nolint:gocritic // value receiver required by list.ItemDelegate interface
125+
func (d catalogDelegate) FullHelp() [][]key.Binding {
126126
if d.fullHelp != nil {
127127
return d.fullHelp()
128128
}
@@ -131,7 +131,7 @@ func (d catalogDelegate) FullHelp() [][]key.Binding { //nolint:gocritic // value
131131
}
132132

133133
// Render prints an item with title, description, and metadata row.
134-
func (d catalogDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) { //nolint:gocritic // value receiver required by list.ItemDelegate interface
134+
func (d catalogDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
135135
entry, isEntry := item.(*ComponentEntry)
136136
if !isEntry {
137137
return
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package redesign_test
2+
3+
import "errors"
4+
5+
// failingWriter always returns an error from Write, for exercising
6+
// write-failure branches.
7+
type failingWriter struct{}
8+
9+
func (failingWriter) Write(_ []byte) (int, error) {
10+
return 0, errors.New("write failed")
11+
}

0 commit comments

Comments
 (0)