Skip to content

fix(locals): stack-name derivation reads vars/settings/env merged across imports (#2374) - #2623

Open
Andriy Knysh (aknysh) wants to merge 10 commits into
mainfrom
aknysh/locals-name-template-imports
Open

Andriy Knysh (aknysh) wants to merge 10 commits into
mainfrom
aknysh/locals-name-template-imports

Conversation

@aknysh

@aknysh Andriy Knysh (aknysh) commented Jun 17, 2026 •

Copy link
Copy Markdown
Member

what

  • Fix stack-name derivation so name_template can reference identifying values that live in a parent _defaults.yaml import.
  • deriveStackNameFromTemplate now feeds vars + settings + env to the template (previously only vars), and rejects any rendering that contains <no value> (falling back to the filename) so a malformed identifier never reaches downstream code.
  • New deriveStackNameSections performs a lite, YAML-only import walk that merges vars/settings/env across the leaf file and its transitive imports (imports are the base, the leaf overrides). It does not process Go templates or YAML functions; unresolvable paths and non-pure-YAML files are skipped; cycles are broken with a visited set.
  • Adds two fixtures and integration tests for the describe locals path, plus unit tests for the new functions.

why

  • locals seems to be broken #2374 — with name_template: "{{ .settings.* }}", describe locals -s <name> returned stack not found because the derivation only carried vars, never settings. So a settings-based name template could never resolve.
  • locals breaks stack listing when name_template vars come from parent imports #2343 (derivation part) — with name_template referencing a namespace defined in a parent _defaults.yaml, the leaf-only render produced a malformed name like -prod because imported vars were never merged before derivation.
  • Both reproduce only when the leaf stack file also declares a locals: block (which routes derivation through the locals pre-pass). The new integration tests were verified failing before this change (stack not found: acme-prod / cloudlabs-plat-ue1-prod) and passing after.

references

Summary by CodeRabbit

Release Notes

Bug Fixes

  • Fixed stack-name derivation when name_template references values provided via imported parent YAML defaults (vars and .settings).
  • Improved stack-name template evaluation by exposing vars, settings, and env during derivation and safely handling missing values.
  • Prevented malformed stack names by rejecting unresolved template results.

Tests

  • Added regression coverage for imported vars/settings in describe locals, including cycle handling and invalid import scenarios.

Documentation

  • Documented the stack-name derivation fix and the updated import/merge behavior.

@aknysh
Andriy Knysh (aknysh) requested a review from a team as a code owner June 17, 2026 02:40
@aknysh Andriy Knysh (aknysh) added the patch A minor, backward compatible change label Jun 17, 2026
@atmos-pro

atmos-pro Bot commented Jun 17, 2026 •

Copy link
Copy Markdown
Contributor

Tip

Atmos Pro  

No affected stacks workflow was detected for this pull request.
If this is expected, no action is needed.
Learn More. Ask AI.

@github-actions github-actions Bot added the size/m Medium size PR label Jun 17, 2026
@aknysh Andriy Knysh (aknysh) self-assigned this Jun 17, 2026
@github-actions

github-actions Bot commented Jun 17, 2026 •

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@mergify

mergify Bot commented Jun 17, 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 Jun 17, 2026
@coderabbitai

coderabbitai Bot commented Jun 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

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: 397e3b4a-5d68-472b-8ace-46a0d6cefc30

📥 Commits

Reviewing files that changed from the base of the PR and between b477431 and 1f859c4.

📒 Files selected for processing (4)
  • internal/exec/describe_locals.go
  • internal/exec/describe_locals_test.go
  • pkg/config/stack_auth_helpers_test.go
  • pkg/config/stack_auth_loader.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/config/stack_auth_helpers_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/exec/describe_locals.go

📝 Walkthrough

Walkthrough

Fixes deriveStackName in the describe locals pipeline to merge vars, settings, and env from imported parent stack files before evaluating stacks.name_template. Adds a YAML-only DFS import walk with cycle detection, expands deriveStackNameFromTemplate to accept all three sections, and rejects rendered names containing <no value>. Exports a shared import-resolver function. Two new fixture scenarios and corresponding unit and integration tests are included.

Changes

Stack-name derivation fix with import overlay

Layer / File(s) Summary
deriveStackName and deriveStackNameFromTemplate corrections
internal/exec/describe_locals.go
deriveStackName now calls a new import-walk helper to compute merged vars/settings/env before overlaying the caller's varsSection and invoking deriveStackNameFromTemplate. That function is expanded to accept all three sections, builds full template data with nil-safe empty-map defaults, forces ignoreMissingTemplateValues=true, and rejects any rendered name containing <no value> by falling back to the filename.
YAML-only import-walk helpers
internal/exec/describe_locals.go
Introduces deriveStackNameSections, deriveStackNameSectionsInto, and supporting functions that perform best-effort cycle-safe DFS over the import graph, parse files as plain YAML, shallow-merge vars/settings/env with imports-first/leaf-last semantics, resolve paths via ResolveStackImportFiles, and skip failures silently.
Unit tests for template sections, import walk, and helpers
internal/exec/describe_locals_test.go
Six new unit test functions cover template rendering from all three sections, <no value> and unresolved-marker rejection, section extraction and overlay merging, import cycle breaking, malformed template fallback, and invalid import section handling.
Test fixture scenarios
tests/fixtures/scenarios/locals-name-template-vars-imports/..., tests/fixtures/scenarios/locals-name-template-settings-imports/...
Two new fixture scenarios each provide an atmos.yaml (with name_template referencing .vars.* or .settings.*), a _defaults.yaml supplying identity values, and a prod.yaml leaf stack with a locals: block to exercise the fixed derivation path.
Integration regression tests
tests/cli_locals_test.go
TestLocalsNameTemplateVarsFromImportsDescribeLocals and TestLocalsNameTemplateSettingsFromImportsDescribeLocals run ExecuteDescribeLocals against the new fixtures and assert the returned locals map contains the expected leaf-file values.
Fix documentation
docs/fixes/2026-06-16-locals-name-template-import-derivation.md
New markdown fix page documents the two root defects (missing sections in template data, no import merging), the YAML-only overlay approach, <no value> rejection behavior, affected test fixtures, and remaining out-of-scope pipeline issues.
Export ResolveStackImportFiles from stack_auth_loader
pkg/config/stack_auth_loader.go, pkg/config/stack_auth_helpers_test.go
Exposes the import-path resolver function as ResolveStackImportFiles (previously unexported), updates its call site in mergeImportedAuthDefaults, and updates the corresponding test to use the renamed function.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • cloudposse/atmos#2303: Both PRs use ResolveStackImportFiles for traversing YAML import chains to resolve identity values across stack defaults.
  • cloudposse/atmos#2619: Directly modifies the same deriveStackNameFromTemplate code path in internal/exec/describe_locals.go, specifically around ProcessTmpl and ignoreMissingTemplateValues handling.

Suggested reviewers

  • osterman
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately summarizes the main fix: stack-name derivation now merges vars/settings/env across imports to resolve name_template references.
Linked Issues check ✅ Passed Code changes directly address issue #2374: name_template can now resolve settings/vars from imports, reject malformed results, and enable describe locals to work correctly.
Out of Scope Changes check ✅ Passed All changes are scoped to locals-based name derivation with test fixtures and helpers. The refactoring of resolveAuthImportPaths to ResolveStackImportFiles is a necessary supporting change for consistent import resolution.
Docstring Coverage ✅ Passed Docstring coverage is 94.74% which is sufficient. The required threshold is 80.00%.

✏️ 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 aknysh/locals-name-template-imports

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[bot]
coderabbitai Bot previously approved these changes Jun 17, 2026
@codecov

codecov Bot commented Jun 17, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.55556% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.46%. Comparing base (3562be2) to head (e94adf5).
⚠️ Report is 266 commits behind head on main.

Files with missing lines Patch % Lines
internal/exec/describe_locals.go 79.71% 7 Missing and 7 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2623      +/-   ##
==========================================
+ Coverage   80.44%   80.46%   +0.01%     
==========================================
  Files        1444     1444              
  Lines      134759   134824      +65     
==========================================
+ Hits       108406   108482      +76     
+ Misses      20348    20329      -19     
- Partials     6005     6013       +8     
Flag Coverage Δ
unittests 80.46% <80.55%> (+0.01%) ⬆️

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

Files with missing lines Coverage Δ
pkg/config/stack_auth_loader.go 97.93% <100.00%> (ø)
internal/exec/describe_locals.go 88.00% <79.71%> (-2.64%) ⬇️

... and 8 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…rivation

Address review feedback: don't reinvent helpers that already exist, and keep
shared helpers in a general package.

- Promote pkg/config's import-path resolver to an exported, generally-named
  `ResolveStackImportFiles` (was `resolveAuthImportPaths`). It is a lite,
  YAML-only resolver already used by the auth-defaults pre-pass; the stack-name
  derivation pre-pass now reuses it so both resolve imports identically.
- Delete the duplicated helpers from describe_locals.go: `resolveImportFilePathsForStackName`,
  `globMatchesWithExt`, `hasYAMLExt`, `findFirstExistingWithExt`, `mergeMapShallow`,
  and the `stackNameImportYAMLExts` var. Map merges now use stdlib `maps.Copy`;
  import resolution delegates to `cfg.ResolveStackImportFiles`.
- deriveStackNameSections resolves the logical stack file name to a path under the
  stacks base so the shared resolver (which resolves `./` imports against the
  importing file's directory) sees a real path.

No behavior change for stack-name derivation; the describe-locals integration
tests and unit tests still pass, and the auth-loader tests cover the shared
resolver. All touched functions remain >=80% covered.
@mergify

mergify Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

💥 This pull request now has conflicts. Could you fix it Andriy Knysh (@aknysh)? 🙏

@mergify mergify Bot added the conflict This PR has conflicts label Sep 9, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflict This PR has conflicts needs-cloudposse Needs Cloud Posse assistance patch A minor, backward compatible change size/m Medium size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

locals seems to be broken

1 participant