You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Three parallel whole-PR reviews surfaced no blockers but several
genuine resilience and clarity improvements. Applied:
* Added a CLI regression test covering the realistic CI scenario: a
config.yaml declaring a Postgres state connection whose credentials
come from unset env vars. Proves end-to-end that no secrets are
needed for format. Skipped when psycopg2 isn't importable.
Non-vacuity verified: temporarily forcing load_state=True makes the
test fail with the patched RuntimeError.
* Hardened the lint test's string-replace anchors with explicit
`assert anchor in read_file` checks. If sushi's config.py shape ever
drifts, the test will now fail at the anchor with a useful message
instead of silently no-op-ing and producing a confusing downstream
symptom.
* Documented the plan-state guard-rail test's mechanic in its
docstring (we don't assert on exit_code because state is patched to
raise; the spy records the constructor call regardless).
* Added a code comment by `load_state = ...` in cli/main.py explaining
why the assignment is outside the single-path conditional, so a
future tidy-up doesn't re-introduce the multi-path regression that
the previous fix commit just closed.
* Tightened wording in the `load_state` docstring on GenericContext
("Consulted by load(); has no effect when load() is not called"
rather than "Only meaningful when load=True", which was imprecise
for manual post-construction `context.load()` calls).
* Replaced `f.writelines(read_file)` with `f.write(read_file)` in the
lint test. The original worked because strings are iterable, but
read as a bug.
* Documented the pre-existing Snowflake-default-auth limitation in
the spec's Risks section: Postgres state configs validate fine with
env_var-resolved None values, but Snowflake's
`_validate_authenticator` raises ConfigError at config-load time if
user and password are both missing under default auth. Not
introduced by this PR (the validator predates it) but it's the one
realistic CI setup where "zero secrets" doesn't hold.
Coding-Agent: pi
Model: anthropic/claude-opus-4-7
Signed-off-by: Joe Hartshorn <8881940+j-hartshorn@users.noreply.github.com>
Copy file name to clipboardExpand all lines: docs/2026-05-21_local-only-format/spec.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -67,6 +67,7 @@ Tests: add a regression test that constructs a `Context` against a project whose
67
67
-**`update_model_schemas` cache state.**`load(update_schemas=True)` runs after the state-merge block. When the block is skipped, the local `MappingSchema` won't contain remote snapshot columns. For `format` and `lint` this is fine — neither needs resolved column types from remote projects — but if a linter rule is ever added later that relies on cross-project column resolution, it would silently produce different results under `load_state=False`. Note in the linter rule contract, but no code change needed today.
68
68
-**CLI test isolation.** Asserting "no state connection was opened" is easier to assert by patching than by mocking the network. The cleanest seam is `EngineAdapterStateSync.get_versions` — patching it to raise should be enough; we then assert `format`/`lint` succeed and the patched method is never called. If that seam turns out to be wrong (e.g., a different method gets called first), we'll adjust during implementation.
69
69
-**Multi-project monorepos.** The state-merge block's purpose is to import remote snapshots for *other* projects when the current load covers only a subset (`context.py:681-697`, gated on `any(self._projects)`). For `format`/`lint`, this means a model that depends on a model defined in a sibling project not currently being loaded won't have its upstream resolved. That's already the behavior for any model `format`/`lint` touches — they operate per-file, not on rendered downstream queries — so there should be no observable difference. Flagging in case a reviewer raises it.
70
+
- **Snowflake default-auth state connections.** `PostgresConnectionConfig` accepts `password=None` from a missing `{{ env_var() }}` (Pydantic coercion), so a Postgres state config validates with no secrets and the gate then prevents the connection. `SnowflakeConnectionConfig._validate_authenticator` (`sqlmesh/core/config/connection.py:633-638`) is stricter: under default authentication it raises `ConfigError("User and password must be provided")` at config-load time if both are missing. That validation runs before our `load_state` gate can take effect, so a project whose state lives in Snowflake with default-auth still requires user/password env vars to be set (any non-empty values — they won't be used). This is pre-existing Snowflake validator behavior, not something this change introduces, but it's the one realistic CI configuration where "zero secrets" doesn't hold. Workarounds: use the Snowflake key-pair or OAuth authenticators (which have their own validators with different requirements), or set placeholder env vars in the CI job.
Copy file name to clipboardExpand all lines: sqlmesh/core/context.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -363,7 +363,7 @@ class GenericContext(BaseContext, t.Generic[C]):
363
363
connection as it appears in configuration will be used.
364
364
concurrent_tasks: The maximum number of tasks that can use the connection concurrently.
365
365
load: Whether or not to automatically load all models and macros (default True).
366
-
load_state: Whether to merge remote state into the local project during load (default True). Only meaningful when load=True.
366
+
load_state: Whether to merge remote state into the local project during load (default True). Consulted by load(); has no effect when load() is not called.
367
367
console: The rich instance used for printing out CLI command results.
0 commit comments