Skip to content

[CFX-6414] fix(dotenv): make --if-needed skip only when .env is complete - #750

Merged
ajalon1 merged 3 commits into
datarobot-oss:mainfrom
ajalon1:aj/CFX-6414-dotenv-setup-propagate
Aug 13, 2026
Merged

[CFX-6414] fix(dotenv): make --if-needed skip only when .env is complete#750
ajalon1 merged 3 commits into
datarobot-oss:mainfrom
ajalon1:aj/CFX-6414-dotenv-setup-propagate

Conversation

@ajalon1

@ajalon1 ajalon1 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

RATIONALE

dr dotenv setup --if-needed was skipping the wizard when .env existed but was incomplete, leaving .env incomplete and causing downstream failures (e.g., deployment issues reported in CFX-6414).

Two root causes, both in the skip check (shouldSkipSetup):

  1. OS environment leak: shouldSkipSetup used ValidateEnvironment, which checks both .env file values and os.LookupEnv. Environment variables satisfied validation even when .env was missing core variables, so the wizard never ran and .env was never populated.
  2. Synthesis leak: even after switching to a file-only validator, gatherUserPrompts still applied YAML default values, ran ApplyGeneratedValues (auto-generating secrets), and Valid() accepted non-empty commented entries. A required variable satisfied only by a default, a generated secret, or a commented-out .env line could make the skip check pass, leaving .env incomplete.

CHANGES

  • Added ValidateEnvironmentFileOnly to validate .env contents only, ignoring OS environment variables.
  • Updated shouldSkipSetup to use ValidateEnvironmentFileOnly so --if-needed skips only when .env itself is complete.
  • Made ValidateEnvironmentFileOnly presence-only: it no longer applies YAML defaults, does not run ApplyGeneratedValues, and treats commented-out .env entries as absent. A required variable now counts as present only if it has an effective, uncommented value in the .env file.
  • Threaded a synthesize flag through gatherUserPrompts / validateEnvironment / promptsWithValues / resolvePromptValue. GatherUserPrompts and ValidateEnvironment keep synthesize=true (unchanged behavior); ValidateEnvironmentFileOnly uses synthesize=false.
  • Removed the unused GatherUserPromptsFromFile public wrapper; the includeEnv/synthesize distinction stays private to the envbuilder package.
  • Refactored promptsWithValues to accept includeEnv/synthesize flags and extracted resolvePromptValue to reduce cyclomatic complexity.
  • The PULUMI_CONFIG_PASSPHRASE viper-config value remains an intentional non-file exception (resolvePulumiPassphrase), documented as such.
  • Regression tests cover the OS-env case and the three synthesis leaks (YAML default, generated secret, commented entry) plus a positive control.

BEHAVIOR CHANGE NOTE

dr dotenv setup --if-needed now runs the wizard in three cases where it previously skipped (exit 0): a required var satisfied only by a YAML default, a required generate: true secret absent from .env, and a required var commented out in .env. This is a bug fix (the .env was incomplete), but it is an observable change to a user-facing flag.

For automation/CI that runs dr dotenv setup --if-needed non-interactively, pair it with --yes (or DATAROBOT_CLI_NON_INTERACTIVE=true) so the wizard runs headless and writes the missing values, then exits 0. A script using --if-needed without --yes that previously got a silent skip for one of these cases will now launch the wizard and block on a prompt.

dr dotenv validate is unchanged — it still uses ValidateEnvironment (synthesize=true), so a var satisfied only by a default still passes validate.

TESTING

  • go test ./cmd/dotenv/... ./internal/envbuilder/... -count=1 -race — all pass, including TestShouldSkipSetup_PresenceOnly (3 leak cases + positive control).
  • task lint — clean across linux/darwin/windows.
  • Manual CLI exercise of 7 scenarios (baseline skip, missing core var, OS-env-doesn't-satisfy, YAML-default-doesn't-satisfy, commented-doesn't-satisfy, validate unchanged) — all pass.

RELATED


Note

Medium Risk
Changes when dotenv setup is skipped in automation paths; incorrect skip behavior previously caused deployment failures, so regressions here could reintroduce incomplete .env files or force unexpected wizard runs.

Overview
Fixes dr dotenv setup --if-needed skipping the wizard when required vars were present only in the OS environment, leaving .env incomplete and breaking downstream deploys.

shouldSkipSetup now uses new file-only validation (ValidateEnvironmentFileOnly / GatherUserPromptsFromFile) that ignores os.LookupEnv, so an incomplete .env still triggers setup. Prompt value resolution was refactored with an includeEnv flag and resolvePromptValue, and a regression test covers the env-var-only case.

Reviewed by Cursor Bugbot for commit ac8d5d7. Configure here.

@datarobot-pr-review-router

Copy link
Copy Markdown

🎫 Jira: CFX-6414 — dotenv setup does not propagate most of the variables with non empty .env

@ajalon1
ajalon1 marked this pull request as ready for review August 11, 2026 21:12
@ajalon1
ajalon1 requested a review from a team as a code owner August 11, 2026 21:12
@ajalon1

ajalon1 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

/approve-smoke-tests

@github-actions

Copy link
Copy Markdown
Contributor

🔐 Fork PR smoke tests triggered by @ajalon1

⚠️ Security Notice: This will run tests with access to repository secrets.

What happens next:

  1. Security scans will run automatically (Trivy, gosec)
  2. If security scans pass, smoke tests will run
  3. Results will be posted as PR comments

⚠️ Important: Review the PR code carefully before approving!

Previously, shouldSkipSetup used ValidateEnvironment which checked both
.env file values and OS environment variables. This caused the wizard to
be skipped when core variables (DATAROBOT_API_TOKEN, DATAROBOT_ENDPOINT)
were set via environment but missing from .env, leaving .env incomplete.

Change shouldSkipSetup to use ValidateEnvironmentFileOnly, which ignores
OS environment variables for the skip decision. This ensures the wizard
runs whenever .env itself is missing required variables.

- Add ValidateEnvironmentFileOnly and GatherUserPromptsFromFile
- Refactor promptsWithValues to accept includeEnv flag
- Add regression test for env-var-only core variables

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@ajalon1
ajalon1 force-pushed the aj/CFX-6414-dotenv-setup-propagate branch from ac8d5d7 to 49a3a5b Compare August 11, 2026 21:13
@github-actions

Copy link
Copy Markdown
Contributor

🔐 Fork smoke tests started by maintainer

⏳ Security scans passed. Running smoke tests...

Commit: ac8d5d7d6267ccfbd456f2bcd83d9b46a0f7e490
View run

@github-actions

Copy link
Copy Markdown
Contributor

All smoke tests passed! (Fork PR)

✅ Security Scan: success
✅ Linux: success
✅ Windows: success

View run details

@datarobot-pr-review-router

Copy link
Copy Markdown

Code Ownership

Cli Maintainers

  • cmd/dotenv/cmd.go
  • cmd/dotenv/if_needed_test.go
  • internal/envbuilder/builder.go
  • internal/envbuilder/validator.go
  • internal/envbuilder/validator_test.go

Review requested from the teams above. Labels will be removed automatically upon approval.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates dotenv validation so --if-needed checks .env independently of OS environment variables.

Changes:

  • Adds file-only validation and prompt gathering.
  • Refactors prompt value resolution.
  • Adds regression coverage for OS-only core variables.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/envbuilder/validator.go Adds file-only validation and value-resolution modes.
internal/envbuilder/validator_test.go Updates tests for the new resolver parameter.
internal/envbuilder/builder.go Adds file-only prompt gathering.
cmd/dotenv/if_needed_test.go Tests missing core variables supplied by OS environment.
cmd/dotenv/cmd.go Uses file-only validation for skip decisions.
Suppressed comments (1)

internal/envbuilder/validator.go:126

  • The new file-only mode still depends on the OS environment in the Pulumi special case below. If PULUMI_CONFIG_PASSPHRASE exists both in the OS and in drconfig, the lookup suppresses loading the Viper value; resolvePromptValue then ignores the OS value, so validation fails solely because that environment variable is present. In file-only mode, allow the Viper fallback regardless of os.LookupEnv.
func promptsWithValues(prompts []UserPrompt, variables Variables, includeEnv bool) []UserPrompt {

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/envbuilder/validator.go Outdated

// Gather all user prompts from the repository
userPrompts, err := GatherUserPrompts(repoRoot, variables)
userPrompts, err := gatherUserPrompts(repoRoot, variables, includeEnv)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to pull this back and work on this bit tomorrow.

Comment thread internal/envbuilder/builder.go Outdated
ajalon1 and others added 2 commits August 12, 2026 15:29
Copilot review identified that in file-only mode, if PULUMI_CONFIG_PASSPHRASE
was set in OS env but not in .env, validation would fail incorrectly. The
first loop skipped viper load due to os.LookupEnv, but resolvePromptValue
ignored the OS value.

Fix: Extract resolvePulumiPassphrase helper that respects includeEnv flag.
In file-only mode, always check viper config regardless of OS env.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
ValidateEnvironmentFileOnly still synthesized values: gatherUserPrompts
applied YAML defaults and ApplyGeneratedValues, and Valid() accepted
non-empty commented entries. A required variable satisfied only by a
default, a generated secret, or a commented-out .env line could therefore
make shouldSkipSetup return true, leaving .env incomplete and skipping the
wizard.

Add a synthesize flag to gatherUserPrompts/validateEnvironment/
promptsWithValues/resolvePromptValue. ValidateEnvironmentFileOnly now
runs in presence-only mode (includeEnv=false, synthesize=false):
- YAML defaults are not applied
- ApplyGeneratedValues is skipped
- commented .env entries count as absent

Also remove the unused GatherUserPromptsFromFile public wrapper; the
includeEnv distinction stays private to the package.

The PULUMI_CONFIG_PASSPHRASE viper-config value remains an intentional
non-file exception (resolvePulumiPassphrase) and is documented as such.

Regression tests cover the three synthesis leaks (default, generated
secret, commented entry) plus a positive control.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@ajalon1
ajalon1 force-pushed the aj/CFX-6414-dotenv-setup-propagate branch from 370a933 to 9c3b77c Compare August 13, 2026 00:34
@ajalon1

ajalon1 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

/approve-smoke-tests

@github-actions

Copy link
Copy Markdown
Contributor

🔐 Fork PR smoke tests triggered by @ajalon1

⚠️ Security Notice: This will run tests with access to repository secrets.

What happens next:

  1. Security scans will run automatically (Trivy, gosec)
  2. If security scans pass, smoke tests will run
  3. Results will be posted as PR comments

⚠️ Important: Review the PR code carefully before approving!

@github-actions

Copy link
Copy Markdown
Contributor

🔐 Fork smoke tests started by maintainer

⏳ Security scans passed. Running smoke tests...

Commit: 9c3b77cff68b957cf2b87ff3665c52cb0726356e
View run

@github-actions

Copy link
Copy Markdown
Contributor

All smoke tests passed! (Fork PR)

✅ Security Scan: success
✅ Linux: success
✅ Windows: success

View run details

@ajalon1
ajalon1 merged commit dea6c5c into datarobot-oss:main Aug 13, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants