diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6cb63f7..7dae5e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -343,6 +343,7 @@ jobs: # - 28 after agent_skill (cute-dbt#304) # - 29 after macro_perspective (cute-dbt#265) # - 30 after explore_macro_view (cute-dbt#345) + # - 31 after pr_comments (cute-dbt#419) # The README is not a feature. The job name deliberately carries no # number (cute-dbt#68 — the old `==6` display label went stale across # several bumps): the enforced count lives ONLY in the `expected=` @@ -360,7 +361,7 @@ jobs: - name: features/*.feature count matches expected run: | set -euo pipefail - expected=30 + expected=31 count=$(find features -maxdepth 1 -name '*.feature' | wc -l | tr -d ' ') echo "feature-count: expected ${expected}, found ${count}" if [ "$count" != "$expected" ]; then @@ -710,6 +711,24 @@ jobs: output: examples/prdiff-minidag-report.html project_root: tests/fixtures/prdiff-minidag-source experimental: "1" + # cute-dbt#419–#422 (epic #353) — the GOLDEN PR review-comments + # showcase. REUSES the prdiff-minidag manifest + patch + source (so + # no manifest regen — the threads anchor onto its real diff lines) + # and adds a SYNTHETIC `gh api graphql` review-threads payload via + # --pr-comments. The `pr-comments` experiment is on, so the committed + # golden exercises the gated surface: an inline OPEN thread on + # stg_orders line 2, a RESOLVED thread + an OUTDATED tail on + # fct_orders, the per-model count tooltip, and the top-of-report + # count button (3 comments total). No baseline — --pr-diff only. + - name: comments-showcase + mode: report + current: tests/fixtures/prdiff-minidag-current.json + baseline: "" + pr_diff: tests/fixtures/prdiff-minidag-pr-diff.patch + output: examples/comments-showcase-report.html + project_root: tests/fixtures/prdiff-minidag-source + experimental: "1" + pr_comments: tests/fixtures/comments-showcase-pr-comments.json # cute-dbt#100 — the GOLDEN explore pages: the full synthetic # playground manifest rendered to the two-file --out-dir shape # (examples/explore/dag.html + tests.html), each independently @@ -790,6 +809,9 @@ jobs: # pins a far-future date so the golden is wall-clock-independent. FINDINGS_OUT: ${{ matrix.findings_out }} GENERATED_AT: ${{ matrix.generated_at }} + # cute-dbt#419: optional synthetic PR review-comments payload (the + # comments-showcase row); empty = no --pr-comments arg. + PR_COMMENTS: ${{ matrix.pr_comments }} run: | set -euo pipefail mkdir -p target/example-check @@ -889,16 +911,25 @@ jobs: findings_args=(--findings-out "$rendered_findings" --generated-at "$GENERATED_AT") findings_hint=" --findings-out $FINDINGS_OUT --generated-at $GENERATED_AT" fi + # cute-dbt#419: the optional --pr-comments arg (the comments-showcase + # row's synthetic review-threads payload). Built only when set. + pr_comments_args=() + pr_comments_hint="" + if [ -n "$PR_COMMENTS" ]; then + pr_comments_args=(--pr-comments "@$PR_COMMENTS") + pr_comments_hint=" --pr-comments @$PR_COMMENTS" + fi cargo run --quiet --locked --bin cute-dbt -- report \ --manifest "$CURRENT_MANIFEST" \ "${scope_args[@]}" \ "${project_root_args[@]}" \ "${config_args[@]}" \ "${findings_args[@]}" \ + "${pr_comments_args[@]}" \ --out "$rendered" if ! diff -q "$rendered" "$OUTPUT_PATH" >/dev/null; then echo "::error::example-report-up-to-date: $OUTPUT_PATH does not match the renderer output ($EXAMPLE_NAME). Regenerate with:" - echo " ${regen_env}cargo run --bin cute-dbt -- report --manifest $CURRENT_MANIFEST$scope_hint$regen_hint$config_hint$findings_hint --out $OUTPUT_PATH" + echo " ${regen_env}cargo run --bin cute-dbt -- report --manifest $CURRENT_MANIFEST$scope_hint$regen_hint$config_hint$findings_hint$pr_comments_hint --out $OUTPUT_PATH" echo "Sizes:" ls -l "$rendered" "$OUTPUT_PATH" exit 1 @@ -910,7 +941,7 @@ jobs: if [ -n "$FINDINGS_OUT" ]; then if ! diff -q "$rendered_findings" "$FINDINGS_OUT" >/dev/null; then echo "::error::example-report-up-to-date: $FINDINGS_OUT does not match the renderer output ($EXAMPLE_NAME findings envelope). Regenerate with:" - echo " ${regen_env}cargo run --bin cute-dbt -- report --manifest $CURRENT_MANIFEST$scope_hint$regen_hint$config_hint$findings_hint --out $OUTPUT_PATH" + echo " ${regen_env}cargo run --bin cute-dbt -- report --manifest $CURRENT_MANIFEST$scope_hint$regen_hint$config_hint$findings_hint$pr_comments_hint --out $OUTPUT_PATH" echo "Sizes:" ls -l "$rendered_findings" "$FINDINGS_OUT" exit 1 diff --git a/examples/comments-showcase-report.html b/examples/comments-showcase-report.html new file mode 100644 index 0000000..7a28e31 --- /dev/null +++ b/examples/comments-showcase-report.html @@ -0,0 +1,11765 @@ + + + + + +cute-dbt report + + + + + + +
+

cute-dbt report

+
+ +
+

+ Showing 2 unit tests in scope — from PR file diff. +

+ + + + + + +
+ + +
+ + +
+
+ +
+ +
+
+

PR scope lineage experimental

+ +
+

2 modified models · 1 connector model — modified emphasized, connectors quiet, context dimmed, deleted as ghosts. Click a node to select it below.

+
+ +
+ + +
+
+ + + +
+
+ + + + + +
+ + +
+
+

Coverage checks

+

Static checks over the manifest and compiled SQL — tiers are labeled, never averaged.

+
+
+
+ +
+
+ Model SQLraw, with Jinja + +
+
+
+
+
+ + +
+
+ Model YAMLauthored schema entry +
+
+
+
+
+ +
+
+

CTE dependency DAG

+ + +
+ + +
+
+
+ + +
+
+ node role + +
+
+ edge type + +
+
+
+ +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ +
+
+
+ +
+ +
+ +
+

Given

+
+
+
+ +
+
+

Expected

+ 0 rows +
+
+
+ +
+ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/diff-showcase-report.html b/examples/diff-showcase-report.html index ca7485a..98b4903 100644 --- a/examples/diff-showcase-report.html +++ b/examples/diff-showcase-report.html @@ -2256,6 +2256,66 @@ color: var(--text-muted); overflow-wrap: anywhere; margin: 0.5rem 0; } +/* PR review comments (cute-dbt#419 / #420 / #421 / #422, epic #353). + The whole surface is JS-rendered from DATA.pr_comments; these rules + dress the inline threads, the top count button, and the per-model count + chip. No `overflow:hidden` ancestor clips the focusable-bubble tooltip + (the .model-comment-count-chip reuses the shared .expect-tooltip family, + whose bubble is position:absolute over a position:relative trigger). */ +.pr-comments-count { + display: inline-flex; align-items: center; gap: 0.4rem; + margin: 0.6rem 0 0; padding: 0.35rem 0.7rem; + border: 1px solid var(--border, #ccc); border-radius: var(--radius-sm, 6px); + background: var(--surface-2, rgba(0,0,0,0.03)); color: var(--text, inherit); + font: inherit; font-size: 0.92em; cursor: pointer; +} +.pr-comments-count:hover { background: var(--surface-3, rgba(0,0,0,0.06)); } +.pr-comments-count:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } +.pr-comments-count-label { font-weight: 600; } +.pr-comments-count[hidden] { display: none; } + +.model-comments-row { margin: 0.3rem 0; } +.model-comments-row[hidden] { display: none; } +.model-comment-count-chip { + border-bottom: none; padding: 0.15rem 0.5rem; + border: 1px solid var(--border, #ccc); border-radius: 999px; + background: var(--surface-2, rgba(0,0,0,0.03)); cursor: help; +} +.model-comment-bubble { text-align: left; } +.model-comment-bubble-row { display: block; white-space: nowrap; padding: 0.05rem 0; } + +/* Inline thread cards, injected after the anchored Model-SQL diff line. */ +.pr-comment-thread { + display: block; margin: 0.3rem 0 0.5rem; padding: 0.5rem 0.7rem; + border: 1px solid var(--border, #ccc); + border-left: 3px solid var(--accent); + border-radius: var(--radius-sm, 6px); + background: var(--surface-1, rgba(0,0,0,0.02)); + font-size: 0.9em; white-space: normal; +} +.pr-comment-resolved { border-left-color: var(--ok, #2e7d32); opacity: 0.85; } +.pr-comment-outdated { border-left-color: var(--warn, #b45c0c); } +.pr-comment-thread-head { + display: flex; align-items: center; gap: 0.4rem; + margin-bottom: 0.35rem; color: var(--text-muted); +} +.pr-comment-anchor { font-weight: 600; } +.pr-comment-badge { + font-size: 0.78em; padding: 0.05rem 0.4rem; border-radius: 999px; + border: 1px solid currentColor; +} +.pr-comment-badge-resolved { color: var(--ok, #2e7d32); } +.pr-comment-badge-outdated { color: var(--warn, #b45c0c); } +.pr-comment-collapse > summary { cursor: pointer; color: var(--text-muted); } +.pr-comment { margin: 0.25rem 0; } +.pr-comment-author { font-weight: 600; color: var(--accent); } +.pr-comment-text { white-space: pre-wrap; overflow-wrap: anywhere; margin-top: 0.1rem; } +.pr-comment-tail { + margin: 0.6rem 0; padding: 0.5rem 0.7rem; + border: 1px dashed var(--border, #ccc); border-radius: var(--radius-sm, 6px); +} +.pr-comment-tail-label { margin: 0 0 0.4rem; color: var(--text-muted); font-style: italic; } + /* end of cute-dbt report chassis v1 (cute-dbt#177) */ @@ -2273,6 +2333,9 @@

cute-dbt report

+ + + @@ -2525,6 +2588,8 @@

PR scope lineage