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.
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(scaffold): handle file deletions during scaffold/init --update Jorrit Elfferich (@jorrite)
atmos scaffold generate --update / atmos init --update under --update-strategy=rendered now deletes a file the template stopped generating between refs, but only when the on-disk copy is still byte-identical to the old pristine render. If local edits survived, the update fails with an unresolved merge conflict instead of silently deleting or keeping it.--update-strategy, --update no longer silently recreates a file you deleted yourself — both tracked and rendered now check whether a path was previously generated before recreating it, and skip it if so.--recreate-deleted flag (on both scaffold generate and init) opts back into always recreating a deleted file. It's deliberately its own flag rather than folded into --force: --force already means "the template's version wins" for merge conflicts under --update, so tying recreation to it would make "manual conflict resolution" and "recreate what I deleted" mutually exclusive.--force now also resolves a deletion conflict (deletes through local edits), consistent with that same existing meaning.--update-strategy=tracked does not support template-side deletion propagation — documented as a limitation, not implemented, since there's no safe way to know which files in a target's git history actually belonged to the template.spec.files[].target: rename regression where the renamed file would never be created and the error message wrongly blamed the user for "deleting" itErrSymlinkWrite)--force previously couldn't resolve a deletion conflict at all--recreate-deleted as the way to override it--recreate-deleted for both atmos scaffold generate and atmos init.docs/prd/atmos-scaffold.md, website/docs/cli/commands/init.mdx, website/docs/cli/commands/scaffold/generate.mdx, plus a changelog post and roadmap entry.--update unconditionally overwrote a user's own deletion of a previously-generated file on every run, unlike tools like Copier that respect it.target: rename-migration path — along with a few consistency gaps, before any of it shipped.init --update and scaffold generate --update preserve files you deleted locally by default. Use --recreate-deleted to restore them with the template’s current content.--force deletes them.CrashLoopBackOff/ImagePullBackOff, exit code, restart count), and - at debug/trace level - the failing container's log tail and the pod's recent events.on_failure rollback/uninstall itself (after collecting diagnostics) instead of relying on Helm's inline RollbackOnFailure, which runs before Atmos sees the error.Example (--logs-level=Debug):
Error: failed to perform helm release operation
workload diagnostics:
pod keda-operator-7d9f keda-operator CrashLoopBackOff (exit 1, 5 restarts)
last log (keda-operator):
panic: failed to load config: invalid duration "5x"
events:
BackOff Back-off restarting failed container
kubectl get pods/describe/logs - impossible in CI with no interactive cluster access.upgrade.on_failure: rollback (or install uninstall-on-failure) is configured, the recovery deleted the crashing pods first, destroying the evidence before anyone could look. Capturing diagnostics before recovery makes a failed controller, webhook, or gateway rollout legible from the Atmos output alone.server_side_apply/force_conflicts workdocs/fixes/2026-10-04-native-helm-crashloop-diagnostics.mdwebsite/blog/2026-10-04-native-helm-crashloop-diagnostics.mdx; roadmap milestone under container-compositionpkg/component/helm/diagnostics.go: collectReleaseFailureDiagnostics lists pods by the standard app.kubernetes.io/instance=<release> label and summarizes not-ready init/regular containers. In verbose mode it also tails the failing container's log (the previous instance for a crash-looping container), bounded by both TailLines and LimitBytes, and the pod's recent events - narrowed server-side by field selector, sorted newest-first (with LastTimestamp/EventTime/CreationTimestamp fallbacks), and capped. Output is bounded throughout (max pods and events, message and log-byte caps); the clientset is behind a newReleaseClientset test seam.pkg/component/helm/client.go: configureInstallLifecycle/configureUpgradeLifecycle no longer set Helm's inline RollbackOnFailure. On failure, installRelease/upgradeRelease collect diagnostics, then run Atmos-owned recovery:
rollbackFailedUpgrade rolls back to the latest successful (deployed/superseded) revision via lastSuccessfulRevision, mirroring Helm's own failRelease (plain version 0 could target an earlier failed revision), and honors the policy's chart_hooks/force_conflicts/server_side_apply; history is trimmed via enforceReleaseHistoryLimit.uninstallFailedInstall honors chart_hooks, and install recovery runs only when a release record exists (releaseRecordExists) - a pre-mutation failure (bad chart, chart-load error, cancellation before apply) neither diagnoses nor uninstalls.releaseOperationErrorWithDiagnostics folds the summary into the error. New ErrHelmReleaseRollback sentinel.lastSuccessfulRevision (skips failed revisions; none-successful; no-release), releaseRecordExists, a pre-mutation install failure that skips diagnostics/uninstall, and end-to-end that a failed upgrade and install fold diagnostics into ErrHelmReleaseOperation before the Atmos-owned recovery (which still runs). Existing rollback/history/dry-run tests still pass.go build ./..., go test ./pkg/component/helm/..., golangci-lint (0 issues), and cd website && npm run build pass.Nothing published for this version
docs: add focused navigation and a first-class Steps reference Erik Osterman (Cloud Posse) (@osterman)
/steps, preserve legacy redirects and release markers, update website references, rename Custom Components, and update the Go documentation inventory test for the shared catalog and initialized registry.New Features
tflint step.Documentation
/steps routes and added guides for step configuration and usage.With --use-mocks, !terraform.state and !terraform.output now use the real value when it exists and fall back to the component's mocks only when the referenced state is not provisioned or the output is missing. Precedence: real value → mock → YQ // default → original error.
Credential, network, and backend errors still fail; mocks never hide them.
New atmos.yaml setting components.terraform.mocks.mode (fallback | always, env ATMOS_COMPONENTS_TERRAFORM_MOCKS_MODE). always keeps the previous hermetic behavior: mocks only, no Terraform init, credentials, or backend reads.
--use-mocks is now value-bearing: absent/false = off, bare/true = on with the configured mode, fallback/always = on with a per-run override. It is still accepted only by atmos terraform plan and atmos describe component.
The new default is journaled as a config edition entry (2026-10-01, always → fallback), following the components.terraform.init.mode precedent, so projects pinned to an earlier edition keep mocks-only behavior with no changes.
An invalid mocks.mode in atmos.yaml fails loudly under --use-mocks instead of silently disabling mocks.
Updated the PRD, mocks/flag/YAML-function/configuration/environment-variable docs, Terragrunt migration page (also fixing its incorrect "any command" claim), example README, agent skills, help-text snapshots, defaults snapshot, and atmos.yaml JSON schema. Added a changelog post, a roadmap milestone, and a fix-log record.
Bumped github.com/containerd/containerd/v2 to v2.3.6 (go directive 1.26.6 → 1.26.8, which v2.3.6 requires) to fix GO-2026-6597, published 2026-10-01. Atmos reaches the affected package through the OPA SDK, which forced govulncheck into whole-program analysis that exceeds the standard runner's memory and failed the job repo-wide.
--use-mocks short-circuited every lookup to the mocks map, so a plan against a partly deployed environment showed fake values for components that already had real state.// defaults use) keeps real infrastructure problems visible.--use-mocks changes meaning in a released version, so the change is edition-gated to avoid surprising pinned projects.docs/prd/terraform-component-mocks.mdwebsite/blog/2026-10-01-terraform-component-mocks-fallback.mdx🤖 Generated with Claude Code
New Features
fallback prefers real state and outputs, using mocks when values are missing; always uses mocks only.--use-mocks and Terraform configuration, with clearer validation and command restrictions.. now return all outputs.Bug Fixes
Documentation
atmos mcp add / atmos mcp remove now respect the .atmos.d/ config-fragment convention when choosing which file to edit.--config is given and the project already keeps its MCP config in an auto-discovered atmos.d/ or .atmos.d/ fragment (one that declares an mcp: section), that fragment is edited instead of the root atmos.yaml. mcp.enabled (flipped during add self) lands in the same file.mcp:, behavior is unchanged: the root atmos.yaml is edited. An explicit --config <file> still wins over detection.atmos mcp add docs now explain which file is edited and the --config escape hatch.atmos.d//.atmos.d/ fragments when it loads config, so mcp.servers declared in a fragment are read correctly and show up in atmos mcp list. Only the write path lagged: mcp add always targeted the root atmos.yaml, splitting a modular-config project's MCP configuration across two files and risking duplicate or conflicting mcp.servers entries.add/remove.docs/fixes/2026-10-04-mcp-add-respects-atmos-d-fragments.mdatmos mcp addpkg/config/config_edit.go: new ResolveEditableConfigFileForSection(atmosConfig, override, section) — same precedence as ResolveEditableConfigFile (explicit override wins) but prefers an auto-discovered fragment that already declares the given top-level section before falling back to the root atmos.yaml. Helpers fragmentDeclaringSection / fragmentSearchDirs (current working directory before git root, mirroring mergeDefaultImports precedence) and fileDeclaresTopLevelKey.pkg/mcp/config/config.go: ResolveFile now calls ResolveEditableConfigFileForSection(..., "mcp").pkg/mcp/config), plus fallback and --config-override tests; direct unit tests for the new pkg/config functions (fragment variants atmos.d/.atmos.d, nested, .yml; fallback; override; no-config error; fileDeclaresTopLevelKey edge cases). New functions at 90–100% coverage.atmos.yaml + .atmos.d/mcp.yaml, atmos mcp add <url> --name demo --yes added demo to .atmos.d/mcp.yaml and left atmos.yaml untouched.go build ./..., affected test suites, golangci-lint (0 issues), and cd website && npm run build all pass.New Features
atmos mcp add and remove select a configuration file based on where the server is declared. Overwrites target the highest-precedence file declaring that server; new servers go to the highest-precedence file declaring mcp.servers, or the root atmos.yaml if none does.mcp.enabled go to the highest-precedence file declaring that setting, or the root config if none does.--config <file> to explicitly choose a target.Documentation
add writes only to the configuration file unless --install is used.atmos support (CLI output and the atmos support docs page) to say paid support is available as part of Atmos Pro, or consulting from Cloud Posse, with links to https://atmos-pro.com and https://cloudposse.com/support.atmos support golden snapshot.atmos-support.cast screengrab still shows the old text and needs a screengrabs regeneration run.🤖 Generated with Claude Code
Nothing published for this version
Nothing published for this version
feat(helm): native Helm server-side apply conflict control Andriy Knysh (@aknysh)
server_side_apply (auto | true | false) - selects the apply method.force_conflicts (boolean, opt-in, default off) - resolves field-ownership conflicts by overwriting the contested fields and becoming their sole manager.release policy and on the per-phase install / upgrade blocks (rejected on delete, which has no server-side apply surface).--server-side-apply (bare value selects true) and --force-conflicts flags to the apply and deploy operations.action.Install.ServerSideApply is a bool; action.Upgrade.ServerSideApply is a string). When unset, Atmos sets nothing, so behavior is byte-for-byte unchanged.managedFields ledger was orphaned - fails with a conflict.kubectl apply --server-side --force-conflicts or hand-editing managedFields) followed by a re-run. That breaks dependency-ordered rollouts and cannot be remediated in CI.force_conflicts clears the conflict through the normal atmos helm apply path, so the release reaches a successful state and its dependents proceed. It is opt-in because forcing overrides other field managers, so the default leaves conflicts fatal and visible.docs/prd/native-helm-force-conflicts.mdauto, true, or false in release, install, and upgrade settings.--server-side-apply and the opt-in --force-conflicts flags with apply and deploy; CLI options override stack settings.Nothing published for this version
Improved vulnerability scanning capacity and added a configurable swap-space action.
--max-changes int flag to both atmos scaffold generate --update and atmos init --update (env vars ATMOS_SCAFFOLD_MAX_CHANGES / ATMOS_INIT_MAX_CHANGES), wired through the existing (previously test-only) engine.Processor.SetMaxChanges.50 (no behavior change for existing callers). Only negative values are rejected — there is intentionally no upper bound (see "why" below).SetMaxChanges to the ScaffoldUI/InitUI interfaces (and regenerates their mocks), renaming the previously-unwired InitUI.SetThreshold to SetMaxChanges to match.tracked and rendered update strategies.docs/prd/atmos-scaffold.md and the scaffold generate/init CLI docs.website/blog/2026-09-30-scaffold-max-changes-flag.mdx) and a roadmap milestone, since this is a new user-visible flag.--update was hardcoded at 50% with no way to configure it — any update whose conflict touched more than half a file's lines failed outright, with no option to proceed and resolve conflict markers by hand instead.pkg/generator/merge, pre-existing, untouched here) isn't capped at 100 — countDifferentLines counts both deletions and insertions, so a realistic multi-line conflict routinely computes past 100%, and can exceed 200% when both the user's local edits and the template's changes diverge heavily from the common base.
0 guarantees the check never fires — any positive value just makes a hard failure progressively less likely, never impossible.docs/prd/atmos-scaffold.md previously listed --max-changes under "Still not implemented."--update, already shipped, not touched here).🤖 Generated with Claude Code
New Features
--max-changes to atmos init and atmos scaffold generate --update. The default limit is 50%; set it to 0 to disable the change-percentage check.ATMOS_INIT_MAX_CHANGES or ATMOS_SCAFFOLD_MAX_CHANGES. Positive values do not guarantee an update will proceed because the calculated change percentage can exceed 100%.Bug Fixes
Documentation
agent-skills/skills/atmos-migration/references/to-native-ci.md, that maps common third-party GitHub Actions Terraform CI patterns to Atmos Native CI equivalents: running Atmos from the container image instead of an install/setup action, replacing hashicorp/setup-terraform/opentofu/setup-opentofu with the toolchain, replacing aws-actions/configure-aws-credentials (and azure/login/google-github-actions/auth) with auth.providers/auth.identities and CI profiles, replacing the dflook/terraform-github-actions suite and tfcmt, native planfile storage semantics, tfsec/checkov/kics/infracost scanning hooks, notification hooks (kind: command and kind: step + type: webhook), and status-check/comment/template configuration.atmos-migration/SKILL.md (frontmatter references: list, routing table, and "When to Escalate" section) and adds a back-link from atmos-ci/SKILL.md's Related Skills table for discoverability..gitleaksignore (pkg/component/helm/secret_values_integration_test.go, pkg/io/masker_test.go) surfaced by a local merge from origin/main; both are intentional fake-secret fixtures for the secrets-masking tests, not real credentials..github/actions/swap-space local action. It puts a swapfile on whichever of /mnt or / has more free space, sizes it to leave a reserve of free disk, and warns and shrinks or skips the file rather than failing when space is short. The govulncheck job in .github/workflows/codeql.yml uses it to add 20G of swap, its GOMEMLIMIT goes from 12GiB to 32GiB, and the scan step is capped at 30 minutes. The full analysis now completes in about 11 minutes instead of OOM-killing the runner.atmos-migration skill already covered migrating Terraform code/state (native Terraform, Terraform Workspaces, Terragrunt, Terramate, task runners, auth configs) but had no guidance for migrating an existing repo's CI/CD off third-party GitHub Actions onto Atmos Native CI, even though atmos-ci and atmos-modernization only cover Cloud Posse's own deprecated wrapper actions.aws-actions/configure-aws-credentials and dflook/terraform-github-actions are the most widely used Terraform GitHub Actions in the wild, so agents need a concrete, verified recipe for converting them (and adjacent tools like tfcmt, tfsec/checkov, infracost) rather than inventing unverified config.govulncheck was failing on every branch still pinned to containerd/v2 v2.3.5. Advisory GO-2026-6597 (published 2026-10-01) makes govulncheck build its whole-program call graph. On this module that pass peaked at about 25GB RSS when measured locally, past the public runner's 16GB, so the runner was OOM-killed (Killed, exit 143, or "The operation was canceled"). The old 12GiB limit couldn't shrink a heap that size; it only kept the garbage collector running nonstop.azure/pim-role auth identity kind that activates a PIM-eligible Azure resource role just-in-time as part of the identity chain.SelfActivate request, and polls until it provisions.Authenticate returns the parent credentials unchanged and the activation is inherited transparently by atmos terraform, atmos auth exec, the AKS exec plugin, and MCP servers.role_definition_id (required), scope (required), duration (optional Go-style, converted to ISO-8601), justification (optional default).--justification flag (like --identity) or ATMOS_AUTH_JUSTIFICATION. Precedence: --justification > ATMOS_AUTH_JUSTIFICATION > principal.justification > interactive prompt; the flag/env reach the identity through the justification viper key.PIMClient interface (dependency-injection seam) with an HTTP implementation that targets the correct Resource Manager endpoint per cloud environment (public / US Gov / China) and filters to the caller via $filter=asTarget().errors/errors.go; register the kind in the auth factory; export a token object-id helper and a ResourceManagerEndpoint() cloud-environment helper.commands/auth usage + login notes, a changelog blog post, and a roadmap milestone. PRD status updated to Implemented.az command for activating an eligible Azure resource role, so activation is a multi-step ARM REST dance that operators otherwise hand-roll every working session.azure/subscription. This expresses the elevation once, in config, so every downstream consumer inherits it with no extra wiring.docs/prd/azure-pim-role-identity.mdduration at the role's PIM activation-policy maximum): #3238requestType: SelfActivate, api-version 2020-10-01); Role Eligibility Schedule Instances ($filter=asTarget())--justification, ATMOS_AUTH_JUSTIFICATION, identity configuration, or an interactive prompt.HOMEBREW_NO_INSTALL_FROM_API: "1" from the "Bump Homebrew formula" step in .github/workflows/build.yml so brew bump-formula-pr runs in its default formulae-API mode.HOMEBREW_NO_AUTO_UPDATE: "1"; update the step comment to explain why the var must not be set.homebrew-core tap clone and makes bump-formula-pr resolve the formula from the freshly cloned tree, which fails with No available formula with the name "atmos". Did you mean aptos? — on every release run sampled (v1.228.0, v1.229.0, v1.230.0, v1.230.1). As a result the Homebrew bump has always been done manually.Formula/a/atmos.rb on homebrew-core's main, served by formulae.brew.sh). The var was added on the mistaken premise that it was needed to make the formula editable; bump-formula-pr edits, forks under the bot token, and opens the PR itself without it.brew: command not found PATH bug and let this step run for the first time, exposing this latent failure).brew bump-formula-pr --dry-run --version=1.230.1 atmos in API mode resolves atmos cleanly (proceeds to the duplicate-PR check with no "No available formula" error — the exact CI failure). actionlint reports no findings in the edited step.docs/fixes/2026-10-01-homebrew-bump-no-install-from-api.mdatmos formula, avoiding lookup failures caused by forced tap mode.Updates github.com/containerd/containerd/v2 from 2.3.5 to 2.3.6
Sourced from github.com/containerd/containerd/v2's releases.
containerd 2.3.6
Welcome to the v2.3.6 release of containerd!
The sixth patch release for containerd 2.3 contains various fixes and updates including a security patch.
Security Updates
- containerd
Highlights
Container Runtime Interface (CRI)
- Fix bug where container creation failed when SELinux relabeling was unsupported by the filesystem (#14211)
- Enable mount manager for image mounts in CRI (#14147)
Image Storage
- Ensure all layers are fetched when multiple manifests in an index share a config descriptor (#14139)
Runtime
- Avoid unexpected mutation of mount options in mount helpers (#14192)
- Mask /proc/interrupts and CPU thermal throttle sysfs paths in Linux containers by default (#14144)
Please try out the release binaries and report any issues at https://github.com/containerd/containerd/issues.
Contributors
- Paweł Gronowski
- Samuel Karp
- Chris Henzie
- Maksym Pavlenko
- Wei Fu
- Gao Xiang
- Nan Liu
Changes
086fc0d40ePrepare release notes for v2.3.63e3b3daabcMerge commit from fork03fbef37daBound Walk referencesbfe167214bBound Dispatch concurrency and references- Fix input mutation in mount option helpers (#14192)
5f17a29a9bcore/mount: Keep lazy copy for filtered options
... (truncated)
Commitsee27353 Merge pull request #14226 from samuelkarp/prepare-release-2.3.6086fc0d Prepare release notes for v2.3.63e3b3da Merge commit from fork92e6694 Merge pull request #14192 from vvoland/13433-release/2.3f7ae0f2 Merge pull request #14211 from k8s-infra-cherrypick-robot/cherry-pick-14207-t...7fd198f cri: tolerate wrapped ENOTSUP during relabel03fbef3 Bound Walk referencesbfe1672 Bound Dispatch concurrency and references5f17a29 core/mount: Keep lazy copy for filtered options4979657 core/mount: Return copied filtered mount optionsDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase will rebase this PR@dependabot recreate will recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency@dependabot ignore <dependency name> major version will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)@dependabot ignore <dependency name> minor version will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)@dependabot ignore <dependency name> will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)@dependabot unignore <dependency name> will remove all of the ignore conditions of the specified dependency@dependabot unignore <dependency name> <ignore condition> will remove the ignore condition of the specified dependency and ignore conditionsNothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
fix(ci): put Homebrew on PATH in the release formula-bump step Andriy Knysh (@aknysh)
brew command was unavailable.init.pass_vars is enabled, while keeping TF_VAR_* variables out of the regular Terraform execution environment.init.pass_vars is enabled.Nothing published for this version
Nothing published for this version
Corrected deprecated GitHub Action detection, including plan-storage and component-updater actions.
v prefix. Cosign workflow references now match the actual release tag, while version-like segments in unrelated key paths remain unchanged.--set, and cannot be referenced by when: conditions or options:.settings.pro.errors.enabled and the ATMOS_PRO_ERRORS_ENABLED environment variable to control reporting independently. Reporting can be disabled without changing command exit codes or existing Sentry destinations.atmos ai, with automatic detection and optional model selection.--update-strategy to initialization and scaffold updates.tracked strategy uses target Git history.rendered strategy reconstructs prior template state from recorded configuration, supporting updates without target Git history.--base-ref combinations, missing configuration, and strategy switches.atmos describe component now preserves Helm chart, values, and values_files configuration in its default schema-filtered output.atmos_component and deps continue to be excluded.atmos without a subcommand opens the interactive picker when stack configuration is available and both input and output are interactive; otherwise, help is shown.ATMOS_IDENTITY, is validated before processing; authentication failures are no longer silently skipped.describe affected detects added, modified, and deleted Ansible, container, and emulator components, alongside existing component types, including native Helm and Kubernetes deletions.type: atmos scaffold hook steps now default to the generated project’s target directory. Bare-relative working directories resolve under that target, while working_directory: "." retains launch-directory behavior. type: atmos steps use the launch directory when no working directory is set; explicit values are honored.{{ .TargetPath }}.type: atmos exception.enabled: false, override inherited stack defaults.settings.provision.workdir configuration is no longer supported.ttl settings and expired workdir cleanup eligibility.vendor clean --prune-lock to forget lock entries Andriy Knysh (@aknysh) (#3201)
--prune-lock option to atmos vendor clean for permanently removing selected vendored components and their lock-file entries.:), including namespaced formats.kind value.vendor update --pull-request alternatives.265dd1a go.mod: update golang.org/x dependencies2af88d6 gopls/internal/cache: handle multiple legacy build constraints in standalone ...9e18529 gopls/internal/test/integration/fake: don't poll after a workspace edit2543006 go/gcexportdata: update package docs + minor tweaks7c2cac4 gopls/internal/golang/completion: handle new(expr)28649ea go/analysis/passes/modernize: elide red…b1afb4f to ea49a6a in /demo/screenshots @dependabot[bot] (#3224)
[!WARNING] > Cooldown could not be applied because no publication date was available from the registry. >
b1afb4f to ea49a6a. Commits @dependabot rebase.@dependabot rebase will rebase this PR - @dependabot recreate will recreate this PR, overwriting any edits that have…0.168.0 | 0.171.0 | | github/codeql-action/upload-sarif | 4.37.9 | 4.38.0 | | github/codeql-action/init | 4.37.9 | 4.38.0 | | github/codeql-action/autobuild | 4.37.9 | 4.38.0 | | github/codeql-action/analyze | 4.37.9 | 4.38.0 | | actions/cache | 5.0.5 | 5.1.0 | | cloudposse/.github/.github/workflows/shared-go-auto-release.yml | 0.170.0 | 0.171.0 | | actions/cache/save | 5.0.5 | 5.1.0 | | hadolint/hadolint-action | 3.4.0 | 3.5.0 | | trufflesecurity/trufflehog | 3.97.0 | 3.97.4 | | [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-a…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: report CLI exceptions to Atmos Pro with metadata and Pact Erik Osterman (Cloud Posse) (@osterman)
settings.pro.errors.enabled and the ATMOS_PRO_ERRORS_ENABLED environment variable to control reporting independently. Reporting can be disabled without changing command exit codes or existing Sentry destinations..tool-versions during automatic installs, enforce existing artifact checksums, record missing lock entries, and add opt-in frozen lockfile configuration for CI.ATMOS_TOOLCHAIN_FILE_PATH and ATMOS_TOOLCHAIN_INSTALL_PATH during explicit installs, automatic dependencies, and Atmos self-bootstrap.atmos when stacks exist, retain help for stackless projects, and preserve CLI/environment configuration overrides.pkg/deferred contract with subsystem-owned auth, store, secret, and stack adapters; one AuthManager owns deferred/disabled state and cached authentication instead of parallel resolver fields and caller flags.(computed) according to warn/silent policy while strict mode remains fatal.New Features
atmos without a subcommand opens the interactive picker when stack configuration is available and both input and output are interactive; otherwise, help is shown.Bug Fixes
ATMOS_IDENTITY, is validated before processing; authentication failures are no longer silently skipped.atmos describe affected now evaluates the full eight-type canonical set of component types in both its added/modified and deleted paths — matching describe component / describe dependents.
describe affected was the outlier: its added/modified path (processStackAffected) and deleted path (detectDeletedComponents) each enumerated a partial, hardcoded type list, so changed/deleted components of the missing types were silently unreported — breaking CI/CD pipelines built on it.ansible/container/emulator were absent from both paths.deletableComponentTypes = the full 8 types, so the deleted path stays in sync with the added/modified path.processHelmfileComponentsIndexed/processPackerComponentsIndexed with a generic processSimpleComponentsIndexed(componentType, ...); routes helmfile/packer/ansible/container/emulator through it via simpleAffectedComponentTypes. terraform/kubernetes/helm keep dedicated processors (Spacelift/Atlantis, k8s manifests, helm values files).emulator has no filesystem source tree (getComponentBasePath returns ""): empty path pattern, folder-change detection skipped; ansible/container base paths added to the pattern cache, relevant-files switch, and base-path index; BuildComponentPath resolves ansible/container.settings section; settings-equality guarded on presence (!= nil), so an emptied settings: {} is still reported.stack.vars and stack.env); settings-section + emptied-settings cases; file dependency without settings; pattern cache resolves ansible/container and returns empty for emulator.ansible/container/emulator component-instance first-class fields (e.g. container image/build/run, emulator driver) are not compared — no such schema exists yet (those kinds are upcoming; driver lives on container workflow steps). The section-check mechanism already covers the standard sections these components use.
go build ./...go test ./internal/exec/ -run 'Affected|DetectDeleted|IsAbstract|ProcessComponents|ComponentPathPattern'atmos lint --changed (0 issues)describe affected detects added, modified, and deleted Ansible, container, and emulator components, alongside existing component types, including native Helm and Kubernetes deletions.--ui attribute values within the terminal width, preserve tree rails and aligned attribute headers, align scalar continuations after →, and place multiline documents beneath their attribute headers at every terminal width.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
fix(toolchain): keep the 'v' prefix in cosign certificate-github-workflow-ref Andriy Knysh (@aknysh)
--certificate-github-workflow-ref value with the tool's actual downloaded asset tag, the same way the existing URL correction already aligns --certificate-identity. This unblocks toolchain installs (and CI) for tools whose release tag is v-prefixed (tflint, gum, ...).Error: expected GitHub Workflow Ref not found in certificate
--certificate-github-workflow-ref refs/tags/0.64.0 (should be refs/tags/v0.64.0)
aquaproj/aqua-registry main added a --certificate-github-workflow-ref refs/tags/{{.Version}} assertion to the tflint/gum cosign configs that day. Runs before passed, runs after failed (no Atmos code change; not a cold cache).{{.Version}} is meant to be the actual release tag, and tflint has no version_prefix (per aqua semantics the tag is used as-is). The failure is that Atmos renders {{.Version}} v-stripped (0.64.0) while the asset it downloaded is at v0.64.0 — a divergence in Atmos's version handling (normalizeGitHubVersion strips v when registry metadata is unavailable; the download fallback re-adds it on a 404). The new assertion just made a previously-harmless divergence fatal.renderArgs already realigned URL args to the downloaded tag via replaceVersionSegmentInURL (URLs only). The bare workflow-ref isn't a URL, so it stayed v-stripped and mismatched the cert.This is a targeted, symptomatic fix — it aligns the workflow-ref with the downloaded asset tag so the mismatch can't break verification. It does not infer v from the tool name and does not add any request. It does not attempt to prove which exact resolution/download path produced the v-stripped version in the live run.
The canonical fix — make the aqua registry version_prefix + real tag the single source of truth for {{.Version}}, and remove the v-prefix heuristics — is tracked in #3211 (per Erik Osterman (Cloud Posse) (@osterman)'s guidance that the registry is the authority for tag format). Once #3211 lands, this correction becomes a no-op safety net.
pkg/toolchain/verification/checksum.go: add replaceVersionSegmentInPath (non-URL counterpart of replaceVersionSegmentInURL).pkg/toolchain/verification/signature.go: renderArgs applies it scoped to the --certificate-github-workflow-ref value only (so an unrelated non-URL option like --key /keys/0.64.0/public.pem is never rewritten). Previous arg tracked in a local var (avoids gosec G602 false positive).TestReplaceVersionSegmentInPath + TestRenderArgsCorrectsCosignWorkflowRef (asserts the workflow-ref gets the v, and a --key path does not).go test ./pkg/toolchain/verification/ (incl. reproduction test; fails before, passes after)go build ./...atmos lint --changed (0 issues); package coverage 88.9% (both replaceVersionSegment* 100%, renderArgs 92.9%)v prefix. Cosign workflow references now match the actual release tag, while version-like segments in unrelated key paths remain unchanged.before.scaffold.generate/after.scaffold.generate, kind: step/kind: steps) now default a step's working_directory to the scaffold's target/output directory instead of falling through to the process's own cwd.{{ .TargetPath }}, alongside the existing {{ .Answers }}.pkg/hooks/step_engine.go into an exported hooks.ApplyDefaultWorkingDirectory(step, anchorDir), reused by both component/stack lifecycle hooks and scaffold hooks instead of duplicating the logic.scaffoldhooks.Run now takes a RunInput struct instead of six positional parameters, to stay within revive's argument-limit.working_directory: "." override) next to every existing scaffold-hooks example in the website docs, the atmos-hooks skill, and the scaffold PRD.docs/fixes/ record.atmos scaffold generate <template> <target> allows target to differ from the invoking shell's cwd, but nothing anchored a hook's working_directory to target. An unset value fell through ShellHandler into exec.Cmd.Dir = "", which Go defaults to the process's own cwd — so the documented terraform fmt -recursive example (and any other scaffold hook) silently ran against the wrong directory whenever target != cwd.pkg/hooks.ComponentPath); scaffold hooks had no equivalent anchor. This brings scaffold hooks in line with that existing convention rather than inventing a new one.target resolves to the same absolute directory as the invoking shell's cwd (e.g. running atmos scaffold generate <template> .), the resolved working directory is identical before and after this change — existing hooks that already worked keep working exactly the same way. This fix only changes behavior for the previously-broken case: a target whose absolute path differs from cwd.working_directory: "." in a hook's with: block — dot-prefixed and absolute values are left untouched, same convention lifecycle hooks already use.TestExecuteWithSetup_HooksDefaultWorkingDirectoryToTargetPath in pkg/generator/ui/ui_test.go) and confirmed it failed against the pre-fix code before implementing the fix.go build ./... and go test ./pkg/hooks ./pkg/generator/scaffoldhooks/... ./pkg/generator/ui/... all pass.golangci-lint scoped to upstream/main (this fork's origin/main is stale) reports 0 issues.cd website && npm run build succeeds after the doc edits.type: atmos scaffold hook steps now default to the generated project’s target directory. Bare-relative working directories resolve under that target, while working_directory: "." retains launch-directory behavior. type: atmos steps use the launch directory when no working directory is set; explicit values are honored.{{ .TargetPath }}.type: atmos exception.terraform.provision, helmfile.provision, ...) - consistent with global vars, metadata, and secrets - not in atmos.yaml settings.provision.provision.workdir (including an explicit enabled: false).settings.provision.workdir config surface and adds regression tests + corrected docs for the stack-level default.settings.provision.workdir.enabled (documented in atmos.yaml) was ignored - only component-level worked.settings. Wiring up settings.provision was the wrong direction; the correct mechanism (terraform.provision) already exists.Workdir from ProvisionSettings; deleted the unused ProvisionWorkdirSettings type; regenerated pkg/datafetcher/schema/atmos/config/1.0.json (go generate ./pkg/config/schema). Component-level provision.workdir in the stack-config/manifest schemas is unchanged.stack_processor_merge.go to the inline four-layer merge (GlobalProvisionSection → base → component → overrides); removed the stack_processor_provision.go settings injection.provision/workdir.mdx, provision/index.mdx, provision/backend.mdx now document the stack-level terraform.provision default; deleted cli/configuration/settings/provision.mdx (documented the removed, never-implemented global).tests/fixtures/scenarios/workdir-global-default/ declares the default as stack-level terraform.provision.workdir.enabled: true; regression tests confirm inheritance and the component-level enabled: false override.go build ./...go test ./internal/exec/ -run TestGlobalWorkdirProvisionDefault -vgo test ./pkg/config/schema/ ./pkg/schema/ ./pkg/provisioner/...atmos lint --changed (0 issues)cd website && npm run build (no broken links)Configuration
enabled: false, override inherited stack defaults.settings.provision.workdir configuration is no longer supported.Documentation
ttl settings and expired workdir cleanup eligibility.Validation
Nothing published for this version
feat(ai): add opencode CLI provider Andriy Knysh (@aknysh)
opencode), alongside claude-code, codex-cli, and copilot-cli. Atmos runs the opencode binary non-interactively (opencode run <prompt>), reusing the user's opencode auth and model-provider configuration — no API key in atmos.yaml.mcp.servers are configured, Atmos writes a temporary opencode config (auth-requiring servers wrapped with atmos auth exec -i <identity>, toolchain PATH injected) and points opencode at it via the OPENCODE_CONFIG env var. opencode deep-merges it, so the user's own opencode.json is never modified and nothing is left behind (temp file cleaned up per invocation).claude-code → codex-cli → copilot-cli → opencode → gemini-cli) and the IsCLIProvider set. cmd/ai/init.go needs no change — its MCP handling is generic via IsCLIProvider.buildArgs, ExtractResult, temp-config schema incl. auth-wrapping, and a cross-platform subprocess round-trip via a TestMain fake binary — 86.7% coverage), provider documentation, a changelog post, and a roadmap milestone.atmos ai through their existing opencode installation with zero extra credentials./cli/configuration/ai/providerswebsite/blog/2026-09-18-opencode-cli-provider.mdxNew Features
atmos ai, with automatic detection and optional model selection.Documentation
Tests
spec.files[].path can now be a glob pattern (doublestar syntax: *, ?, [...], ** for any depth, {a,b}), matched against every file the template discovers, instead of only a literal path.path: combined with when: gates or skips an entire directory recursively, in one entry, instead of one when:-gated entry per file.path: combined with matrix: and target: duplicates an entire directory's files once per matrix combination, the same way a single-file matrix entry already does. Two new template variables, .file.Path and .file.RelPath (the matched file's path with the entry's glob literal prefix stripped), are available in target: and content so a directory-level target: can differentiate which matched file an output came from.spec.files[] entry's path: matches the same discovered file, the last declared entry wins — the same precedence convention .gitignore/CODEOWNERS use.spec.Path, not once per matched file, so a non-deterministic axis expression (e.g. Sprig's randAlphaNum) resolves the same value across every file one entry matches, instead of a different value per file.[/{) now fails scaffold load and atmos scaffold validate immediately (ErrScaffoldFilePathPatternInvalid), instead of silently and permanently matching nothing.path: pattern is now always normalized to a forward slash regardless of OS, instead of only working correctly on Windows.target: that fails to reference .file.Path/.file.RelPath now fails deterministically before any file in the run is written (ErrScaffoldMatrixTargetMissingFileContext), instead of leaving a partial write on disk once a collision is discovered mid-run. This check parses target: with the scaffold's real delimiters and walks the resulting template AST for a genuine .file.Path/.file.RelPath field access, rather than a lexical substring match — so it can't be fooled by a literal .file. in unrelated text or an invalid .file.Unknown reference.atmos scaffold generate --update can now recover a real 3-way merge base after a target: migration (e.g. adopting a glob + .file.RelPath-based target on an entry that previously rendered verbatim to its own path): the merge-base lookup falls back to the file's original discovered source path when git history has nothing at the new rendered path, instead of always treating it as user-added and silently freezing its content forever.atmos-scaffold AI agent skill (agent-skills/skills/atmos-scaffold/) now documents glob path:, directory-level matrix, and .file.Path/.file.RelPath, so AI agents helping a user author a scaffold.yaml know this capability exists.spec.files[] matched files one at a time by exact literal path, so gating or duplicating an entire directory meant repeating the same when: or matrix:/target: on every file inside it, one entry per file, kept in sync by hand as the directory grew — a gap the original matrix: PRD explicitly called out as a non-goal at the time. Directory-level matrix duplication is a natural extension of the existing single-file matrix feature (e.g. one components/ tree instance per environment), and directory-wide skip is the same gap for when: alone (a legacy docs tree gated behind an opt-in answer, a cloud-provider-specific subtree).
Several bullets under "what" are bugs found either while field-testing the feature against a real build, or during CodeRabbit review — each reproduced live before and after the fix, with a new regression test.
website/blog/2026-09-18-scaffold-directory-glob.mdxdocs/prd/atmos-scaffold.md ("Glob path: and Directory-Level Matrix")website/docs/cli/commands/scaffold/generate.mdx ("Glob Paths and Directory-Level Matrix")examples/scaffolding-directory-matrix/agent-skills/skills/atmos-scaffold/ai.providers:
openrouter — OpenRouter (https://openrouter.ai/api/v1, OPENROUTER_API_KEY). A router across hundreds of models; switch models by changing the provider-prefixed model slug (e.g. anthropic/claude-sonnet-4-5, openai/gpt-4o, deepseek/deepseek-chat). Default model: deepseek/deepseek-chat.deepseek — DeepSeek (https://api.deepseek.com, DEEPSEEK_API_KEY). Default deepseek-chat; deepseek-reasoner for the reasoning model.zai — Z.AI / Zhipu GLM (https://api.z.ai/api/paas/v4, ZAI_API_KEY). Default glm-5.3.grok provider using the shared base/openaicompat conversion layer, self-registers via init(), and works everywhere the other providers do (atmos ai ask/chat, --ai).base_url, api_key, and model already exist on the AI provider config.httptest round-trip exercising all five send methods), factory registration coverage, provider documentation, a changelog post, and a roadmap milestone.openai provider at a hand-copied base URL and hope the defaults lined up. These providers make the common choices first-class: sensible default model, API-key env var, and endpoint out of the box./cli/configuration/ai/providerswebsite/blog/2026-09-18-more-ai-providers.mdxNew Features
Documentation
Bug Fixes
release-assets.githubusercontent.com:443 to the harden-runner allowed-endpoints in .github/workflows/website-preview-deploy.yml.main and every recent PR for days — its Set up Go step dies with connect ECONNREFUSED …:443 while downloading the Go toolchain.s3-deploy composite action runs go tool mage s3:deploy. So removing the step isn't an option — the toolchain download must be allowed.actions/setup-go fetches Go from GitHub's release-asset CDN (release-assets.githubusercontent.com), but that host was missing from the deploy job's egress allowlist while harden-runner runs with egress-policy: block. The build job (website-preview-build.yml) already allows this host, which is why the site build succeeds but the deploy fails.website-deploy-preview build check already passes); it is not a merge gate. Because workflow_run workflows execute the copy on the default branch, the fix has to land on main to take effect..github/workflows/website-preview-build.yml.--update-strategy=tracked|rendered to atmos init --update and atmos scaffold generate --update, controlling where the three-way merge base comes from, independently of --merge-strategy (conflict resolution) and --merge-driver (merge algorithm).
tracked (default): unchanged behavior — base read from the target's own git history at --base-ref.rendered: base is a pristine re-render of the template at the ref that produced what's currently on disk, using that generation's own recorded .atmos/scaffold.yaml answers. No dependency on the target being a git repository at all.pkg/generator/engine.UpdateStrategy type + ParseUpdateStrategy, a baseContentLoader interface abstraction on Processor (satisfied by both the existing storage.GitBaseStorage and the new storage.RenderedBaseStorage), and pkg/generator/source.ResolveRenderedBase (loads the target's project record and fetches the old ref before the current run overwrites it).rendered requires the template to carry a scaffold.yaml (so its answers are recoverable) — plain --set-only templates aren't supported yet and get a clear error pointing at tracked.--base-ref + --update-strategy=rendered is a mutually-exclusive-flags error, since rendered's ref comes from .atmos/scaffold.yaml, not --base-ref.rendered works for OCI-sourced templates too: the resolved manifest digest is pinned the same way a git commit SHA is, so a later re-render always resolves the exact original content instead of whatever a mutable tag currently points to.<dt>/<dd> flag entries and usage examples on init.mdx/scaffold/generate.mdx/scaffold/usage.mdx, updates to the atmos-scaffold.md/atmos-init.md PRDs, a changelog post, and a roadmap milestone.A /field-test pass and two rounds of CodeRabbit review against the shipped feature surfaced several real gaps, all fixed in this branch:
--update regardless of strategy and wrote a resolved value into spec.baseRef even under rendered — whose whole point is to have no git-history dependency at all. Introduced spec.renderedRef, a separate project-record field recording the actual resolved ref (git commit SHA or OCI manifest digest) at generation time, and gated every place that previously wrote spec.baseRef unconditionally on --update-strategy — including two retry-only code paths (the "confirm update instead" offer, and the interactive-declined-then-retried flow) that a first fix pass missed.rendered mode's base-render step with no base source ever resolved, panicking on a nil pointer. Fixed with both a functional retry-path fix and a defensive nil-check that turns any future recurrence into a clear error instead of a panic.baseRef/renderedRef now doubles as a record of which strategy last managed it; switching strategies against an existing project fails loudly instead of silently misinterpreting the other strategy's provenance.go-getter's git fetch for a //subdir source (the shape atmos init aws/app itself uses) clones the full repo into its own internal temp location and copies only the subdir out, so the destination directory never has a usable .git to inspect — spec.renderedRef silently stayed empty for any subdir-sourced template. Fixed with a best-effort fallback re-fetch scoped to resolving just the commit.WithValidValues flag-validation framework for --update-strategy/--merge-driver/--merge-strategy (previously registered but never actually checked), fixed a misleading error message that assumed git under rendered mode, and closed several direct-unit test-coverage gaps left by cross-package-only test exercise.--update's merge base has always been read from the target's own git history at a pinned commit. That has two real costs:
--update fail outright.--update-strategy=rendered sidesteps both: no git dependency, and the base always reflects exactly one update cycle's worth of drift, since it's re-rendered fresh from the recorded prior generation each time.
New Features
--update-strategy to initialization and scaffold updates.tracked strategy uses target Git history.rendered strategy reconstructs prior template state from recorded configuration, supporting updates without target Git history.Bug Fixes
--base-ref combinations, missing configuration, and strategy switches.Documentation
--prune-lock flag to atmos vendor clean that also removes the cleaned components' entries from vendor.lock.yaml (in addition to removing their files).--component/--tags/--stack/--labels selectors matched — never entries the caller didn't target. Preservation stays the default.lockfile.CleanOptions{Force,DryRun,PruneLock}, pruneSelectedLockEntries, CleanReport.Forgotten, unit + cmd tests, and CLI docs.vendor clean now preserves lockfile entries for future reinstalls"), there was no supported way to permanently remove a vendored source using the native lock: after deleting it from vendor.yaml, the orphan lock entry keeps its recorded files, and vendor verify then reports them as missing.vendor pull --refresh-lock was rejected: vendor.yaml and legacy component.yaml vendoring share one vendor.lock.yaml (both call lockfile.Record), so a full vendor pull blindly pruning non-declared artifacts could delete legitimate component.yaml lock entries. The surgical, zero-over-pruning fix is an explicit flag on vendor clean that forgets only what the selectors matched.# Permanently remove a component: delete its files AND forget its lock entry,
# then remove its source from vendor.yaml (no orphan left for `vendor verify`).
atmos vendor clean --component vpc --prune-lock/cli/commands/vendor/vendor-cleandocs/fixes/2026-09-22-vendor-clean-prune-lock.mdNew Features
--prune-lock option to atmos vendor clean for permanently removing selected vendored components and their lock-file entries.Documentation
source:) with provision.workdir.enabled: true, provision the isolated workdir up front in ProvisionAndResolveComponentPath — before backend/varfile generation — instead of only at the before.terraform.init hook.backend.tf.json and *.tfvars.json now land in the per-run workdir instead of the shared source component directory.TestProvisionAndResolveComponentPath_LocalComponentWorkdirProvisionedEarly) and a fix record under docs/fixes/.info.ComponentSection[WorkdirPathKey]; when that key is unset, generation falls back to the source component dir.WorkdirPathKey) ran at before.terraform.init — after runPreExecutionSteps had already written backend.tf.json/varfile. So those files were written into components/terraform/<component>/, polluting the source tree, and under atmos terraform plan --all --max-concurrency N parallel runs read/wrote the same source backend.tf.json concurrently, producing Error: ... The JSON data ends prematurely HCL parse failures.source: components were unaffected because their workdir is set early (during source download).before.terraform.init run of the same provisioner becomes a safe no-op (it early-returns when WorkdirPathKey is already set), and the -reconfigure signal it records still persists on the shared ComponentSection.settings.provision.workdir.enabled is still ignored (only component-level is honored) — tracked separately in #3197.docs/fixes/2026-09-21-workdir-backend-race-source-dir.mdBug Fixes
Documentation
auth.identities, auth.providers, and secrets.providers keys may contain a colon (:), enabling namespaced names such as example/prod:terraform_applier.auth_identities, auth_providers, and secret_providers patternProperties key pattern from ^[a-zA-Z0-9/_-]+$ to ^[a-zA-Z0-9/_:-]+$ in both the embedded schema (pkg/datafetcher/schema/atmos/manifest/1.0.json) and the hand-synced test fixture (tests/fixtures/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json).auth_identity / auth_provider definition parity in the test fixture (it still required kind and was missing the required/tags fields).auth.identities rejected globally configured identity names containing :, even though the atmos.yaml config schema and the runtime identity model already accept them (identity/provider names are opaque map keys, resolved case-insensitively with no character validation).additionalProperties was false, a namespaced identity like example/prod:terraform_applier failed stack validation before identity resolution and could not be selected as a component default.secrets.providers shared the identical inconsistency (config schema accepts any key; manifest schema rejected :; provider names are opaque map keys at runtime), so it was relaxed in the same pass for consistency.required_providers local names (^[a-zA-Z0-9-_]+$, no colons per Terraform's own rule) and component-instance-name patterns were reviewed and intentionally left unchanged.docs/fixes/2026-09-17-auth-identity-name-colon-schema.mdNew Features
:), including namespaced formats.kind value.Documentation
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Detect ten deprecated GitHub Actions explicitly and emit warning annotations linking to the migration hub.
The first unchanged production rerun after #3176 did not meet the zero-write cost gate. Run 35259983114 reported Changed/new: 2654; deleted: 7 even though it built the exact same merge commit as the bootstrap deployment.
Wall-clock timestamps from three Docusaurus plugins, the generated media-kit ZIP, and the footer year changed content-hashed output. New bundle names then cascaded into thousands of otherwise unchanged HTML files, defeating the manifest-based S3 uploader and preserving much of the request cost that #3176 was intended to remove.
SOURCE_DATE_EPOCH from the checked-out Git commit in production and preview buildsExternal source data can still produce legitimate content changes. A rerun with the same source and external inputs is now byte-identical.
bc212b2d76 with the same SOURCE_DATE_EPOCHdiff -qr: 0 byte differencesactionlint passes for production and preview workflowsThis restores the intended #3176 steady state: one manifest GET and zero S3 PUT/COPY/DELETE requests on an unchanged deployment, instead of rewriting approximately 2,654 objects per run.
New Features
Bug Fixes
Tests
Bug Fixes
Documentation
vendor update --pull-request alternatives.Warning: diagnostics from plan/apply/deploy now become inline GitHub ::warning CI annotations, the same mechanism already used for failing terraform test assertions.file/line from the diagnostic's on <file> line <N> locator when Terraform includes one, falling back to a file-level annotation otherwise.errorLocationRe) to match the locator formats Terraform actually emits (on main.tf line 20, in resource "x" "y":, and bare on main.tf line 1 with no trailing colon), not just the narrower terraform test diagnostic format it previously matched.onAfterPlan/onAfterApply/onAfterTest/onAfterDeploy hook so annotation emission runs first, immediately after parsing output, ahead of summary/output/upload/check/comment — so it survives later warn-only failures and the fatal planfile-upload early-return in onAfterPlan.None.
New Features
Bug Fixes
ubuntu-latestStandard GitHub-hosted runners are free for public repositories, removing the largest recurring core-auto workload while keeping macOS and Windows behavior unchanged.
runs-on/action steps remain in workflowsExpected savings: approximately $200-300/month.
s3:deploy Mage targetmagefiles/README.md with all 20 currently exposed Mage targets and their environment controlsdocs/fixes/2026-09-16-content-aware-s3-website-deploy.mdThe previous deployment was request-heavy even when website content had not
changed:
aws s3 sync could upload rebuilt files because generated mtimes changed.--metadata-directive REPLACE.The metadata pass was not optional: the website requires correct MIME and
charset headers. aws s3 sync can apply one --content-type value to a whole
invocation, but it cannot selectively append charset=utf-8 while preserving
each file's distinct MIME type. The workaround therefore restamped every text
object after each sync.
AWS Cost Explorer for the seven complete days from September 9-15, 2026 showed
6,433,267 PutObject/CopyObject requests costing $32.25 across the development
and production documentation-origin accounts. That is a $138/month normalized
run rate for those two request types alone; S3 Tier-1 requests overall were
running at approximately $145/month.
This PR targets the Atmos website's share of that spend, estimated at
$70-85/month. The first deployment performs a one-time bootstrap, but every
unchanged repeat deployment thereafter performs one manifest read and zero S3
PUT/COPY/DELETE writes. A changed deployment writes only the actual delta.
The Mage target uses Atmos's existing AWS SDK v2 dependencies rather than
wrapping the AWS CLI. This removes subprocess and temporary JSON request-file
handling, gives each upload an explicit typed Content-Type and content length,
uses the SDK's retry and context-cancellation behavior, and exposes per-object
DeleteObjects failures directly to tests. One local glob matcher now controls
protected paths during both manifest diffs and bootstrap cleanup.
The manifest is uploaded only after all object writes and deletes succeed. A failed deployment keeps the old manifest, so the next run retries the incomplete delta.
The one-time bootstrap uploads all local files before listing and deleting stale unprotected objects, so a protected local path is never accidentally omitted. Retained paths remain tracked in the manifest so removing a protection pattern later makes them eligible for cleanup again. Typed batch deletion rejects per-object S3 errors before publishing the new manifest. Existing demo media and immutable versioned schemas remain protected.
Deployments to the same bucket and prefix are serialized by the existing production and per-preview-PR workflow concurrency groups. In-flight runs are never cancelled, so manifest reads, object changes, and final manifest publication cannot interleave for one destination.
Manifest traversal accepts regular files only; symlinks, devices, pipes, and other non-regular entries fail before any source content is opened.
An unchanged deployment performs one manifest read and zero S3 write requests.
go test -tags=mage ./magefilesgo test -tags=mage -race -coverprofile=.context/s3-deploy-sdk-coverage.out ./magefiles/...go vet -tags=mage ./magefilesactionlint .github/workflows/website-preview-deploy.yml .github/workflows/website-deploy-prod.ymlgo tool mage -l confirms all 20 targets are represented in magefiles/README.mdExpected savings: approximately $70-85/month.
New Features
Bug Fixes
Documentation
The first unchanged production rerun after #3176 did not meet the zero-write cost gate. Run 35259983114 reported Changed/new: 2654; deleted: 7 even though it built the exact same merge commit as the bootstrap deployment.
Wall-clock timestamps from three Docusaurus plugins, the generated media-kit ZIP, and the footer year changed content-hashed output. New bundle names then cascaded into thousands of otherwise unchanged HTML files, defeating the manifest-based S3 uploader and preserving much of the request cost that #3176 was intended to remove.
SOURCE_DATE_EPOCH from the checked-out Git commit in production and preview buildsExternal source data can still produce legitimate content changes. A rerun with the same source and external inputs is now byte-identical.
bc212b2d76 with the same SOURCE_DATE_EPOCHdiff -qr: 0 byte differencesactionlint passes for production and preview workflowsThis restores the intended #3176 steady state: one manifest GET and zero S3 PUT/COPY/DELETE requests on an unchanged deployment, instead of rewriting approximately 2,654 objects per run.
New Features
Bug Fixes
Tests
Nothing published for this version
Nothing published for this version
test(ci): live-GitHub canaries, ATMOS_TEST_OFFLINE, toolchain retry Erik Osterman (Cloud Posse) (@osterman)
create_namespace through the stack processor Andriy Knysh (@aknysh) (#3134)feat(metrics): measure terraform subprocess resource usage Erik Osterman (Cloud Posse) (@osterman)
terraform plan/apply/deploy from the actual subprocess tree (the terraform/tofu process and everything it spawns, e.g. provider plugins) instead of only the Atmos CLI wrapper's own negligible usage.ui.Info summary line after each terraform plan/apply/deploy run, plus one aggregate summary at the end of the whole atmos invocation covering every subprocess spawned during the run (e.g. every component in a multi-component --affected plan).settings.metrics.enabled setting (default true); it never affects the Atmos Pro upload.describe affected) are unaffected.RUSAGE_SELF, which excludes the terraform subprocess entirely — the actual expensive part of any plan/apply/deploy run. This restores the subprocess-tree measurement approach from the feature's original design (#2217, closed unmerged) at the shared execution funnel every component type goes through, so the reported numbers reflect what a run actually cost, both locally and in Atmos Pro.New Features
Configuration
settings.metrics.enabled, enabled by default, to control local metric summaries.Documentation
tests/live_github_canary_test.go): an unauthenticated vendor pull of cloudposse/terraform-null-label, its authenticated twin, an unauthenticated toolchain release-asset install (peteretelej/tree, the tool behind the recent bootstrap 404), and an unauthenticated !include of a raw GitHub file. Each drives the built atmos binary with every GitHub credential source scrubbed (GITHUB_TOKEN/ATMOS_*_TOKEN/GH_TOKEN blanked, GH_CONFIG_DIR pointed at an empty dir to defeat the gh auth token fallback) and the local git-mirror rules stripped, so they genuinely exercise the unauthenticated routes against real GitHub.ATMOS_TEST_OFFLINE (documented in docs/prd/test-preconditions.md but never wired up): RequireGitHubAccess, RequireNetworkAccess, and the new RequireLiveGitHub/RequireLiveGitHubAuthenticated skip under it, independently of ATMOS_TEST_SKIP_PRECONDITION_CHECKS (which CI sets and which only bypasses the connectivity probes).live_github / live_github_authenticated as YAML test-case preconditions; the harness scrubs auth and removes the mirror's insteadOf rules for those cases (gitconfigenv.Without/IsInsteadOfEntry, unit-tested)..github/actions/ci-toolchain's atmos toolchain install step one bounded retry: atmos toolchain install skips tools already on disk, so the retry only re-attempts what failed (e.g. a transient release-asset download error). No shell loop.tests/test_preconditions.go → tests/preconditions.go; document ATMOS_TEST_OFFLINE and the two preconditions accurately.docs/fixes/2026-08-10-github-transient-error-tls-cert-flake.md — the transient-vs-real pattern the canaries follow.New Features
Bug Fixes
Documentation
tests/testhelpers/httpmock.GitHubMockServer into a small GitHub HTTP façade: releases/tags API (with Link pagination), /api/v3/rate_limit with X-RateLimit-* headers on every API response, release-asset and archive downloads, GHES-shape raw content (/raw/{owner}/{repo}/{ref}/{path}), and an aqua-registry index + per-package files. Helpers to register tools/assets/raw files, build tiny tar.gz/zip archives, inject failures (FailWith, FailWithTimes, FailWithHeaders), set the rate limit, inspect the request log, and export the five routing env vars for subprocess tests (EnvForSubprocess/Setenv). Legacy RegisterFile/Transport/HTTPClient unchanged.jq install mechanics (TestToolchainCustomCommands_InstallJQViaMock, the jq entry of TestToolchainAquaTools_InstallAllTools), TestToolchainAquaTools_NonExistentToolError, and a new !include case against a sibling fixture (atmos-include-yaml-function-mock) routed at the mock via GITHUB_SERVER_URL/GITHUB_API_URL. The original raw.githubusercontent.com !include case is byte-identical to main and stays live — atmos evaluates every manifest matched by included_paths on any stack resolution, so a co-located mock stack would have forced the live fetch anyway.env: values now expand ${VAR} against the process environment (expandTestCaseEnv, unit-tested); TestMain starts one process-wide façade exported as ATMOS_TEST_GITHUB_MOCK_URL — deliberately not the routing vars themselves, so the real toolchain bootstrap and the live canaries are unaffected.pkg/github GetLatestRelease/GetReleases on 401 / 404 / 429; the three live _Integration rate-limit tests in pkg/github/ratelimit_test.go become _ViaMock (+ an exhausted-but-reset case); the downloader's pre-fetch rate-limit check fires only for GitHub URLs and doesn't block on a passed reset. Aqua's 403→unauthenticated-retry fallback and the installer's 4xx/5xx handling already had deterministic httptest coverage — left as is.GITHUB_SERVER_URL / GITHUB_API_URL / ATMOS_TOOLCHAIN_*, so a plain http://127.0.0.1:<port> server can stand in for GitHub for both in-process and built-binary tests. This PR is the test-side half of that seam.*_LiveNetwork, the live !include case) stay live as canaries (#3109).HTTPS_PROXY pointed at a closed port (no GitHub reachable); the untouched live !include case fails under that same guard, proving it is still genuinely live.docs/fixes/2026-08-10-github-transient-error-tls-cert-flake.md (rate-limit / transient handling background).Bug Fixes
Reliability
pkg/github Endpoints.Host was built from url.Hostname() (port stripped) while IsHost preserved non-default ports on the candidate, so a GHES on a custom port could never match its own configured URL. Now built from url.Host; covered by TestRepoEndpoints_NonDefaultPortPreserved. Default-port and portless configurations are unaffected.pkg/github/endpoints.go) that reads the standard GITHUB_SERVER_URL / GITHUB_API_URL variables (the ones GitHub Actions exports on both github.com and GitHub Enterprise Server) and route every place Atmos talked to your repositories through it: the CI provider, remote imports and vendoring raw fetches, the GitHub API client (releases, tags, artifacts, archived checks), the token host allowlist, and token injection for git operations.atmos toolchain install does not follow GITHUB_SERVER_URL. It gets its own env-only knobs — ATMOS_TOOLCHAIN_GITHUB_URL, ATMOS_TOOLCHAIN_GITHUB_API_URL, ATMOS_TOOLCHAIN_AQUA_REGISTRY_URL — for corporate release proxies/mirrors.github.com/<owner>/<repo>/releases/download/...); the allowlist previously covered only api.github.com, raw.githubusercontent.com, and uploads.github.com, so those fetches went out unauthenticated even with a token configured. Verified GitHub returns the same 302 with or without the header, and Go strips Authorization on the cross-host redirect to the storage host.github.com/org/repo detection deliberately stays github.com-only (a bare hostname can't be told from a relative path); documented. No atmos.yaml changes, no schema changes — env vars only, all defaulting to today's github.com behavior.pkg/ci/providers/github and pkg/http (extend, don't fork).httptest server (next PR in this stack), which is how we stop the test matrix from depending on live GitHub.New Features
GITHUB_SERVER_URL and GITHUB_API_URL endpoint configuration.ATMOS_TOOLCHAIN_* variables.Security
Documentation
!terraform.output, !terraform.state, atmos.Component(), and custom-command execution while preserving terminal masking and credential-free inspection.<MASKED> placeholders without retrieving secrets; the new tests reproduce this behavior when the fix is removed.Restore Changelog / Roadmap discovery with a shared, stable header and accessible navigation, paginate curated highlights six at a time with Q2/Q3 2026 first, simplify quarter lists, and correct audited milestone statuses, progress, and links across 15 initiatives.
Keep Terraform Maturity Journey in its Resources submenu, remove it from Get Started, and order Stage 0–10 then Nirvana without an overview self-link; replace the unrelated vendoring cast in the Version Tracker announcement with its actual dev/prod tracks demo.
Audit Features against current docs and implementation, expand coverage from 22 to 44 cards, correct component inventories and stale claims, repair obsolete reference links, and reframe Make/Just/Task migration guides and the bundled skill around general-purpose task running.
Root-causes a week of system-wide file-descriptor exhaustion that required repeated reboots.
atmos scaffold generate walks a template's source directory verbatim, copying every file/subdirectory not explicitly declared in spec.files straight through to the target at the same relative path. A template configured with source: "." whose target lands inside that same source tree (e.g. generated/<name>, right next to atmos.yaml) therefore re-copies its own accumulated prior output into every new target -- and since sibling targets share that same container directory, any previously generated sibling leaks in too. Confirmed live in tests/fixtures/scenarios/scaffold-matrix-freetext/generated/: 47,000+ self-nested directories, 2.7GB, after repeated local atmos test runs (scaffold-matrix-computed hit the same bug at smaller scale).clean: true only removed paths git status reports as Untracked -- but go-git's Status(), like plain git status, never reports a gitignored path at all, so a fixture whose own output directory is gitignored (as generated/ is here) was never actually cleaned between runs despite clean: true on every relevant test case.pkg/generator/templates: LoadConfigurationFromDir gains a variadic WithExcludePath(absPath) option. When the resolved generation target falls inside the template's source directory, the walk now excludes the whole shared top-level container the target lives under (not just the literal target path), so a sibling's leftover output can never leak into a fresh target either.cmd/scaffold/scaffold.go: threads the resolved absTargetDir through loadScaffoldTemplates -> mergeConfiguredTemplates -> convertScaffoldTemplateToConfiguration so every local-source template load knows its run's real target.tests/cli_test.go: cleanDirectory now also removes gitignored entries directly under workdir, using the git index (not gitignore pattern matching) as the source of truth for what's tracked, so it never deletes a directory that still holds tracked content.generated/ output from both fixtures (gitignored, never tracked).go test ./pkg/generator/... -- all packages pass, including two new regression tests (TestLoadConfigurationFromDir_WithExcludePath, TestLoadConfigurationFromDir_WithExcludePath_OutsideSourceIsNoop)go test ./cmd/scaffold/... -- passes with existing tests updated for the new function signaturesgo test ./tests/... -run 'TestCLICommands/scaffold' -- full scaffold CLI suite passesgenerated/ directory count stays flat (no compounding) across repeated runs./custom-gcl run --new-from-rev=origin/main -- 0 issues...Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
feat: add concurrent vendoring with edition-aware defaults Erik Osterman (Cloud Posse) (@osterman)
New Features
--max-concurrency, configuration, and environment-variable controls, defaulting to four workers.vendor clean now preserves lockfile entries for future reinstalls.Documentation
from-* reference guides to the atmos-migration agent skill, mirroring its existing IaC migration references, for helping users migrate authentication tooling into atmos auth:
from-aws-config.md (~/.aws/config/credentials), from-gcp-config.md (gcloud), from-azure-config.md (az)from-leapp.md, from-granted.md, from-aws2saml.md (saml2aws), from-okta-cli.md (okta-aws-cli)SKILL.md's frontmatter, a new "Migrating Authentication" routing table, and "Additional Resources".kind:/field mapping table, a CLI command-equivalence table, and an explanation of how atmos auth shell/exec/env interact with (or deliberately avoid touching) each cloud's default config file.from-aws-config.md also covers the aws/user browser-based OAuth2 PKCE login fallback (no static keys required), native ECR/EKS integrations, and aws/assume-root.from-okta-cli.md documents partial support only: aws/saml + driver: Okta is a full replacement when an org allows direct password+MFA API auth, but there's no equivalent yet for OIDC device-flow, m2m, or direct auth grants.agent-skills/ tree: only that directory ships to installed skill consumers (not the rest of the Atmos monorepo), so any skill citing a pkg/..., cmd/..., docs/..., or local website/... file path was pointing at something an installed skill can never read. Swept and fixed every instance, in both the new auth-migration guides and 7 pre-existing skills (atmos-kubernetes, atmos-helm, atmos-settings, atmos-steps, atmos-git, atmos-introspection, atmos-ai, and atmos-schemas — the bulk of it, 23 hits). Fixes either drop the path and keep the claim as prose, or swap in the real public atmos.tools URL (verified via frontmatter slug fields and existing site cross-links, not guessed from filenames).aws/gcloud/az/gh output rather than relying on recall -- several early drafts had inaccuracies (a fabricated granted sso populate command, wrong flag names, an incorrect premise about Okta's AWS integration having two separate app types) that were caught and corrected during review.credential_process, Okta OIDC device flow) are called out rather than papered over, so an agent following these guides doesn't promise users something Atmos can't do yet.docs/prd/atmos-agent-skills.md documents that only agent-skills/ is distributed to installed skill consumers, so any citation outside it was dead on arrival for every user except contributors working inside this monorepo.docs/prd/okta-auth-identity.md, docs/prd/aws-browser-auth.md, docs/prd/atmos-agent-skills.mdDocumentation
Bug Fixes
pull-requests: write and update Stopwatch's token description and permission documentation.atmos lint --changed, actionlint, git diff --check, and commit hooks passed; confirm comment creation and subsequent updates after the change reaches main.403 Resource not accessible by integration with issues: write and pull-requests: read.New Features
Documentation
Configuration
github.com/cloudposse/atmos.git//examples/... git sources in the acceptance suite from a local git-over-HTTP mirror of this checkout's examples/, built once in TestMain (tests/testhelpers/gitmirror): a bare repo published via git init --bare + push, served by git http-backend behind an httptest server that validates a static token (atmos-test-mirror-token, plus any ambient CI token) with HTTP Basic auth, records every request, and rejects pushes.insteadOf rules written to a temp gitconfig delivered via GIT_CONFIG_GLOBAL, one rule per token in the exact userinfo form atmos hands git after injecting the token (https://x-access-token:<token>@github.com/cloudposse/atmos.git → http://x-access-token:<token>@127.0.0.1:<port>/cloudposse/atmos.git) plus the anonymous https/ssh forms. Fixtures keep their real github.com URLs; file_exists assertions are unchanged.GITHUB_TOKEN for a case only when neither the case nor the environment provides one, so atmos never falls back to gh auth token (an unknown token would miss the rules and silently go live).tests/testhelpers/gitconfigenv, an appending GIT_CONFIG_COUNT/KEY_n/VALUE_n builder for the harness's per-test credential.helper/extraheader entries.github_token precondition (a ghcr/OCI probe) from the git-only vendor and demo cases; add an additive atmos_vendor_pull_git case; make demo-vendoring's first case clean its workdir so repeated runs don't see stale output.tests/jit_source_local_repo_test.go into gitmirror; tests/testhelpers.DefaultTools now reads pins from .tool-versions (all five had drifted).tests/snapshots/ is byte-identical to main.docs/fixes/2026-09-02-vendor-pull-dns-resolution-flake.md, 2026-09-07-jit-source-network-flakes.md), and GitHub's recent unauthenticated-traffic protections add another source of 401/404-shaped failures.GIT_CONFIG_GLOBAL (not GIT_CONFIG_* env) matters: pkg/downloader/custom_git_detector.go scans the env form for broker rewrites and would skip token injection — which is precisely the behavior change the golden snapshots would have caught, and now don't need to.file://) exercises git's real smart-HTTP transport and lets the mirror validate the credential; the 401-challenge path is proven end-to-end in gitmirror's own tests. The shared server allows anonymous fetches because cloudposse/atmos is public and the fixture's explicit git::https:// source bypasses atmos's detector (no injection), exactly as in production.terraform-null-label (pinned to an upstream commit no mirror can reproduce) and failed the ci_summary plan cases.HTTPS_PROXY pointed at a closed port (no GitHub reachable): all pass in each.First PR of a stack; the later PRs add GitHub Enterprise Server support (#3107), live-GitHub canaries with ATMOS_TEST_OFFLINE (#3109), and a local GitHub HTTP façade for toolchain/registry/raw fetches.
docs/fixes/2026-09-07-jit-source-network-flakes.md (the local-repo precedent this generalizes)--tags=git, including credential-free and token-authenticated scenarios.warn-daily caching as an edition-aware default, preserve explicit overrides and error/disable enforcement, and suppress repeated startup notices in child Atmos invocations.New Features
warn-daily, showing each experimental warning at most once every 24 hours.warn, error, and disable modes.Bug Fixes
Documentation
cmd packer test that runs a real atmos packer command its own private copy of the packer fixture (new packerFixtureWorkDir helper), instead of sharing the tracked fixture directory.internal/ci/acceptance from 4 to 2.TestExecuteProLock and TestExecuteProUnlock (and their subtests) in parallel.docs/fixes/2026-09-13-ci-flakes-packer-fixture-windows-cap-pro-race.md.Three flakes kept forcing reruns on 2026-09-12 and 2026-09-13, none caused by the code under test:
-shuffle=on -parallel=4, TestPackerInitCmd and TestPackerInspectCmd write and remove the same generated nonprod-aws-bastion.packer.vars.json in the shared fixture and one of them fails with "Failed to open file". TestPackerValidateCmd already used a private copy for exactly this reason; the other tests now do the same.internal/ci/acceptance crashed the Go runtime ("fatal error: found pointer to free object") four more times on Windows shard 3 on 2026-09-12 (runs 34699763477, 34703060789, and 34726124320 twice) despite the cap of 4 added in #3116. Halving the cap halves the concurrent allocation and syscall pressure that triggers the runtime race documented there.executeProLock and executeProUnlock write through the process-global UI writer; running both tests in parallel produced a DATA RACE on the race job (run 34726125072, shard 3/4). No per-test UI isolation seam exists in pkg/io/pkg/ui that is safe under t.Parallel(), so the two tests are serialized.Test-only; no user-visible change.
🤖 Generated with Claude Code
Bug Fixes
Documentation
Add conditional component dependencies through dependencies.components[].required.
required defaults to true.required: false makes an edge optional when its target is unavailable.flowchart TD
A[Read component dependency] --> B{Dependency parses and templates resolve?}
B -- no --> C[Error: identify declaring component and stack]
B -- yes --> D{Source component is in the selected closure?}
D -- no --> E[Do not validate this required target]
D -- yes --> F{required is false?}
F -- yes --> G{Target present and enabled?}
G -- yes --> H[Include optional edge]
G -- no --> I[Skip optional edge and continue]
F -- no --> J{Target present and enabled?}
J -- yes --> K[Include required edge]
J -- no --> L[Error: source component and stack, target component and stack, reason]missing, disabled, and abstract targets all take the unavailable-target branch. An abstract target is reported as missing so every graph builder has the same typed error contract.
flowchart TD
A[Terraform bulk command] --> B{Any stack, component, tag, label, query, or affected filter?}
B -- yes --> C[Select matching components]
C --> D[Expand requested dependency and dependent closure]
D --> E[Validate only closure sources]
B -- no --> F[Bare --all selects every component in every stack]
F --> G[Validate every source]--all --stack dev--all means every component inside the current filter scope, not every component in the repository.
flowchart TD
A[atmos terraform plan --all --stack dev] --> B[Select every dev component]
B --> C{Required target available?}
C -- yes --> D[Plan selected dev components]
C -- no --> E[Error with source, target, and reason]
F[Broken qa component] --> G[Excluded by --stack dev]
G --> H[Cannot block the dev command]--allflowchart TD
A[atmos terraform plan --all] --> B[Select every component in every stack]
B --> C{Any selected required target missing, disabled, or abstract?}
C -- no --> D[Plan all components]
C -- yes --> E[Error with source, target, and reason]The dependencies-components-inheritance fixture intentionally references network-baseline and security-group, but does not define either target. Those fixture entries now declare required: false.
This preserves the fixture purpose: verify that a child dependency list replaces inherited entries, without accidentally asserting that intentionally absent targets are required.
--all --stack dev ignores a broken required target in qa, while preserving strict validation for dev.conditional-component-dependenciesCloses #3053
New Features
required: false, including templated values and custom delimiters.Bug Fixes
Documentation
terraform init is skipped when nothing that affects it (root config, lock file, CLI config, resolved binary, relevant env vars) has changed since the last successful init for a component.components.terraform.init settings — mode, reconfigure, upgrade (each auto/always/never, default auto) — with matching --init-mode/--init-reconfigure/--init-upgrade flags and ATMOS_COMPONENTS_TERRAFORM_INIT_* env vars.-reconfigure and -upgrade are now added only when warranted (backend change, or a Terraform/OpenTofu diagnostic requires it) instead of unconditionally on every init.!terraform.output/atmos.Component.init_run_reconfigure boolean: false maps to init.reconfigure: never; the previous default true now maps to init.reconfigure: auto (not always) — the one deliberate default-behavior change, callable out explicitly in the docs and blog post.atmos terraform subcommand — plan, apply, shell, destroy, and even the read path behind !terraform.output/atmos.Component — runs a full terraform init -reconfigure unconditionally, so atmos terraform apply followed immediately by atmos terraform output on the same component pays the full init cost twice for identical inputs.-upgrade handling instead of requiring users to pass it by hand after every provider version bump.--skip-init already exists but is all-or-nothing and per-invocation, with no middle ground between "always re-init" and "the user manually judges when it's safe to skip." A fingerprint-based skip rule with automatic recovery closes that gap safely.docs/prd/terraform-auto-init.mdwebsite/blog/2026-09-11-smart-terraform-init.mdx/cli/commands/terraform/init#automatic-initialization, /cli/configuration/components/terraform#configuration-referenceNew Features
auto, always, and never controls for initialization, reconfiguration, and upgrades through configuration, flags, and environment variables.--skip-init remains available for one-time opt-out; workspace selection and creation still perform required initialization.Documentation
Harden the existing Atmos Helm plugin installer against transient download failures and incomplete installs. CI declares Helm Diff in stack configuration and reuses the existing Atmos toolchain cache.
atmos helm plugin install --component ci-plugins --stack dev commands. Hash the stack pins into the cache key; preserve shard counts and parallelism.workdir.BuildPath, a loopback source, and assertions for zero downloads, preserved fixture contents, and the expected guard.The source-cache regression seeded an obsolete path and unexpectedly cloned GitHub, failing on DNS in #3001. A repeated Helm Diff release download returned HTTP 500 before tests in #3000. These failures belong in Atmos's existing provisioning and plugin paths.
The installer remains generic: Helm controls repository installation and hooks. Validation checks plugin metadata and completed-install receipts; it does not run plugin-specific binary version commands. No custom setup action, shell wrapper, or separate artifact transport is needed.
Public commands and application APIs are unchanged. This PR targets main; existing CloudFormation branches and PRs remain unchanged.
-race -count=10 -shuffle=on; full source/workdir tests also passed with race detection.-race -shuffle=on, covering transient recovery, exhaustion, cleanup, cancellation, metadata/receipt validation, custom plugin names, concurrency, rollback, and preserved file modes.New Features
Bug Fixes
CI
flociHealthCheck (pkg/emulator/driver/floci.go) to use the floci image's own /usr/local/bin/healthcheck.sh readiness script when present, falling back to the previous curl-based probe only for older images that don't ship the script. A failing native probe is never masked by a curl fallback.TestFlociHealthCheck_Readiness (pkg/emulator/driver/floci_health_test.go) covering native-only success, native failure not falling back to curl, legacy curl-only success, and legacy curl-only failure.docs/fixes/2026-09-15-floci-health-check-curl-missing.md.curl. Since the health check probed exclusively with curl, it failed to execute at all against those images (the emulator was reachable; the check itself couldn't run), breaking atmos emulator up against those images and the floci E2E jobs in CI.main quickly and unblock CI everywhere, rather than waiting on a larger, unrelated PR that happens to bundle the same fix.docs/fixes/2026-08-31-floci-azure-health-check-race.md — prior, unrelated floci health-check incident (TCP-accepted-before-HTTP-ready race), already fixed.Bug Fixes
Documentation
New Features
Bug Fixes
atmos describe affected now honors the ATMOS_PROCESS_TEMPLATES and ATMOS_PROCESS_FUNCTIONS--process-templates / --process-functions CLI flags.DescribeAffectedCmdArgs.ProcessYamlFunctions.docs/fixes/.list, terraform,terraform generate command families — but describe affected silently ignored them, soPersistentFlags and read back only whencmd.Flags().Changed(name) is true. Setting an environment variable never flips a Cobra flag'sChanged bit, so env-sourced values were dropped before reaching the affected computation.ATMOS_PROCESS_FUNCTIONS=false skips the credential-backed!store, !terraform.state, !terraform.output) during affected detection —--error-mode pattern (cmd/describe_error_mode_flag.go): aflags.StandardParser with WithEnvVars registers the flags and binds the env varsdescribe Viper prefix to avoid colliding with the list family's barepkg/flags — no directviper.BindEnv / viper.BindPFlag (Forbidigo-compliant).docs/fixes/2026-09-13-describe-affected-process-env-vars.mdStandardParser pattern in cmd/describe_error_mode_flag.goATMOS_DESCRIBE_ERROR_MODE the same way).Bug Fixes
atmos describe affected now honors the ATMOS_PROCESS_TEMPLATES and ATMOS_PROCESS_FUNCTIONS environment variables.Tests
Documentation
describe affected.| Package | Type | Update | Change |
|---|---|---|---|
| mcr.microsoft.com/vscode/devcontainers/base | final | digest | b8c3669 → 1f85100 |
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.
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: add test steps, build controls, and default CLI help Erik Osterman (Cloud Posse) (@osterman)
Add type: test to workflows, custom commands, and lifecycle hooks with continuation by default, parallel/matrix checks, existing failure policies, buffered failures/all output, and isolated concurrent state
Add themed test trees with status dots, leaf progress, durations, immediate failure logs, and CI output; update schemas, documentation, tests, the roadmap, and a custom-command example with a recorded cast and success announcement
Implement live output viewports for shell/Atmos commands, including sizing and horizontal padding; use a four-line padded window labeled Compiling for builds and add --no-cache
Make bare atmos display help without requiring stacks and suppress duplicate error boxes for already-reported custom-command test failures
Bundle an atmos-tests agent skill with HTTP, script/interpreter, shell, require, parallel/dependency, matrix, and post-deployment hook patterns
New Features
test workflow steps with progress reporting, pass/fail summaries, parallel and matrix checks, retries, and configurable failure handling.--no-cache support for builds to force recompilation without clearing shared caches.atmos without a subcommand now displays usage and available commands.Bug Fixes
Documentation
Your coding agent can read these notes before it upgrades. Set up the MCP server →