Skip to content

v1.224.1

Latest

Choose a tag to compare

@cloudposse-releaser cloudposse-releaser released this 26 Jul 19:35
b0dcb79
fix(ci): publish Docker images for prereleases Erik Osterman (Cloud Posse) (@osterman) (#2792)

what

  • Publish the existing multi-architecture Atmos Docker image for both stable and prerelease GitHub releases.
  • Keep Docker image publishing disabled for manual workflow dispatches.

why

  • Native CI users consume Atmos through Docker images and need prerelease tags to test upcoming releases.
  • Homebrew remains stable-release-only.

references

  • N/A

Summary by CodeRabbit

  • Chores
    • Updated release automation so the Docker build job runs for release events.

🚀 Enhancements

fix(hooks): resolve component path from metadata.component target Erik Osterman (Cloud Posse) (@osterman) (#2802)

what

  • Hooks (infracost, trivy, checkov, kics, tflint, kind: command, kind: git, kind: step/kind: steps) now resolve $ATMOS_COMPONENT_PATH — and the hook subprocess's own working directory — from the component's resolved metadata.component target or provisioned workdir, instead of the stack-facing component/alias name.
  • Path resolution for all hook kinds is consolidated behind one exported hooks.ComponentPath(), extended to cover every provisionable component type (terraform/helmfile/packer/ansible/kubernetes/helm).
  • kind: git hooks with no repository: now use the resolved component directory (not the repo root) as their Git workdir, so commit.paths are component-relative like other hook kinds.
  • kind: step/kind: steps hooks default working_directory to the resolved component path when not explicitly set — except type: atmos steps, which re-invoke the atmos binary itself and must keep inheriting the ambient working directory so the nested run resolves the project's atmos.yaml/stacks, not the target component's own directory.
  • A component with a JIT source: and hooks configured now has its source provisioned before those hooks fire (before.terraform.* is a "run before Terraform" event, not a "run before provisioning" event) — except before.terraform.init, which is the source provisioner's own lifecycle event and must keep running first. This only triggers for components that actually have hooks; every terraform subcommand already provisions its own component independently in RunE, so gating on hooks.HasHooks() avoids a second, racing provisioning attempt for components with no hooks at all.
  • When the resolved component directory doesn't exist on disk (component never provisioned, or an early failure before Terraform ever reaches it), the hook subprocess now falls back to the ambient process working directory instead of refusing to start — needed for when: always after-hooks that must still fire and report the failure.
  • A failed JIT provisioning attempt no longer leaves its target directory behind (surfaced by review: a test promised this but didn't assert it, and asserting it failed). vendorToTarget created the target directory before downloading, so a failed download left an empty component directory — enough for path resolution to treat the component as existing — and a partial copy failure would leave a non-empty one that needsProvisioning treats as fully provisioned, silently skipping re-provisioning on the next run. The provisioner now removes the directory only when this attempt created it; a pre-existing directory is left untouched (covered by positive/negative unit tests in pkg/provisioner/source).
  • Multi-component invocations (--all/--affected/--components/--query/--tags/--labels) no longer fail with "component is required": the metadata-resolution step is skipped for the global before/after hook (no single component is resolved yet at that point) and is best-effort everywhere else, so an intentionally invalid stack/component test scenario is rejected by Terraform's own validation with its normal message, not by hook-context preparation with a different one.
  • Added a fix-log record (docs/fixes/2026-07-24-hook-component-path-metadata-component.md) and updated the custom-hooks, git-ops, and hooks-step-types PRDs to document all of the above.
  • Fixed a pre-existing Windows-only test bug (TestComponentPathFor_Fallbacks) surfaced by this change: a hand-rolled filepath.Separator-prefixed "absolute" path isn't actually absolute per Go's filepath.IsAbs on Windows, so u.GetComponentPath's Abs() call legitimately expanded it with the current drive letter, breaking the test's literal expectation. Rooted the fixture paths in a genuine t.TempDir() instead.
  • Fixed pre-existing 3-space (odd) markdown indentation in docs/prd/git-ops.md that failed editorconfig-checker's indent_size=2 rule once this PR made the file "affected" by CI's affected-file validation.
  • Remediated 2 open Dependabot alerts flagged on this branch: github.com/google/cel-go v0.26.0 → v0.29.0 (GHSA-gcjh-h69q-9w9g), and the website's transitive postcss pin bumped from ^8.5.10 to ^8.5.18 (resolves to 8.5.23, GHSA-r28c-9q8g-f849). NOTICE and website/pnpm-lock.yaml regenerated accordingly.

why

  • For a component using the shared-module / "abstract component" pattern (metadata.component: nat-gateway on a component named e.g. nat-gateway-alias), hooks pointed at a directory that doesn't exist on disk (.../nat-gateway-alias instead of .../nat-gateway). For kind: infracost this failed silently — it just logged "Could not autodetect any projects" and reported $0.00, looking like a normal (if boring) result instead of a broken cost-estimation run. atmos describe component already resolved metadata.component correctly; hooks just weren't sharing that resolution.
  • Making that resolution (and JIT provisioning) happen ahead of hook execution surfaced several ordering assumptions across the rest of the hook/lifecycle system that weren't true before — multi-component bulk runs, type: atmos steps, before.terraform.init's own provisioner event, and when: always fallback hooks on early failures — each of which needed its own narrow fix to keep working the way it did before this PR, without losing the original fix.
  • The security fixes close a high-severity path-traversal issue in postcss (arbitrary .map file disclosure) and a medium-severity private-field-exposure issue in cel-go, both flagged by Dependabot on this branch; folding them in here keeps this PR mergeable without a separate open vulnerability.

references

  • Closes #2799
  • Supersedes #2805 (closed) — a narrower fix for the same metadata.component path resolution, fully subsumed by this PR
  • Related prior fixes in the JIT/source.uri code path: #2364 / #2371, #2134 / #2137, #2309 (Bug 2), #2684 — this PR covers the plain/local metadata.component branch they didn't reach

Summary by CodeRabbit

  • Bug Fixes
    • Terraform lifecycle hooks now resolve component metadata consistently (including alias-based selections) and carry the resolved component context into hook execution.
    • Hook subprocesses, Git current-repository actions, and step hooks run from the resolved component directory; ATMOS_COMPONENT_PATH now matches that resolved location.
    • Components with configured source: are provisioned (best-effort) before applicable before.terraform.* hooks; provisioning failures are non-blocking.
    • Step hooks default working_directory to the component directory while preserving explicit values and ambient behavior for Atmos steps.
  • Documentation
    • Updated hook-path, working-directory, and Terraform timing rules; clarified Git and env var behavior.
  • Tests
    • Expanded coverage for metadata resolution, JIT source: provisioning, and working-directory defaults.
fix(install): self-elevate install.sh via sudo on Linux Erik Osterman (Cloud Posse) (@osterman) (#2806)

what

  • Added a maybe_sudo helper in website/static/install.sh and routed every root-requiring command in the apt/yum/apk (install_via_cloudsmith) path through it, so the script self-elevates via sudo when not already root, and fails with a clear actionable message (pointing at the rootless binary install) if no sudo is available.
  • Added a CI smoke-test step in .github/workflows/install-sh-smoke.yml that exercises the package install method on ubuntu-latest, to catch regressions of this class of bug going forward.
  • Fixed website/docs/quick-start/install-atmos.mdx: a stray Unicode box-drawing character () had silently replaced the literal pipe (|) in the Debian/Ubuntu, RedHat/CentOS, and Alpine manual install snippets, breaking them if copy-pasted; also added sudo to the Debian/Ubuntu tab's commands to match the RedHat tab's existing convention.

why

  • A user reported that curl -fsSL https://atmos.tools/install.sh | bash — the install command shown on the homepage — fails on a plain (non-root) Ubuntu 24.04 shell with Permission denied writing to /usr/share/keyrings/ and /etc/apt/sources.list.d/, since the apt/yum/apk install path never elevated privileges.
  • This affects the primary documented install path for most Linux users, not an edge case; it went unnoticed because the CI smoke test only ever exercised the root-free binary-download method.
  • The fix is scoped so it only affects the apt/yum/apk code path — Homebrew and Nix installs (e.g. on macOS) are untouched, since maybe_sudo is never invoked from those functions.

references

  • Reported by a user running the homepage install command on Ubuntu 24.04.4 LTS.

Summary by CodeRabbit

  • Bug Fixes
    • Improved non-root installs by using sudo when available, with clearer guidance when neither root nor sudo exists.
    • Made post-install verification more reliable by resolving the atmos executable via command -v (and normalizing its path).
  • Documentation
    • Fixed Cloudsmith command piping syntax and refined install examples for DEB/RPM/APK (including sudo usage and version selection).
  • Tests
    • Updated the install.sh smoke workflow to run an additional package-mode install and verify atmos is present in PATH on ubuntu-latest.
fix: restore auth for evaluated list commands Erik Osterman (Cloud Posse) (@osterman) (#2801)

what

  • Restore default identity scanning whenever list/describe stack processing evaluates Go templates or YAML functions; preserve --identity=false.
  • Apply the policy to all list describe-stacks callers and verify atmos.Component() forwards an inherited context to an auth-less nested target.
  • Keep graceful degradation limited to unprovisioned state/output; credential, IMDS, and template failures remain fatal.

why

  • v1.222.0-rc.14 made list inventory authentication opt-in while templates still ran by default, leaving nested Terraform output resolution without an AuthContext and falling back to IMDS.
  • The scoped per-component cache remains unchanged, so automatic auth does not restore the prior unscoped per-component authentication behavior.

references

Summary by CodeRabbit

  • Bug Fixes
    • Fixed authentication initialization for describe stacks and list so credentials are prepared only when template processing / YAML-function evaluation is enabled, or when identity is explicitly selected (while respecting the disabled identity sentinel).
    • Updated auth-skip guard to require both processing flags to be disabled, even when identity is set via environment.
    • Restored correct parent AuthContext inheritance for nested template/YAML evaluations.
    • Tightened warn/silent behavior so backend/credential/network failures are fatal (with recovery limited to unprovisioned Terraform state/output).
  • Tests
    • Added/expanded coverage for auth policy, auth inheritance, and warn-mode error classification.
  • Documentation
    • Documented the nested auth inheritance and warn-mode behavior changes.
feat(auth): improve AWS user webflow and console access Erik Osterman (Cloud Posse) (@osterman) (#2786)

What

  • Enable AWS federation console URLs for authenticated aws/user identities.
  • Add atmos auth login --webflow to force a fresh browser OAuth2/PKCE sign-in for a direct aws/user identity without reading, deleting, or overwriting configured IAM access keys.
  • Preserve temporary AWS session credentials in the existing session-file cache, while enforcing webflow_enabled: false and clear validation errors for provider mode or non-aws/user identities.
  • Improve AWS browser-auth UX: remove the misleading credential-configuration info message, display short authorization URLs in the dialog, and place long URLs below it.
  • Emit experimental-command notices once per command execution.
  • Stabilize acceptance-test setup and snapshots, including dependency retries/timeouts and Packer setup retries.

Why

IAM-user identities can obtain temporary STS credentials through Atmos browser authentication, but they could not open the AWS console and could not explicitly choose browser authentication when saved IAM credentials existed. This change makes both flows available while keeping long-lived credentials intact.

Validation

  • Added focused command, AWS user, browser-dialog, and experimental-notice regression coverage.
  • Added coverage for forced-webflow error, validation, and persistence branches; Codecov reports all modified coverable lines are covered.
  • Ran affected Go package suites, focused acceptance snapshots, actionlint, and repository pre-commit checks.

References

  • N/A

Summary by CodeRabbit

  • New Features

    • Added --webflow to force a fresh browser login for AWS IAM user identities.
    • AWS IAM users can now access the AWS console using temporary session credentials.
    • Improved browser authentication dialogs for long authorization URLs.
  • Bug Fixes

    • Experimental command notices are now shown only once per execution.
    • Added clearer validation and errors for unsupported webflow identity types.
  • Documentation

    • Updated authentication, console access, and webflow usage guidance.
fix(secrets): store SSM scalar secrets without JSON quotes Erik Osterman (Cloud Posse) (@osterman) (#2797)

what

  • Write string values to secret: true AWS SSM stores without JSON quoting.
  • Preserve JSON encoding for structured secrets and regular SSM stores, with regression coverage.
  • Document absolute SSM parameter prefixes.

why

  • AWS-native consumers need the raw SecureString value rather than a JSON-wrapped scalar.

references

Summary by CodeRabbit

  • Bug Fixes

    • Improved AWS SSM secret handling to preserve raw string values (including number-like, boolean, and null text) without unwanted formatting or type changes.
    • Added/strengthened round-trip behavior for structured secret values (maps and lists), plus correct handling of empty secret strings.
    • Updated retrieval behavior to decode stored values consistently (including for GetKey).
  • Documentation

    • Clarified AWS SSM prefix must start with /.
    • Documented secret: true read/write behavior and related decoding ambiguity.
  • Tests

    • Expanded SSM secret set/get/get-key coverage for both raw and legacy formats.
    • Updated Terraform-compatible tooling test isolation to cover both terraform and tofu.
fix(terraform): propagate provider cache to output lookups Erik Osterman (Cloud Posse) (@osterman) (#2791)

Summary

  • apply Atmos's provider plugin-cache policy to internal !terraform.output and atmos.Component() Terraform runs
  • serialize internal terraform init calls that share a provider cache
  • preserve explicit cache overrides and add regression coverage

Root cause

The normal Terraform command pipeline synthesized TF_PLUGIN_CACHE_DIR, but the internal output executor created a separate subprocess environment without that automatic cache configuration. Each lookup therefore initialized providers in its component workdir unless CI injected the cache manually.

Validation

  • go test ./...
  • focused provider-cache and output-executor tests
  • scripts/run-custom-golangci-lint.sh
  • pre-commit hooks (go-fumpt, Go build, custom lint)

Summary by CodeRabbit

  • New Features
    • Automatic Terraform provider plugin caching now derives and reuses a shared cache directory for Terraform subprocesses.
    • Internal Terraform output lookups reuse the same caching policy.
  • Bug Fixes
    • Cache precedence is now component override → process environment → global config, with safer invalid-path fallback.
    • Shared provider initialization is serialized, and init failures now propagate during output lookups.
  • Tests
    • Added coverage for cache resolution, environment wiring, init-lock serialization, and cross-platform behavior.
  • Documentation
    • Added fix notes for provider-cache reuse, Windows plugin-cache test issues, and a repo-copy race.
  • Chores
    • Updated dependency versions and website build overrides.
fix(ci): serialize verifier lifecycle and color errors Erik Osterman (Cloud Posse) (@osterman) (#2794)

what

  • Keep each bootstrap verifier's install, trust repair, and execution inside its version lock.
  • Render structured error output with ANSI color in CI while preserving NO_COLOR behavior.

why

  • Parallel tool installs could reinstall cosign while another worker was executing it, causing Linux ETXTBSY failures.
  • The structured error formatter omitted the standard CI signal even though the rest of Atmos recognizes CI as ANSI-capable.

references

Summary by CodeRabbit

  • Bug Fixes
    • CI now correctly enables ANSI color rendering unless disabled via NO_COLOR.
    • Verifier bootstrap now preserves the per-version install lock through trust repair and verifier execution, reducing binary replacement race conditions.
    • Added a bounded timeout for verifier subprocesses when no deadline is provided to prevent indefinite lock holding.
  • Documentation
    • Added a dated fixes note describing the verifier install-lock and CI color behavior.
  • Tests
    • Hardened CI/ANSI-dependent assertions by stripping ANSI escape codes where needed.
Add deprecation validation warnings Erik Osterman (Cloud Posse) (@osterman) (#2793)

what

  • Keep supported legacy Atmos configuration valid while emitting schema-driven deprecation warnings in CLI validation and the LSP.
  • Restore legacy Terraform dependency compatibility and add a customer regression scenario.

why

  • Prevent 1.224 schema validation from blocking existing customer configuration while providing actionable migrations.

references

  • N/A

Summary by CodeRabbit

  • New Features
    • Added deprecated-field warnings (with replacement guidance and file/line/column locations) to config validation, stack validation, schema validation, and language-server diagnostics.
    • Updated schemas to mark legacy and dependency-related fields as deprecated, including depends_on replacement guidance.
    • Restored backward-compatible depends_on handling for legacy manifest layouts.
  • Bug Fixes
    • Schema validation now succeeds when there are no schema errors, even if warnings are present.
    • Deprecation scanning is best-effort: failures no longer abort validation.
  • Tests
    • Added fixtures and unit/CLI tests covering deprecated-field compatibility and dependency fallback behavior.
  • Documentation
    • Documented deprecation warnings behavior across CLI and LSP.
fix(yaml): decode JSON after whitespace-trimmed function tags Erik Osterman (Cloud Posse) (@osterman) (#2780)

what

  • Accept [ and { as valid boundaries after YAML function tags.
  • Add end-to-end coverage for whitespace-trimmed !template list and map output.
  • Add a durable fix record under docs/fixes.

why

  • Go-template whitespace trimming can render !template[...] or !template{...}, which strict tag matching left as literal strings.

references

Summary by CodeRabbit

  • Bug Fixes
    • Fixed YAML !template parsing so whitespace-trimmed templates that render JSON arrays/objects decode correctly.
    • Improved !template boundary handling around whitespace, JSON delimiters, end-of-input, and zero-argument tags, preventing accidental literal-string output.
  • Documentation
    • Added a fix record documenting the corrected parsing behavior and edge cases.
  • Tests
    • Extended fixtures and added unit/integration assertions for trimmed list/map outputs and near-miss tag names.