NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules · #1416 by repository stars
Last release today
07 Oct 2026
Ships on a steady schedule
a new release about every 8 days
Rarely documented
notes for 5 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
2162 releases · first in 2021
One column per quarter.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
feat(terraform): declarative defaults for lock/concurrency CLI flags Erik Osterman (Cloud Posse) (@osterman)
flags: block that sets defaults for terraform CLI execution flags — lock_timeout, lock, parallelism, refresh, compact_warnings — settable globally in atmos.yaml, at the stack level (root-level terraform: block), and per component, with field-level merge across all three layers.terraform import gets only lock/lock_timeout; apply <planfile> never gets -refresh, since Terraform rejects it there; terraform test gets none).atmos terraform plan vpc -s dev -- -lock-timeout=30s) always wins over any declared default.ATMOS_COMPONENTS_TERRAFORM_FLAGS_* env var overrides for the global default, regenerates the atmos.yaml JSON schema, hand-extends the stack-config JSON schema, and documents the new block on the Terraform configuration page plus plan/apply/destroy/refresh/import command docs.-lock-timeout default is 0s (fail immediately on state-lock contention), which caused avoidable failures whenever concurrent pipelines touched the same component's state around the same time. There was previously no declarative way to set a longer retry window — only a raw CLI pass-through flag that had to be retyped on every single invocation.New Features
Bug Fixes
Documentation
ci.enabled) is on or off, and whether Atmos Pro is configured.cloudposse/github-action-atmos-* marketplace actions (via GITHUB_ACTION_REPOSITORY) and emit a warning nudging migration to Native CI.pkg/ci/startup package holds the decision logic (kept out of cmd//internal/exec per repo convention); pkg/ci/providers/github gained the legacy-action env-var check.ci.enabled: true, or running without a Pro workspace configured) was previously silent until something failed downstream — this surfaces it immediately in CI logs.New Features
Documentation
Nothing published for this version
Nothing published for this version
Deprecate Type (on CommandArgument ) and SemanticType (on CommandFlag ) via the existing jsonschema_extras deprecation pattern (schema marks them depr…
provides: field to custom-command arguments: and flags:, replacing the two inconsistent spellings of the same "this value provides the component/stack name" concept: type: component/type: stack on arguments, and semantic_type: component/semantic_type: stack on flags.Type (on CommandArgument) and SemanticType (on CommandFlag) via the existing jsonschema_extras deprecation pattern (schema marks them deprecated with x-atmos-replacement: provides), with a new EffectiveProvides() helper so existing configs using the old fields keep working unchanged.arguments.mdx, flags.mdx, component.mdx, custom.mdx), the examples/custom-components/ fixture, and the atmos-modernization skill's legacy-pattern checklist.semantic_type existed only on CommandFlag because Flag.Type was already used for the flag's data type (string/bool); CommandArgument.Type carried the identical role under a different name purely because arguments don't have a competing data-type field. Same concept, two field names, driven by an implementation detail rather than a naming decision.provides: uses one consistent field name on both arguments and flags, and matches the wording the docs already used to describe the behavior in prose ("this flag provides the stack name").N/A
New Features
provides configuration for identifying component and stack values in command arguments and flags.Bug Fixes
type and semantic_type configurations, with the new provides value taking precedence.Documentation
provides.Nothing published for this version
Add json file manager, fix empty version.files, fix lock YAML indent Erik Osterman (Cloud Posse) (@osterman)
json file manager to the Version Tracker (manager: json), configured via options.set: [{path, from}], that writes locked values into JSON files using sjson/gjson — patching only the targeted field and leaving the rest of the document's formatting, key order, and whitespace untouched.atmos version track apply to treat an explicit version.files: [] as "manage zero files" instead of silently falling back to each manager's default paths — previously there was no way to configure zero managed files.toolchain.lock.yaml, vendor.lock.yaml, and versions.lock.yaml to write with the repo's 2-space YAML indent standard instead of yaml.v3's bare-Marshal 4-space default.json manager.marker manager (needs an adjacent comment annotation, which JSON has no syntax for) nor the template manager (requires hand-maintaining a separate *.tmpl source in sync with the generated file) could cleanly keep a version field in a plain JSON file — such as a package.json or a Claude Code plugin manifest — up to date. This gap was found while wiring Atmos's own agent-skills/.claude-plugin/plugin.json / .claude-plugin/marketplace.json to track Atmos's release version.fileRules() used len(Version.Files) > 0, which can't distinguish an omitted version.files key (should fall back to manager defaults) from an explicitly configured empty list (should manage nothing) — both took the same fallback path.yaml.Marshal, which drifted their indentation away from every other Atmos-generated YAML file.New Features
Documentation
Improvements
GOFIPS140=latest, linking Go's native FIPS 140-3 validated cryptographic module and defaulting the binary to FIPS-enforcing mode (GODEBUG=fips140=on) at runtime. No flag or config change is required.docs/prd/fips-140-mode.md: the age/NaCl-based encryption used by declarative secrets management (atmos secret keygen, the SOPS/age backend, and sealed GitHub Actions secret values) sits outside Go's FIPS module boundary and isn't covered by this change.scripts/build-atmos.sh to a native Go mage target (magefiles/build.go, Build.Binary), matching the repo's existing mage-based tooling for lint and acceptance-test orchestration, and updates every CI workflow and doc comment that referenced the old script.scripts/build-atmos.sh was the last shell-script build entrypoint in a repo that otherwise self-hosts its build/lint/test tooling through Atmos custom commands and mage targets; converting it removes the shell/Go split and adds proper unit test coverage the shell script never had.docs/prd/fips-140-mode.mdNew Features
atmos version reports the current runtime FIPS status, including structured output.Bug Fixes
Documentation
Tests
describe affected CI base auto-detection resolving a wrong base commit for merged pull requests: merged PRs now classify what the workflow actually checked out (PR head, merge commit, or synthetic refs/pull/<n>/merge) and anchor the base on event-payload facts (merge_commit_sha^1, or base.sha for fast-forward merges where merge_commit_sha == head.sha), instead of the old merge-base(HEAD, origin/<target>) → HEAD~1 chain that degenerates after the merge.describe affected mis-computing BASE worktree paths when the repository lives under a symlinked path (e.g. macOS /tmp): symlink-normalize both sides of the path re-basing, and hard-error (instead of silently guessing) when a config path cannot be represented inside the BASE checkout.Auto-detected CI base log line (checkout=head.sha|merge-commit|synthetic-merge|unknown) so wrong-base reports are diagnosable from a single line.pkg/git helpers (CommitParents, MergeBaseSHAs, FetchCommit), red-first regression tests for every checkout × merge-strategy combination (merge, squash, fast-forward, queue-merged, synthetic, unknown, closed-unmerged), and a new end-to-end test covering base auto-detection through the full affected computation.describe affected CLI docs and the native-CI base-resolution PRD to match; add fix-log entries under docs/fixes/.pull_request closed (merged) event with the PR head checked out (the documented workflow), merge-base(HEAD, origin/<target>) collapses to HEAD (the head is now an ancestor of the target) and the HEAD~1 fallback diffs only the PR's final commit. A multi-commit PR whose last commit reverts an earlier org-wide change then reports every component as affected and dispatches a wall of post-merge plan/apply runs; conversely, changes in earlier commits could be silently missed. Observed in production with the zero-config setup.merge_commit_sha == head.sha) would hit the same last-commit-only failure through the new anchor, so they get a dedicated payload-base.sha anchor — caught in an adversarial field-test pass before release.filepath.Rel mixed git's symlink-resolved repo root with logical CWD-derived config paths, producing an escaping path that — depending on filesystem depth — either scanned a nonexistent BASE (greenfield fallback → everything affected) or clamped back onto the HEAD repo (BASE == HEAD → nothing affected). Both failure modes were silent.docs/fixes/2026-08-27-describe-affected-merged-pr-base-resolution.mddocs/fixes/2026-08-27-describe-affected-symlink-base-path-mangling.mddocs/prd/native-ci/framework/base-resolution.md (updated resolution matrix)🤖 Generated with Claude Code
Bug Fixes
atmos describe affected accuracy for merged pull requests and varied checkout strategies.Documentation
Tests
Nothing published for this version
fix: implement MarshalYAML on Condition to make sure it survives marshalling roundtrip Jorrit Elfferich (@jorrite)
Condition.MarshalYAML() to pkg/condition/condition.go so a when: condition survives being marshaled back to YAML.pkg/condition/condition_test.go: add TestConditionYAMLMarshalRoundTrip (predicate/CEL/all/any-not shapes) and TestConditionYAMLEmptyMarshalRoundTrip, asserting the marshaled-then-decoded value matches the expected shape and evaluates identically to the original across representative facts.pkg/project/config/config_baseref_test.go: add TestSaveAndLoadProjectRecord_FieldWhenSurvivesRoundTrip, exercising the real SaveProjectRecord/LoadProjectRecord path with a field-level when: condition (mirroring examples/scaffolding/scaffold.yaml's enable_vendoring/vendor_version pair) and asserting the reloaded condition evaluates correctly.condition.Evaluate, CEL compilation, or the JSON marshal/unmarshal paths — out of scope, and unaffected since the fix reuses the same node.value() reconstruction MarshalJSON already relies on.Condition's only field, node *Node, is unexported. Condition already implements UnmarshalYAML, UnmarshalJSON, and MarshalJSON, but had no MarshalYAML. Without one, yaml.Marshal falls back to reflecting the struct, sees zero exported fields, and writes {} — silently discarding the condition instead of erroring.atmos scaffold generate's project record (.atmos/scaffold.yaml): a spec.fields[].when CEL string (e.g. "answers.topology == 'multi'") rendered correctly on first generate, but got written back as when: {}. Since --update re-reads that same record on every subsequent run, the project was permanently stuck failing schema validation (expected string, but got object) with no way to self-heal.spec.files[].when never showed the same symptom, but not because that path is correct — SaveProjectRecord never copies templateConfig.Spec.Files into the persisted record at all (only Fields, Delimiters, Source, BaseRef, Values are copied), so there's nothing there to corrupt. Verified this holds with a matrix:-expanded files[] entry too: generation succeeds, but spec.files is simply absent from the written record.node.value() — the same method MarshalJSON already uses. This isn't new behavior: cloneCommand (cmd/cmd_utils.go) already JSON round-trips every custom command's Task.When through this exact normalization on every invocation, so a bare CEL string already canonicalizes to !cel <expr> there today. Extending it to MarshalYAML just makes YAML and JSON serialization consistent with each other.Bug Fixes
Tests
Nothing published for this version
No changes
Add Validation, Scaffolding, and Emulators cards to landing grid Erik Osterman (Cloud Posse) (@osterman)
/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.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.BasePath field.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.container.Config/DefaultConfig()/parseConfig(), and fixed a hardcoded "components/container" literal in describe_stacks.go that ignored any configured override.atmos.yaml JSON schema, updated the container CLI docs and the atmos-container agent skill, and added a changelog post + roadmap milestone.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.base_path + component:/metadata.component) plus JIT source provisioning; containers were the one component kind never wired into it.New Features
components/container.source: when needed.Documentation
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.
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.
.golangci-cache/, .golangci-tmp/) to the OS user cache directory: <user-cache>/atmos-lint/<worktree-hash>/{cache,tmp} (~/Library/Caches/atmos-lint/... on macOS).<worktree-hash> (first 12 hex chars of SHA-256 of the absolute worktree path) preserves #2701's per-worktree isolation of golangci-lint's single-instance lock — the dirs just no longer live under the worktree tree.ATMOS_LINT_SHARED_CACHE=1 opt-out and explicit GOLANGCI_LINT_CACHE overrides behave exactly as before.docs/fixes/2026-08-24-fsmonitor-worktree-saturation.md with the full measured diagnosis.#2701 put a 156MB / ~37k-file cache that churns on every lint run inside each worktree — directly under any filesystem watcher observing that tree (git fsmonitor, Conductor's watchexec). At multi-worktree scale this saturated macOS FSEvents: git status measured 2.9s–timeout (>2min) with fsmonitor vs 0.04–0.15s without, and every pre-commit run pays that tax dozens of times, stretching commits to minutes. Moving the churn outside the watched tree makes this impossible to re-trigger on any machine, regardless of watcher configuration.
Measured after the fix: cold lint:precommit 9.1s, warm 1.5s, no cache dirs created in the worktree; a full commit through all pre-commit hooks + signing completes in ~5s.
perf(lint): isolate golangci-lint cache and lock per worktree) — introduced the in-worktree location this PR relocates; its lock-isolation intent is preserveddocs/fixes/2026-08-24-fsmonitor-worktree-saturation.md — full diagnosis, timeline, and machine-level remediation notesBug Fixes
Documentation
"moby": false on the docker-outside-of-docker devcontainer feature in .devcontainer/devcontainer.json.The Codespaces Prebuilds workflow (prebuild) fails on every push to main. Example failed run: https://github.com/cloudposse/atmos/actions/runs/32431458655/job/96623702606
The base image mcr.microsoft.com/vscode/devcontainers/base:debian now resolves to Debian 13 (trixie), which does not package moby-cli. The docker-outside-of-docker feature defaults to moby: true and errors out during the prebuild image build:
(!) The 'moby' option is not supported on debian 'trixie' because 'moby-cli'
and related system packages are not available in that distribution.
(!) To continue, either set the feature option '"moby": false' or use a
different base image (for example: 'debian:bookworm' or 'ubuntu-24.04').
ERROR: Feature "Docker (docker-outside-of-docker)" failed to install!
Setting moby: false makes the feature install Docker CE instead. This is safe and non-redundant: the devcontainer Dockerfile already configures Docker's official apt repo and installs docker-ce/docker-ce-cli, so no moby packages were ever needed — the feature only wires up the forwarded host Docker socket.
Docker Build step in .github/workflows/build.yml from cloudposse/github-action-docker-build-push v3.1.0 (02993d67) to v3.2.1 (ff59bd5).release / Build and push Docker image for Atmos CLI job has been failing on the post-build Docker Inspect summary step with jq: error (at inspect.json:79): Cannot iterate over null (null) → exit code 5, even though the image builds and pushes fine.docker inspect fields (.Config.Entrypoint, .Config.Cmd, .Config.Env, .RootFS.Layers) straight into jq's join/.[]/to_entries, all of which iterate. Atmos's image is FROM debian:trixie-slim with no ENTRYPOINT, so .Config.Entrypoint is null and jq aborts; under the default bash -e shell that fails the whole step.// []), released as v3.2.1. Verified ff59bd5 contains all four guards. This bump pins Atmos to that release so the release job's summary no longer crashes.pkg/aws.ExecuteAwsEksUpdateKubeconfig — thin public wrapper delegating to internal/exec.ExecuteAwsEksUpdateKubeconfig.pkg/utils.JSONToMapOfInterfaces — decodes a JSON string into a schema.AtmosSectionMapType (errors on non-object top-level values, unlike ConvertFromJSON).deadcode -test set).docs/fixes/.refactor(utils): drop dead helpers ...) removed both functions because the deadcode sweep reported zero callers inside the Atmos repo. That analysis does not see external module consumers, so these were public-API removals, not truly dead code.cloudposse/terraform-provider-utils embeds the Atmos Go library and relies on both:
utils_aws_eks_update_kubeconfig data source calls pkg/aws.ExecuteAwsEksUpdateKubeconfig;pkg/utils.JSONToMapOfInterfaces.internal/exec, which external modules cannot import; JSONToMapOfInterfaces was deleted). This pins the provider to v1.221.1 and prevents it from tracking newer Atmos releases — which matters because the provider must embed the same deep-merge semantics as the paired Atmos CLI.terraform-provider-utils against this branch (local replace + atmos@v1.226.1): go build ./..., go vet ./internal/..., and its full unit/library test suite all pass. deadcode -test ./... no longer reports either function.utils_aws_eks_update_kubeconfig data source, internal/convert tests)docs/fixes/2026-08-25-restore-public-provider-api-wrappers.mdNew Features
Bug Fixes
null, and other non-object input.Documentation
defaultCliConfig (the config used when no atmos.yaml is discoverable) to state settings.terminal.help.filter: true, matching the journaled/SetDefault value.TestJournalAgreesWithDefaultCliConfig that treated "field absent from the struct" and "field explicitly serialized as false" as equivalent, letting this exact class of drift through silently.TestLoadConfigNoAtmosYamlDefaults, a regression test that loads config from a directory with no atmos.yaml anywhere — the one fallback path every existing edition/help test skips.--help was regressing to the full --help=all output (all flags, no focused view, no --help=usage/--help=all hint) whenever no atmos.yaml was discoverable — e.g. running atmos --help right after install or from outside a project directory.defaultCliConfig's Terminal literal never set Help, so it zero-valued to HelpSettings{Filter: false}. Since the field has no omitempty tag, that explicit false was marshaled into Viper's CONFIG layer and silently overrode the intended true from SetDefault, which only reaches the lower-priority DEFAULT layer. Introduced in #2762, which added the journal entry but missed the matching defaultCliConfig entry.atmos --help (no config file) now differs from --help=all and shows the expected hint.New Features
Bug Fixes
atmos.yaml configuration file is available.Tests
false, empty strings, and 0.pkg/provisioner/workdir's injective character-escaping scheme (-->-h, /->-s, \->-b) with a <stack>-<sanitized-name>-<hash> naming scheme for .workdir/<type>/... directories.pkg/provisioner/workdir, pkg/provisioner/source, pkg/component, internal/terraform_backend, pkg/terraform/output, and tests/ that asserted on the old escaped naming.vpc-flow-logs-1.226.1) were mangled into unreadable directory names like vpc-hflow-hlogs-h1.226.1, since - was both the most common character in real component names and the encoding's own escape marker.docs/fixes/2026-08-22-workdir-naming-hash-suffix.mdNew Features
workdir clean --all --dry-run lists workdirs without deleting them.Bug Fixes
Documentation
atmos scaffold generate --update's default 3-way-merge base ref to the commit--git generation, instead of always defaulting toHEAD..git directories when reading a template's files, for both local-directorygit:: remote sources fetched into a temp dir.atmos scaffold generate --dry-run to match real generation exactly: skipspec.files[].when conditions, and render file paths withspec.delimiters.--update could silently discard a customization a user had already committed to theHEAD, a committed edit becamegit::) leaked its.git internals (objects, refs, a config pointing at the source repo) into every--dry-run reported more files than a real run actually produces (directories countedwhen: false files listed anyway, custom-delimiter paths shown unrendered),[EXPERIMENTAL]) scaffold feature,docs/fixes/2026-08-24-scaffold-update-git-dryrun-fixes.mdNew Features
Bug Fixes
.git contents from being copied into generated projects.Documentation
atmos aws ecr login / atmos azure acr login ambient-credential fallback (no Atmos identitylogin --identity <name> or configure via.identity.--identity (no value) failing with flag needs an argument instead of showing theatmos.yaml commands:),describe, list, aws ecr login, aws eks token, and azure aks token. Each had hand-rolled--identity flag registration instead of using the shared flags.WithIdentityFlag()NoOptDefVal wiring that--identity legal and triggers the picker.auth.ResolveSelectedIdentity (pkg/auth/manager_helpers.go) so theaws ecr login) or missing entirely (the other five commands).atmos app build): first--identity (bare) rejected as a usage error instead of prompting, and separately — once--identity flag exists as a single, centrally-defined flag specifically so this class ofNoOptDefVal fix already present on aws ecr login) instead of being fixed once.docs/fixes/2026-08-20-ecr-acr-ambient-credential-identity-hint.mddocs/fixes/2026-08-21-identity-flag-noOptDefVal-consolidation.mdNew Features
--identity now opens interactive identity selection across supported AWS, Azure, EKS, listing, description, and custom commands.Bug Fixes
Documentation
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.pkg/hooks.GetHooks to forward the AtmosConfig it already received into ExecuteDescribeComponentParams, removing a redundant second, independently concurrent config load per hook invocation.mergedConfigFiles in pkg/config/load.go) by wrapping it in its own mutex-guarded tracker.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.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).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.go test -race, it reliably reproduces the exact viper.(*Viper).Set race reported in production; against the fixed code it passes clean.--max-concurrency 2 and 3.Bug Fixes
--ci=false now overrides CI environment settings and automatic CI detection.Tests
TF_CLI_ARGS_apply configured through atmos.yaml no longer reaches Terraform-exec's internal output command. Post-apply output-store hooks can retrieve and publish the declared Terraform output after a successful apply.
Terraform-exec rejects manual command-specific argument variables during its output invocation. Atmos filtered inherited variables but restored them from the resolved component environment. The output path now ignores TF_CLI_ARGS and TF_CLI_ARGS_* while preserving normal environment variables and TF_VAR_* values.
TF_VAR_*.go build ./...atmos fix coverage origin/main0 issues.Closes #2990
Bug Fixes
TF_VAR_* values, while excluding TF_CLI_ARGS settings from output processing.Documentation
atmos packer now sets up Atmos Auth the same way terraform and helmfile do: it creates and authenticates the component AuthManager, passes it to ProcessStacks, and injects the resolved identity's credentials into the packer subprocess environment before executing.resolveDefaultIdentity and the renamed prepareComponentAuthEnvironment, formerly prepareHelmfileAuthEnvironment) into internal/exec/utils_auth.go so helmfile and packer share one path instead of duplicating it.internal/exec/packer_auth_test.go) via two test seams: one asserts a non-nil AuthManager is passed to ProcessStacks; the other asserts an injected credential reaches the packer subprocess env.docs/fixes/.atmos packer build ran completely unauthenticated when relying on Atmos Auth. internal/exec/packer.go called ProcessStacks(..., nil) (nil AuthManager) and never called PrepareShellEnvironment, so no AWS credentials ever reached the packer process. Its datasources failed with:
Error: Datasource.Execute failed: No valid credential sources found
Both other component executors already do this — terraform via setupTerraformAuth + auth.TerraformPreHook, helmfile via SetupComponentAuthForCLI + credential injection — so packer was the odd one out, even though the AuthManager interface docstring explicitly lists Packer as a supported subprocess.
Verified against a real workload: atmos packer build <component> -s <stack> now proceeds into the AMI build (VPC prevalidation, keypair creation, etc.) where the stock binary failed with the credential error.
internal/exec/helmfile.go.AuthManager contract: pkg/auth/types/interfaces.go (PrepareShellEnvironment — "Use this for all subprocess invocations: Terraform, Helmfile, Packer, ...").docs/fixes/2026-08-23-packer-atmos-auth-credential-injection.md.atmos packer build now honors configured authentication settings.This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merge
This is a feature preview based on an open pull request. It is intended for testing artifacts and validating functionality before the feature is merged.
Warning
This release is temporary and may be removed at any time without notice.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →