Skip to content

feat: [SNOW-3444080] add env.yml support to snow dbt deploy#3097

Open
sfc-gh-yuding wants to merge 2 commits into
mainfrom
worktree-SNOW-3444080-dbt-deploy-env
Open

feat: [SNOW-3444080] add env.yml support to snow dbt deploy#3097
sfc-gh-yuding wants to merge 2 commits into
mainfrom
worktree-SNOW-3444080-dbt-deploy-env

Conversation

@sfc-gh-yuding

@sfc-gh-yuding sfc-gh-yuding commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Pre-review checklist

  • If my changes add or modify user-facing interface (commands, flags, output formats), I consulted maintainers and got sign-off beforehand (how).
  • I've confirmed that instructions included in README.md are still correct after my changes in the codebase.
  • I've added or updated unit tests to verify correctness of my new code.
  • I've added or updated integration tests to verify correctness of my new code.
  • Manually tested on macOS
  • Manually tested on Windows
  • I've confirmed my changes are up-to-date with the target branch.
  • I've described my changes in RELEASE-NOTES.md (see when and how).
  • I've updated documentation if behavior changed.

Changes description

Adds three flags to snow dbt deploy that bring env.yml into the deploy flow alongside profiles.yml:

  • --env-file-dir <path>: inject env.yml from a separate directory into the staged project root, mirroring --profiles-dir.
  • --default-environment <name>: set DEFAULT_ENVIRONMENT on the DBT PROJECT object (CREATE / CREATE OR REPLACE / ALTER SET).
  • --unset-default-environment: clear DEFAULT_ENVIRONMENT on alter, mutually exclusive with --default-environment.

env.yml is staged like profiles.yml: copied from the source directory by default, optionally overridden via --env-file-dir, and round-tripped through pyyaml so YAML comments don't leak onto the stage. The CLI does no client-side schema validation — the server enforces env-var prefixes, secret-key rules, and reserved environment names.

Server support for these properties is gated by ENABLE_DBT_ENV_VARS (GS PR #404443).

Tested live on qa6 (ENABLE_DBT_ENV_VARS = true) against branch commit f43ee31e.

# Command Behavior Expected?
1 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment dev --unset-default-environment exit 2; mutex error Parameters '--unset-default-environment' and '--default-environment' are incompatible and cannot be used simultaneously.; no SQL sent
2 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./empty_envs CliError: env.yml does not exist in directory ./empty_envs.; no stage created
3 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./dup_envs --default-environment dev (env.yml has DBT_FOO repeated) CliError: env.yml has duplicate key 'DBT_FOO'; aborts before sending CREATE/ALTER SQL
4 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment staging (no staging block in env.yml) server rejects: SQL compilation error … Invalid env.yml: environment 'staging' not found.
5 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment dev (first deploy) emits CREATE DBT PROJECT … DEFAULT_ENVIRONMENT='dev'; dbt list reports default_environment: "dev"
6 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment prod (redeploy) emits ALTER DBT PROJECT … SET DEFAULT_ENVIRONMENT='prod' + ADD VERSION; default_environment: "prod"
7 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --unset-default-environment (redeploy) emits ALTER DBT PROJECT … UNSET DEFAULT_ENVIRONMENT + ADD VERSION; default_environment: null
8 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --unset-default-environment (redeploy when project already has default_environment: null) UNSET is still emitted; server treats it as no-op; default_environment: null
9 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment dev --force emits CREATE OR REPLACE DBT PROJECT … DEFAULT_ENVIRONMENT='dev'; default_environment: "dev"
10 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment dev --default-target prod emits CREATE DBT PROJECT … DEFAULT_TARGET='prod' DEFAULT_ENVIRONMENT='dev'; both fields set
11 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs (no --default-environment) env.yml staged but default_environment: null — env.yml is inert at deploy when no flag is passed
12 snow dbt deploy SMOKE_3444080 --source ./project_with_env --env-file-dir ./override_envs --default-environment prod (source's env.yml has only dev; override has only prod) succeeds; default_environment: "prod" confirms --env-file-dir overrides the source's env.yml on stage
13 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment "" succeeds; default_environment: null — empty string is treated as not-provided (consistent with --default-target "", --dbt-version "", etc. across the dbt module)
14 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment $'dev\nMALICIOUS' CliError: --default-environment must not contain control characters (newlines, tabs, etc.); no SQL sent
15 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir /tmp/does_not_exist_xyz --default-environment dev CliError: env.yml does not exist in directory /tmp/does_not_exist_xyz.
16 snow dbt deploy --help with ENABLE_DBT_PROJECT_ENV_VARS off vs on flag off: --default-environment, --unset-default-environment, --env-file-dir are hidden from help; flag on: all three visible. With flag on, help text reads "Default environment for the dbt project. Selects the environment block from env.yml that the project compiles and executes with by default. Mutually exclusive with --unset-default-environment."
17 snow dbt deploy SMOKE_3444080 --source ./project_with_env --default-environment dev (env.yml lives inside --source dir, no --env-file-dir) succeeds; default_environment: "dev" — confirms env.yml is auto-staged from source dir without an explicit --env-file-dir
18 snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./bad_envs --default-environment dev (bad_envs/env.yml has malformed YAML — bad indentation) CliError: env.yml is not valid YAML: while scanning a simple key … could not find expected ':' …; no SQL sent

@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch 2 times, most recently from 1547508 to f0f73f6 Compare June 8, 2026 23:22
@sfc-gh-yuding sfc-gh-yuding changed the base branch from main to worktree-SNOW-3563127-dbt-execute-env-vars June 8, 2026 23:26
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3563127-dbt-execute-env-vars branch from 0394b8c to f1b19ce Compare June 8, 2026 23:42
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch 2 times, most recently from c3b823f to 8900854 Compare June 9, 2026 00:07
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3563127-dbt-execute-env-vars branch from f1b19ce to 0f93ce5 Compare June 9, 2026 00:21
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from 8900854 to 2130b36 Compare June 9, 2026 00:26
@sfc-gh-yuding sfc-gh-yuding changed the base branch from worktree-SNOW-3563127-dbt-execute-env-vars to main June 9, 2026 01:56
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from 2130b36 to db1ad47 Compare June 9, 2026 01:57
@sfc-gh-yuding sfc-gh-yuding marked this pull request as ready for review June 9, 2026 01:58
@sfc-gh-yuding sfc-gh-yuding requested review from a team as code owners June 9, 2026 01:58

@sfc-gh-jwilkowski sfc-gh-jwilkowski 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.

Please apply similar changes as listed in #3096 (review)

@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from db1ad47 to 2991ac3 Compare June 9, 2026 22:39
@sfc-gh-yuding sfc-gh-yuding changed the base branch from main to worktree-SNOW-3563127-dbt-execute-env-vars June 9, 2026 22:45
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from 2991ac3 to 76e1b09 Compare June 9, 2026 22:51
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3563127-dbt-execute-env-vars branch 3 times, most recently from 8cdda4e to 3f76c3c Compare June 10, 2026 01:15
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from 76e1b09 to c74ffdd Compare June 10, 2026 01:16
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from c74ffdd to 041d2ac Compare June 10, 2026 01:22
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3563127-dbt-execute-env-vars branch from 3f76c3c to af7a4bc Compare June 10, 2026 01:28
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from 041d2ac to c8dc914 Compare June 10, 2026 01:28
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3563127-dbt-execute-env-vars branch from af7a4bc to b441203 Compare June 10, 2026 01:35
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch 2 times, most recently from 6876ca9 to 48f7c87 Compare June 10, 2026 01:47
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3563127-dbt-execute-env-vars branch 2 times, most recently from 9a09e1e to 0aa53e7 Compare June 10, 2026 22:58
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from 48f7c87 to faf32c0 Compare June 11, 2026 00:02
Base automatically changed from worktree-SNOW-3563127-dbt-execute-env-vars to main June 11, 2026 10:38

@sfc-gh-jwilkowski sfc-gh-jwilkowski 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.

Mostly looks good to me, but I'm leaving some questions. Please rebase your changes as going through changes from this PR and 3097 makes it more difficult to understand :)

),
default_environment: Optional[str] = DefaultEnvironmentOption(
help=(
f"Default environment for the dbt project (DEFAULT_ENVIRONMENT). "

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.

I don't understand why that info needs to be duplicated?

Suggested change
f"Default environment for the dbt project (DEFAULT_ENVIRONMENT). "
f"Default environment for the dbt project. "

with source_env_file.open(
read_file_limit_mb=DEFAULT_SIZE_LIMIT_MB
) as sfd, target_env_file.open(mode="w") as tfd:
yaml.safe_dump(yaml.safe_load(sfd), tfd)

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.

Shouldn't you use _NoDuplicatesSafeLoader?

@sfc-gh-yuding sfc-gh-yuding Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, we should use _NoDuplicatesSafeLoader here. Added a test case for duplicate key in env.yml as well.

Comment on lines +402 to +413
# Stage env.yml inside the project source so the server has something to
# match the DEFAULT_ENVIRONMENT against.
env_yml = {
"env_config": {
"default_environment": "dev",
"environments": [
{"name": "dev", "env": {"DBT_FOO": "bar"}},
{"name": "prod", "env": {"DBT_FOO": "baz"}},
],
}
}
(root_dir / ENV_FILENAME).write_text(yaml.dump(env_yml))

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.

is this needed when we test only setting the attribute on dbt project level here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, we need this env.yaml setup, given server-side validation enforces that DEFAULT_ENVIRONMENT='dev' requires an env.yml containing an environment named dev on the stage. Without it, CREATE fails with Invalid env.yml: environment 'dev' not found.

Adds three flags to `snow dbt deploy` that bring env.yml into the deploy
flow alongside profiles.yml:

- `--env-file-dir <path>`: inject env.yml from a separate directory into
  the staged project root, mirroring `--profiles-dir`.
- `--default-environment <name>`: set DEFAULT_ENVIRONMENT on the DBT
  PROJECT object (CREATE / CREATE OR REPLACE / ALTER SET).
- `--unset-default-environment`: clear DEFAULT_ENVIRONMENT on alter,
  mutually exclusive with --default-environment.

env.yml is staged like profiles.yml: copied from the source directory by
default, optionally overridden via `--env-file-dir`, and round-tripped
through pyyaml so YAML comments don't leak onto the stage. The CLI does
no client-side schema validation — the server enforces env-var prefixes,
secret-key rules, and reserved environment names.

Server support for these properties is gated by ENABLE_DBT_ENV_VARS
(GS PR #404443).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from faf32c0 to 01cea57 Compare June 11, 2026 20:12
sfc-gh-yuding added a commit that referenced this pull request Jun 11, 2026
- Trim --default-environment help text (drop redundant DEFAULT_ENVIRONMENT
  parenthetical).
- Use _NoDuplicatesSafeLoader in _prepare_env_file so duplicate keys in
  env.yml surface as a clear CliError instead of silent last-wins,
  matching the existing pattern for --env-vars and the server's parser.
- Add unit test covering the duplicate-key rejection.
- Drop trailing blank line left over from rebase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Trim --default-environment help text (drop redundant DEFAULT_ENVIRONMENT
  parenthetical).
- Use _NoDuplicatesSafeLoader in _prepare_env_file so duplicate keys in
  env.yml surface as a clear CliError ("env.yml has duplicate key 'X'")
  instead of silent last-wins. Reword the matching --env-vars message
  for consistency so "duplicate key" appears once rather than twice.
- Catch yaml.YAMLError in _prepare_env_file so malformed env.yml
  surfaces as "env.yml is not valid YAML: ..." instead of a raw pyyaml
  traceback, mirroring the existing pattern in _parse_env_vars.
- Add unit tests for duplicate-key and malformed-YAML rejection.
- Drop trailing blank line left over from rebase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sfc-gh-yuding sfc-gh-yuding force-pushed the worktree-SNOW-3444080-dbt-deploy-env branch from bd522e7 to f43ee31 Compare June 11, 2026 23:33
@sfc-gh-yuding sfc-gh-yuding enabled auto-merge (squash) June 11, 2026 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants