feat: YAML key delimiter for dot notation in stack files @osterman (#2139)
## what- Implement configurable
settings.yaml.key_delimiterthat expands dotted YAML keys into nested maps in stack files (e.g.,metadata.component: vpc-base->metadata: { component: vpc-base }) - Unquoted keys containing the delimiter expand automatically; quoted keys stay literal (escape mechanism)
- Support custom delimiters, not just
.(e.g.,::) - Mark feature as experimental with runtime notifications via
ui.Experimental() - 21 comprehensive unit tests covering expansion logic, merging, conflicts, quoted preservation, edge cases
example
With settings.yaml.key_delimiter enabled:
settings:
yaml:
key_delimiter: "."Stack files can use concise unquoted dotted keys for nested component configuration. metadata stays at the component level; it is not nested under vars:
components:
terraform:
vpc:
metadata.component: vpc-base
metadata.description: Base VPC component
vars.tags.environment: prod
vars.tags.team: networkAtmos expands that as if the stack had been written in nested form:
components:
terraform:
vpc:
metadata:
component: vpc-base
description: Base VPC component
vars:
tags:
environment: prod
team: networkQuoted mapping keys remain literal, so existing dotted keys can be preserved:
components:
terraform:
app:
vars:
"output.json": true
'config.file': /etc/app.confwhy
Documentation claimed dot notation worked in stack files but it didn't. Go's yaml.v3 treats dotted keys literally without expansion. Users want concise notation instead of deeply nested YAML structures. This brings feature parity with atmos.yaml's native support via Viper's deepSearch() algorithm. Backwards compatible (disabled by default) and opt-in.
references
Extends experimental features system (like atmos devcontainer, atmos list affected). Respects settings.experimental mode configuration (silence/warn/error/disable).
Summary by CodeRabbit
- New Features
- Experimental YAML key expansion (
settings.yaml.key_delimiter): unquoted dotted keys can expand into nested maps in stack and settings files; custom delimiters are supported. - Enhanced experimental configuration checks so YAML/settings features follow the same warn/disable/error modes.
- Experimental YAML key expansion (
- Documentation
- Added a blog post and expanded YAML dot-notation reference with examples for quoting, custom delimiters, and edge cases.
- Tests
- Added coverage for delimiter expansion behavior and merge/conflict scenarios.
- Chores
- Updated the Playwright-Go license reference.
Refactor Make workflows into Atmos commands @osterman (#2677)
## what- Moves build, lint, test, screengrab, check, format, and cache tasks from Make into grouped
.atmos.dAtmos commands, withatmos buildas the default binary build command. - Converts Makefiles to migration guidance, updates CI/docs to call Atmos commands, adds setup-atmos bootstrapping, and adds Linux/macOS/Windows install script smoke coverage.
- Cleans example commands from root
atmos.yaml, keeps.tool-versionsinstalls explicit toatmos toolchain install, addsatmos shell, and adds a blog post embedding live.atmos.dexamples. - Fixes custom-command dogfooding gaps for
defaultsubcommands,.atmos.dcommand-list merging across files with YAML tags,.cwdtemplate data, and local alias precedence over config custom commands.
why
- Dogfoods Atmos custom commands for Atmos development while removing Make from active local and CI workflows.
- Keeps command definitions grouped and reusable while preserving existing build, lint, test, screengrab, and devcontainer alias behavior.
references
- Validation:
go test ./cmd ./pkg/config ./pkg/schema,git commithooks,./build/atmos build,./build/atmos build --target linux,./build/atmos build version --target linux,./build/atmos screengrabs build --all,./build/atmos screengrabs build about, Makefile migration checks,atmos build deps,pnpm build. - Note:
atmos test shortstill reports unrelated workspace failures ininternal/tui/utilsandpkg/utils.
Summary by CodeRabbit
- New Features
- Added grouped
.atmos.dcommand entrypoints for build, test (short/full/coverage/race/mocks), lint, check, format, cache (list/clear), and screengrabs (including Docker). - Added a cross-platform smoke test for
website/static/install.sh.
- Added grouped
- Bug Fixes
- Custom commands can now fall back to a configured default subcommand when run without arguments.
- Improved environment handling and made coverage/profile merging more reliable.
- Documentation
- Updated development, CLI, demo, screengrabs, and test docs to use
atmos; Makefile now redirects toatmoscommands.
- Updated development, CLI, demo, screengrabs, and test docs to use
- Tests
- Expanded CLI/custom-command and config-merge regression coverage.
Add CEL-backed when conditions @osterman (#2689)
## what- Add
pkg/conditionto ownwhenparsing, predicate handling, CEL compilation/evaluation, runtime context, and tests. - Keep
pkg/schemacompatible through aliases while wiring CEL-awarewhenevaluation into workflow steps, custom command steps, and hooks. - Update YAML tag normalization, JSON schemas, validation tests, and docs so bare CEL strings and explicit
!celconditions are supported.
why
- This lets users write expressive, sandboxed boolean
whenexpressions without replacing the existing predicate keywords. - Keeping schema aliases preserves current call sites while allowing condition behavior to evolve in a focused package.
- Hook implicit-success behavior and workflow/custom-command failure predicate restrictions remain intact.
example
workflows:
deploy:
steps:
- name: plan-prod
type: shell
command: terraform plan
when: !cel 'ci && stack == "prod" && status == "success"'references
- Validation:
go test ./pkg/condition ./pkg/schema ./pkg/workflow ./pkg/hooks ./pkg/datafetcher;go test ./cmd -run TestCustomCommandIntegration_SkipsStepWhenConditionIsFalse;go test ./pkg/workflow/... ./pkg/hooks/...;./custom-gcl run --new-from-rev=origin/main.
Summary by CodeRabbit
- New Features
- Added CEL expressions support for
whenconditions across workflows, hooks, and custom command steps, including explicit!celtagging and access toci,status,stack,component,workflow,step,hook,event, andenv.
- Added CEL expressions support for
- Bug Fixes
whenevaluation errors now fail fast instead of being treated as non-matching.- Step/hook execution context is now richer and more precise when deciding matches/skips.
- Documentation
- Updated CLI/docs and JSON schemas to reflect CEL-capable
whenvalidation and evaluation.
- Updated CLI/docs and JSON schemas to reflect CEL-capable
- Tests
- Expanded unit/integration coverage for CEL and env-gated scenarios.
- Chores
- Updated NOTICE and dependency/license allowlists.
feat(ci): fork-PR safety gate for `atmos git clone` @osterman (#2661)
## whatatmos git clone(Atmos's nativeactions/checkoutreplacement) now refuses by default to clone untrusted fork content under GitHub's elevatedpull_request_targetandworkflow_runevents.- The gate triggers only on the dangerous combination — an elevated event plus a fork-targeting clone (a PR head/merge ref override like
refs/pull/<N>/merge, or an ad hoc clone URI whoseowner/repodiffers from the baseGITHUB_REPOSITORY). Safe no-arg base checkouts and low-privilegepull_request/push/merge_groupevents are unaffected. - Adds a grep-able opt-in:
--allow-unsafe-forkflag,ATMOS_ALLOW_UNSAFE_FORK_EXECUTIONenv var, andci.allow_unsafe_fork_executionconfig key. - Adds the provider-agnostic gate core (
pkg/ci.EvaluateForkCheckout), aContext.ElevatedEventtrust signal set by the GitHub provider, theErrUnsafeForkCheckoutsentinel, and unit tests (incl. negative paths). - Documents it: new PRD
docs/prd/native-ci/framework/fork-pr-trust-gate.md,atmos git cloneCLI docs, CI configuration reference, and a changelog blog post + roadmap milestone.
why
- Because
atmos git clonefills the same role asactions/checkout, it inherited the same "pwn request" risk: cloning a fork's PR code in a job that holds the base repository's secrets/GITHUB_TOKEN/cloud credentials lets a malicious contributor exfiltrate them. - This mirrors the
actions/checkoutv7 hardening (fail-closed by default, explicit grep-able opt-out), bringing Atmos's checkout replacement to parity.
references
- actions/checkout v7 changelog: https://github.blog/changelog/2026-06-18-safer-pull_request_target-defaults-for-github-actions-checkout/
- PRD:
docs/prd/native-ci/framework/fork-pr-trust-gate.md - Docs:
/cli/commands/git/clone#fork-pr-safety-gate
Summary by CodeRabbit
- New Features
- Added a “Fork-PR safety gate” to
atmos git clone: it refuses to clone untrusted fork content during elevated GitHub CI events (pull_request_target,workflow_run) when checkout targets look like PR ref overrides or forked repositories. - Added an opt-in bypass via
--allow-unsafe-fork,ATMOS_ALLOW_UNSAFE_FORK_EXECUTION, orci.allow_unsafe_fork_execution.
- Added a “Fork-PR safety gate” to
- Bug Fixes
- Fail-closed behavior when CI context can’t be evaluated, with guidance for safer workflows.
- Documentation
- Updated CLI docs, CI configuration, PRD/overview, roadmap, and release blog with behavior details and a full opt-in matrix.
- Tests
- Added unit tests covering trust evaluation, ref/URI detection, and bypass behavior.
- Chores
- Improved native CI Go module fetching resilience.
fix(algolia): surface page Intro as search-result subtext @osterman (#2429)
## what- Reorder Algolia
customRankingto[desc(weight.pageRank), asc(weight.position), desc(weight.level)]so the first content record on a page wins the per-URLdistinctdedup. - Broaden the content selector to lead with
article .introso every page's<Intro>block is indexed even when MDX doesn't wrap its children in a<p>. - Update crawler unit-test assertions for the new selector and ranking; add a live-relevance regression test (gated on
ALGOLIA_LIVE_RELEVANCE_TESTS) asserting the topatmos authhit has a non-empty_snippetResult.content.
why
- Queries matching page titles (e.g.
atmos auth) were resolving tolvl1records, which the DocSearch React UI renders title-only with no snippet — so search results looked like a bare list with no description text. - With
desc(weight.level)ahead ofasc(weight.position), heading records always outranked content records insidedistinct, locking in the no-subtext outcome. The reorder lets the Intro content record (position 0) win the dedup so its snippet renders as subtext. - MDX v3 emits
<Intro>foo</Intro>with no blank lines as a bare text node inside<div class="intro">, so the priorarticle p, …selector missed the Intro text entirely. Addingarticle .introindexes it regardless of MDX paragraph wrapping.
references
- Requires a recrawl for the selector change to take effect (
npm run algolia:deploy); the ranking change applies as soon asinitialIndexSettingsis pushed.
Summary by CodeRabbit
- Search Improvements
- Search results now capture more complete content from article introductions, improving snippet quality and relevance
- Optimized search result ranking for better relevance
🚀 Enhancements
[codex] Fix CI and native component compatibility regressions @osterman (#2685)
## what- Fix Terraform native CI planfile upload for workdir-provisioned components by resolving the effective
.workdirartifact path. - Fix native Helm plugin binary resolution to use the
helmdependency scope, and expose--cion native Kubernetes operation commands. - Stabilize tests by disabling telemetry in schema dogfood tests, clearing color-disabling env vars in TUI output tests, and ignoring environment-dependent GitHub token debug noise in snapshots.
- Document each fix separately under
docs/fixes. - Fail loudly when
--verify-plan(orATMOS_TERRAFORM_VERIFY_PLAN=true) is set but planfile storage is not configured undercomponents.terraform.planfiles— previously the flag silently no-op'd and deploy applied an unverified fresh plan. A config-setverify:mode without storage now logs a warning. Docs updated everywhere the flag/prerequisite is mentioned, and the missingplanfilessection was added to the terraform configuration reference. - Raise patch test coverage: REST artifact download error paths, workdir artifact-path failure path, and emulator shared-network attachment.
- Fix the Acceptance Tests Playwright failure and broken
aws/samlBrowser-driver installs: playwright-go's driver download hits the retired azureedge.net CDN (build purged from the replacement CDN), so Atmos now pre-seeds the driver from the official npm registry and nodejs.org with checksum verification (docs/fixes/playwright-driver-retired-cdn.md).
why
- These changes address compatibility gaps found during the recent merged-code audit, including issue #2684 where Terraform planfiles could be skipped for auto-provisioned workdir components.
- The test updates remove unrelated environment and network side effects so local and CI verification are deterministic.
references
- Fixes #2684
- Verified with
go test ./cmd/... ./internal/... ./pkg/...andgo test ./tests -count=1.
Summary by CodeRabbit
- New Features
- Added a
--ciflag to all native Kubernetes operation commands to enable consistent CI-mode behavior.
- Added a
- Bug Fixes
- Fixed native Helm plugin
helmbinary resolution to use the correct native dependency scope. terraform deploy --verify-plannow errors when Terraform planfile storage isn’t configured (instead of silently skipping).- CI planfile uploads now correctly handle workdir-provisioned components.
- Fixed native Helm plugin
- Documentation
- Updated docs to clarify
--verify-planrequirescomponents.terraform.planfiles. - Added documentation for Playwright driver pre-seeding and Linux musl Node.js handling.
- Updated docs to clarify
Support --profile flag for custom commands with autocomplete @osterman (#2190)
## what- Added early parsing of
--profileflag (before Cobra parses) to ensure profiles are applied during initial config load, so custom commands receive a properly profiledatmosConfig - Extended
StringSliceFlagto support custom completion functions - Implemented profile autocomplete that lists available profiles from the profile manager
- Updated
FlagRegistry.SetCompletionFunc()to support bothStringFlagandStringSliceFlagtypes
why
Previously, custom commands could accept --profile but the flag was never applied because atmosConfig was loaded at boot time (before Cobra parsed flags). Custom commands captured this pre-profile config in their closure. Built-in commands worked because they called GetConfigAndStacksInfo() which re-extracted --profile during command execution.
This fix follows the same pattern as --chdir: parse the flag early from os.Args and pass it to InitCliConfig, ensuring all commands (built-in and custom) get properly profiled configuration.
The autocomplete feature provides users with shell suggestions of available profiles when typing atmos commands.
references
Resolves the gap where custom commands couldn't use the --profile flag effectively.
Summary by CodeRabbit
-
New Features
- CLI supports profiles via a global --profile and ATMOS_PROFILE; profiles are loaded at startup and available for shell completion.
- Early config selection via command-line or environment variables (base path, config, config-path).
- Improved shell completion for profile and multi-value flags.
-
Tests
- Added tests for flag completion and for profile/config selection parsing.
fix: replace log.Info/Error with ui.* in vendor non-TTY output @osterman (#2268)
## what- Replaced all
log.Infoandlog.Errorcalls in the vendor non-TTY code path with properui.*methods (ui.Success,ui.Error,ui.Info) - Per-package status lines now use
ui.Successf/ui.Errorfwhich provide consistent icons and styling - Summary and dry-run messages use
ui.Successf/ui.Infoinstead of structured log key-value pairs - Extracted repeated format string into a
pkgStatusFmtconstant
why
- The vendoring non-TTY path was abusing
log.Infofor user-facing status messages, which are UI output not diagnostic logs log.Inforenders as structured key-value pairs (e.g.,INFO package=vpc version=(v1.0)) instead of the clean styled output the TUI provides- Using
ui.*methods ensures consistent formatting with proper icons (checkmarks/X marks) across both TTY and non-TTY environments
references
pkg/ui/formatter.go— UI output methods useddocs/logging.md— logging level guidelines
Summary by CodeRabbit
- Improvements
- Refined vendoring CLI output for non-interactive runs with consistent symbol-based status lines and clearer success/error reporting.
- Improved per-component status messages to clearly distinguish failures vs. successes.
- Updated completion/dry-run summaries to use consistent info/check symbols and explicit success/failed counts.
- Tests
- Updated stderr golden snapshots and matchers for the new formatting.
- Added non-TTY test coverage for per-component and final vendoring status output.
- Chores
- Updated the Playwright-Go license reference in the NOTICE file.