DCM early access command output improvements#3066
Open
sfc-gh-jsommerfeld wants to merge 37 commits into
Open
Conversation
Poll SYSTEM$GET_DCM_PROJECT_PROGRESS during async deploy and show a phase checklist with per-phase progress for PLAN and DEPLOY. Co-authored-by: Cursor <cursoragent@cursor.com>
Add UPLOAD as the first checklist phase with folder summaries, per-phase durations and colors, and a file-count progress bar without extra I/O. Co-authored-by: Cursor <cursoragent@cursor.com>
Use project scope for stage message, show upload summaries above the UPLOAD phase, fix plan completion styling, and align Upload N file(s) lines. Co-authored-by: Cursor <cursoragent@cursor.com>
Simulate RENDER/COMPILE/PLAN phases for plan without progress API, simplify upload summary lines, and remove extra indentation from progress output. Co-authored-by: Cursor <cursoragent@cursor.com>
Surface the nested changes for ALTER entries as indented sub-lines (kind plus item desc) so users can see what is actually changing instead of just "ALTER ROLE …". Handles every observed payload shape: dict and string item_id, set/unset attribute changes, modified entries that carry their own nested changes, and collection wrappers. CREATE/DROP stay terse because their changes are noisy attribute dumps. Each sub-line is colored semantically (added/set green, removed/unset red, modified/renamed yellow). Co-authored-by: Cursor <cursoragent@cursor.com>
Render the UPLOAD checklist row first, then indent the stage-creation message and folder counters beneath it (two-space indent, dim style), so the live progress UI reads top-down as a single phase block instead of a preamble followed by the phase header. Co-authored-by: Cursor <cursoragent@cursor.com>
Gated on ENABLE_DCM_EARLY_ACCESS, the new `snow dcm analyze` command runs the same EXECUTE DCM PROJECT ... ANALYZE query as `raw-analyze` but prints a styled report instead of raw JSON: errors in red, issues in yellow, each with their error code, source line/column, and (when applicable) the fully-qualified definition identifier and domain. A plan-style summary line is always rendered at the end. If nothing was reported, a green `Analysis completed successfully.` is shown; otherwise both counts are printed with the error count in red and the issue count in yellow. The command exits with status 1 only when errors are present; warning-only runs exit 0. Supports `--save-output` to persist the raw JSON response under `out/analyze.json` and download server-side artifacts to `out/analyze/`, mirroring `snow dcm plan`. Co-authored-by: Cursor <cursoragent@cursor.com>
Wire `snow dcm analyze` into `DeployProgressTracker` with a new `operation="analyze"` mode that exposes only the client-side UPLOAD phase (no server-side RENDER/COMPILE/PLAN/DEPLOY rows). The UPLOAD line, progress bar, checkmark, timestamp, duration, and dim per-folder upload summaries now match `snow dcm deploy` byte-for-byte. After upload completes the existing spinner runs the synchronous ANALYZE query, then the formatted findings and summary line are rendered as before. Co-authored-by: Cursor <cursoragent@cursor.com>
The styled analyze report now prints just the actual diagnostic message
for each error / issue (still colored red / yellow respectively), grouped
under the source file and definition identifier. The previous per-finding
header line ("error [001597] line 10:0") is dropped, and the server-side
"DCM project ANALYZE error: " prefix is stripped from the message text.
The full raw payload (codes, source positions, types) is still preserved
in the JSON response and in `--save-output` artifacts.
Co-authored-by: Cursor <cursoragent@cursor.com>
All DCM commands that go through a Reporter (plan, deploy, purge, analyze, raw-analyze, refresh, test) now print an 80-character `=` divider as the last visible line of their TABLE-format output. This gives a clean visual break between the command's results and the next shell prompt or the error box rendered for a failing run. The divider is auto-suppressed in --format json / --format csv runs because cli_console is silenced for machine-readable outputs. Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the generic "Analysis ..." summary line emitted by both AnalyzeReporter and AnalyzeErrorsReporter (success and failure branches) with the more specific "Static Analysis of DCM Project files ..." phrasing, and update unit, integration, and release-notes references accordingly. Co-authored-by: Cursor <cursoragent@cursor.com>
Adjust the DCM analyze summary to "Static analysis of DCM Project files found no errors." on success (lowercase "analysis") and apply the same casing to the failure variant. Render source-file headers in the analyze output in bold blue (new FILE_PATH_STYLE) so file names stand out from the inline finding messages. Co-authored-by: Cursor <cursoragent@cursor.com>
A PLAN or DEPLOY failure bubbles up through DeployProgressTracker.session()'s exception handler, which called fail_upload() unconditionally and overwrote an already-completed UPLOAD as failed. Make fail_upload() a no-op once the UPLOAD phase has terminated (done or failed) so a downstream error stops at its own phase row without retroactively marking the successful upload as failed. Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the terse `N refreshed, M up-to-date.` summary with a two-line styled summary printed above the `===` divider, mirroring the pattern used by `snow dcm plan` / `snow dcm analyze`: * Always: `N Dynamic Tables refreshed successfully.` (green) — counts every table that completed without error (REFRESHED + UP-TO-DATE). * When applicable: `M Refreshes failed.` (red) — counts tables the server returned without statistics (previously the `unknown` bucket). The command now exits with status 1 only when at least one refresh failed; the styled summary still renders above the divider in that case (via the same `_is_success` + post-hoc `typer.Exit` trick used by `AnalyzeErrorsReporter`), instead of being swallowed into an "Error" box. Snapshots, the mixed-success test, and the qa-only integration assertions are updated to match the new wording. Co-authored-by: Cursor <cursoragent@cursor.com>
The server now returns a single `issues[]` array per level (top-level, file, per-definition) where each entry carries a `severity` field (`ERROR`, `WARN`/`WARNING`, or `INFO`). Drop the legacy `errors[]` parsing entirely and drive the reporter off severity: * `ERROR` — red, triggers exit code 1 (unchanged). * `WARN`/`WARNING` — yellow, informational. * `INFO` — plain blue (new `INFO_STYLE` to distinguish from bold-blue source file headers), informational. Unknown or missing severity values are coerced to `ERROR` so a buggy server payload never silently downgrades a real problem. The summary now breaks down by severity, omitting zero buckets and using proper singular/plural plus an Oxford comma when three buckets are present, e.g.: * `Static analysis of DCM Project files found no errors.` (all clean) * `Static analysis of DCM Project files found 1 error.` * `Static analysis of DCM Project files found 1 error and 2 warnings.` * `Static analysis of DCM Project files found 2 errors, 1 warning, and 3 infos.` Each numeric segment is colored to match its severity. `raw-analyze` keeps its simpler error-only summary and counts ERROR-severity issues across all three levels of the response. Tests are updated to use the new `issues[]`+`severity` shape; added parametrized coverage that each severity uses the matching style (`FAIL_STYLE` / `WARNING_STYLE` / `INFO_STYLE`) and that unknown severity values still fail the run. Co-authored-by: Cursor <cursoragent@cursor.com>
Previously the semantic style (added=green, removed=red, modified=yellow, set=green, unset=red) was applied to BOTH the kind keyword and the description text on every indented sub-line under an ALTER row. With verbose ALTERs (e.g. role grants, data metric functions with nested expectations) that meant a wall of red/green/yellow that drowned out the actual entity names. Restrict the color to the kind keyword only; the description (entity identifier, attribute = value, etc.) now renders with the terminal default so the eye lands on the verb and the names stay readable. The parent ALTER row's operation keyword and its FQN coloring are unchanged. Updated `test_detail_kind_keyword_is_colored_desc_is_default` to assert the new contract: kind segment carries the semantic style, desc segment has style "" (default). Co-authored-by: Cursor <cursoragent@cursor.com>
Commit a82b15d (simplify upload copy) dropped the trailing-space pad on the singular form, so adjacent rows in the upload details block no longer lined up: "Upload 1 file from ..." vs "Upload 12 files from ...". Restore the trailing space on the singular so the column after the word stays aligned, e.g.: Upload 1 file from sources/macros Upload 12 files from sources/definitions Test asserts the literal two-space gap; a comment notes that the double-space is intentional so future formatters / linters don't "correct" it away. Co-authored-by: Cursor <cursoragent@cursor.com>
Indented sub-lines previously used a flat two-space indent per depth,
which made it hard to tell which leaves belonged to which "modified"
parent in a busy ALTER (think ROLE grants or a DMF with nested
expectations).
Switch to a tree-style prefix using Unicode box-drawing characters in
narrow 3-column cells:
ALTER ROLE DCM_DEVELOPER
├─ removed DATABASE_ROLE DCM_DEMO_1_DEV2.ADMIN_DEV2
├─ added DATABASE_ROLE DCM_DEMO_1_DEV3.ADMIN_DEV3
├─ modified ON SCHEMA DCM_DEMO_1_DEV2.TEST_TEAM
│ └─ added OWNERSHIP
├─ removed ROLE TEST_TEAM_OWNER_DEV2
└─ added ROLE TEST_TEAM_OWNER_DEV3
ALTER TABLE ...ENRICHED_ORDER_DETAILS
└─ added SNOWFLAKE.CORE.NULL_COUNT$V1(CUSTOMER_CITY)
└─ added NO_MISSING_CITIES
└─ set expression = value = 0
Implementation:
* Replace ``PlanDetail.depth: int`` with ``is_last_chain: Tuple[bool, ...]``
(one bool per ancestor level, ending with the node itself). Keep
``depth`` as a derived ``@property`` for callers that still want the
count.
* Pre-expand ``collection`` wrappers in ``_flatten_changes`` /
``_flatten_changes_from_raw`` so the ``is_last`` computation reflects
the *displayed* sibling list (collections produce no line of their
own; their children take their place as siblings of their grandparent).
* New ``_render_tree_prefix`` turns the chain into ``├─ ``, ``└─ ``,
``│ ``, or `` `` cells. The prefix renders with the default style
so the colored verb (added/removed/modified/set/…) still catches the
eye, matching the previous "only the keyword is colored" contract.
* Tests updated: dataclass equality assertions now pass
``is_last_chain=(...)``; the nested-grants indent check compares the
column where each kind keyword starts (survives the tree prefix).
* Snapshots regenerated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Group sub-changes under an ALTER row by category at every depth so users scan creations first, then modifications, then deletions, matching the top-level CREATE → ALTER → DROP ordering. Stable sort preserves server-supplied order within each bucket. Co-authored-by: Cursor <cursoragent@cursor.com>
Replaces the static yellow "…" placeholder with a braille spinner that animates inside the live phase checklist, so the user sees activity on the running phase itself instead of having a separate spinner appear below the tracker. * Adds an ANALYZE phase to the analyze tracker mode so the spinner has a place to render; the analyze command now runs through the same Live session as deploy/plan instead of opening a second cli_console spinner. * Generalizes ``run_plan_execute`` into ``run_loader_phase(phase_name=, simulated_phases=)`` and routes both plan and analyze through it. * Passes ``self`` to ``rich.live.Live`` and implements ``__rich__`` so Rich's refresh loop re-renders the tracker every ~100 ms; the spinner glyph is derived from ``time.monotonic()`` for a smooth cycle. * Collapses three near-identical poll loops in ``run_deploy_poll`` into a single body behind an ``_ensure_live`` context manager. Bundled cleanups while touching the file: * Replaces the stringly-typed phase status with a ``PhaseStatus`` enum. * Replaces the if/elif phase-list chain with a ``_PHASES_BY_OPERATION`` dict so adding a new mode is one line. * Hoists the three lazy ``get_cli_context`` imports to module level. * Removes the unused ``DeployProgressTracker.run`` alias. The ``mock_deploy_tracker`` fixture now stubs ``run_loader_phase`` to invoke its closure so analyze command tests continue to exercise the real ``manager.raw_analyze`` mock. Co-authored-by: Cursor <cursoragent@cursor.com>
Three internal cleanups that follow up on the live-progress / analyze / refresh work without changing observable output (apart from the test summary, see below). * Plan reporter: collapse _KIND_SORT_ORDER + _style_for_change_kind into a single _KIND_INFO[kind] = (sort_key, style) table. A new sub-change kind now lives in one place and can't drift between coloring and sort order. * Plan reporter: merge _flatten_changes / _flatten_changes_from_raw and _expand_collections / _expand_collections_raw behind a small _ChangeReader adapter, eliminating ~80 lines of duplicated traversal code while keeping the strict (PlanChange) and fallback (raw dict) paths separated. * Analyze reporter: move the top-level _top_level_issues tally from print_renderables into extract_data, mirroring the per-file and per-definition tally path so the summary counts stay correct even if the printing side ever short-circuits. * Test reporter: align with the always-True _is_success + override process_payload(...) pattern adopted by AnalyzeErrorsReporter and RefreshReporter. Failures now render the styled "N passed, M failed" summary line above the === divider (instead of stuffing it into a CliError box) and exit 1 via typer.Exit, so the three reporters that can fail behave identically. Snapshots regenerated; test_process_raises_cli_error_on_failures renamed to test_process_exits_nonzero_on_failures to match the new contract. Co-authored-by: Cursor <cursoragent@cursor.com>
…LYZE phase Backfills RELEASE-NOTES.md with the user-facing dcm changes that landed earlier on this branch but weren't yet noted: the live phase checklist (now with an inline animated spinner) for deploy/plan/analyze, the tree-style sub-change rendering under ALTER rows (sorted added → modified → removed), and the new "test" styled summary aligned with analyze / refresh. Co-authored-by: Cursor <cursoragent@cursor.com>
Replaces the block-character bar (``[██████░░░░] 50%``) with a pip/Rich-style minimal bar using heavy-horizontal cells (``━``) and a ``╺`` leading-edge transition cell at the boundary. The filled portion is blue, the empty portion dim, and the percentage follows in blue — no surrounding brackets. Widens the bar from 20 to 30 cells so the leading-edge transition has room to read as a smooth progress indicator. The line still comfortably fits in an 80-column terminal alongside the phase name, timestamp, and duration. Co-authored-by: Cursor <cursoragent@cursor.com>
Now that the parenthesised elapsed duration is shown for every running and completed phase, the leading "HH:MM:SS" start timestamp is redundant — it doubled the timing column without adding new information. Drops it from the rendered phase line so each row reads as ``<name> <indicator> (X.Ys)``. Bumps the progress bar from 30 to 40 cells now that there's room to spare on the line; the leading edge ``╺`` has more space to read as a smooth indicator and the bar matches the pip-style aesthetic. Renames the internal _Phase.hide_timestamp field to .hide_timing since it now only suppresses duration display (used by ``_simulate_instant_phase`` for fast-forwarded RENDER/COMPILE rows in plan mode). Co-authored-by: Cursor <cursoragent@cursor.com>
Top-level CREATE/ALTER/DROP rows still pad their operation keyword to a
fixed column for alignment between entities. Child rows under an ALTER
no longer pad — the tree prefix already provides visual indentation, so
a single space between keyword and description keeps the indented lines
compact:
ALTER ROLE DCM_DEVELOPER
├─ added DATABASE_ROLE DCM_DEMO_1_DEV3.ADMIN_DEV3
├─ added ROLE TEST_TEAM_OWNER_DEV3
├─ modified ON SCHEMA DCM_DEMO_1_DEV2.TEST_TEAM
│ └─ added OWNERSHIP
├─ removed DATABASE_ROLE DCM_DEMO_1_DEV2.ADMIN_DEV2
└─ removed ROLE TEST_TEAM_OWNER_DEV2
Snapshot tests and substring assertions updated; the now-unused
``_KIND_WIDTH`` constant is removed.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replaces the laconic ``N passed, M failed out of T total.`` line with the more conversational ``Ran T data quality tests: N passed, M failed expectation(s).`` The trailing noun (``expectation`` / ``expectations``) pluralizes with the *last* visible bucket — ``unknown`` when present, otherwise ``failed`` — so the line reads naturally for every combination: * "Ran 6 data quality tests: 5 passed, 1 failed expectation." * "Ran 6 data quality tests: 4 passed, 2 failed expectations." * "Ran 6 data quality tests: 6 passed, 0 failed expectations." * "Ran 6 data quality tests: 4 passed, 1 failed, 1 unknown expectation." Styling is preserved (total bolded, ``passed`` green, ``failed`` / ``unknown`` red); the empty-project line is unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
The braille spinner glyph for a running ANALYZE / PLAN / DEPLOY phase was yellow; every other "this is in flight" element on the row — filled bar cells, leading-edge ``╺``, the percentage text, the bold phase name itself — was blue. The mixed palette read as two different signals instead of one. Switching the spinner to ``blue`` unifies the entire running row under the active-indicator color. Co-authored-by: Cursor <cursoragent@cursor.com>
H1 — _update_from_poll: ignore unknown / empty / non-string phase
Earlier, a poll payload whose ``phase`` field was missing, empty,
non-string, or not in the operation's phase list flipped every
server-side phase to ``done`` on the very first poll while the
query was still running. The tracker now refuses to mutate phase
state from such payloads and logs at debug. Five regression tests
added in ``TestUpdateFromPoll``.
M1 — _poll_progress: close the cursor
Each poll opened a fresh cursor (1 Hz then 0.1 Hz) and never closed
it. Wrapped in ``with self._conn.cursor() as cursor:`` so resources
are released every tick.
M2 — _update_from_poll: use PhaseStatus enum members
Replaced the ``("done", "failed")`` string-literal check with the
enum members; the file is now internally consistent and won't
silently break if ``PhaseStatus`` ever stops inheriting from str.
M3 — _poll_progress: validate sfqid before interpolating into SQL
Defense-in-depth: ``sfqid`` is server-generated, but we never want
an unvalidated string embedded into a SQL literal. A new
``_SFQID_RE`` UUID regex gates the interpolation; non-matching ids
disable polling for the run.
M4 — run_loader_phase: leave phase state intact in silent mode
Silent mode (JSON/CSV output, ``--silent``) has no UI to drive, so
``run_loader_phase`` now returns ``execute_fn()`` immediately
without touching ``complete_upload`` / ``observe_running`` etc.
This avoids leaking stale RUNNING entries that could mislead later
introspection. ``TestRunLoaderPhaseSilent`` covers both the happy
path and the exception path.
M5 — analyze: share a single error-counting iterator
``AnalyzeReporter`` and ``AnalyzeErrorsReporter`` used to count
severities along divergent paths (raw-payload walk vs typed
``_AnalyzeFinding`` walk). Introduced ``_iter_findings`` + a
``_tally_by_severity`` Counter helper so both reporters tally off
the same source — the totals can no longer disagree.
M6 — plan: render tree prefix dim
The ``├─ │ └─`` glyphs in front of ALTER child rows now render
with ``style="dim"`` so they recede visually; the colored
``added`` / ``removed`` / ``modified`` keyword that follows is
what catches the eye.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add `snow dcm dependencies`, which runs the same analysis as `analyze-errors` but renders the project's object dependencies as a Mermaid flowchart written to a Markdown file. The CLI prints a link to the generated file so it can be opened in an IDE Markdown preview. Co-authored-by: Cursor <cursoragent@cursor.com>
Remove the blank line between the ANALYZE phase line and the summary, indent all three summary lines by two spaces, and render them in dim grey so the path and hint text feel secondary to the phase result. Co-authored-by: Cursor <cursoragent@cursor.com>
Switch Mermaid curve from monotoneX to step so edges exit horizontally from the right port of each source node and enter horizontally into the left port of the target, with a single clean vertical bend in between. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Rename `snow dcm analyze` → `snow dcm compile` on the early-access branch. Updates the command function, artifact names, reporter command_name, debug-data mapping, and all test invocations. Co-authored-by: Cursor <cursoragent@cursor.com>
GitOrigin-RevId: 2b8d9a0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pre-review checklist
RELEASE-NOTES.md(see when and how).Changes description
snow dcm plansnow dcm deploysnow dcm analyzesnow dcm refreshsnow dcm test