github cloudposse/atmos v1.229.1-rc.2

pre-release4 hours ago
fix(toolchain): keep the 'v' prefix in cosign certificate-github-workflow-ref @aknysh (#3210) ## what
  • Align the bare (non-URL) cosign --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, ...).

why

  • Toolchain installs began failing cosign verification on 2026-09-23:
    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)
    
  • Trigger: the unpinned upstream 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).
  • The aqua template is not wrong. {{.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.

scope

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 @osterman's guidance that the registry is the authority for tag format). Once #3211 lands, this correction becomes a no-op safety net.

changes

  • 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).
  • Tests: TestReplaceVersionSegmentInPath + TestRenderArgsCorrectsCosignWorkflowRef (asserts the workflow-ref gets the v, and a --key path does not).

references

  • Fixes #3209
  • Canonical follow-up: #3211
  • Unblocks the merge queue (#3200) and example-lint jobs on other PRs (e.g. #3204)

validation

  • 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%)

Summary by CodeRabbit

  • Bug Fixes
    • Fixed signature verification for releases whose version tags include a v prefix. Cosign workflow references now match the actual release tag, while version-like segments in unrelated key paths remain unchanged.
  • Documentation
    • Added a note describing the signature-verification issue and its resolution, including reproduction details, validation coverage, and related follow-up considerations.

🚀 Enhancements

fix(scaffold): default hook working directory to the scaffold target path @jorrite (#3206) ## what
  • Scaffold hooks (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.
  • The scaffold's target path is also exposed to hook templates as {{ .TargetPath }}, alongside the existing {{ .Answers }}.
  • Extracted the shared empty/bare/dot/absolute working-directory defaulting convention out of 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.
  • Documented the new default (and the working_directory: "." override) next to every existing scaffold-hooks example in the website docs, the atmos-hooks skill, and the scaffold PRD.
  • Added a docs/fixes/ record.

why

  • 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.
  • Component/stack lifecycle hooks already default to the component's own working directory (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.
  • Not a behavior change for the common case. When 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.
  • Hook authors can still opt back into the old cwd-relative behavior with an explicit working_directory: "." in a hook's with: block — dot-prefixed and absolute values are left untouched, same convention lifecycle hooks already use.

Testing

  • Wrote a regression test first (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.

references

Summary by CodeRabbit

  • Bug Fixes
    • Non-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.
  • New Features
    • Hook templates can reference the scaffold target directory with {{ .TargetPath }}.
  • Documentation
    • Updated scaffold and initialization guides to explain working-directory defaults and the type: atmos exception.
fix(provision): global workdir default lives in stack config, not settings @aknysh (#3200) ## what
  • A workdir global default belongs in the stack configuration under the toolchain section (terraform.provision, helmfile.provision, ...) - consistent with global vars, metadata, and secrets - not in atmos.yaml settings.provision.
  • That stack-level default already works today (lowest-precedence merge layer), and is overridden by component-level provision.workdir (including an explicit enabled: false).
  • This PR removes the non-functional settings.provision.workdir config surface and adds regression tests + corrected docs for the stack-level default.

why

  • Issue #3197 reported that settings.provision.workdir.enabled (documented in atmos.yaml) was ignored - only component-level worked.
  • Per maintainer review (@osterman): provisioning is component configuration, so its global default belongs in stack config, not settings. Wiring up settings.provision was the wrong direction; the correct mechanism (terraform.provision) already exists.

changes

  • schema: dropped 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.
  • merge: reverted the provision merge in stack_processor_merge.go to the inline four-layer merge (GlobalProvisionSection → base → component → overrides); removed the stack_processor_provision.go settings injection.
  • docs: 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: 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.

references

validation

  • go build ./...
  • go test ./internal/exec/ -run TestGlobalWorkdirProvisionDefault -v
  • go test ./pkg/config/schema/ ./pkg/schema/ ./pkg/provisioner/...
  • atmos lint --changed (0 issues)
  • cd website && npm run build (no broken links)

Summary by CodeRabbit

  • Configuration

    • Configure workdir provisioning defaults at the toolchain level in stack manifests.
    • Component-level settings, including enabled: false, override inherited stack defaults.
    • Global settings.provision.workdir configuration is no longer supported.
  • Documentation

    • Updated provisioning guidance for configuration scope and backend defaults.
    • Documented workdir ttl settings and expired workdir cleanup eligibility.
  • Validation

    • Added coverage for stack-level defaults and component-level overrides.

Don't miss a new atmos release

NewReleases is sending notifications on new releases.