Skip to content

feat: Add structured component dependencies with cross-type and file monitoring - #2193

Merged
Andriy Knysh (aknysh) merged 6 commits into
mainfrom
osterman/docs-depends-on-fix
Mar 15, 2026
Merged

Andriy Knysh (aknysh) merged 6 commits into
mainfrom
osterman/docs-depends-on-fix

Conversation

@osterman

@osterman Erik Osterman (Cloud Posse) (osterman) commented Mar 14, 2026 •

Copy link
Copy Markdown
Member

what

  • Introduce a new dependencies.components format in stack configurations for declaring explicit component dependencies
  • Add ComponentDependency struct with component, stack, kind, and path fields
  • Support cross-type dependencies (terraform components can depend on helmfile, packer, or plugin components via the kind field)
  • Support file/folder dependencies for external config and source code monitoring (kind: file / kind: folder)
  • Enable Go template support for dynamic stack references in dependency declarations
  • Implement dependency inheritance with append merge behavior during stack inheritance
  • Update describe dependents and describe affected commands to resolve dependencies from the new format
  • Restructure documentation from single dependencies.mdx into dependencies/ directory with dedicated component dependencies page
  • Add blog post announcing the feature

why

  • The existing settings.depends_on format is limited: it uses a map with numeric keys, requires separate namespace/tenant/environment/stage fields instead of stack templates, and mixes file/folder tracking with component dependencies
  • Cross-type dependencies (e.g., terraform depending on helmfile) were not possible with the old format
  • File and folder dependency monitoring needed a cleaner syntax (kind: file + path vs legacy file field)
  • Stack templates ({{ .vars.tenant }}-{{ .vars.environment }}-prod) provide a more flexible and readable way to reference cross-stack dependencies
  • The new list-based format (dependencies.components: [...]) is more intuitive than the map-based settings.depends_on format
  • Legacy settings.depends_on continues to work for backward compatibility

references

  • PRD: docs/prd/component-dependencies.md
  • Blog post: website/blog/2026-01-02-dependencies-components.mdx
  • Documentation: /stacks/dependencies/components

Summary by CodeRabbit

  • New Features

    • Structured component dependencies: add a components list with component, stack, kind (component/file/folder), and path; supports cross-stack, cross-type, and file/folder triggers with append-merge semantics.
  • Documentation

    • Comprehensive docs, examples, migration guide, updated docs pages, and a blog post covering usage and behavior.
  • Tests

    • Extensive unit/integration tests and fixtures validating new format, inheritance, append-merge, and migration scenarios.
  • Deprecation

    • Legacy settings.depends_on marked deprecated with migration instructions.

…monitoring

Introduce `dependencies.components` format in stack configurations:

- ComponentDependency struct with component, stack, kind, and path fields
- Cross-type dependencies (terraform can depend on helmfile/packer/plugin)
- File/folder watching for external config and source code monitoring
- Go template support for dynamic stack references
- Dependency inheritance with append merge behavior
- Updated describe dependents/affected commands for new dependency format
- Test fixtures for inheritance and append merge scenarios
- Restructured documentation into dependencies/ directory
- Blog post announcing the feature

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added the size/l Large size PR label Mar 14, 2026
@mergify

mergify Bot commented Mar 14, 2026

Copy link
Copy Markdown
Contributor

Important

Cloud Posse Engineering Team Review Required

This pull request modifies files that require Cloud Posse's review. Please be patient, and a core maintainer will review your changes.

To expedite this process, reach out to us on Slack in the #pr-reviews channel.

@mergify mergify Bot added the needs-cloudposse Needs Cloud Posse assistance label Mar 14, 2026
@github-actions

github-actions Bot commented Mar 14, 2026 •

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@coderabbitai

coderabbitai Bot commented Mar 14, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 617704d4-8e47-49e8-b0f3-5a20f37a78f8

📥 Commits

Reviewing files that changed from the base of the PR and between 21a3e6b and ee561bd.

📒 Files selected for processing (4)
  • docs/prd/component-dependencies.md
  • internal/exec/describe_affected_utils_2_test.go
  • internal/exec/describe_dependents_test.go
  • pkg/schema/dependencies_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/schema/dependencies_test.go

📝 Walkthrough

Walkthrough

Introduces a structured dependencies.components format and a new ComponentDependency type (component, stack, kind, path), adds helpers for kind detection, updates describe-affected / describe-dependents to prefer the new format with a legacy settings.depends_on fallback and deprecation logging, and adds tests, fixtures, docs, blog and roadmap entries for migration and behavior (append-merge, file/folder, cross-type).

Changes

Cohort / File(s) Summary
Core Schema & Public API
pkg/schema/dependencies.go, docs/prd/component-dependencies.md, docs/prd/tool-dependencies-integration.md
Add ComponentDependency struct and helpers (IsFileDependency, IsFolderDependency, IsComponentDependency); add Components []ComponentDependency to Dependencies; document schema, validation and merge rules.
Dependency Resolution Logic
internal/exec/describe_affected_components.go, internal/exec/describe_dependents.go, internal/exec/describe_affected_utils_optimized.go
Introduce loaders/converters (getFileFolderDependencies, getComponentDependencies, contextToComponentDependency), unified matching helpers for new vs legacy formats, deprecation logging, and switch callers to use []ComponentDependency.
Matching Implementation & Error Handling
internal/exec/describe_affected_utils_optimized.go
Change signature to []schema.ComponentDependency, use index-based iteration, predicate helpers for kinds, compute absolute paths and propagate path-match errors.
Tests
internal/exec/describe_affected_optimizations_test.go, internal/exec/describe_affected_utils_2_test.go, internal/exec/describe_dependents_test.go, pkg/schema/dependencies_test.go
Replace map-based legacy DependsOn tests with slice-based []ComponentDependency; add extensive unit and integration tests for extraction, matching, list-merge inheritance (append), and helper methods.
Fixtures / Scenarios
tests/fixtures/scenarios/dependencies-components-inheritance*/...
Add atmos.yaml, stack/component YAMLs and mock Terraform/Helmfile files to validate replacement vs append inheritance, cross-stack and file/folder dependency scenarios.
Docs & Website
website/docs/stacks/dependencies/components.mdx, website/docs/stacks/dependencies/index.mdx, website/docs/stacks/settings/depends_on.mdx, website/docs/stacks/settings/index.mdx, website/docs/stacks/stacks.mdx, website/docs/deploy/deploy.mdx, website/docs/learn/next-steps.mdx
Add comprehensive Component Dependencies docs, migration guidance, mark settings.depends_on deprecated, update examples and cross-links across docs.
Blog / Roadmap / Redirects / Metadata
website/blog/2026-03-14-dependencies-components.mdx, website/src/data/roadmap.js, website/docusaurus.config.js, website/docs/stacks/dependencies/_category_.json, website/docs/cli/commands/toolchain/registry/_category_.json
Add announcement blog and roadmap entry, update redirect for old dependencies path, add docs category; minor JSON ordering tweak.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/CLI
    participant DAC as Describe<br/>Affected
    participant Loader as getFileFolder<br/>Dependencies
    participant Matcher as Dependency<br/>Checker
    participant FS as File System

    User->>DAC: Execute "describe affected"
    DAC->>Loader: Load dependencies (new or legacy)
    alt New Format
        Loader->>Loader: Parse dependencies.components -> []ComponentDependency
    else Legacy Format
        Loader->>Loader: Parse settings.depends_on -> convert to ComponentDependency
        Loader-->>Loader: Log deprecation
    end
    Loader-->>DAC: Return dependencies slice
    DAC->>Matcher: Check dependencies against changed files
    Matcher->>FS: Match dep.Path (handles file/folder patterns)
    alt Match Found
        Matcher->>DAC: Mark component as affected
    else No Match
        Matcher->>DAC: No action
    end
    DAC-->>User: Return affected components
Loading
sequenceDiagram
    participant User as User/CLI
    participant DDeps as Describe<br/>Dependents
    participant Loader as getComponent<br/>Dependencies
    participant Matcher as isDependency<br/>Match
    participant Output as Dependents<br/>Collector

    User->>DDeps: Execute "describe dependents"
    DDeps->>Loader: Load component dependencies (new/legacy)
    alt New Format
        Loader->>Loader: Parse dependencies.components
    else Legacy Format
        Loader->>Loader: Convert settings.depends_on -> ComponentDependency
        Loader-->>Loader: Log deprecation
    end
    Loader-->>DDeps: Return dependencies slice
    loop for each dependency
        DDeps->>Matcher: Apply new or legacy matching rules
        alt Match
            Matcher->>Output: Include dependent component
        else No match
            Matcher->>Output: Skip
        end
    end
    Output-->>User: Return dependent components
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • osterman
  • kevcube
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main feature being introduced: structured component dependencies with cross-type and file monitoring capabilities.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch osterman/docs-depends-on-fix
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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.

Actionable comments posted: 13

Caution

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

⚠️ Outside diff range comments (3)
internal/exec/describe_dependents.go (2)

205-208: ⚠️ Potential issue | 🟠 Major

kind is not part of dependent matching yet.

Lines 205-208 and 244-256 still key on component name alone, and isDependencyMatch() only checks stack/context. With the new cross-type feature, terraform/vpc and helmfile/vpc are distinct targets; right now a kind: helmfile dependency can still match the terraform vpc, and a same-named component in another type gets skipped as "self". Please carry the provided component type through this path and compare it to dependsOn.Kind (defaulting empty kind to the declaring component type) before matching.

Also applies to: 242-256, 416-429

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/exec/describe_dependents.go` around lines 205 - 208, The current
dependent-matching logic only compares component names (e.g., stackComponentName
vs args.Component) and relies on isDependencyMatch() which ignores target kind;
update the flow to carry the provided component type (args.Kind or similar)
through the path and use it when skipping and when calling isDependencyMatch():
when reading dependsOn entries treat empty dependsOn.Kind as the declaring
component's kind (default to the current stack/component kind), and ensure you
compare both name and resolved kind before skipping a "self" match (replace the
simple stackComponentName == args.Component check) and before treating a
dependency as matching; update references in describe_dependents.go functions
that use stackComponentName, args.Component, isDependencyMatch(), and
dependsOn.Kind (affecting the matching blocks around those areas) to enforce
kind-aware matching.

260-305: ⚠️ Potential issue | 🟠 Major

Stop after the first match to avoid duplicate dependents.

Once one dependency entry matches, this code appends the dependent but keeps scanning. With append-merge inheritance, the same dependency can legitimately show up in both parent and child stacks, so the same dependent can be emitted more than once.

Suggested fix
 					if args.IncludeSettings {
 						dependent.Settings = settingsSection
 					}

 					dependents = append(dependents, dependent)
+					break
 				}
 			}
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/exec/describe_dependents.go` around lines 260 - 305, The loop that
builds and appends a dependent (creating variable dependent and calling
BuildSpaceliftStackNameFromComponentConfig/BuildAtlantisProjectNameFromComponentConfig)
continues scanning after appending, causing duplicate dependents; after
appending to the dependents slice add a break to stop scanning further matches
for that dependency (i.e., exit the current dependency-matching loop immediately
after dependents = append(dependents, dependent)) so each dependent is emitted
only once.
internal/exec/describe_affected_utils_optimized.go (1)

104-127: ⚠️ Potential issue | 🟠 Major

Resolve dependency paths against the same base as the changed-files index.

Line 122 resolves dep.Path using filepath.Abs, which anchors relative paths to the process working directory. However, changedFilesIndex normalizes files relative to gitRepoRoot (not the current working directory). This causes a path-matching mismatch when atmos runs from different directories. Additionally, an empty Path collapses to the current working directory via Abs(""), risking over-matches against unrelated changes.

The function needs either gitRepoRoot passed as a parameter to match the indexing strategy, or paths should be resolved against atmosConfig.BasePath. Also validate and reject empty paths before matching.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/exec/describe_affected_utils_optimized.go` around lines 104 - 127,
The code currently resolves dependency paths with filepath.Abs(dep.Path) which
anchors relative paths to the process CWD and treats an empty Path as the CWD;
change this to resolve dep.Path against the same base used by the changed-files
index (pass gitRepoRoot into the routine or use atmosConfig.BasePath) instead of
calling filepath.Abs directly, and validate/reject empty dep.Path before
building pathPattern (so you don't collapse to CWD); update references around
dep.Path, the filepath.Abs call, and pathPattern construction to use the chosen
base and add a guard for empty paths.
🧹 Nitpick comments (1)
tests/fixtures/scenarios/dependencies-components-inheritance/components/terraform/mock/main.tf (1)

1-5: Looks good for a test fixture.

The mock component is appropriately minimal. The enabled variable serves its purpose for testing dependency scenarios.

If you want to enhance clarity, consider adding a description to the variable—but it's purely optional for test code.

📝 Optional: Add variable description
 # Mock component for testing.
 variable "enabled" {
   type    = bool
   default = true
+  description = "Enable or disable the mock component"
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@tests/fixtures/scenarios/dependencies-components-inheritance/components/terraform/mock/main.tf`
around lines 1 - 5, The test fixture's variable "enabled" is fine but could be
clearer by adding a description; open the Terraform mock file and update the
variable "enabled" block to include a description attribute (e.g., description =
"Enable mock component for dependency tests") so the variable declaration
(variable "enabled") documents its intent while keeping default and type
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/prd/component-dependencies.md`:
- Around line 237-242: Update the failing absolute site routes in the markdown
by replacing the site-rooted URLs with repo-resolvable references or plain text:
change the link targets for "Component Dependencies User Guide"
(/stacks/dependencies/components) and the two "describe" links
(/cli/commands/describe/dependents and /cli/commands/describe/affected) to
either relative repository paths that point to the corresponding docs files
(e.g., a relative path into the docs tree) or convert the links to plain text if
no repo path exists; ensure the link text remains unchanged so readers still see
the same labels while the targets resolve in repo doc validation.

In `@docs/prd/tool-dependencies-integration.md`:
- Line 98: The link "[Component Dependencies
documentation](/stacks/dependencies/components)" is not repo-resolvable from
this doc; replace the absolute path with a relative, repo-resolvable path (for
example change "/stacks/dependencies/components" to the correct relative path to
the components doc from this file) so the docs validation passes; update the
link in the line containing the markdown reference to ensure it points to the
actual file location in the repository.
- Around line 61-70: The PRD still shows the old dependency shape: update the
Dependencies struct and all examples to use the new []ComponentDependency type
instead of []Context and remove legacy fields like stage: prod; specifically
change the Dependencies.Components field to be Components []ComponentDependency
and update sample snippets that drop Components (lines ~197-203) to include the
new ComponentDependency entries using the new keys stack, kind, and path so
examples reflect the current implementation; ensure all occurrences (including
the examples called out around lines 78-86 and 197-203) consistently use
ComponentDependency with stack/kind/path and no legacy stage/context fields.

In `@internal/exec/describe_affected_components.go`:
- Around line 573-587: The code in the block that builds result from
stackComponentSettings.DependsOn drops folder values when a legacy entry
contains both file and folder because it uses "else if"; modify the logic in the
loop that builds result (the code that appends schema.ComponentDependency from
stackComponentSettings.DependsOn) to append a ComponentDependency for the file
when dep.File != "" and also independently append a ComponentDependency for the
folder when dep.Folder != "" (i.e., remove the else-if relationship so both
branches can run), keeping the Kind values "file" and "folder" and Path set to
dep.File/dep.Folder respectively so legacy entries that include both are
preserved.

In `@internal/exec/describe_dependents_test.go`:
- Around line 20-225: The PR is missing unit tests for two resolution paths:
non-default dependency kinds and Go-templated components[].stack values; add two
new t.Run cases in TestGetComponentDependencies (or adjacent tests in
describe_dependents_test.go) that exercise getComponentDependencies and
schema.ComponentDependency: (1) add a fixture where dependencies.components
includes an item with Kind "helmfile" (and Path or Component as appropriate) and
assert IsFile/IsFolder helpers are false and Kind/Path are preserved and the
returned source is dependencySourceDependenciesComponents; (2) add a fixture
where a component's "stack" field is a Go template (e.g., "{{ .ParentStack
}}-prod" or similar) that simulates resolved cross-stack reference (provide a
componentMap representing the post-resolution state with the templated value
resolved across stacks) and assert the resolved Stack value appears in deps and
that edge type (terraform→terraform) is correctly recorded; ensure both tests
call getComponentDependencies and assert on deps length, per-item
Kind/Component/Stack and returned source so these new code paths are covered.

In
`@tests/fixtures/scenarios/dependencies-components-inheritance/stacks/catalog/base.yaml`:
- Around line 1-12: The comment in base.yaml incorrectly states that parent
dependencies "should be inherited by child stacks"; update the comment to
reflect the actual tested behavior used by
TestDescribeDependents_DependenciesComponentsFormat: list-valued dependencies
under components use replace-merge (child lists replace parent lists), so note
that the VPC dependencies in base.yaml are replaced by dev.yaml rather than
appended; update the comment near components -> terraform -> vpc -> dependencies
-> components to explicitly state "replace merge (child replaces parent)
behavior" and mention the related test name for clarity.

In
`@tests/fixtures/scenarios/dependencies-components-inheritance/stacks/deploy/dev.yaml`:
- Around line 1-2: Update the top comment in the dev.yaml fixture for the
dependencies-components-inheritance scenario to reflect the default replace
merge behavior (not append); change the sentence that currently reads "Tests
that child dependencies are APPENDED to parent dependencies." to indicate that
child dependencies REPLACE parent dependencies, and ensure it matches the
documented behavior in TestDescribeDependents_DependenciesComponentsFormat.
- Around line 20-27: The inline comment above the vpc dependencies is incorrect
about merge behavior; update the comment to state that with the replace merge
strategy the vpc.dependencies block replaces the parent entries from base.yaml
(account-settings, iam-baseline) rather than appending to them, referencing the
vpc key and its dependencies mapping so readers understand the actual replace
semantics.

In `@website/blog/2026-01-02-dependencies-components.mdx`:
- Line 40: The doc line "Inheritance: Dependencies are appended during stack
inheritance (not replaced)" is misleading; update the "Inheritance" sentence to
state that dependencies default to the replace strategy during stack inheritance
and are only appended when explicitly configured via list_merge_strategy:
append, e.g., change the wording under the "Inheritance" heading to mention the
default replace behavior and call out the explicit list_merge_strategy: append
option for appending dependencies.

In `@website/docs/stacks/dependencies/components.mdx`:
- Around line 260-271: The example JSON in the docs still uses the legacy
affected value "stack.settings.depends_on.folder"; update the JSON example so
the affected field uses the new plain-reason format (e.g., change the subnet
entry's "affected" value to "folder" and any similar legacy strings to "file" or
"folder" as appropriate), verify the example shows both possible plain values if
relevant, and ensure the doc now matches the CLI output for the
"component"/"subnet" example.

In `@website/docs/stacks/dependencies/index.mdx`:
- Line 220: The sentence overstates behavior—change the claim about
"dependencies.components" so it is scoped to only the flows that support
dependency metadata (e.g., commands and integrations that consume dependency
info). Locate the sentence referencing "dependencies.components" and replace it
with a scoped version that notes it controls execution order only for supported
flows (such as commands and integrations that read dependency metadata) and does
not imply a universal guarantee.

In `@website/docs/stacks/settings/depends_on.mdx`:
- Around line 19-25: The example under dependencies.components uses the
deprecated selector field "stage" — update the snippet to use the new selector
key "stack" instead (i.e., replace any occurrence of "stage: prod" with "stack:
prod") so the documentation example matches the new dependencies.components
schema; look for the YAML block showing dependencies.components and ensure the
selector uses "stack" in the component entry.

In `@website/docs/stacks/settings/index.mdx`:
- Line 161: The subsection currently teaches the legacy config key
settings.depends_on but links to the new dependencies.components page, which is
contradictory; either move the concrete examples and sample YAML from this
subsection into the new dependencies.components documentation and update this
page to reference that new examples section, or explicitly mark this subsection
as “Legacy: settings.depends_on” and change the link to point to the legacy
documentation for settings (not dependencies.components); update any example
headings and text to reference the correct symbol (settings.depends_on or
dependencies.components) so CLI docs and website examples remain in sync.

---

Outside diff comments:
In `@internal/exec/describe_affected_utils_optimized.go`:
- Around line 104-127: The code currently resolves dependency paths with
filepath.Abs(dep.Path) which anchors relative paths to the process CWD and
treats an empty Path as the CWD; change this to resolve dep.Path against the
same base used by the changed-files index (pass gitRepoRoot into the routine or
use atmosConfig.BasePath) instead of calling filepath.Abs directly, and
validate/reject empty dep.Path before building pathPattern (so you don't
collapse to CWD); update references around dep.Path, the filepath.Abs call, and
pathPattern construction to use the chosen base and add a guard for empty paths.

In `@internal/exec/describe_dependents.go`:
- Around line 205-208: The current dependent-matching logic only compares
component names (e.g., stackComponentName vs args.Component) and relies on
isDependencyMatch() which ignores target kind; update the flow to carry the
provided component type (args.Kind or similar) through the path and use it when
skipping and when calling isDependencyMatch(): when reading dependsOn entries
treat empty dependsOn.Kind as the declaring component's kind (default to the
current stack/component kind), and ensure you compare both name and resolved
kind before skipping a "self" match (replace the simple stackComponentName ==
args.Component check) and before treating a dependency as matching; update
references in describe_dependents.go functions that use stackComponentName,
args.Component, isDependencyMatch(), and dependsOn.Kind (affecting the matching
blocks around those areas) to enforce kind-aware matching.
- Around line 260-305: The loop that builds and appends a dependent (creating
variable dependent and calling
BuildSpaceliftStackNameFromComponentConfig/BuildAtlantisProjectNameFromComponentConfig)
continues scanning after appending, causing duplicate dependents; after
appending to the dependents slice add a break to stop scanning further matches
for that dependency (i.e., exit the current dependency-matching loop immediately
after dependents = append(dependents, dependent)) so each dependent is emitted
only once.

---

Nitpick comments:
In
`@tests/fixtures/scenarios/dependencies-components-inheritance/components/terraform/mock/main.tf`:
- Around line 1-5: The test fixture's variable "enabled" is fine but could be
clearer by adding a description; open the Terraform mock file and update the
variable "enabled" block to include a description attribute (e.g., description =
"Enable mock component for dependency tests") so the variable declaration
(variable "enabled") documents its intent while keeping default and type
unchanged.
🪄 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: 442dcd62-6b59-4cfa-b8e9-b06a2da3bb74

📥 Commits

Reviewing files that changed from the base of the PR and between 76a269b and 847b7d6.

📒 Files selected for processing (29)
  • docs/prd/component-dependencies.md
  • docs/prd/tool-dependencies-integration.md
  • internal/exec/describe_affected_components.go
  • internal/exec/describe_affected_optimizations_test.go
  • internal/exec/describe_affected_utils_2_test.go
  • internal/exec/describe_affected_utils_optimized.go
  • internal/exec/describe_dependents.go
  • internal/exec/describe_dependents_test.go
  • pkg/schema/dependencies.go
  • tests/fixtures/scenarios/dependencies-components-inheritance-append/atmos.yaml
  • tests/fixtures/scenarios/dependencies-components-inheritance-append/components/terraform/mock/main.tf
  • tests/fixtures/scenarios/dependencies-components-inheritance-append/stacks/catalog/base.yaml
  • tests/fixtures/scenarios/dependencies-components-inheritance-append/stacks/deploy/dev.yaml
  • tests/fixtures/scenarios/dependencies-components-inheritance/atmos.yaml
  • tests/fixtures/scenarios/dependencies-components-inheritance/components/terraform/mock/main.tf
  • tests/fixtures/scenarios/dependencies-components-inheritance/stacks/catalog/base.yaml
  • tests/fixtures/scenarios/dependencies-components-inheritance/stacks/deploy/dev.yaml
  • website/blog/2026-01-02-dependencies-components.mdx
  • website/docs/cli/commands/toolchain/registry/_category_.json
  • website/docs/deploy/deploy.mdx
  • website/docs/learn/next-steps.mdx
  • website/docs/stacks/dependencies/_category_.json
  • website/docs/stacks/dependencies/components.mdx
  • website/docs/stacks/dependencies/index.mdx
  • website/docs/stacks/settings/depends_on.mdx
  • website/docs/stacks/settings/index.mdx
  • website/docs/stacks/stacks.mdx
  • website/docusaurus.config.js
  • website/src/data/roadmap.js

Comment thread docs/prd/component-dependencies.md
Comment thread docs/prd/tool-dependencies-integration.md
Comment thread docs/prd/tool-dependencies-integration.md Outdated
Comment thread internal/exec/describe_affected_components.go
Comment thread internal/exec/describe_dependents_test.go
Comment thread website/blog/2026-01-02-dependencies-components.mdx Outdated
Comment thread website/docs/stacks/dependencies/components.mdx
Comment thread website/docs/stacks/dependencies/index.mdx Outdated
Comment thread website/docs/stacks/settings/depends_on.mdx
Comment thread website/docs/stacks/settings/index.mdx Outdated
@codecov

codecov Bot commented Mar 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.49593% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.40%. Comparing base (89d32db) to head (ee561bd).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/exec/describe_affected_components.go 82.22% 4 Missing and 4 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2193      +/-   ##
==========================================
+ Coverage   77.35%   77.40%   +0.05%     
==========================================
  Files         961      962       +1     
  Lines       91169    91239      +70     
==========================================
+ Hits        70524    70627     +103     
+ Misses      16564    16536      -28     
+ Partials     4081     4076       -5     
Flag Coverage Δ
unittests 77.40% <93.49%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
internal/exec/describe_affected_utils_optimized.go 80.00% <100.00%> (+0.33%) ⬆️
internal/exec/describe_dependents.go 87.55% <100.00%> (+8.55%) ⬆️
pkg/schema/dependencies.go 100.00% <100.00%> (ø)
internal/exec/describe_affected_components.go 65.00% <82.22%> (+2.78%) ⬆️

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Fix else-if bug in legacy dependency conversion that dropped folder entries
when both file and folder were present. Correct documentation to reflect
replace merge as default behavior (not append). Update PRD links to be
repo-resolvable, fix legacy field names (stage→stack), and update blog post
date.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@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

Caution

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

⚠️ Outside diff range comments (2)
website/docs/stacks/dependencies/index.mdx (1)

259-263: ⚠️ Potential issue | 🟡 Minor

Disambiguate the two “Component Dependencies” links in Related Documentation.

Both entries use the same title but point to different pages (new vs legacy), which is easy to misread.

Suggested fix
 - [Component Dependencies](/stacks/dependencies/components) - Detailed component dependency configuration
 - [Toolchain Management](/cli/commands/toolchain/usage) - Installing and managing CLI tools
 - [Toolchain Configuration](/cli/configuration/toolchain/) - Configuring toolchain behavior
-- [Component Dependencies](/stacks/settings/depends_on) - Configure dependencies between components
+- [Legacy `settings.depends_on`](/stacks/settings/depends_on) - Configure dependencies between components (legacy format)
 - [YAML Functions](/functions/yaml) - Using `!terraform.output` and other functions for cross-component dependencies

As per coding guidelines, “Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@website/docs/stacks/dependencies/index.mdx` around lines 259 - 263, Two
identical link labels "[Component Dependencies]" in the Related Documentation
section are ambiguous; change the link text to disambiguate the two
targets—e.g., rename the first "[Component
Dependencies](/stacks/dependencies/components)" to "Component Dependencies (new
components)" or "Component Dependencies — Components" and rename the second
"[Component Dependencies](/stacks/settings/depends_on)" to "Component
Dependencies (legacy/settings)" or "Component Dependencies —
Settings/depends_on" so readers can tell them apart while leaving the hrefs
unchanged; update only the link labels in the file index.mdx where the two
duplicate "[Component Dependencies]" entries appear.
internal/exec/describe_affected_components.go (1)

190-199: ⚠️ Potential issue | 🟠 Major

dependencies.components checks are skipped when settings is missing.

In these blocks, dependency processing only runs inside if settingsSection .... Components that define dependencies.components but have no settings block will never run file/folder dependency checks, so describe affected can miss valid changes.

Suggested fix
@@
-        if settingsSection, ok := componentSection[cfg.SettingsSectionName].(map[string]any); ok {
-            err := checkSettingsAndDependenciesIndexed(
-                &affected, atmosConfig, componentName, stackName, cfg.TerraformComponentType,
-                &componentSection, settingsSection, remoteStacks, currentStacks, filesIndex,
-                includeSpaceliftAdminStacks, includeSettings,
-            )
-            if err != nil {
-                return nil, err
-            }
-        }
+        settingsSection, _ := componentSection[cfg.SettingsSectionName].(map[string]any)
+        err := checkSettingsAndDependenciesIndexed(
+            &affected, atmosConfig, componentName, stackName, cfg.TerraformComponentType,
+            &componentSection, settingsSection, remoteStacks, currentStacks, filesIndex,
+            includeSpaceliftAdminStacks, includeSettings,
+        )
+        if err != nil {
+            return nil, err
+        }
@@
-        if settingsSection, ok := componentSection[cfg.SettingsSectionName].(map[string]any); ok {
-            err := checkSettingsAndDependenciesIndexed(
-                &affected, atmosConfig, componentName, stackName, cfg.HelmfileComponentType,
-                &componentSection, settingsSection, remoteStacks, currentStacks, filesIndex,
-                includeSpaceliftAdminStacks, includeSettings,
-            )
-            if err != nil {
-                return nil, err
-            }
-        }
+        settingsSection, _ := componentSection[cfg.SettingsSectionName].(map[string]any)
+        err := checkSettingsAndDependenciesIndexed(
+            &affected, atmosConfig, componentName, stackName, cfg.HelmfileComponentType,
+            &componentSection, settingsSection, remoteStacks, currentStacks, filesIndex,
+            includeSpaceliftAdminStacks, includeSettings,
+        )
+        if err != nil {
+            return nil, err
+        }
@@
-        if settingsSection, ok := componentSection[cfg.SettingsSectionName].(map[string]any); ok {
-            err := checkSettingsAndDependenciesIndexed(
-                &affected, atmosConfig, componentName, stackName, cfg.PackerComponentType,
-                &componentSection, settingsSection, remoteStacks, currentStacks, filesIndex,
-                includeSpaceliftAdminStacks, includeSettings,
-            )
-            if err != nil {
-                return nil, err
-            }
-        }
+        settingsSection, _ := componentSection[cfg.SettingsSectionName].(map[string]any)
+        err := checkSettingsAndDependenciesIndexed(
+            &affected, atmosConfig, componentName, stackName, cfg.PackerComponentType,
+            &componentSection, settingsSection, remoteStacks, currentStacks, filesIndex,
+            includeSpaceliftAdminStacks, includeSettings,
+        )
+        if err != nil {
+            return nil, err
+        }
@@
 func checkSettingsAndDependenciesIndexed(
@@
 ) error {
     // Check settings section changes.
-    if !isEqual(remoteStacks, stackName, componentType, componentName, settingsSection, cfg.SettingsSectionName) {
+    if settingsSection != nil && !isEqual(remoteStacks, stackName, componentType, componentName, settingsSection, cfg.SettingsSectionName) {
         err := addAffectedComponent(affected, atmosConfig, componentName, stackName, componentType,
             componentSection, affectedReasonStackSettings, includeSpaceliftAdminStacks, currentStacks, includeSettings)
         if err != nil {
             return err
         }

Also applies to: 300-309, 410-419

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/exec/describe_affected_components.go` around lines 190 - 199, The
dependency checks are only executed when a settings block exists because the
call to checkSettingsAndDependenciesIndexed is nested under if settingsSection
...; update the logic so dependency processing runs even when settings is
absent: extract the dependencies map (dependencies.components) from
componentSection and call the dependency-checking routine (reuse or refactor
checkSettingsAndDependenciesIndexed into a separate function for pure dependency
checks, or call it with a nil/empty settingsSection) for
componentName/stackName/ cfg.TerraformComponentType using
remoteStacks/currentStacks/filesIndex/includeSpaceliftAdminStacks/includeSettings
as before; apply the same change to the other analogous blocks that call
checkSettingsAndDependenciesIndexed so components without settings still get
their file/folder dependency checks.
♻️ Duplicate comments (1)
tests/fixtures/scenarios/dependencies-components-inheritance/stacks/deploy/dev.yaml (1)

20-20: ⚠️ Potential issue | 🟡 Minor

Update Line 20 comment to match replace behavior.

Line 20 still says VPC “inherits … AND adds,” which contradicts the replace semantics documented in this scenario.

Suggested wording fix
-    # VPC inherits base dependencies AND adds its own.
+    # VPC defines its own dependencies; parent entries are replaced.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@tests/fixtures/scenarios/dependencies-components-inheritance/stacks/deploy/dev.yaml`
at line 20, Update the comment on Line 20 referencing "VPC inherits base
dependencies AND adds its own" to reflect the replace semantics for this
scenario: change the wording to state that the VPC replaces the base
dependencies (does not inherit them) and specify any VPC-specific dependencies
it defines, e.g., "VPC replaces base dependencies with its own" or "VPC uses
replace semantics — it does not inherit base dependencies; it defines its own."
Ensure the comment mentions "replace semantics" and "VPC" so readers understand
the behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/prd/component-dependencies.md`:
- Around line 167-181: The helper methods IsFileDependency, IsFolderDependency,
and IsComponentDependency are declared with value receivers but the
ComponentDependency type uses pointer receivers elsewhere; change each method
signature to use a pointer receiver (e.g., func (d *ComponentDependency)
IsFileDependency() bool etc.) so the receivers match the implementations and
calls that expect pointer semantics, keeping the method bodies unchanged.
- Around line 134-135: The sentence incorrectly ties the append merge behavior
of dependencies.components to list_merge_strategy: append; update the wording so
it states that dependencies.components uses append-merge by design (child stacks
add their dependencies to parent dependencies) regardless of list_merge_strategy
in atmos.yaml, and remove or rephrase any implication that list_merge_strategy
controls this behavior; reference symbols: dependencies.components,
list_merge_strategy, atmos.yaml, and ensure the doc explains that this
dependency-merge semantics is intentional and documented elsewhere in the PR.

---

Outside diff comments:
In `@internal/exec/describe_affected_components.go`:
- Around line 190-199: The dependency checks are only executed when a settings
block exists because the call to checkSettingsAndDependenciesIndexed is nested
under if settingsSection ...; update the logic so dependency processing runs
even when settings is absent: extract the dependencies map
(dependencies.components) from componentSection and call the dependency-checking
routine (reuse or refactor checkSettingsAndDependenciesIndexed into a separate
function for pure dependency checks, or call it with a nil/empty
settingsSection) for componentName/stackName/ cfg.TerraformComponentType using
remoteStacks/currentStacks/filesIndex/includeSpaceliftAdminStacks/includeSettings
as before; apply the same change to the other analogous blocks that call
checkSettingsAndDependenciesIndexed so components without settings still get
their file/folder dependency checks.

In `@website/docs/stacks/dependencies/index.mdx`:
- Around line 259-263: Two identical link labels "[Component Dependencies]" in
the Related Documentation section are ambiguous; change the link text to
disambiguate the two targets—e.g., rename the first "[Component
Dependencies](/stacks/dependencies/components)" to "Component Dependencies (new
components)" or "Component Dependencies — Components" and rename the second
"[Component Dependencies](/stacks/settings/depends_on)" to "Component
Dependencies (legacy/settings)" or "Component Dependencies —
Settings/depends_on" so readers can tell them apart while leaving the hrefs
unchanged; update only the link labels in the file index.mdx where the two
duplicate "[Component Dependencies]" entries appear.

---

Duplicate comments:
In
`@tests/fixtures/scenarios/dependencies-components-inheritance/stacks/deploy/dev.yaml`:
- Line 20: Update the comment on Line 20 referencing "VPC inherits base
dependencies AND adds its own" to reflect the replace semantics for this
scenario: change the wording to state that the VPC replaces the base
dependencies (does not inherit them) and specify any VPC-specific dependencies
it defines, e.g., "VPC replaces base dependencies with its own" or "VPC uses
replace semantics — it does not inherit base dependencies; it defines its own."
Ensure the comment mentions "replace semantics" and "VPC" so readers understand
the behavior.
🪄 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: 5698cd83-17f2-4194-be7f-b1908e706225

📥 Commits

Reviewing files that changed from the base of the PR and between 847b7d6 and 495250b.

📒 Files selected for processing (10)
  • docs/prd/component-dependencies.md
  • docs/prd/tool-dependencies-integration.md
  • internal/exec/describe_affected_components.go
  • tests/fixtures/scenarios/dependencies-components-inheritance/stacks/catalog/base.yaml
  • tests/fixtures/scenarios/dependencies-components-inheritance/stacks/deploy/dev.yaml
  • website/blog/2026-03-14-dependencies-components.mdx
  • website/docs/stacks/dependencies/components.mdx
  • website/docs/stacks/dependencies/index.mdx
  • website/docs/stacks/settings/depends_on.mdx
  • website/docs/stacks/settings/index.mdx
✅ Files skipped from review due to trivial changes (1)
  • website/blog/2026-03-14-dependencies-components.mdx
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/fixtures/scenarios/dependencies-components-inheritance/stacks/catalog/base.yaml

Comment thread docs/prd/component-dependencies.md
Comment thread docs/prd/component-dependencies.md
… dependencies

Fix fixture comment to match replace merge semantics, fix PRD pointer
receiver signatures, and add comprehensive tests for dependency matching,
context conversion, and file/folder change detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add helmfile component (nginx) that depends on terraform VPC to test
cross-type dependency resolution. Add eks component with templated
stack reference ({{ .vars.stage }}) to test Go template evaluation
in dependency declarations. Both paths are now covered by the
DependenciesComponentsFormat integration test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@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: 1

♻️ Duplicate comments (1)
docs/prd/component-dependencies.md (1)

134-135: ⚠️ Potential issue | 🟡 Minor

Merge semantics wording is currently incorrect.

Line 134 ties append behavior to list_merge_strategy: append, but this feature is documented and implemented as append-merge by design for dependencies.components. Please remove the conditional wording so users don’t misconfigure inheritance behavior.

Suggested doc fix
-`dependencies.components` uses **append merge** behavior when `list_merge_strategy: append` is configured in `atmos.yaml`. Child stacks add their dependencies to parent dependencies.
+`dependencies.components` uses **append merge** behavior by design. Child stacks add their dependencies to parent dependencies.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/prd/component-dependencies.md` around lines 134 - 135, The wording
incorrectly ties append behavior of dependencies.components to the presence of
list_merge_strategy: append; update the text so it states that
dependencies.components uses append-merge by design (always inheriting child
stack entries into parent) and remove the conditional/“when list_merge_strategy:
append” phrasing; ensure references to dependencies.components and
list_merge_strategy: append remain for context but do not imply that the
append-merge behavior is configurable.
🧹 Nitpick comments (4)
internal/exec/describe_affected_utils_2_test.go (1)

720-725: Tighten unchanged-path assertions to prevent metadata leakage.

When expectChanged is false, also assert empty changedType and changedPath. This catches regressions where the function reports stale match metadata even when no change is detected.

Proposed test hardening
 			require.NoError(t, err)
 			assert.Equal(t, tt.expectChanged, changed)
 			if tt.expectChanged {
 				assert.Equal(t, tt.expectChangedType, changedType)
 				assert.Equal(t, tt.expectChangedPath, changedPath)
+			} else {
+				assert.Empty(t, changedType)
+				assert.Empty(t, changedPath)
 			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/exec/describe_affected_utils_2_test.go` around lines 720 - 725,
Tighten the test assertions in internal/exec/describe_affected_utils_2_test.go
so that when tt.expectChanged is false you also assert that changedType and
changedPath are empty; in the existing block that checks require.NoError(t, err)
and assert.Equal(t, tt.expectChanged, changed), add assertions for empty strings
(or nil/zero values as appropriate) for changedType and changedPath to ensure no
stale match metadata is returned by the function under test.
pkg/schema/dependencies_test.go (2)

100-104: Cover plugin kind in IsComponentDependency tests.

The PR adds cross-type support including plugin dependencies; this path should be asserted here too.

Diff suggestion
 		{
 			name:     "packer kind returns true",
 			dep:      ComponentDependency{Kind: "packer", Component: "ami"},
 			expected: true,
 		},
+		{
+			name:     "plugin kind returns true",
+			dep:      ComponentDependency{Kind: "plugin", Component: "custom"},
+			expected: true,
+		},
 		{
 			name:     "file kind returns false",
 			dep:      ComponentDependency{Kind: "file", Path: "config.json"},
 			expected: false,
 		},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/schema/dependencies_test.go` around lines 100 - 104, Add a test case
covering plugin-kind dependencies in the existing IsComponentDependency tests:
in pkg/schema/dependencies_test.go add an entry similar to the existing "packer
kind returns true" case but with dep: ComponentDependency{Kind: "plugin",
Component: "some-plugin"} and expected: true so that IsComponentDependency (and
the ComponentDependency type) is asserted to return true for Kind == "plugin".

15-35: Add empty-path boundary cases for file and folder kinds.

Right now, all file/folder scenarios include a populated path. Add empty-path cases to lock down classifier behavior for malformed entries.

Diff suggestion
 func TestComponentDependency_IsFileDependency(t *testing.T) {
 	tests := []struct {
 		name     string
 		dep      ComponentDependency
 		expected bool
 	}{
 		{
 			name:     "file kind returns true",
 			dep:      ComponentDependency{Kind: "file", Path: "config.json"},
 			expected: true,
 		},
+		{
+			name:     "file kind without path returns false",
+			dep:      ComponentDependency{Kind: "file"},
+			expected: false,
+		},
 		{
 			name:     "folder kind returns false",
 			dep:      ComponentDependency{Kind: "folder", Path: "src/"},
 			expected: false,
 		},
@@
 func TestComponentDependency_IsFolderDependency(t *testing.T) {
 	tests := []struct {
 		name     string
 		dep      ComponentDependency
 		expected bool
 	}{
 		{
 			name:     "folder kind returns true",
 			dep:      ComponentDependency{Kind: "folder", Path: "src/lambda"},
 			expected: true,
 		},
+		{
+			name:     "folder kind without path returns false",
+			dep:      ComponentDependency{Kind: "folder"},
+			expected: false,
+		},
 		{
 			name:     "file kind returns false",
 			dep:      ComponentDependency{Kind: "file", Path: "config.json"},
 			expected: false,
 		},
As per coding guidelines "Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages."

Also applies to: 50-70

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/schema/dependencies_test.go` around lines 15 - 35, Add boundary unit
tests for empty Path values: in the existing test table (in
pkg/schema/dependencies_test.go) add two cases using the ComponentDependency
struct — one with Kind: "file" and Path: "" and one with Kind: "folder" and
Path: "" — and assert the classifier returns false for both; ensure these
entries follow the same table-driven format as the other cases so they exercise
the file/folder validation logic in the same test function.
internal/exec/describe_dependents_test.go (1)

140-160: File/folder Kind coverage is good; consider adding cross-type Kind test.

The unit test covers kind: "file" and kind: "folder" well. Per PR objectives, kind also enables cross-type dependencies (e.g., kind: "helmfile"). While the integration test at line 1027 validates this via fixtures, adding a unit test case here would directly verify getComponentDependencies parsing for cross-type kinds.

Example addition:

map[string]any{"component": "chart", "kind": "helmfile"},

This is optional since integration tests do cover the behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/exec/describe_dependents_test.go` around lines 140 - 160, Add a unit
subcase to the test that ensures getComponentDependencies parses cross-type
kinds: extend the componentMap in the t.Run block to include an entry like
map[string]any{"component":"chart","kind":"helmfile"}, call
getComponentDependencies (same as existing), assert source equals
dependencySourceDependenciesComponents, then assert the returned deps includes
an entry with Component=="chart" and Kind=="helmfile" (and any relevant Path if
applicable); this verifies the parser handles non-file/folder kinds alongside
existing vpc/file/folder assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/prd/component-dependencies.md`:
- Line 198: Update the numbered list item text "3. Supports legacy
`file`/`folder` fields for backward compatibility" to include a trailing period
so it reads "3. Supports legacy `file`/`folder` fields for backward
compatibility." — edit the line in docs/prd/component-dependencies.md where that
exact list item appears.

---

Duplicate comments:
In `@docs/prd/component-dependencies.md`:
- Around line 134-135: The wording incorrectly ties append behavior of
dependencies.components to the presence of list_merge_strategy: append; update
the text so it states that dependencies.components uses append-merge by design
(always inheriting child stack entries into parent) and remove the
conditional/“when list_merge_strategy: append” phrasing; ensure references to
dependencies.components and list_merge_strategy: append remain for context but
do not imply that the append-merge behavior is configurable.

---

Nitpick comments:
In `@internal/exec/describe_affected_utils_2_test.go`:
- Around line 720-725: Tighten the test assertions in
internal/exec/describe_affected_utils_2_test.go so that when tt.expectChanged is
false you also assert that changedType and changedPath are empty; in the
existing block that checks require.NoError(t, err) and assert.Equal(t,
tt.expectChanged, changed), add assertions for empty strings (or nil/zero values
as appropriate) for changedType and changedPath to ensure no stale match
metadata is returned by the function under test.

In `@internal/exec/describe_dependents_test.go`:
- Around line 140-160: Add a unit subcase to the test that ensures
getComponentDependencies parses cross-type kinds: extend the componentMap in the
t.Run block to include an entry like
map[string]any{"component":"chart","kind":"helmfile"}, call
getComponentDependencies (same as existing), assert source equals
dependencySourceDependenciesComponents, then assert the returned deps includes
an entry with Component=="chart" and Kind=="helmfile" (and any relevant Path if
applicable); this verifies the parser handles non-file/folder kinds alongside
existing vpc/file/folder assertions.

In `@pkg/schema/dependencies_test.go`:
- Around line 100-104: Add a test case covering plugin-kind dependencies in the
existing IsComponentDependency tests: in pkg/schema/dependencies_test.go add an
entry similar to the existing "packer kind returns true" case but with dep:
ComponentDependency{Kind: "plugin", Component: "some-plugin"} and expected: true
so that IsComponentDependency (and the ComponentDependency type) is asserted to
return true for Kind == "plugin".
- Around line 15-35: Add boundary unit tests for empty Path values: in the
existing test table (in pkg/schema/dependencies_test.go) add two cases using the
ComponentDependency struct — one with Kind: "file" and Path: "" and one with
Kind: "folder" and Path: "" — and assert the classifier returns false for both;
ensure these entries follow the same table-driven format as the other cases so
they exercise the file/folder validation logic in the same test function.
🪄 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: 6fb8567c-c1e3-4bd0-b657-7e9a24bf77a4

📥 Commits

Reviewing files that changed from the base of the PR and between 495250b and 21a3e6b.

📒 Files selected for processing (7)
  • docs/prd/component-dependencies.md
  • internal/exec/describe_affected_utils_2_test.go
  • internal/exec/describe_dependents_test.go
  • pkg/schema/dependencies_test.go
  • tests/fixtures/scenarios/dependencies-components-inheritance/atmos.yaml
  • tests/fixtures/scenarios/dependencies-components-inheritance/components/helmfile/mock/helmfile.yaml
  • tests/fixtures/scenarios/dependencies-components-inheritance/stacks/deploy/dev.yaml
✅ Files skipped from review due to trivial changes (1)
  • tests/fixtures/scenarios/dependencies-components-inheritance/components/helmfile/mock/helmfile.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/fixtures/scenarios/dependencies-components-inheritance/stacks/deploy/dev.yaml

Comment thread docs/prd/component-dependencies.md Outdated
Add plugin kind test case, empty-path boundary cases for file/folder
classifiers, cross-type helmfile kind unit test for getComponentDependencies,
tighten empty-deps metadata assertions, and fix PRD terminal punctuation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aknysh
Andriy Knysh (aknysh) merged commit 49272a6 into main Mar 15, 2026
58 checks passed
@aknysh
Andriy Knysh (aknysh) deleted the osterman/docs-depends-on-fix branch March 15, 2026 15:07
@mergify mergify Bot removed the needs-cloudposse Needs Cloud Posse assistance label Mar 15, 2026
@github-actions

Copy link
Copy Markdown

Warning

Release Documentation Required

This PR is labeled minor or major and requires documentation updates:

  • Changelog entry - Add a blog post in website/blog/YYYY-MM-DD-feature-name.mdx
  • Roadmap update - Update website/src/data/roadmap.js with the new milestone

Alternatively: If this change doesn't require release documentation, remove the minor or major label.

@github-actions

Copy link
Copy Markdown

These changes were released in v1.210.0-rc.0.

@github-actions

Copy link
Copy Markdown

These changes were released in v1.210.0-test.25.

Erik Osterman (Cloud Posse) (osterman) added a commit that referenced this pull request Aug 6, 2026
…tion guide

Step 3 of the migration workflow still mapped mock_outputs to the YQ // "default"
pattern, contradicting the mocks:/--use-mocks mapping documented a few paragraphs
earlier. Quotes the YQ default expressions for consistency with
atmos-yaml-functions/SKILL.md and atmos-components/SKILL.md.

dag-concurrent-execution.md had two more self-contradictions: the Subprocess
Execution section still described the os.Stdout race that Phase 1 already fixed
(terraform_plan_diff.go now captures via bytes.Buffer), and the Resolved Questions
section claimed cross-type dependency syntax was "solved by PR #2193" — traced the
code and found pkg/scheduler/adapters/terraform.go explicitly skips any dependency
whose kind isn't "terraform", so the kind field is schema-parseable but not yet
consumed by the scheduler; corrected to match the already-accurate Phase 3 status.

terragrunt.mdx's list-affected example claimed to compare against main by default
without passing --ref; list affected has no --base flag (unlike describe affected),
so made the comparison explicit with --ref main instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
zack-is-cool pushed a commit to zack-is-cool/atmos that referenced this pull request Sep 8, 2026
…dposse#2878)

* docs(prd): correct stale status headers found during Terragrunt migration research

Checkpoint before syncing this branch with origin/main — these fixes were made
against an older snapshot and will likely need rework once current upstream
content is merged in.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(migration): add Terragrunt migration skill reference and correct stale PRD statuses

Adds the atmos-migration skill's Terragrunt reference (classic and Stacks
patterns, concept mapping, migration workflow), hands-on-validated against a
real Terragrunt Stacks example run end to end on the floci/aws emulator.
Corrects four PRD status headers that had gone stale relative to shipped
code, fixes pre-existing EditorConfig indentation violations the commit hook
surfaced in two of those files, and documents the mocks/--use-mocks feature
in the website Terragrunt migration guide as the direct equivalent of
mock_outputs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(docs): use clean !terraform.state syntax and fix EditorConfig indentation

CI caught two real issues in the new Terragrunt migration reference:
- Two examples used the legacy doubled-double-quote YQ escaping
  (!terraform.state x ".field // ""default""") instead of the clean current
  syntax (!terraform.state x .field // "default"), which scripts/check-
  terraform-example-syntax.sh flags outside its designated compatibility
  fixtures.
- The "Migration Workflow" numbered list used 3-space continuation
  indentation, not a multiple of the repo's 2-space EditorConfig setting.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(docs): address CodeRabbit findings and field-test gaps on Terragrunt migration guide

Reconciles PRD status claims that contradicted themselves (dag-concurrent-execution.md
Phase 3 is only partially shipped, not fully; custom-hooks.md's relative "today" date),
completes the from-terragrunt.md 5-level merge listing, and fixes a hallucinated
`settings.terraform.provider_overrides` key found via hands-on field testing. Also
recommends `atmos list affected` over `atmos describe affected` for human-run migration
comparisons (table output vs. a wall of YAML), notes both diff committed trees only,
and updates the Change Tracking table to the current `dependencies.files`/`folders`
syntax instead of the legacy inline `kind: file`/`kind: folder` form.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(docs): resolve second CodeRabbit review round on Terragrunt migration guide

Step 3 of the migration workflow still mapped mock_outputs to the YQ // "default"
pattern, contradicting the mocks:/--use-mocks mapping documented a few paragraphs
earlier. Quotes the YQ default expressions for consistency with
atmos-yaml-functions/SKILL.md and atmos-components/SKILL.md.

dag-concurrent-execution.md had two more self-contradictions: the Subprocess
Execution section still described the os.Stdout race that Phase 1 already fixed
(terraform_plan_diff.go now captures via bytes.Buffer), and the Resolved Questions
section claimed cross-type dependency syntax was "solved by PR cloudposse#2193" — traced the
code and found pkg/scheduler/adapters/terraform.go explicitly skips any dependency
whose kind isn't "terraform", so the kind field is schema-parseable but not yet
consumed by the scheduler; corrected to match the already-accurate Phase 3 status.

terragrunt.mdx's list-affected example claimed to compare against main by default
without passing --ref; list affected has no --base flag (unlike describe affected),
so made the comparison explicit with --ref main instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* chore: trigger CI re-run

* fix(mocks): correct provenance rendering, error wording, and // default parity

A field test of --use-mocks found `describe component` silently rendering
empty output whenever a component's provenance path wasn't matched due to an
unnormalized lookup, a mock-output error that mislabeled the output name as a
component name, and a YQ `//` default that only rescued a missing key inside
a declared `mocks` map, not a component with no `mocks` section at all --
inconsistent with how `//` already rescues real state. Also cross-references
the mocks:/--use-mocks feature from the docs pages and skill most likely to
be read first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(snapshots): regenerate describe_component golden snapshots after provenance fix

The filterEmptySections fix (6c22503) corrected describe_component to stop
silently dropping real sections (backend, metadata, env, overrides) that lack
a stack-root section of the same name. CI caught the resulting golden
snapshot drift on both linux and macos; regenerated via
`-regenerate-snapshots` per CLAUDE.md, verified the diffs only add the
previously-hidden, now-correct content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(provenance): address CodeRabbit review on PR cloudposse#2878

Add periods to the rendering-constant comments (godot's inline-comment
scope missed these, but CLAUDE.md's comment convention still applies), and
cover the array-element provenance path (vars[0].foo) alongside the
already-tested dot-nested form. The trailing-period finding on
ErrTerraformMockOutputNotDeclared was already resolved by an earlier commit
in this PR — no change needed there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(test): widen RunSession timeouts to fix Windows CI flake

Acceptance Tests (windows, shard 4/10) failed with ErrWaitTimeout in
TestRunSessionExecutesScriptedShellActions and
TestRunSessionAppliesDirectoryAndEnvironment: the write->echo->match round
trip against a spawned child (no PTY on Windows, unlike session_unix.go)
never completed within the 2s wait/3s context budget. Widened both to 8s/15s
across all four RunSession-based tests; no production code changed since
static review found no concrete pipe-wiring bug. Not reproduced locally (no
Windows environment available) — documented in docs/fixes/ per this repo's
convention for unconfirmed Windows-only CI fixes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(fixes): address CodeRabbit findings on PR cloudposse#2878

- Add a text language tag to the failure-output fenced block (markdownlint
  MD040).
- Correct the documented timeout values to match what actually shipped after
  merge-conflict resolution: 10s per wait (not 8s), and 25s outer context for
  TestRunSessionAppliesDirectoryAndEnvironment's two sequential waits (not
  15s) — the outer context must exceed the sum of sequential wait timeouts,
  not just one of them, per waitForOutput's ctx.Done()-vs-deadline-timer race.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(fixes): document CI exit-code test failure as a registry network flake

Acceptance Tests (linux, shard 9/10) failed
TestCLICommands/atmos_exit_code_should_be_same_as_command_exit_code_(2) with
"Expected exit code 2, got 1". The real cause was tofu init timing out
reaching registry.opentofu.org (context deadline exceeded) before any plan
could run -- confirmed the fixture has no registry-mirror config to regress,
and the sibling (0)/(1) exit-code cases in the same file passed. No code
change: there's nothing in this repo that fixes a transient outage on a
public third-party registry, and loosening the exit-code assertion would
mask a real CLI exit-code-propagation regression if one ever occurs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(ci): don't fail test-required/k3s-required on a cancelled run

All five attached failure logs (Acceptance Tests linux/macos/windows,
[k3s] demo-helmfile, Build windows) traced to one event: workflow run
33394180592 on this PR was cancelled (confirmed via gh api), not failed. The
test/k3s matrix jobs were skipped as a result, but the -required gate jobs
(if: always()) still ran and misreported the cancellation as a hard failure
("expected 10 shard jobs, found 0" / "k3s matrix result was 'skipped'").

needs.test.result and needs.k3s.result both report "skipped" for a genuine
upstream failure and for a whole-run cancellation alike, so they can't
distinguish the two - cancelled() can, and is the fix. It's only valid in an
if:, not inside a run: script (caught by actionlint), so both gates get a
"Skip verification" step under if: cancelled() plus if: !cancelled() on
their existing check steps, leaving the fail-loudly-on-genuine-anomalies
logic untouched for real failures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* [autocommit] formatting fixes

* fix(ci): pin cuelang.org/go's NOTICE URL to a deterministic override

Review Dependency Licenses failed: NOTICE had "URL: Unknown" for
cuelang.org/go, but a fresh generate-notice.sh run resolved a real URL,
tripping the out-of-date check. Root cause was a race, not one bad run:
this branch's merge commit already had the correct URL, but a subsequent
[autocommit] formatting fixes commit (atmos-pro[bot]) regenerated NOTICE
under a network condition where go-licenses' live resolution for
cuelang.org/go failed, silently reverting it to "Unknown" and committing
that regression - exactly the oscillation scripts/generate-notice.sh's
REPO_OVERRIDES mechanism exists to prevent for modules go-licenses can't
resolve reliably, cuelang.org/go just wasn't in the list yet.

Added it (repo github.com/cue-lang/cue, no tag prefix, LICENSE path),
which reconstructs the exact URL CI itself resolved
(https://github.com/cue-lang/cue/blob/v0.16.1/LICENSE) from go.mod's
pinned v0.16.1 with no network dependency, and applied that one-line NOTICE
fix by hand: a local generate-notice.sh run silently produced a truncated
102-dependency report (vs. CI's 643) with 0 Apache-2.0/BSD licenses found,
consistent with this machine lacking a Linux-targeting C cross-compiler for
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 - so that broken local output was
discarded rather than committed, and the NOTICE line was hand-verified
against the override's own URL-construction formula and go.mod's version
instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(ci): retry go install go-licenses on transient sum.golang.org failures

Review Dependency Licenses failed installing go-licenses@v1.6.0: a
mid-stream HTTP/2 reset (stream ID 1155; INTERNAL_ERROR) reading
sum.golang.org during go install's go.sum verification, unrelated to any
actual dependency problem and unrelated to the immediately preceding commit
on this branch (confirmed via gh api against head_sha 5ac5d97, which only
touched an unrelated NOTICE URL override).

Same failure class already fixed once for go mod download
(docs/fixes/2026-08-25-build-atmos-go-mod-download-retry.md, later ported to
magefiles/build.go's runGoModDownload) - just hit a different network call
(go install's dependency-graph resolution) in a different script. Wrapped
generate-notice.sh's bare go install in the same 3-attempt/15s-backoff until
loop, matching .github/actions/download-artifact-retry's convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(docs): replace a literal tab with spaces in a fix-log fenced block

Run pre-commit hooks failed atmos-validate-editorconfig: a fenced code block
in docs/fixes/2026-08-31-notice-go-licenses-install-retry.md quoted a Go
toolchain error message verbatim, including its original tab-indented
continuation line - violating this repo's *.md indent_style=space rule.
Replaced the literal tab with two spaces (matching indent_size=2), content
otherwise unchanged. Scanned every other 2026-08-31 fix-log doc added this
session for the same issue; none found.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(blog): bump terraform-component-mocks date to when its content changed

fix(mocks) commit 6c22503 edited this post's body (the // default
behavior clarification) on 2026-08-06, but the post kept displaying/sorting
under its original 2026-07-15 publish date since Docusaurus has no separate
date. Added an explicit date: frontmatter override for the edit date,
matching this repo's existing convention for date overrides (e.g.
2026-01-02-unified-task-runner.mdx).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(security): remediate 4 Dependabot alerts

- google.golang.org/grpc v1.82.1 -> v1.83.1 (go get + go mod tidy),
  bumping compatible transitive deps
- website pnpm overrides: browserslist -> ^4.28.7, postcss-selector-parser
  (^6.0.11 and ^6.0.16 requesters) -> ^6.1.3
- regenerate NOTICE to reflect the grpc bump

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(fixes): document atmos_vendor_pull DNS-resolution CI flake

Acceptance Tests (macos, shard 4/10) failed with "tty did not match
pattern \"Vendored 3 components\"" because git itself could not resolve
github.com on the runner (OS-level resolver failure, corroborated by the
same job's Harden Runner network log) -- not a code regression. No code
change; re-running the job is expected to pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix: address CodeRabbit review findings on mocks docs, fix-logs, and noticegen tests

- agent-skills/skills/atmos-migration/references/from-terragrunt.md: correct
  the mock_outputs -> mocks migration guidance -- Terragrunt scopes
  mock_outputs per dependency consumer, Atmos scopes mocks per producer
  component (shared by every consumer). Document that a shared mock value
  only works when every consumer agrees on it, and that a genuinely
  different per-consumer value needs its own producer component instance.
- docs/fixes/2026-08-31-notice-go-licenses-install-retry.md: the retry loop
  now lives in tools/noticegen/report.go's ensureGoLicenses (tested in
  tools/noticegen/report_test.go), not scripts/generate-notice.sh, which was
  deleted when the NOTICE generator was rewritten as a Go tool. Updated the
  title, Context, Changes, and Validation sections accordingly.
- docs/fixes/2026-08-31-required-check-gates-fail-on-cancelled-run.md:
  reworded "passing (all-steps-skipped) job" to "a passing job whose
  verification steps are skipped" -- the explicit Skip verification step
  still runs, so the job isn't literally all-skipped.
- tools/noticegen/report.go: extracted lookPathGoLicenses as a package-level
  var (previously a direct exec.LookPath call inside ensureGoLicenses) so
  tests can force the "not found" branch deterministically.
- tools/noticegen/report_test.go: both retry tests now inject
  lookPathGoLicenses to return exec.ErrNotFound, instead of relying on the
  real PATH not already containing go-licenses -- which it may, e.g. from a
  prior local run, silently skipping runGoInstall and making the retry
  assertions vacuous.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix: address CodeRabbit findings on SKILL.md link casing and vendor-pull fix-log wording

- agent-skills/skills/atmos-migration/SKILL.md: lowercase the
  from-terragrunt.md reference link's display text to match the actual
  lowercase repo path and the style of the overview section's own link.
- docs/fixes/2026-09-02-vendor-pull-dns-resolution-flake.md: correct the
  fixture description -- tests/fixtures/scenarios/vendor/vendor.yaml
  exercises a local file:// source and a git::https:// source, not an OCI
  source or a separate plain-HTTPS source.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(security): remediate 3 Dependabot/CodeQL alerts

- golang.org/x/crypto v0.55.0 -> v0.56.0 (go get + go mod tidy), fixing two
  govulncheck alerts (GO-2026-6354, GO-2026-6355): a malicious SSH peer could
  deadlock a connection via crafted channel messages
  (golang.org/x/crypto/ssh). No direct callers in this repo beyond
  pkg/store/providers/github_actions_client.go; verified via go build and
  pkg/store/... tests.
- website pnpm override: fast-uri@^3 -> ^3.1.6 (patched; published 10 days
  ago, clears this repo's 7-day minimum-release-age cooldown).
- regenerate NOTICE to reflect the x/crypto bump.

qs (Dependabot cloudposse#283/cloudposse#284, patched at 6.16.0) is intentionally NOT bumped:
6.16.0 was published 4 days ago, still inside website/.npmrc's 7-day
minimum-release-age cooldown -- forcing it in via
minimumReleaseAgeExclude would defeat the cooldown's purpose. Will pick it
up once it clears.

browserslist (cloudposse#281/cloudposse#282) and postcss-selector-parser (cloudposse#280) are already
fixed on this branch from an earlier commit; GitHub just hasn't re-scanned
yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(ci): whitelist go.googlesource.com/go.dev/pkg.go.dev for CodeQL Go jobs

StepSecurity's blocked-call detections (analyzed via the stepsecurity MCP
server) showed the analyze and govulncheck jobs' harden-runner egress
policies blocking go.googlesource.com, go.dev, and pkg.go.dev during Go
module/toolchain resolution -- both are trusted Go project domains
(GOTOOLCHAIN auto-download and go-getter's git-host fallback path).
go.googlesource.com was already allowed for govulncheck but missing from
analyze; go.dev and pkg.go.dev were missing from both. Also removed a
duplicate storage.googleapis.com entry in analyze's list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: atmos-pro[bot] <173522224+atmos-pro[bot]@users.noreply.github.com>
Co-authored-by: Andriy Knysh <aknysh@users.noreply.github.com>

This branch was successfully deployed

1 active deployment
preview — ee561bdf Deployed Mar 15, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features that do not break anything size/l Large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants