diff --git a/Makefile b/Makefile index 6abc18ee56..d39020b5f0 100644 --- a/Makefile +++ b/Makefile @@ -101,6 +101,7 @@ CLIDOC_SRC_FILES := \ CLIDOCGEN_INPUTS := \ $(wildcard scripts/clidocgen/*.go) \ + $(filter-out %_test.go,$(wildcard scripts/docgenenv/*.go)) \ scripts/clidocgen/command.tpl \ $(CLIDOC_SRC_FILES) diff --git a/scripts/clidocgen/main.go b/scripts/clidocgen/main.go index 47998fca17..9550308cef 100644 --- a/scripts/clidocgen/main.go +++ b/scripts/clidocgen/main.go @@ -5,10 +5,10 @@ import ( "os" "path/filepath" "sort" - "strings" "github.com/coder/coder/v2/enterprise/cli" "github.com/coder/coder/v2/scripts/atomicwrite" + "github.com/coder/coder/v2/scripts/docgenenv" "github.com/coder/flog" "github.com/coder/serpent" ) @@ -29,32 +29,6 @@ type manifest struct { Routes []route `json:"routes,omitempty"` } -func prepareEnv() { - // Unset CODER_ environment variables - for _, env := range os.Environ() { - if strings.HasPrefix(env, "CODER_") { - split := strings.SplitN(env, "=", 2) - if err := os.Unsetenv(split[0]); err != nil { - panic(err) - } - } - } - - // Override default OS values to ensure the same generated results. - err := os.Setenv("CLIDOCGEN_CACHE_DIRECTORY", "~/.cache") - if err != nil { - panic(err) - } - err = os.Setenv("CLIDOCGEN_CONFIG_DIRECTORY", "~/.config/coderv2") - if err != nil { - panic(err) - } - err = os.Setenv("TMPDIR", "/tmp") - if err != nil { - panic(err) - } -} - func deleteEmptyDirs(dir string) error { return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { @@ -79,7 +53,7 @@ func deleteEmptyDirs(dir string) error { } func main() { - prepareEnv() + docgenenv.Prepare() workdir, err := os.Getwd() if err != nil { diff --git a/scripts/docgenenv/docgenenv.go b/scripts/docgenenv/docgenenv.go new file mode 100644 index 0000000000..587e1543a9 --- /dev/null +++ b/scripts/docgenenv/docgenenv.go @@ -0,0 +1,33 @@ +// Package docgenenv normalizes the process environment so documentation +// generators produce host-independent output. +package docgenenv + +import ( + "os" + "strings" +) + +// Prepare clears CODER_* variables and pins the cache, config, and temp +// directories so generated docs don't embed the generating host's home +// directory. +func Prepare() { + for _, env := range os.Environ() { + if !strings.HasPrefix(env, "CODER_") { + continue + } + name, _, _ := strings.Cut(env, "=") + if err := os.Unsetenv(name); err != nil { + panic(err) + } + } + + mustSetenv("CLIDOCGEN_CACHE_DIRECTORY", "~/.cache") + mustSetenv("CLIDOCGEN_CONFIG_DIRECTORY", "~/.config/coderv2") + mustSetenv("TMPDIR", "/tmp") +} + +func mustSetenv(key, value string) { + if err := os.Setenv(key, value); err != nil { + panic(err) + } +} diff --git a/scripts/docgenenv/docgenenv_test.go b/scripts/docgenenv/docgenenv_test.go new file mode 100644 index 0000000000..0fb0a803f4 --- /dev/null +++ b/scripts/docgenenv/docgenenv_test.go @@ -0,0 +1,26 @@ +package docgenenv_test + +import ( + "os" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/v2/scripts/docgenenv" +) + +//nolint:paralleltest // Prepare mutates the process environment. +func TestPrepare(t *testing.T) { + t.Setenv("CODER_ACCESS_URL", "https://example.com") + t.Setenv("CLIDOCGEN_CACHE_DIRECTORY", "") + t.Setenv("CLIDOCGEN_CONFIG_DIRECTORY", "") + t.Setenv("TMPDIR", "") + + docgenenv.Prepare() + + _, ok := os.LookupEnv("CODER_ACCESS_URL") + require.False(t, ok, "CODER_ prefixed variables should be cleared") + require.Equal(t, "~/.cache", os.Getenv("CLIDOCGEN_CACHE_DIRECTORY")) + require.Equal(t, "~/.config/coderv2", os.Getenv("CLIDOCGEN_CONFIG_DIRECTORY")) + require.Equal(t, "/tmp", os.Getenv("TMPDIR")) +}