Skip to content

chore: Expand pure testing through venv#6090

Merged
yhakbar merged 8 commits into
mainfrom
chore/expand-pure-testing-through-venv
Jun 18, 2026
Merged

chore: Expand pure testing through venv#6090
yhakbar merged 8 commits into
mainfrom
chore/expand-pure-testing-through-venv

Conversation

@yhakbar

@yhakbar yhakbar commented May 13, 2026

Copy link
Copy Markdown
Collaborator

Description

Expands the pure testing we can do throughout the codebase using venv.

TODOs

Read the Gruntwork contribution guidelines.

  • I authored this code entirely myself
  • I am submitting code based on open source software (e.g. MIT, MPL-2.0, Apache)
  • I am adding or upgrading a dependency or adapted code and confirm it has a compatible open source license
  • Update the docs.
  • Update the changelog in the docs.
  • Run the relevant tests successfully, including pre-commit checks.
  • This change is backwards compatible.
  • If this change is not forwards compatible (e.g. a new feature), it is gated behind a feature flag.

Summary by CodeRabbit

  • Tests

    • Improved test isolation by replacing real external process calls with in-memory stubs across multiple test suites.
    • Added comprehensive tests for hook lifecycle behavior and action execution with hooks.
    • Refactored integration tests to use in-memory filesystems and command execution.
  • Chores

    • Enhanced internal dependency injection patterns for better maintainability and testability.

@vercel

vercel Bot commented May 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
terragrunt-docs Ready Ready Preview, Comment Jun 18, 2026 1:53pm

Request Review

@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e4d9f1b5-0916-4d4a-a1f6-b2bd2889aa49

📥 Commits

Reviewing files that changed from the base of the PR and between 17510c1 and 124f427.

📒 Files selected for processing (24)
  • internal/cli/commands/catalog/catalog.go
  • internal/cli/commands/catalog/cli.go
  • internal/cli/commands/catalog/tui/load.go
  • internal/cli/commands/catalog/tui/model.go
  • internal/cli/commands/catalog/tui/model_test.go
  • internal/cli/commands/catalog/tui/scaffold.go
  • internal/cli/commands/catalog/tui/update.go
  • internal/cli/commands/catalog/tui/view_test.go
  • internal/cli/commands/catalog/tui/welcome.go
  • internal/cli/commands/catalog/tui/welcome_test.go
  • internal/cli/commands/commands.go
  • internal/discovery/graph_target_test.go
  • internal/runner/run/action_with_hooks_test.go
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • internal/runner/run/download_source_test.go
  • internal/runner/run/hook_internal_test.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/runner/run/hook_test.go
  • internal/runner/run/run_e2e_test.go
  • internal/runner/run/version_check_mem_test.go
  • internal/services/catalog/module/repo.go
  • internal/services/catalog/module/repo_tag_test.go
  • internal/shell/git_mem_test.go
  • pkg/config/config_helpers_hcl_mem_test.go
✅ Files skipped from review due to trivial changes (2)
  • internal/shell/git_mem_test.go
  • internal/runner/run/version_check_mem_test.go
🚧 Files skipped from review as they are similar to previous changes (13)
  • internal/cli/commands/catalog/cli.go
  • internal/cli/commands/commands.go
  • internal/runner/run/hook_test.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/runner/run/download_source_test.go
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • pkg/config/config_helpers_hcl_mem_test.go
  • internal/services/catalog/module/repo.go
  • internal/runner/run/run_e2e_test.go
  • internal/services/catalog/module/repo_tag_test.go
  • internal/runner/run/action_with_hooks_test.go
  • internal/discovery/graph_target_test.go
  • internal/runner/run/hook_internal_test.go

📝 Walkthrough

Walkthrough

venv.Venv is threaded through the catalog CLI, TUI model/welcome/scaffold/load, and ResolveLatestTag, replacing all hardcoded OS exec/vfs defaults with injected dependencies. Concurrently, discovery, shell, config helper, and runner tests are converted from real-process execution to mem-backed vexec stubs, and new hook lifecycle contract tests and run.Run end-to-end pipeline tests are added.

Changes

Catalog venv.Venv threading

