feat: [SNOW-3444080] add env.yml support to snow dbt deploy#3097
feat: [SNOW-3444080] add env.yml support to snow dbt deploy#3097sfc-gh-yuding wants to merge 2 commits into
Conversation
1547508 to
f0f73f6
Compare
0394b8c to
f1b19ce
Compare
c3b823f to
8900854
Compare
f1b19ce to
0f93ce5
Compare
8900854 to
2130b36
Compare
2130b36 to
db1ad47
Compare
sfc-gh-jwilkowski
left a comment
There was a problem hiding this comment.
Please apply similar changes as listed in #3096 (review)
db1ad47 to
2991ac3
Compare
2991ac3 to
76e1b09
Compare
8cdda4e to
3f76c3c
Compare
76e1b09 to
c74ffdd
Compare
c74ffdd to
041d2ac
Compare
3f76c3c to
af7a4bc
Compare
041d2ac to
c8dc914
Compare
af7a4bc to
b441203
Compare
6876ca9 to
48f7c87
Compare
9a09e1e to
0aa53e7
Compare
48f7c87 to
faf32c0
Compare
sfc-gh-jwilkowski
left a comment
There was a problem hiding this comment.
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). " |
There was a problem hiding this comment.
I don't understand why that info needs to be duplicated?
| 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) |
There was a problem hiding this comment.
Shouldn't you use _NoDuplicatesSafeLoader?
There was a problem hiding this comment.
Yes, we should use _NoDuplicatesSafeLoader here. Added a test case for duplicate key in env.yml as well.
| # 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)) |
There was a problem hiding this comment.
is this needed when we test only setting the attribute on dbt project level here?
There was a problem hiding this comment.
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>
faf32c0 to
01cea57
Compare
- 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>
bd522e7 to
f43ee31
Compare
Pre-review checklist
RELEASE-NOTES.md(see when and how).Changes description
Adds three flags to
snow dbt deploythat 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 commitf43ee31e.snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment dev --unset-default-environmentParameters '--unset-default-environment' and '--default-environment' are incompatible and cannot be used simultaneously.; no SQL sentsnow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./empty_envsCliError: env.yml does not exist in directory ./empty_envs.; no stage createdsnow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./dup_envs --default-environment dev(env.yml hasDBT_FOOrepeated)CliError: env.yml has duplicate key 'DBT_FOO'; aborts before sending CREATE/ALTER SQLsnow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment staging(nostagingblock in env.yml)SQL compilation error … Invalid env.yml: environment 'staging' not found.snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment dev(first deploy)CREATE DBT PROJECT … DEFAULT_ENVIRONMENT='dev';dbt listreportsdefault_environment: "dev"snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment prod(redeploy)ALTER DBT PROJECT … SET DEFAULT_ENVIRONMENT='prod'+ADD VERSION;default_environment: "prod"snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --unset-default-environment(redeploy)ALTER DBT PROJECT … UNSET DEFAULT_ENVIRONMENT+ADD VERSION;default_environment: nullsnow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --unset-default-environment(redeploy when project already hasdefault_environment: null)default_environment: nullsnow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment dev --forceCREATE OR REPLACE DBT PROJECT … DEFAULT_ENVIRONMENT='dev';default_environment: "dev"snow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment dev --default-target prodCREATE DBT PROJECT … DEFAULT_TARGET='prod' DEFAULT_ENVIRONMENT='dev'; both fields setsnow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs(no--default-environment)default_environment: null— env.yml is inert at deploy when no flag is passedsnow dbt deploy SMOKE_3444080 --source ./project_with_env --env-file-dir ./override_envs --default-environment prod(source's env.yml has onlydev; override has onlyprod)default_environment: "prod"confirms--env-file-diroverrides the source's env.yml on stagesnow dbt deploy SMOKE_3444080 --source ./project --env-file-dir ./envs --default-environment ""default_environment: null— empty string is treated as not-provided (consistent with--default-target "",--dbt-version "", etc. across the dbt module)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 sentsnow dbt deploy SMOKE_3444080 --source ./project --env-file-dir /tmp/does_not_exist_xyz --default-environment devCliError: env.yml does not exist in directory /tmp/does_not_exist_xyz.snow dbt deploy --helpwithENABLE_DBT_PROJECT_ENV_VARSoff vs on--default-environment,--unset-default-environment,--env-file-dirare 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."snow dbt deploy SMOKE_3444080 --source ./project_with_env --default-environment dev(env.yml lives inside--sourcedir, no--env-file-dir)default_environment: "dev"— confirms env.yml is auto-staged from source dir without an explicit--env-file-dirsnow 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