github cloudposse/atmos v1.226.2-rc.1

pre-release3 hours ago
Add Validation, Scaffolding, and Emulators cards to landing grid @osterman (#2974) ## what
  • Add three feature cards to the homepage "Batteries included" grid: Validation, Scaffolding, and Emulators.
  • Each card follows the existing schema (icon, title, description, tag line, doc link) and slots next to its closest existing sibling card (Validation next to Vendoring, Scaffolding next to Toolchain, Emulators next to Workflows & Automation) so the grid still fills to full rows of 4.
  • Link targets (/validation/validating, /cli/commands/scaffold/usage, /cli/commands/emulator/usage) were verified against how other docs pages already link to these same destinations internally, not guessed.

why

  • These three capabilities already ship in Atmos and have full docs, but weren't represented anywhere on the landing page, understating what the runtime includes out of the box.
  • Kept to three additions (not four) so the grid still lands on a clean multiple of 4 cards per row instead of leaving a new single orphaned card in the last row.

references

  • N/A

Summary by CodeRabbit

  • New Features
    • Added Validation, Scaffolding, and Emulators to the landing page’s battery features.
    • Updated workflow messaging to highlight 35+ step types and revised emulator wording.
  • Bug Fixes
    • Improved retries for transient Sigstore trust-root CDN errors while excluding unrelated certificate-fetch failures.
  • Documentation
    • Explained how custom commands and workflows can work together as a task runner replacement.
    • Clarified custom command configuration, optional usage, wrapped commands, and examples.
    • Updated the custom commands link to point to the expanded documentation.
fix(container): resolve build/mount paths via base_path, add JIT source support @osterman (#2979) ## what
  • Container components (components.container) now resolve build.context, build.dockerfile, and run.mounts[].source the same way Terraform/Helmfile/Kubernetes/Helm components resolve theirs: relative to components.container.base_path joined with the component's own name, via a new precomputed ContainerDirAbsolutePath and a "container" case in the shared component-path resolver.
  • components.container.base_path is promoted from an ad hoc, silently-ignored config value into a real, typed Components.Container field.
  • Container components gain the same just-in-time source: provisioning as Terraform/Helmfile/Kubernetes/Helm — a component declaring a source is auto-vendored into a workdir, which then anchors build/mount paths instead of the static base path.
  • Removed the now-redundant bespoke container.Config/DefaultConfig()/parseConfig(), and fixed a hardcoded "components/container" literal in describe_stacks.go that ignored any configured override.
  • Regenerated the atmos.yaml JSON schema, updated the container CLI docs and the atmos-container agent skill, and added a changelog post + roadmap milestone.

why

  • build.context/build.dockerfile were passed to docker build/podman build completely unanchored, so they silently resolved against whatever directory atmos happened to be invoked from instead of the project — working by accident only when run from the repo root.
  • run.mounts[].source anchored to the bare project root rather than the component itself, and components.container.base_path had no effect anywhere despite being accepted as valid config.
  • Every other component type already has a consistent, CWD-independent path-resolution mechanism (base_path + component:/metadata.component) plus JIT source provisioning; containers were the one component kind never wired into it.

references

  • N/A

Summary by CodeRabbit

  • New Features

    • Added configurable container component base paths, defaulting to components/container.
    • Relative build contexts and mount sources now resolve from the component directory; Dockerfiles resolve from the build context.
    • Added automatic provisioning for container components using source: when needed.
  • Documentation

    • Added guidance on path resolution, configuration, migration, and source provisioning.
    • Updated the product roadmap to reflect the shipped functionality.
fix(ci): scope test-required aliases to their own OS's shard results @osterman (#2976) ## what

test-required (the legacy compatibility shim that aliases the sharded test matrix under the three historical required-check names) checked needs.test.result, which is a single aggregated verdict across the entire test matrix (3 OSes × 10 shards). A failure in any one shard on any one OS flipped that aggregate to failure, so all three aliases (Acceptance Tests (linux/macos/windows)) failed together even when only one OS actually had a failing shard.

This PR rewrites test-required to query the run's actual per-job results via gh api .../actions/runs/.../jobs, filtered by OS, so each alias only fails when a shard belonging to its own OS failed. It also stops gating the macos alias on terraform-registry-cache (whose matrix only has linux/windows legs and has no macos job to report on), which had the same cross-OS aggregation bug.

why

Observed on #2972: windows shard 2/10 failed after 57s, and Acceptance Tests (linux), (macos), and (windows) all failed within 3-4s as sympathetic failures with no real linux/macos test failures, forcing unnecessary re-runs/investigation of unaffected OSes.

references

🚀 Enhancements

fix: ECR/ACR ambient-credential errors and broken --identity selector @osterman (#2977) ## what
  • atmos aws ecr login / atmos azure acr login ambient-credential fallback (no Atmos identity
    configured) now returns a rich, actionable error when the underlying cloud SDK fails to retrieve
    credentials (e.g. EC2 IMDS timeout, Azure managed identity failure), with an explanation and a
    hint to run login --identity <name> or configure via.identity.
  • Fixed bare --identity (no value) failing with flag needs an argument instead of showing the
    interactive identity selector, on 6 commands: custom commands (atmos.yaml commands:),
    describe, list, aws ecr login, aws eks token, and azure aks token. Each had hand-rolled
    its own --identity flag registration instead of using the shared flags.WithIdentityFlag()
    builder that ~150 other commands already use, so each silently lost the NoOptDefVal wiring that
    makes bare --identity legal and triggers the picker.
  • Exported auth.ResolveSelectedIdentity (pkg/auth/manager_helpers.go) so the
    sentinel-to-interactive-picker resolution logic lives in one place instead of being duplicated
    (aws ecr login) or missing entirely (the other five commands).

why

  • A user hit both issues running a downstream custom command (atmos app build): first
    --identity (bare) rejected as a usage error instead of prompting, and separately — once
    ambient AWS credentials were tried as a fallback — a bare EC2 IMDS timeout with no indication
    that configuring an Atmos identity was the fix.
  • The --identity flag exists as a single, centrally-defined flag specifically so this class of
    bug can't happen; these 6 commands were the stragglers that never got migrated onto that shared
    definition, so the bug had to be independently rediscovered and patched (see the ad-hoc
    NoOptDefVal fix already present on aws ecr login) instead of being fixed once.

references

  • docs/fixes/2026-08-20-ecr-acr-ambient-credential-identity-hint.md
  • docs/fixes/2026-08-21-identity-flag-noOptDefVal-consolidation.md

Summary by CodeRabbit

  • New Features

    • Bare --identity now opens interactive identity selection across supported AWS, Azure, EKS, listing, description, and custom commands.
    • Selected identities are consistently applied to subsequent authentication and operations.
  • Bug Fixes

    • Improved ECR and ACR authentication errors with actionable identity configuration guidance.
    • Preserved underlying authentication and selection errors for easier troubleshooting.
  • Documentation

    • Added guidance covering interactive identity selection and ambient credential troubleshooting.
fix: prevent concurrent-map-write panic in global Viper singleton @osterman (#2980) ## what
  • Routes every access to the process-wide global Viper singleton through a new mutex-guarded pkg/config.GlobalViper() wrapper (SafeViper), instead of calling viper.GetViper()/viper.Set/viper.Get* directly — mirroring the embedded-mutex pattern already used by pkg/io/pkg/ui.
  • Fixes pkg/hooks.GetHooks to forward the AtmosConfig it already received into ExecuteDescribeComponentParams, removing a redundant second, independently concurrent config load per hook invocation.
  • Closes a second, independently racy package-level slice (mergedConfigFiles in pkg/config/load.go) by wrapping it in its own mutex-guarded tracker.
  • Adds pkg/config/load_concurrent_test.go, a -race-driven regression test that spins up concurrent LoadConfig calls against a real fixture and reproduces the original panic on unfixed code.
  • Minor cleanup: bridgeVendorUpdaterConfig now fetches GlobalViper() once instead of once per Set call, and a new ciFlagKey constant replaces 10 duplicated "ci" string literals in cmd/terraform/utils.go (surfaced by golangci-lint's add-constant check once those lines were touched).

why

  • atmos terraform ... --max-concurrency 3 (and even 2) could panic with fatal error: concurrent map writes inside viper.(*Viper).Set, reported from production usage. Root cause: pkg/config.LoadConfig bridges profiles.base_path and vendor.update.*/vendor.ci.* into the process-wide global Viper singleton on every call, with zero locking (spf13/viper has no internal synchronization), while the DAG scheduler runs LoadConfig concurrently — once per graph node — whenever --max-concurrency > 1.
  • GetHooks was also triggering a second, entirely redundant InitCliConfig/LoadConfig call per node because it never forwarded the AtmosConfig it was already given, doubling the exposure to the race for no reason.
  • The regression test proves the fix: run against the pre-fix code under go test -race, it reliably reproduces the exact viper.(*Viper).Set race reported in production; against the fixed code it passes clean.

references

  • Reported in Slack by two engineers hitting the same panic at --max-concurrency 2 and 3.

Summary by CodeRabbit

  • Bug Fixes

    • Improved configuration handling during concurrent operations, preserving environment-key casing and preventing cross-load contamination.
    • Ensured hooks use the active configuration when describing components.
    • Standardized CI mode and profile settings detection across commands.
    • Explicit --ci=false now overrides CI environment settings and automatic CI detection.
    • Improved reliability when reading shared configuration during shell and command execution, including masking settings.
  • Tests

    • Added coverage for concurrent configuration loading, CI precedence, shared configuration access, and configuration-aware hook execution.

Don't miss a new atmos release

NewReleases is sending notifications on new releases.