Layer / File(s) Summary
ResolveLatestTag exec injection
internal/services/catalog/module/repo.go, internal/services/catalog/module/repo_tag_test.go
ResolveLatestTag accepts vexec.Exec and uses it to build the git runner. Tests converted from bare-git-repo setup to mem exec stubs; two new contract tests for prerelease skipping and git failure handling added.
TUI Model, WelcomeModel, and LoadURL venv threading
internal/cli/commands/catalog/tui/load.go, internal/cli/commands/catalog/tui/model.go, internal/cli/commands/catalog/tui/welcome.go
Model struct gains venv field; NewModelStreaming, newModelWithItems, NewWelcomeModel, and tui.Run all accept venv.Venv. LoadURL uses v.FS for repo/discovery construction and passes v.Exec to ResolveLatestTag.
Scaffold and update venv wiring
internal/cli/commands/catalog/tui/scaffold.go, internal/cli/commands/catalog/tui/update.go
scaffoldCmd gains a venv field; newScaffoldCmd accepts it; Run uses c.venv. enterFormState passes m.venv to discoverFormCmd; discoverModuleFields passes it to scaffold.Prepare; scaffoldComponentWithPlanCmd passes m.venv to newScaffoldCmd.
CLI entry point and command registration
internal/cli/commands/catalog/catalog.go, internal/cli/commands/catalog/cli.go, internal/cli/commands/commands.go
catalog.Run accepts and threads venv.Venv into tui.Run, tui.LoadURL, and discoverAndLoad. NewCommand accepts venv.Venv; commands.New passes the instance to catalog.NewCommand.
TUI test call-site updates
internal/cli/commands/catalog/tui/model_test.go, internal/cli/commands/catalog/tui/view_test.go, internal/cli/commands/catalog/tui/welcome_test.go
All NewModelStreaming and NewWelcomeModel call sites updated to pass venv.OSVenv() as the new third argument. No assertion or interaction logic changes.

Mem-exec test isolation and new hook/e2e tests

Layer / File(s) Summary
Hook test recorder refactor and stubExitErr
internal/runner/run/hook_test.go, internal/runner/run/hook_internal_test.go
recorder gains a record() helper; handler delegates to it. hook_internal_test replaces getExitError/fuzzExitErr with a local stubExitErr type, removing the os/exec dependency.
ProcessHooks and ProcessErrorHooks contract tests
internal/runner/run/hook_lifecycle_test.go
New contract tests: declaration-order dispatch, error accumulation with RunOnError=true bypass, WorkingDir propagation per hook, all-matching error hook dispatch, and error hook failure accumulation.
RunActionWithHooks unit tests
internal/runner/run/action_with_hooks_test.go
New tests: happy-path before/action/after order, before_hook failure skips action and dispatches matching error_hooks, action failure dispatches matching error_hooks, after_hooks RunOnError suppression, and no-hooks direct action path.
run.Run end-to-end pipeline tests
internal/runner/run/run_e2e_test.go
Three e2e tests using mem exec and real FS: plan success with invocation capture, plan failure propagation, and before/after hook dispatch ordering. Scaffold helpers create minimal terragrunt.hcl/.terraform directories.
Graph-target discovery tests converted to mem exec
internal/discovery/graph_target_test.go
Removes real git init setup from four tests; injects memGitTopLevelExec via WithExec(), limiting git dispatch to rev-parse --show-toplevel. New helper fails on unexpected git invocations.
HCL config helper mem-exec tests
pkg/config/config_helpers_hcl_mem_test.go
New tests for get_repo_root, get_path_from_repo_root, get_path_to_repo_root, git error propagation, and run_cmd via ParseConfigString with mem exec and mem FS stubs.
Miscellaneous test helper relocations and mem exec conversions
internal/runner/run/download_source_test.go, internal/runner/run/version_check_mem_test.go, internal/runner/run/creds/providers/externalcmd/provider_mem_test.go, internal/shell/git_mem_test.go
download_source_test replaces OSExec with MemExec for PopulateTFVersion. Other files relocate helpers within the file without behavioral changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • gruntwork-io/terragrunt#6089: Threads venv.Venv through CLI command wiring in internal/cli/commands/commands.go, directly part of the same venv-through-CLI refactor pattern applied to catalog.NewCommand.
  • gruntwork-io/terragrunt#6271: Modifies internal/cli/commands/catalog/catalog.go and internal/cli/commands/catalog/tui/* model/welcome/load wiring, the same files where venv.Venv threading is applied in this PR.
  • gruntwork-io/terragrunt#6162: Touches internal/cli/commands/catalog/tui/update.go scaffold interaction path, specifically enterFormState/discoverFormCmd which this PR also modifies to thread venv.

