Skip to content

--config with multiple files skips base_path resolution entirely, breaking atmos terraform test #2863

Description

Describe the Bug

Loading config via --config main.yaml,supplement.yaml (multiple files) causes
atmos terraform test <component> -s <stack> to fail with Error: failed to find import, even
though the exact same settings, saved as a single file and loaded via plain auto-discovery (no
--config flag at all), work correctly end-to-end for the identical terraform test invocation.
Setting ATMOS_BASE_PATH explicitly alongside --config has no effect on the failure either -
see the root cause below for why.

Root cause, traced in source, not just symptoms: In pkg/config/load.go, LoadConfig()
branches early for the CLI-arg config path:

if len(configAndStacksInfo.AtmosConfigFilesFromArg) > 0 || len(configAndStacksInfo.AtmosConfigDirsFromArg) > 0 {
    err := loadConfigFromCLIArgs(v, configAndStacksInfo, &atmosConfig)
    if err != nil {
        return atmosConfig, err
    }
    return atmosConfig, nil   // <-- returns here
}

// Load configuration from different sources.
if err := loadConfigSources(v, configAndStacksInfo); err != nil { ... }
...
setEnv(v)                                    // binds ATMOS_BASE_PATH (and every other ATMOS_* env var)
...
err := v.Unmarshal(&atmosConfig, ...)
...
if err := applyGitRootBasePath(&atmosConfig); err != nil { ... }  // resolves empty base_path to git root

The --config/--config-path branch's early return means none of the following ever run for
that invocation: setEnv() (env var bindings, including ATMOS_BASE_PATH),
applyGitRootBasePath() (git-root resolution for an empty/default base_path), or the later
Unmarshal/fixAuthIdentities/preserveCaseSensitiveMaps steps that normal auto-discovery relies
on.

This matches the documented breaking change in Atmos v1.202.0+ ("empty base_path now triggers
git root discovery instead of defaulting to the current directory" —
https://atmos.tools/changelog/base-path-behavior-change) — my atmos.yaml has base_path: ''
(empty). Via normal auto-discovery, that empty value correctly resolves to the git repo root
through applyGitRootBasePath(). Via --config, that function is never called, so the empty
base_path is left unresolved, which is what terraform test's component-path resolution then
fails on. This is also why setting ATMOS_BASE_PATH explicitly doesn't help: setEnv(), the
function that would bind that env var to anything, is skipped by the same early return.

Relationship to existing issues: searched first to avoid a duplicate. This is related to, but
distinct from, #2183 (fixed in v1.210.1 via #2215/#2236): that issue was about
ATMOS_BASE_PATH/--base-path values being simple relative-path strings resolving against the
wrong anchor. That fix improved resolution within the pipeline that --config skips entirely —
it doesn't touch this.

Expected Behavior

--config with one or more files should resolve base_path (including the empty-string →
git-root-discovery default) the same way normal auto-discovery does, so terraform test (and
presumably other component-path-dependent commands) behaves identically regardless of whether
config was found via auto-discovery or explicitly via --config.

Steps to Reproduce

Minimal, self-contained repro. Creates a throwaway project in a temp dir (its own git init,
minimal atmos.yaml + one supplement file, one trivial component with one test), then runs the
same terraform test invocation three ways. Copy-paste the whole block into a terminal:

REPRO_DIR="$(mktemp -d)"
echo "Reproducing in: $REPRO_DIR"

# Install atmos if not already on PATH (kept outside REPRO_DIR so atmos's own
# config-file discovery doesn't try to parse the binary itself as YAML)
if ! command -v atmos >/dev/null 2>&1; then
  ATMOS_VERSION=1.224.1
  ATMOS_BIN_DIR="$(mktemp -d)"
  curl -fsSL "https://github.com/cloudposse/atmos/releases/download/v${ATMOS_VERSION}/atmos_${ATMOS_VERSION}_linux_amd64" -o "$ATMOS_BIN_DIR/atmos"
  chmod +x "$ATMOS_BIN_DIR/atmos"
  ATMOS="$ATMOS_BIN_DIR/atmos"
else
  ATMOS=atmos
fi
$ATMOS version

cd "$REPRO_DIR"
git init -q
mkdir -p stacks/deploy components/terraform/my-component

cat > atmos.yaml <<'EOF'
base_path: ''
components:
  terraform:
    base_path: components/terraform
stacks:
  base_path: stacks
  included_paths:
    - deploy/**/*
  name_pattern: '{stage}'
EOF

cat > supplement.yaml <<'EOF'
stacks:
  included_paths:
    - extra/**/*
EOF

cat > stacks/deploy/dev.yaml <<'EOF'
vars:
  stage: dev
components:
  terraform:
    my-component:
      vars: {}
EOF

cat > components/terraform/my-component/main.tf <<'EOF'
variable "stage" {
  type = string
}

output "stage" {
  value = var.stage
}
EOF

cat > components/terraform/my-component/tests.tftest.hcl <<'EOF'
run "check_stage" {
  command = plan
  variables {
    stage = "dev"
  }
  assert {
    condition     = output.stage == "dev"
    error_message = "stage mismatch"
  }
}
EOF

echo ""
echo "CASE 1: plain auto-discovery, single atmos.yaml (works)"
$ATMOS terraform test my-component -s dev

echo ""
echo "CASE 2: identical settings, split into atmos.yaml + supplement.yaml, combined via --config (fails)"
$ATMOS --config atmos.yaml,supplement.yaml terraform test my-component -s dev || true

echo ""
echo "CASE 3: same as Case 2, but with ATMOS_BASE_PATH set explicitly (fails identically - setEnv() never runs)"
ATMOS_BASE_PATH="$REPRO_DIR" $ATMOS --config atmos.yaml,supplement.yaml terraform test my-component -s dev

Case 1 prints Success! 1 passed, 0 failed.. Cases 2 and 3 both fail identically with
Error: failed to find import.

Screenshots

No screenshots — CLI output only, included in Steps to Reproduce above. The exact failure:

Error: failed to find import

💡 Verify that base_path and stacks.base_path in atmos.yaml are correct
💡 If using ATMOS_BASE_PATH, ensure the path is correct relative to the working directory
💡 Verify stacks.base_path in atmos.yaml points to the correct directory
💡 Check that the stacks directory exists and contains stack configuration files

Environment

  • OS: Linux
  • Atmos version: 1.224.1
  • Standalone binary (linux/amd64), not run via Docker
  • Config: minimal, ordinary atmos.yaml (base_path: '', stacks.base_path: stacks,
    components.terraform.base_path: components/terraform) — no custom commands, no unusual
    settings involved in triggering this

Additional Context

Suggested fix direction: either route the --config/--config-path branch through the same
setEnv() / applyGitRootBasePath() / Unmarshal steps that loadConfigSources() uses (removing
the early return and threading the CLI-supplied files in as an additional highest-priority source
rather than a fully separate pipeline), or explicitly document that --config bypasses env-var
bindings and git-root base-path resolution, with a hint added to the failed to find import error
message specifically when triggered from this code path.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions