feat: describe affected evaluates all provisioned component sections @osterman (#2573)
## what- Fix
atmos describe affectedso it detects changes in every provisioned component section, not justvars/env/settings/metadata/source/provision. - Newly evaluated sections:
providers,required_providers(provider versions),required_version,hooks,generate,backend,backend_type,remote_state_backend,remote_state_backend_type,auth,command, anddependencies— including scalar sections (previously only map sections were compared). - Add a configurable
describe.affected.sectionssetting inatmos.yamlthat fully replaces the evaluated set (e.g. to track a custom section or narrow the list);metadata/settingsare always evaluated. - Refactor the three component processors to a single table-driven comparison, add a documented "Evaluated sections" list, tests, a changelog blog post, and a roadmap milestone.
why
- The comparison ran against a hand-maintained allow-list that had drifted out of sync with what Atmos actually merges into a component, so changes to
providers,hooks, provider versions,backend, etc. were silently missed — a false negative that could let CI pipelines skip components that genuinely changed. - The table is now tied (via comments) to the sections written in
stack_processor_merge.go, and the new config setting gives users an escape hatch so the bug class can't quietly return. locals,overrides,inheritance, andretryare intentionally excluded (they either fold into other sections or are execution-time only).
references
- Docs: Evaluated sections and
describe.affected.sections
Summary by CodeRabbit
-
New Features
- Describe now evaluates and reports changes across a comprehensive set of top-level component sections (including scalar sections) with per-section reasons; first changed section becomes the headline reason.
- Added configurable describe.affected.sections to fully replace the default evaluated set (metadata/settings remain always evaluated).
-
Documentation
- Blog and CLI/config docs updated with evaluated-sections details, output reason entries, and configuration examples.
-
Tests
- Added tests for section evaluation, equality behavior, remote-locator logic, and override/no-false-positive cases.
-
Chores
- Updated snapshots, roadmap, CI workflow pins, link-checker exclusions, and changelog guidance.
feat(hooks): terraform init lifecycle hooks + --skip-hooks before-* fix @osterman (#2574)
## what- Fix
--skip-hooksfor before- hooks.* Previously it only skippedafter-*hooks;before-terraform-plan/apply/deployhooks ran regardless. Now--skip-hooks(skip all) and--skip-hooks=name1,name2(skip by name) are honored symmetrically for before and after events. - Add
before-terraform-initandafter-terraform-initlifecycle hooks for theatmos terraform initcommand.after-terraform-initis new;before-terraform-initwas documented but never dispatched to user hooks — now it fires. They run through the samerunHooks/RunAllpath, so the skip fix applies to them too. - Add tests (real parsed Cobra flag, not
viper.Set), strengthen hook-inheritance coverage with a fixture proving top-levelterraform.hooks:is inherited by every component (andcomponents.terraform.hooks:is not), update the Hooks docs, blog post, and roadmap.
why
--skip-hooksis a global flag bound to Viper insideRunE, but before-* hooks run earlier inPreRunE— soviper.GetString("skip-hooks")never saw the CLI value and before-hooks fired anyway. The flag is now resolved directly from the parsed command (Viper/ATMOS_SKIP_HOOKSfallback), mirroring how--ciand--verboseare read inPreRunE.- Init had no user-hook surface at all:
init.gowired no hooks and theBeforeTerraformInitevent was never dispatched. WiringPreRunE/PostRunEon the init command (like plan/apply/deploy) closes the lifecycle gap so teams can validate tooling, vendor sources, or notify systems aroundterraform initdeclaratively. - The previous skip tests injected via
viper.Setwith anilcommand, sidestepping the exact flag-binding lifecycle that was broken — which is how the bug shipped; the new tests fail against the old implementation.
references
- Hooks documentation:
/stacks/hooks - Note:
before-/after-terraform-initfire on the explicitatmos terraform init, not the implicit init that plan/apply run.
Summary by CodeRabbit
- New Features
- Added Terraform init lifecycle event: after-terraform-init (alongside before-terraform-init); Terraform-scoped default hooks can be inherited by Terraform components.
- Bug Fixes
- Fixed --skip-hooks precedence so CLI flag reliably overrides env/config and consistently skips before/after hook phases.
- Clarified hook scope handling so misplaced hook keys aren’t incorrectly applied.
- Documentation
- Blog, docs, and roadmap updated to describe init hook events and skip-hooks behavior.
- Tests
- Expanded coverage for hook inheritance, scope, init wiring, event filtering, and skip-hooks CLI behavior.
- Chores
- CI Codecov step made non-fatal for transient upload errors.
feat(auth): share single OIDC session across aws/iam-identity-center providers @Benbentwo (#2553)
## what- Refactors the
aws/iam-identity-center(AWS SSO) provider so that multiple providers pointing at the same SSO portal (identicalstart_url+region) share a single OIDC token — one browser flow now unlocks every provider instead of one flow per provider. - Adds silent refresh-token renewal via
ssooidc:CreateTokenwithgrant_type=refresh_token, so a single browser interaction holds for the full portal session (~8h) rather than re-prompting every hour. - Introduces an in-process
sessionTokenStore(keyed bysha1(start_url|region)) with per-session mutexes that single-flight concurrent device-auth flows; re-keys the on-disk cache fromaws-sso/<provider>/token.jsontoaws-sso/sessions/<sha1>.jsonin the AWS SDKssocreds-compatible format. - Adds the design PRD (
docs/prd/aws-sso-session-support.md), a changelog blog post, and a shipped roadmap milestone under the Unified Authentication initiative.
why
- A common setup has one provider per environment (dev/staging/prod) all backed by the same corporate SSO portal; previously
atmos auth loginlaunched the browser flow once per provider, contradicting AWS's own "credentials have been shared successfully" single-sign-in experience. - The legacy flow re-ran the full browser interaction on every ~1h access-token expiry and keyed its cache by provider name, so renaming a provider silently invalidated a still-valid token — both are eliminated here with zero
atmos.yamlconfig changes.
references
- PRD:
docs/prd/aws-sso-session-support.md - AWS CLI token provider docs: https://docs.aws.amazon.com/cli/latest/userguide/sso-configure-profile-token.html
- AWS SDK for Go v2
ssocreds: https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/credentials/ssocreds
Summary by CodeRabbit
-
New Features
- Shared AWS SSO sessions across providers for the same portal (start URL + region), reducing duplicate logins and browser prompts.
- Silent refresh via refresh tokens to renew credentials without a browser; per-session locking prevents concurrent device-auth flows.
- Session-keyed on-disk cache (compatible with AWS SDK patterns); logout clears shared session data; added session telemetry.
-
Documentation
- Product spec and blog post describing session sharing, cache format, refresh behavior, and rollout plan.
-
Tests
- Added/updated tests validating session sharing, cache semantics, isolation, refresh logic, and concurrency.
feat: implement !append YAML function for list concatenation @osterman (#1513)
## what - Implements the `!append` YAML function that allows fine-grained control over list merging behavior in Atmos stack configurations - Lists tagged with `!append` will be concatenated with base values instead of replaced - Adds comprehensive unit tests and integration test fixtureswhy
- Resolves the ongoing challenge of needing to concatenate lists on a case-by-case basis
- Currently, users have to fall back to using maps instead of lists when they need append behavior
- This is particularly important for fields like
depends_onwhere appending is often the desired behavior rather than replacement - The
!appendtag provides opt-in, per-field control that works alongside the globallist_merge_strategysetting
Key Features
- Opt-in behavior: Only lists explicitly tagged with
!appenduse append mode - Works alongside global settings: The
!appendtag works independently of the globallist_merge_strategysetting - Nested support: Works with deeply nested configurations
- Backward compatible: No impact on existing configurations without the tag
Example Usage
# base.yaml
components:
terraform:
eks:
settings:
depends_on:
- vpc
- iam-role
# override.yaml
components:
terraform:
eks:
settings:
depends_on: !append # This tag indicates append mode
- rds
- elasticache
# Result: depends_on = [vpc, iam-role, rds, elasticache]Testing
- ✅ All unit tests pass
- ✅ Build succeeds without errors
- ✅ Linting passes with no issues
- ✅ Code follows Atmos conventions and patterns
references
- Linear issue: DEV-2980
- Documentation:
!appendYAML function - Changelog: blog post
append-yaml-function; roadmap milestone updated (Extensibility initiative)
🤖 Generated with Claude Code
Summary by CodeRabbit
- New Features
- Added a !append YAML function to append items to lists during configuration merging (per-field, preserves order, supports nested lists/maps, interacts with global list-merge strategies).
- Tests
- Added comprehensive unit and integration tests covering append-tag helpers, parsing, merging, and end-to-end scenarios.
- Documentation
- Added docs, examples, blog post, and index updates explaining !append usage and behavior.
- Chores
- Updated website roadmap/metadata and package config; added a sentinel error alias.
🚀 Enhancements
fix(stacks): honor component list_merge_strategy in metadata.inherits… @JaseKoonce (#2565)
what
-
settings.list_merge_strategy set on a component now applies when merging lists via metadata.inherits
-
Adds tests covering append, replace, and merge strategies across single and multi-level inheritance
chains
why
-
Component-level list_merge_strategy was only honored on the import/stack merge path (fixed in #2480).
The metadata.inherits resolution path always used the global atmosConfig, so per-component overrides were
silently ignored -
A component with list_merge_strategy: append inheriting two bases would get last-wins ([from_b]) instead
of the expected accumulated result ([from_a, from_b])
references
Summary by CodeRabbit
-
Improvements
- Component inheritance now applies per-component list merge strategies during metadata-based inheritance so inherited lists are accumulated, replaced, or merged by index according to the inheriting component’s settings across multi-level chains.
-
Tests
- Added integration tests and fixture scenarios validating append, replace, multi-level append, and merge-by-index behaviors for metadata inheritance.