From 008e4bd0c1c6036c291b46f4581ce197ce57ef86 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Sirois Date: Thu, 26 Mar 2026 08:26:06 +0400 Subject: [PATCH] feat: include sqlcommenter tags in CI query payload Extract SQLCommenter tags from Analyzer.analyze() and thread them through QueryProcessResult and CiQueryPayload to the Site API. This enables the Site frontend to display route, method, file, and other sqlcommenter metadata for CI-captured queries. Companion to Query-Doctor/Site#2615 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/reporters/github/github.test.ts | 8 ++++---- src/reporters/site-api.ts | 8 +++++++- src/runner.ts | 18 ++++++++++++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/reporters/github/github.test.ts b/src/reporters/github/github.test.ts index af82541..aa3ffab 100644 --- a/src/reporters/github/github.test.ts +++ b/src/reporters/github/github.test.ts @@ -147,7 +147,7 @@ describe("buildViewModel", () => { hash: "new-query-1", query: "SELECT 1", formattedQuery: "SELECT 1", - nudges: [], optimization: { state: "no_improvement_found", cost: 10, indexesUsed: [] }, + nudges: [], tags: [], optimization: { state: "no_improvement_found", cost: 10, indexesUsed: [] }, }, ], }), @@ -236,13 +236,13 @@ describe("buildViewModel", () => { hash: "new-1", query: "SELECT 1", formattedQuery: "SELECT 1", - nudges: [], optimization: { state: "no_improvement_found", cost: 10, indexesUsed: [] }, + nudges: [], tags: [], optimization: { state: "no_improvement_found", cost: 10, indexesUsed: [] }, }, { hash: "new-2", query: "SELECT 2", formattedQuery: "SELECT 2", - nudges: [], optimization: { state: "no_improvement_found", cost: 10, indexesUsed: [] }, + nudges: [], tags: [], optimization: { state: "no_improvement_found", cost: 10, indexesUsed: [] }, }, ], }), @@ -269,7 +269,7 @@ describe("buildViewModel", () => { hash: "new-1", query: "SELECT 1", formattedQuery: "SELECT 1", - nudges: [], optimization: { state: "no_improvement_found", cost: 10, indexesUsed: [] }, + nudges: [], tags: [], optimization: { state: "no_improvement_found", cost: 10, indexesUsed: [] }, }, ], }), diff --git a/src/reporters/site-api.ts b/src/reporters/site-api.ts index 59cae0c..599f22e 100644 --- a/src/reporters/site-api.ts +++ b/src/reporters/site-api.ts @@ -1,5 +1,5 @@ import * as github from "@actions/github"; -import type { IndexRecommendation, Nudge } from "@query-doctor/core"; +import type { IndexRecommendation, Nudge, SQLCommenterTag } from "@query-doctor/core"; import { DEFAULT_CONFIG, type AnalyzerConfig } from "../config.ts"; import type { QueryProcessResult } from "../runner.ts"; @@ -19,6 +19,7 @@ export interface CiQueryPayload { formattedQuery: string; optimization: CiOptimization; nudges: Nudge[]; + tags: SQLCommenterTag[]; } export type CiOptimization = @@ -120,6 +121,7 @@ function mapResultToQuery(result: QueryProcessResult): CiQueryPayload | null { query: result.rawQuery, formattedQuery: result.recommendation.formattedQuery, nudges: result.nudges, + tags: result.tags, optimization: { state: "improvements_available", cost: result.recommendation.baseCost, @@ -143,6 +145,7 @@ function mapResultToQuery(result: QueryProcessResult): CiQueryPayload | null { query: result.rawQuery, formattedQuery: result.formattedQuery, nudges: result.nudges, + tags: result.tags, optimization: { state: "no_improvement_found", cost: result.cost, @@ -157,6 +160,7 @@ function mapResultToQuery(result: QueryProcessResult): CiQueryPayload | null { query: result.rawQuery, formattedQuery: result.formattedQuery, nudges: result.nudges, + tags: result.tags, optimization: { state: "no_improvement_found", cost: 0, @@ -171,6 +175,7 @@ function mapResultToQuery(result: QueryProcessResult): CiQueryPayload | null { query: result.rawQuery, formattedQuery: result.formattedQuery, nudges: result.nudges, + tags: result.tags, optimization: { state: "error", error: result.error.message, @@ -183,6 +188,7 @@ function mapResultToQuery(result: QueryProcessResult): CiQueryPayload | null { query: result.rawQuery, formattedQuery: result.warning.formattedQuery, nudges: result.nudges, + tags: result.tags, optimization: result.warning.optimization ? { state: "no_improvement_found", diff --git a/src/runner.ts b/src/runner.ts index b8d20fc..c8e3898 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -14,6 +14,7 @@ import { IndexOptimizer, type IndexRecommendation, type Nudge, + type SQLCommenterTag, OptimizeResult, type Postgres, PostgresQueryBuilder, @@ -239,7 +240,7 @@ export class Runner { const analyzer = new Analyzer(parse); const formattedQuery = await this.formatQuery(query); - const { indexesToCheck, ansiHighlightedQuery, referencedTables, nudges } = + const { indexesToCheck, ansiHighlightedQuery, referencedTables, nudges, tags } = await analyzer.analyze(formattedQuery); const selectsCatalog = referencedTables.find((ref) => @@ -270,6 +271,7 @@ export class Runner { kind: "cost_past_threshold", rawQuery: query, nudges, + tags, warning: { fingerprint: queryFingerprint, formattedQuery, @@ -306,6 +308,7 @@ export class Runner { rawQuery: query, formattedQuery, nudges, + tags, }; } if (out.kind === "ok") { @@ -337,7 +340,9 @@ export class Runner { formattedQuery, cost: out.baseCost, existingIndexes: existingIndexesForQuery, - nudges, explainPlan: out.baseExplainPlan, + nudges, + tags, + explainPlan: out.baseExplainPlan, }; } this.queryStats.optimized++; @@ -350,6 +355,7 @@ export class Runner { kind: "recommendation", rawQuery: query, nudges, + tags, indexRecommendations: newIndexRecommendations, recommendation: { fingerprint: queryFingerprint, @@ -377,6 +383,7 @@ export class Runner { kind: "cost_past_threshold", rawQuery: query, nudges, + tags, warning: { fingerprint: queryFingerprint, formattedQuery, @@ -399,6 +406,7 @@ export class Runner { cost: out.baseCost, existingIndexes: existingIndexesForQuery, nudges, + tags, explainPlan: out.baseExplainPlan, }; } @@ -413,6 +421,7 @@ export class Runner { rawQuery: query, formattedQuery, nudges, + tags, }; } console.timeEnd(`timing`); @@ -467,12 +476,14 @@ export type QueryProcessResult = kind: "cost_past_threshold"; rawQuery: string; nudges: Nudge[]; + tags: SQLCommenterTag[]; warning: ReportQueryCostWarning; } | { kind: "recommendation"; rawQuery: string; nudges: Nudge[]; + tags: SQLCommenterTag[]; indexRecommendations: IndexRecommendation[]; recommendation: ReportIndexRecommendation; } @@ -484,6 +495,7 @@ export type QueryProcessResult = cost: number; existingIndexes: string[]; nudges: Nudge[]; + tags: SQLCommenterTag[]; explainPlan?: object; } | { kind: "error"; @@ -492,6 +504,7 @@ export type QueryProcessResult = rawQuery: string; formattedQuery: string; nudges: Nudge[]; + tags: SQLCommenterTag[]; } | { kind: "zero_cost_plan"; @@ -500,4 +513,5 @@ export type QueryProcessResult = rawQuery: string; formattedQuery: string; nudges: Nudge[]; + tags: SQLCommenterTag[]; };