Suggested reviewers

  • denis256
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: Expand pure testing through venv' accurately describes the main objective of the PR, which is to expand pure testing capabilities using virtual environments.
Description check ✅ Passed The PR description provides a clear purpose (expand pure testing through venv) and completes the template checklist, though it lacks detailed explanation of specific changes and their rationale.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/expand-pure-testing-through-venv

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
internal/cli/commands/catalog/tui/redesign/update.go (3)

612-626: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use injected venv instead of global OSVenv() in module field discovery.

Line 615 calls scaffold.Prepare with venv.OSVenv(), which bypasses the model's injected venv and breaks pure testing. Update discoverModuleFields to accept a venv.Venv parameter (as noted in the prior comment) and pass it to scaffold.Prepare.

🔧 Suggested fix
-func discoverModuleFields(ctx context.Context, l log.Logger, opts *options.TerragruntOptions, c *Component) tea.Msg {
+func discoverModuleFields(ctx context.Context, l log.Logger, v venv.Venv, opts *options.TerragruntOptions, c *Component) tea.Msg {
 	quiet := l.WithOptions(log.WithOutput(io.Discard))
 
-	plan, err := scaffold.Prepare(ctx, quiet, venv.OSVenv(), opts, c.TerraformSourcePath(), "")
+	plan, err := scaffold.Prepare(ctx, quiet, v, opts, c.TerraformSourcePath(), "")
 	if err != nil {
 		return formDiscoveryErrMsg{err: err}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/cli/commands/catalog/tui/redesign/update.go` around lines 612 - 626,
The discoverModuleFields function currently calls scaffold.Prepare with the
global venv.OSVenv(), which ignores the injected venv and hampers testing;
change discoverModuleFields signature to accept a venv.Venv parameter (e.g., add
venv v venv.Venv), and pass that injected venv into scaffold.Prepare instead of
venv.OSVenv(); update any callers to supply the injected venv and keep the rest
of the logic (creating quiet logger, handling err -> formDiscoveryErrMsg,
building fields with FieldsFromParsedVariables, and returning formReadyMsg with
NewFormModel) unchanged.

631-648: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use venv-provided filesystem in values field discovery.

Line 637 constructs a new vfs.NewOSFS() instead of using the venv-provided filesystem. This breaks pure testing by bypassing the injected environment. Update discoverValuesFields to accept a venv.Venv parameter and use v.FS() for CollectValuesReferences.

🔧 Suggested fix
-func discoverValuesFields(c *Component) tea.Msg {
+func discoverValuesFields(v venv.Venv, c *Component) tea.Msg {
 	configName := configFileForKind(c.Kind)
 	if configName == "" {
 		return formDiscoveryErrMsg{err: fmt.Errorf("component kind %q has no associated HCL file", c.Kind)}
 	}
 
-	refs, err := CollectValuesReferences(vfs.NewOSFS(), filepath.Join(c.Repo.Path(), c.Dir, configName))
+	refs, err := CollectValuesReferences(v.FS, filepath.Join(c.Repo.Path(), c.Dir, configName))
 	if err != nil {
 		return formDiscoveryErrMsg{err: err}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/cli/commands/catalog/tui/redesign/update.go` around lines 631 - 648,
discoverValuesFields currently constructs vfs.NewOSFS() directly; change its
signature to accept a venv.Venv (e.g., func discoverValuesFields(c *Component, v
venv.Venv) tea.Msg) and replace vfs.NewOSFS() with v.FS() when calling
CollectValuesReferences so the injected virtual filesystem is used; update any
callers (e.g., where NewFormModel is invoked or discoverValuesFields is passed)
to pass the venv instance.

575-599: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Thread venv through the form discovery path.

The model has m.venv but enterFormState calls discoverFormCmd without passing it. This breaks the pure testing pattern established throughout this PR. discoverFormCmd should accept a venv.Venv parameter and forward it to both discoverModuleFields and the function signature at line 592.

🔧 Suggested signature updates
-func enterFormState(m Model, c *Component, priorState sessionState) (tea.Model, tea.Cmd) {
+func enterFormState(m Model, c *Component, priorState sessionState) (tea.Model, tea.Cmd) {
 	m.priorState = priorState
 	m.State = FormState
 	m.form = nil
 	m.scaffoldPlan = nil
 	m.valuesRefs = nil
 	m.selectedComponent = c
 
-	return m, discoverFormCmd(m.ctx, m.logger, m.terragruntOptions, c)
+	return m, discoverFormCmd(m.ctx, m.logger, m.venv, m.terragruntOptions, c)
 }

-func discoverFormCmd(ctx context.Context, l log.Logger, opts *options.TerragruntOptions, c *Component) tea.Cmd {
+func discoverFormCmd(ctx context.Context, l log.Logger, v venv.Venv, opts *options.TerragruntOptions, c *Component) tea.Cmd {
 	return func() tea.Msg {
 		if c.Kind.IsCopyable() {
-			return discoverValuesFields(c)
+			return discoverValuesFields(v, c)
 		}
 
-		return discoverModuleFields(ctx, l, opts, c)
+		return discoverModuleFields(ctx, l, v, opts, c)
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/cli/commands/catalog/tui/redesign/update.go` around lines 575 - 599,
enterFormState currently calls discoverFormCmd without the model venv; update
the discovery path to thread m.venv through: change discoverFormCmd signature to
accept a venv.Venv (e.g., discoverFormCmd(ctx context.Context, l log.Logger,
opts *options.TerragruntOptions, c *Component, v venv.Venv) tea.Cmd), modify
enterFormState to pass m.venv into that call, and inside discoverFormCmd forward
the venv to the downstream calls (pass the venv into discoverModuleFields and,
if applicable, discoverValuesFields) so the entire form discovery flow uses
Model.m.venv. Ensure all call sites and tests are updated to the new signature.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@internal/cli/commands/catalog/tui/redesign/update.go`:
- Around line 612-626: The discoverModuleFields function currently calls
scaffold.Prepare with the global venv.OSVenv(), which ignores the injected venv
and hampers testing; change discoverModuleFields signature to accept a venv.Venv
parameter (e.g., add venv v venv.Venv), and pass that injected venv into
scaffold.Prepare instead of venv.OSVenv(); update any callers to supply the
injected venv and keep the rest of the logic (creating quiet logger, handling
err -> formDiscoveryErrMsg, building fields with FieldsFromParsedVariables, and
returning formReadyMsg with NewFormModel) unchanged.
- Around line 631-648: discoverValuesFields currently constructs vfs.NewOSFS()
directly; change its signature to accept a venv.Venv (e.g., func
discoverValuesFields(c *Component, v venv.Venv) tea.Msg) and replace
vfs.NewOSFS() with v.FS() when calling CollectValuesReferences so the injected
virtual filesystem is used; update any callers (e.g., where NewFormModel is
invoked or discoverValuesFields is passed) to pass the venv instance.
- Around line 575-599: enterFormState currently calls discoverFormCmd without
the model venv; update the discovery path to thread m.venv through: change
discoverFormCmd signature to accept a venv.Venv (e.g., discoverFormCmd(ctx
context.Context, l log.Logger, opts *options.TerragruntOptions, c *Component, v
venv.Venv) tea.Cmd), modify enterFormState to pass m.venv into that call, and
inside discoverFormCmd forward the venv to the downstream calls (pass the venv
into discoverModuleFields and, if applicable, discoverValuesFields) so the
entire form discovery flow uses Model.m.venv. Ensure all call sites and tests
are updated to the new signature.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 13340220-b5f1-4f7b-b3c7-a72eb2026655

📥 Commits

Reviewing files that changed from the base of the PR and between c12f9aa and 82e2854.

📒 Files selected for processing (30)
  • internal/cli/commands/catalog/catalog.go
  • internal/cli/commands/catalog/catalog_redesign.go
  • internal/cli/commands/catalog/catalog_test.go
  • internal/cli/commands/catalog/cli.go
  • internal/cli/commands/catalog/tui/model_test.go
  • internal/cli/commands/catalog/tui/redesign/load.go
  • internal/cli/commands/catalog/tui/redesign/model.go
  • internal/cli/commands/catalog/tui/redesign/model_test.go
  • internal/cli/commands/catalog/tui/redesign/scaffold.go
  • internal/cli/commands/catalog/tui/redesign/update.go
  • internal/cli/commands/catalog/tui/redesign/view_test.go
  • internal/cli/commands/catalog/tui/redesign/welcome.go
  • internal/cli/commands/catalog/tui/redesign/welcome_test.go
  • internal/cli/commands/commands.go
  • internal/discovery/graph_target_test.go
  • internal/runner/run/action_with_hooks_test.go
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • internal/runner/run/download_source_test.go
  • internal/runner/run/hook_internal_test.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/runner/run/hook_test.go
  • internal/runner/run/run_e2e_test.go
  • internal/runner/run/version_check_mem_test.go
  • internal/services/catalog/catalog.go
  • internal/services/catalog/catalog_test.go
  • internal/services/catalog/module/repo.go
  • internal/services/catalog/module/repo_tag_test.go
  • internal/shell/git_mem_test.go
  • pkg/config/config_helpers_hcl_mem_test.go
  • test/integration_catalog_test.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
internal/cli/commands/catalog/catalog_redesign.go (1)

32-139: ⚖️ Poor tradeoff

Acknowledge SonarCloud cognitive complexity flag.

SonarCloud reports cognitive complexity of 21 (vs. limit of 15). The complexity is inherent to the concurrent loading pattern: parallel discovery, bounded loader pool, mutex-protected error collection, and result aggregation. The function is well-commented and the control flow is clear. Extracting helpers would increase indirection without materially reducing complexity. Consider this acceptable for now, but monitor if the function grows further.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/cli/commands/catalog/catalog_redesign.go` around lines 32 - 139,
SonarCloud flags runRedesign for high cognitive complexity due to the large
anonymous function passed into redesign.RunRedesign; extract that inner block
into a well-named helper (e.g., runRedesignDiscoveryAndLoad) to reduce nesting
and make flow easier to read. Move the discovery and loading logic — the
errgroup creation for discoverCatalogConfigURLs and discoverSourceFileURLs, the
urlCh lifecycle, the loaders errgroup with SetLimit and its loaders.Go that
calls redesign.LoadURL, and the failures collection (failuresMu, failures slice,
and final aggregation/return of redesign.SourceLoadError) — into the new
function, keeping the same signatures and behavior so runRedesign only calls
redesign.RunRedesign with that helper as the callback.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/cli/commands/catalog/catalog_redesign.go`:
- Around line 32-139: SonarCloud flags runRedesign for high cognitive complexity
due to the large anonymous function passed into redesign.RunRedesign; extract
that inner block into a well-named helper (e.g., runRedesignDiscoveryAndLoad) to
reduce nesting and make flow easier to read. Move the discovery and loading
logic — the errgroup creation for discoverCatalogConfigURLs and
discoverSourceFileURLs, the urlCh lifecycle, the loaders errgroup with SetLimit
and its loaders.Go that calls redesign.LoadURL, and the failures collection
(failuresMu, failures slice, and final aggregation/return of
redesign.SourceLoadError) — into the new function, keeping the same signatures
and behavior so runRedesign only calls redesign.RunRedesign with that helper as
the callback.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 24b19d5f-ca9e-428d-83d6-b69ce83403cb

📥 Commits

Reviewing files that changed from the base of the PR and between 82e2854 and e9b5ad2.

📒 Files selected for processing (30)
  • internal/cli/commands/catalog/catalog.go
  • internal/cli/commands/catalog/catalog_redesign.go
  • internal/cli/commands/catalog/catalog_test.go
  • internal/cli/commands/catalog/cli.go
  • internal/cli/commands/catalog/tui/model_test.go
  • internal/cli/commands/catalog/tui/redesign/load.go
  • internal/cli/commands/catalog/tui/redesign/model.go
  • internal/cli/commands/catalog/tui/redesign/model_test.go
  • internal/cli/commands/catalog/tui/redesign/scaffold.go
  • internal/cli/commands/catalog/tui/redesign/update.go
  • internal/cli/commands/catalog/tui/redesign/view_test.go
  • internal/cli/commands/catalog/tui/redesign/welcome.go
  • internal/cli/commands/catalog/tui/redesign/welcome_test.go
  • internal/cli/commands/commands.go
  • internal/discovery/graph_target_test.go
  • internal/runner/run/action_with_hooks_test.go
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • internal/runner/run/download_source_test.go
  • internal/runner/run/hook_internal_test.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/runner/run/hook_test.go
  • internal/runner/run/run_e2e_test.go
  • internal/runner/run/version_check_mem_test.go
  • internal/services/catalog/catalog.go
  • internal/services/catalog/catalog_test.go
  • internal/services/catalog/module/repo.go
  • internal/services/catalog/module/repo_tag_test.go
  • internal/shell/git_mem_test.go
  • pkg/config/config_helpers_hcl_mem_test.go
  • test/integration_catalog_test.go
✅ Files skipped from review due to trivial changes (3)
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • internal/runner/run/version_check_mem_test.go
  • internal/shell/git_mem_test.go
🚧 Files skipped from review as they are similar to previous changes (22)
  • internal/cli/commands/commands.go
  • internal/cli/commands/catalog/tui/redesign/scaffold.go
  • internal/cli/commands/catalog/tui/model_test.go
  • internal/services/catalog/module/repo.go
  • internal/cli/commands/catalog/tui/redesign/load.go
  • internal/cli/commands/catalog/cli.go
  • pkg/config/config_helpers_hcl_mem_test.go
  • internal/runner/run/hook_internal_test.go
  • test/integration_catalog_test.go
  • internal/runner/run/run_e2e_test.go
  • internal/cli/commands/catalog/catalog.go
  • internal/cli/commands/catalog/tui/redesign/view_test.go
  • internal/runner/run/download_source_test.go
  • internal/services/catalog/catalog_test.go
  • internal/services/catalog/catalog.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/cli/commands/catalog/tui/redesign/model_test.go
  • internal/cli/commands/catalog/tui/redesign/welcome_test.go
  • internal/cli/commands/catalog/tui/redesign/welcome.go
  • internal/cli/commands/catalog/tui/redesign/model.go
  • internal/discovery/graph_target_test.go
  • internal/services/catalog/module/repo_tag_test.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/cli/commands/catalog/tui/load.go`:
- Line 50: The change to line 50 where `allowCAS := !opts.NoCAS` is set raises
concerns about scope creep and unclear intent within the PR. To address this,
either add clear documentation and tests explaining why this CAS enablement
logic change is necessary and how it relates to the primary PR objectives, or
revert this line if it is not essential to the main changes being made. The
intent of this modification must be transparent to reviewers and maintainers.

In `@internal/cli/commands/catalog/tui/update.go`:
- Around line 635-642: The discoverFormCmd function receives the venv.Venv
parameter v but when calling discoverValuesFields for copyable kinds, it only
passes the component c. The discoverValuesFields function internally hardcodes
vfs.NewOSFS() instead of using the injected v.FS filesystem. To fix this, modify
the discoverValuesFields function signature to accept the venv.Venv parameter v
(similar to how discoverModuleFields receives it), then update the function call
on the copyable branch to pass v, and within discoverValuesFields replace the
hardcoded vfs.NewOSFS() call with v.FS to ensure consistent filesystem handling
across both copyable and module discovery paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e4d9f1b5-0916-4d4a-a1f6-b2bd2889aa49

📥 Commits

Reviewing files that changed from the base of the PR and between 17510c1 and 124f427.

📒 Files selected for processing (24)
  • internal/cli/commands/catalog/catalog.go
  • internal/cli/commands/catalog/cli.go
  • internal/cli/commands/catalog/tui/load.go
  • internal/cli/commands/catalog/tui/model.go
  • internal/cli/commands/catalog/tui/model_test.go
  • internal/cli/commands/catalog/tui/scaffold.go
  • internal/cli/commands/catalog/tui/update.go
  • internal/cli/commands/catalog/tui/view_test.go
  • internal/cli/commands/catalog/tui/welcome.go
  • internal/cli/commands/catalog/tui/welcome_test.go
  • internal/cli/commands/commands.go
  • internal/discovery/graph_target_test.go
  • internal/runner/run/action_with_hooks_test.go
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • internal/runner/run/download_source_test.go
  • internal/runner/run/hook_internal_test.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/runner/run/hook_test.go
  • internal/runner/run/run_e2e_test.go
  • internal/runner/run/version_check_mem_test.go
  • internal/services/catalog/module/repo.go
  • internal/services/catalog/module/repo_tag_test.go
  • internal/shell/git_mem_test.go
  • pkg/config/config_helpers_hcl_mem_test.go
✅ Files skipped from review due to trivial changes (2)
  • internal/shell/git_mem_test.go
  • internal/runner/run/version_check_mem_test.go
🚧 Files skipped from review as they are similar to previous changes (13)
  • internal/cli/commands/catalog/cli.go
  • internal/cli/commands/commands.go
  • internal/runner/run/hook_test.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/runner/run/download_source_test.go
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • pkg/config/config_helpers_hcl_mem_test.go
  • internal/services/catalog/module/repo.go
  • internal/runner/run/run_e2e_test.go
  • internal/services/catalog/module/repo_tag_test.go
  • internal/runner/run/action_with_hooks_test.go
  • internal/discovery/graph_target_test.go
  • internal/runner/run/hook_internal_test.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/cli/commands/catalog/tui/load.go`:
- Line 50: The change to line 50 where `allowCAS := !opts.NoCAS` is set raises
concerns about scope creep and unclear intent within the PR. To address this,
either add clear documentation and tests explaining why this CAS enablement
logic change is necessary and how it relates to the primary PR objectives, or
revert this line if it is not essential to the main changes being made. The
intent of this modification must be transparent to reviewers and maintainers.

In `@internal/cli/commands/catalog/tui/update.go`:
- Around line 635-642: The discoverFormCmd function receives the venv.Venv
parameter v but when calling discoverValuesFields for copyable kinds, it only
passes the component c. The discoverValuesFields function internally hardcodes
vfs.NewOSFS() instead of using the injected v.FS filesystem. To fix this, modify
the discoverValuesFields function signature to accept the venv.Venv parameter v
(similar to how discoverModuleFields receives it), then update the function call
on the copyable branch to pass v, and within discoverValuesFields replace the
hardcoded vfs.NewOSFS() call with v.FS to ensure consistent filesystem handling
across both copyable and module discovery paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e4d9f1b5-0916-4d4a-a1f6-b2bd2889aa49

📥 Commits

Reviewing files that changed from the base of the PR and between 17510c1 and 124f427.

📒 Files selected for processing (24)
  • internal/cli/commands/catalog/catalog.go
  • internal/cli/commands/catalog/cli.go
  • internal/cli/commands/catalog/tui/load.go
  • internal/cli/commands/catalog/tui/model.go
  • internal/cli/commands/catalog/tui/model_test.go
  • internal/cli/commands/catalog/tui/scaffold.go
  • internal/cli/commands/catalog/tui/update.go
  • internal/cli/commands/catalog/tui/view_test.go
  • internal/cli/commands/catalog/tui/welcome.go
  • internal/cli/commands/catalog/tui/welcome_test.go
  • internal/cli/commands/commands.go
  • internal/discovery/graph_target_test.go
  • internal/runner/run/action_with_hooks_test.go
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • internal/runner/run/download_source_test.go
  • internal/runner/run/hook_internal_test.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/runner/run/hook_test.go
  • internal/runner/run/run_e2e_test.go
  • internal/runner/run/version_check_mem_test.go
  • internal/services/catalog/module/repo.go
  • internal/services/catalog/module/repo_tag_test.go
  • internal/shell/git_mem_test.go
  • pkg/config/config_helpers_hcl_mem_test.go
✅ Files skipped from review due to trivial changes (2)
  • internal/shell/git_mem_test.go
  • internal/runner/run/version_check_mem_test.go
🚧 Files skipped from review as they are similar to previous changes (13)
  • internal/cli/commands/catalog/cli.go
  • internal/cli/commands/commands.go
  • internal/runner/run/hook_test.go
  • internal/runner/run/hook_lifecycle_test.go
  • internal/runner/run/download_source_test.go
  • internal/runner/run/creds/providers/externalcmd/provider_mem_test.go
  • pkg/config/config_helpers_hcl_mem_test.go
  • internal/services/catalog/module/repo.go
  • internal/runner/run/run_e2e_test.go
  • internal/services/catalog/module/repo_tag_test.go
  • internal/runner/run/action_with_hooks_test.go
  • internal/discovery/graph_target_test.go
  • internal/runner/run/hook_internal_test.go
🛑 Comments failed to post (2)
internal/cli/commands/catalog/tui/load.go (1)

50-50: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clarify the CAS behavior change in Line 50 (UNKNOWN-UNKNOWNS trigger).

Line 50 changes CAS enablement to allowCAS := !opts.NoCAS, which broadens behavior beyond venv threading. Signature triggered: UNKNOWN-UNKNOWNS (“cannot articulate why this hunk exists from PR intent”). Please either document the intent in this PR (with tests) or move/revert it to a focused change.

As per coding guidelines **/*: “UNKNOWN-UNKNOWNS SCAN… If not, flag the hunk at HIGH and require the maintainer to explain its intent before merge.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/cli/commands/catalog/tui/load.go` at line 50, The change to line 50
where `allowCAS := !opts.NoCAS` is set raises concerns about scope creep and
unclear intent within the PR. To address this, either add clear documentation
and tests explaining why this CAS enablement logic change is necessary and how
it relates to the primary PR objectives, or revert this line if it is not
essential to the main changes being made. The intent of this modification must
be transparent to reviewers and maintainers.

Source: Coding guidelines

internal/cli/commands/catalog/tui/update.go (1)

635-642: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Copyable form discovery still bypasses injected venv filesystem.

discoverFormCmd threads v, but discoverValuesFields still hardcodes vfs.NewOSFS() (Line 680). That breaks end-to-end venv consistency for copyable kinds when v.FS is not OS-backed.

Suggested fix
-func discoverFormCmd(ctx context.Context, l log.Logger, v venv.Venv, opts *options.TerragruntOptions, c *Component) tea.Cmd {
+func discoverFormCmd(ctx context.Context, l log.Logger, v venv.Venv, opts *options.TerragruntOptions, c *Component) tea.Cmd {
 	return func() tea.Msg {
 		if c.Kind.IsCopyable() {
-			return discoverValuesFields(c)
+			return discoverValuesFields(v, c)
 		}

 		return discoverModuleFields(ctx, l, v, opts, c)
 	}
 }

-func discoverValuesFields(c *Component) tea.Msg {
+func discoverValuesFields(v venv.Venv, c *Component) tea.Msg {
 	configName := configFileForKind(c.Kind)
 	if configName == "" {
 		return formDiscoveryErrMsg{err: fmt.Errorf("component kind %q has no associated HCL file", c.Kind)}
 	}

-	refs, err := CollectValuesReferences(vfs.NewOSFS(), filepath.Join(c.Repo.Path(), c.Dir, configName))
+	refs, err := CollectValuesReferences(v.FS, filepath.Join(c.Repo.Path(), c.Dir, configName))
 	if err != nil {
 		return formDiscoveryErrMsg{err: err}
 	}

Also applies to: 674-683

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/cli/commands/catalog/tui/update.go` around lines 635 - 642, The
discoverFormCmd function receives the venv.Venv parameter v but when calling
discoverValuesFields for copyable kinds, it only passes the component c. The
discoverValuesFields function internally hardcodes vfs.NewOSFS() instead of
using the injected v.FS filesystem. To fix this, modify the discoverValuesFields
function signature to accept the venv.Venv parameter v (similar to how
discoverModuleFields receives it), then update the function call on the copyable
branch to pass v, and within discoverValuesFields replace the hardcoded
vfs.NewOSFS() call with v.FS to ensure consistent filesystem handling across
both copyable and module discovery paths.

// TODO: thread venv from the CLI entrypoint through the catalog TUI
// so this leaf participates in the root virtualized environment.
return scaffold.Run(context.Background(), c.logger, venv.OSVenv(), c.opts, c.component.TerraformSourcePath(), "")
return scaffold.Run(context.Background(), c.logger, c.venv, c.opts, c.component.TerraformSourcePath(), "")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible context leak

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, I'll get to that later.

return formDiscoveryErrMsg{err: fmt.Errorf("component kind %q has no associated HCL file", c.Kind)}
}

refs, err := CollectValuesReferences(vfs.NewOSFS(), filepath.Join(c.Repo.Path(), c.Dir, configName))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New VFS instance, should pass the Venv instance/field as an argument?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incrementalism.

// copyComponentWithValuesCmd schedules the unit/stack copy with the form's
// collected HCL values threaded through CopyCmd.WithValues.
func copyComponentWithValuesCmd(l log.Logger, m Model, c *Component, values map[string]string) tea.Cmd {
cmd := NewCopyCmd(l, m.terragruntOptions, c).WithValues(values)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be passed venv.FS in?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incrementalism.

@yhakbar yhakbar merged commit 90d0a5a into main Jun 18, 2026
54 checks passed
@yhakbar yhakbar deleted the chore/expand-pure-testing-through-venv branch June 18, 2026 15:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants