feat(list): add --skip flag; fix --stack/--filter/--query on list instances @osterman (#2413)
## what--skipacross everyatmos listsubcommand.instances,components,metadata,sources, andstacksnow accept--skip <yaml-function>(repeatable, e.g.--skip terraform.state --skip terraform.output). Mirrors the surface already exposed bydescribe affected | component | stacks. Bound toATMOS_SKIP; the existingATMOS_AFFECTED_SKIPcontinues to work onlist affectedas a back-compat alias. Threads throughExecuteDescribeStacks— which already acceptedskipbut was being passednilat every list callsite.--stack,--filter, and--queryonatmos list instancesnow work. Three documented flags were previously silent:--stackwas ignored (every instance returned),--filterwas a TODO stub, and--querywas read into options and dropped.--stacknow usespath.Matchglob semantics,--filterevaluates a YQ predicate per row, and--queryprojects each row via YQ (scalars land in avaluecolumn, maps flatten to row keys). Closes a latent ENV-precedence gap soATMOS_LIST_FORMATandATMOS_UPLOADare honored via viper.- Tests. Parser, options, and propagation tests for
--skip(with a regression test for the literallist instances --upload --skip terraform.statefailure). Unit + integration tests for the stack/filter/query work. Newpkg/list/filter/yq.go(YQPredicateFilter,YQProjector,isTruthy) with full coverage. - Docs + release artifacts.
--skipdocumented on all five list pages; two release-blog entries; one roadmap milestone under the Discoverability initiative.
why
- The concrete failure on
--skip:atmos list instances --upload --skip terraform.stateerrored withunknown flag.--process-functions=falseis not a substitute because it also disables!template, which Atmos Pro uploads need sosettings.pro.enabledevaluates to a real boolean instead of a literal string. - The concrete failure on
--stack/--filter/--query: the docs promised filtering onlist instancesand the implementation didn't honor it. Users hit silent wrong-result behavior, not an error. - Both features ship through the same set of
listfiles; bundling avoids merge churn and keeps the test+docs surface coherent.
references
- Pattern source for
--skiprollout: #2363 (--process-templates/--process-functionsrollout acrosslist) - Origin of
--skip(describe family): #1006
Summary by CodeRabbit
-
New Features
- Repeatable --skip flag (ATMOS_SKIP; legacy ATMOS_AFFECTED_SKIP preserved) added across list commands; list instances adds --stack glob filtering.
-
Enhancements
- YQ-based --filter (truthy predicates) and --query (projections); format-aware validation for tree/matrix; improved config precedence for list flags.
-
Bug Fixes
- --stack / --filter / --query now honor documented behavior.
-
Tests
- Expanded coverage for skip flag, YQ filters/projectors, and stack-glob filtering.
-
Documentation
- Updated CLI docs, blog posts, and roadmap.
🚀 Enhancements
fix(list): make `list components` output deterministic across runs @osterman (#2422)
## whatatmos list components(and especially--enabled=false/--locked=true) now returns deterministic, consistent results across invocations on the same workspace.- Aggregate per-stack
enabled/lockedstate into the deduplicated component view: any-disabled-wins forenabled, any-locked-wins forlocked.status/status_textare recomputed from the aggregate. - Sort stack names, component names, and the output slice so iteration order no longer depends on Go's randomized map iteration.
- Documentation for
--enabled/--lockednow describes the cross-stack aggregation semantics and points atatmos list instancesfor per-stack-instance state. - Adds regression tests in
pkg/list/extract/: a 200-iteration determinism test for--enabled=false, an aggregation-policy test forenabled/locked, and an output-order stability test.
why
- Reported in #2359: running
atmos list components --enabled=falserepeatedly produced different output every time — sometimes empty, sometimes 1 component, sometimes 2 or 3 different components — with no changes to the workspace. - Root cause:
extractUniqueComponentTypeinpkg/list/extract/components.goextracted metadata only from the first stack iterated for each component, andUniqueComponentsiteratedstacksMap(a Go map) in randomized order. When the same component hadenabled: falsein some stacks andenabled: truein others, the recorded value depended on iteration order — soBoolFilter.Applywould include or exclude the component non-deterministically. - Sorting alone would have made the output stable but not necessarily correct for users with mixed-state components; the aggregation policy ensures a component disabled anywhere shows up under
--enabled=false, which matches the user's expected behavior in the issue.
references
- closes #2359
Summary by CodeRabbit
-
Bug Fixes
- Resolved non-deterministic output in
list componentscommand; results now consistent across invocations. - Adjusted
--enabledand--lockedflags to aggregate state across stack instances: a component is shown as disabled/locked if any instance has that state.
- Resolved non-deterministic output in
-
Documentation
- Clarified
list componentsflag behavior for cross-stack aggregation reporting.
- Clarified
-
Tests
- Added regression test coverage for deterministic component aggregation.
fix(auth): normalize --identity=false to disable authentication @osterman (#2412)
## what- Normalize boolean-false values (
false,0,no,off, case-insensitive) passed via--identity=<value>and--identity <value>to the disabled sentinel (cfg.IdentityFlagDisabledValue), so the auth pre-hook andCreateAndAuthenticateManager*short-circuit instead of trying to authenticate with the literal name"false". - Patch is in
internal/exec/cli_utils.go::parseIdentityFlag— the single arg-walker that feedsinfo.Identity/configAndStacksInfo.Identityfor everyProcessCommandLineArgsconsumer (terraform, helmfile, packer, list, describe, workflow, vendor, pro, validate, atlantis, docs, generate). - Add parser-level unit cases in
TestParseIdentityFlagfor=false/=False/=FALSE/=0/=no/=offplus space-separated form, and end-to-end cases inTestProcessArgsAndFlags_IdentityFlag{,Helmfile,Packer}assertinginfo.Identity == cfg.IdentityFlagDisabledValue.
why
- Regression:
ATMOS_IDENTITY=falsewas fixed in #1935 by normalizing the env-var fallback atcli_utils.go:199, but the env fallback only runs whenIdentity == "". When--identity=falseis passed on the CLI,parseIdentityFlagpopulated the literal"false", the env-fallback branch was skipped, and the literal flowed through topkg/auth/hooks.go::isAuthenticationDisabled(which only matches__DISABLED__). - #2225 extracted
parseIdentityFlaginto a new helper without porting the normalization from the env path, silently breaking the documented--identity=falsecontract. Reported by users foratmos terraform *andatmos list instances. - Centralizing normalization at the parse site means every command sharing
ProcessCommandLineArgsis fixed in one place, and matches the behavior already implemented for the StandardParser path (pkg/flags/global_registry.go) and thecmd/identity_helpers.go/cmd/list/utils.go/cmd/list/affected.goper-command identity reads.
references
- Builds on #1900 / #1935 (env-var normalization) and corrects the regression introduced by the refactor in #2225.
Summary by CodeRabbit
-
Bug Fixes
- The --identity flag now recognizes common boolean-false values (false, 0, no, off, case-insensitive) to disable authentication.
-
New Features
- Passing --identity=false (or equivalent) disables per-component auth resolution and is honored across describe, list, and state-resolution flows.
- Describe and list commands now surface and propagate an "auth disabled" option so outputs respect disabled auth.
-
Tests
- Expanded tests for identity parsing and auth-disabled behavior across commands, env vars, and execution paths.