stacks: Make path.module and path.root relative, to match documentation (#37982)
Some checks failed
build / Determine intended Terraform version (push) Has been cancelled
build / Determine Go toolchain version (push) Has been cancelled
Quick Checks / Unit Tests (push) Has been cancelled
Quick Checks / Race Tests (push) Has been cancelled
Quick Checks / End-to-end Tests (push) Has been cancelled
Quick Checks / Code Consistency Checks (push) Has been cancelled
build / Generate release metadata (push) Has been cancelled
build / Build for freebsd_386 (push) Has been cancelled
build / Build for linux_386 (push) Has been cancelled
build / Build for openbsd_386 (push) Has been cancelled
build / Build for windows_386 (push) Has been cancelled
build / Build for darwin_amd64 (push) Has been cancelled
build / Build for freebsd_amd64 (push) Has been cancelled
build / Build for linux_amd64 (push) Has been cancelled
build / Build for openbsd_amd64 (push) Has been cancelled
build / Build for solaris_amd64 (push) Has been cancelled
build / Build for windows_amd64 (push) Has been cancelled
build / Build for freebsd_arm (push) Has been cancelled
build / Build for linux_arm (push) Has been cancelled
build / Build for darwin_arm64 (push) Has been cancelled
build / Build for linux_arm64 (push) Has been cancelled
build / Build for windows_arm64 (push) Has been cancelled
build / Build Docker image for linux_386 (push) Has been cancelled
build / Build Docker image for linux_amd64 (push) Has been cancelled
build / Build Docker image for linux_arm (push) Has been cancelled
build / Build Docker image for linux_arm64 (push) Has been cancelled
build / Build e2etest for linux_386 (push) Has been cancelled
build / Build e2etest for windows_386 (push) Has been cancelled
build / Build e2etest for darwin_amd64 (push) Has been cancelled
build / Build e2etest for linux_amd64 (push) Has been cancelled
build / Build e2etest for windows_amd64 (push) Has been cancelled
build / Build e2etest for linux_arm (push) Has been cancelled
build / Build e2etest for darwin_arm64 (push) Has been cancelled
build / Build e2etest for linux_arm64 (push) Has been cancelled
build / Run e2e test for linux_386 (push) Has been cancelled
build / Run e2e test for windows_386 (push) Has been cancelled
build / Run e2e test for darwin_amd64 (push) Has been cancelled
build / Run e2e test for linux_amd64 (push) Has been cancelled
build / Run e2e test for windows_amd64 (push) Has been cancelled
build / Run e2e test for linux_arm (push) Has been cancelled
build / Run e2e test for linux_arm64 (push) Has been cancelled
build / Run terraform-exec test for linux amd64 (push) Has been cancelled

* stacks: Make path.module and path.root relative, to match documentation

Previously, we were just handing off the absolute path produced by the
sourcebundle struct. But that's no good, because the value doesn't stay
consistent between plan and apply when running under tfc-agent. (It uses working
directories named after the unique job ID.) It also doesn't match the
documentation, which describes these as relative paths. This was preventing
people from uploading module-provided files to create aws lambda functions, for
example.

This commit addresses that by converting the source-bundle provided module path
to a relative path (relative to Terraform's working directory). In tfc-agent for
stacks runs, that ends up being the directory directly above the sourcebundle
directory, and all the paths below that are consistent between plan and apply.

* I think this is how the changelog thing works?
This commit is contained in:
Nick Fagerlund 2025-12-12 11:05:32 -08:00 committed by GitHub
parent f591872699
commit b2aad914f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 37 additions and 17 deletions

View file

@ -0,0 +1,5 @@
kind: BUG FIXES
body: 'stacks: change absolute paths in path.module/path.root to be relative, as documented'
time: 2025-12-09T23:00:00.316597+00:00
custom:
Issue: "37982"

View file

@ -67,7 +67,31 @@ func (p *SourceBundleParser) LoadConfigDir(source sourceaddrs.FinalSource) (*Mod
})
return nil, diags
}
mod.SourceDir = sourceDir
// The result of sources.LocalPathForSource is an absolute path, but we
// don't actually want to pass an absolute path for a module's SourceDir;
// doing so will cause the value of `path.module` in Terraform configs to
// differ across plans and applies, since tfc-agent performs plans and
// applies in temporary directories. Instead, we try to resolve a relative
// path from Terraform's working directory, which should always be a
// reasonable SourceDir value.
workDir, err := os.Getwd()
if err != nil {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Cannot resolve working directory",
Detail: fmt.Sprintf("Failed to resolve current working directory: %s. This is a bug in Terraform - please report it.", err),
})
}
relativeSourceDir, err := filepath.Rel(workDir, sourceDir)
if err != nil {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Cannot resolve relative path",
Detail: fmt.Sprintf("Failed to resolve relative path to module directory: %s. This is a bug in Terraform - please report it.", err),
})
}
mod.SourceDir = relativeSourceDir
return mod, diags
}

View file

@ -7,7 +7,6 @@ import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"time"
@ -852,17 +851,9 @@ func TestPlanning_PathValues(t *testing.T) {
t.Fatalf("failed to get current working directory: %s", err)
}
normalizePath := func(path string) string {
rel, err := filepath.Rel(cwd, path)
if err != nil {
t.Errorf("rel(%s,%s): %s", cwd, path, err)
return path
}
return rel
}
// path.cwd should be absolute and all others should be relative, as per documentation.
expected := map[string]string{
"cwd": ".",
"cwd": cwd,
"root": "testdata/sourcebundle/planning/path_values/module", // this is the root module of the component
"module": "testdata/sourcebundle/planning/path_values/module", // this is the root module
"child_root": "testdata/sourcebundle/planning/path_values/module", // should be the same for all modules
@ -870,11 +861,11 @@ func TestPlanning_PathValues(t *testing.T) {
}
actual := map[string]string{
"cwd": normalizePath(component.PlannedOutputValues[addrs.OutputValue{Name: "cwd"}].AsString()),
"root": normalizePath(component.PlannedOutputValues[addrs.OutputValue{Name: "root"}].AsString()),
"module": normalizePath(component.PlannedOutputValues[addrs.OutputValue{Name: "module"}].AsString()),
"child_root": normalizePath(component.PlannedOutputValues[addrs.OutputValue{Name: "child_root"}].AsString()),
"child_module": normalizePath(component.PlannedOutputValues[addrs.OutputValue{Name: "child_module"}].AsString()),
"cwd": component.PlannedOutputValues[addrs.OutputValue{Name: "cwd"}].AsString(),
"root": component.PlannedOutputValues[addrs.OutputValue{Name: "root"}].AsString(),
"module": component.PlannedOutputValues[addrs.OutputValue{Name: "module"}].AsString(),
"child_root": component.PlannedOutputValues[addrs.OutputValue{Name: "child_root"}].AsString(),
"child_module": component.PlannedOutputValues[addrs.OutputValue{Name: "child_module"}].AsString(),
}
if cmp.Diff(expected, actual) != "" {