diff --git a/package-lock.json b/package-lock.json index 77b77e5..5df9726 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@libpg-query/parser": "^17.6.3", "@opentelemetry/api": "^1.9.0", "@pgsql/types": "^17.6.2", - "@query-doctor/core": "^0.12.0", + "@query-doctor/core": "^0.13.0", "async-sema": "^3.1.1", "capnweb": "^0.7.0", "dedent": "^1.7.1", @@ -1100,6 +1100,12 @@ "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@pgsql/quotes": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@pgsql/quotes/-/quotes-17.1.0.tgz", + "integrity": "sha512-J/H+LcrENBpYgL45WW6aTjb5Yk4tX4+AmB2/k8KZa+Zh3wiCtqmNIag+HZz5HmWaF6EZK9ZGC95NBD1fs+rUvg==", + "license": "MIT" + }, "node_modules/@pgsql/types": { "version": "17.6.2", "resolved": "https://registry.npmjs.org/@pgsql/types/-/types-17.6.2.tgz", @@ -1187,18 +1193,28 @@ "license": "BSD-3-Clause" }, "node_modules/@query-doctor/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@query-doctor/core/-/core-0.12.0.tgz", - "integrity": "sha512-z2uCIHuHKjcqYTDWW5s13K0iUfBIN5mYZsTNHYzO7FwYuglshWEpsq2bLLLiegL1eqzYK+Et6QF7qy/Vs0TUBw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@query-doctor/core/-/core-0.13.0.tgz", + "integrity": "sha512-xhSgpFLAIVNAIu4V9u9POkdRSvLIH3J/ekz5OXrnN45ObEg8vdSMyqOuwt5ADT8G+PhTbiElFhfPJwHQ2xfDFA==", "dependencies": { "@pgsql/types": "^17.6.2", - "capnweb": "^0.7.0", + "capnweb": "^0.10.0", "colorette": "^2.0.20", "dedent": "^1.7.2", - "pgsql-deparser": "^17.17.2", + "pgsql-deparser": "^17.18.4", "zod": "^4.3.6" } }, + "node_modules/@query-doctor/core/node_modules/capnweb": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/capnweb/-/capnweb-0.10.0.tgz", + "integrity": "sha512-lQ2nlzaifkqBeNfs8RLErn7NZ8FNf3vn1W7J3nSH73edWG+0B5nHZGR51S2S9HMZEuZcEypOO469dZRY/BluFA==", + "license": "MIT", + "workspaces": [ + ".", + "packages/*" + ] + }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", @@ -4366,11 +4382,12 @@ } }, "node_modules/pgsql-deparser": { - "version": "17.17.2", - "resolved": "https://registry.npmjs.org/pgsql-deparser/-/pgsql-deparser-17.17.2.tgz", - "integrity": "sha512-FCjqKY3Sdmce3VUd3CxCXF0kqaZ0s4a6yIMT5UJ9vETh0cF54A8Tpqjn0qBKaPUD8xqTKeLdS+SfiwjAC64wrA==", + "version": "17.18.5", + "resolved": "https://registry.npmjs.org/pgsql-deparser/-/pgsql-deparser-17.18.5.tgz", + "integrity": "sha512-C23etz+aWjp5d09SQwrByisCIV0Zy1dPI0IdBPBaRiMRrDQ2MH8O9txvqpxPyWiXEGRU+MMvZqk48UHxWWbODg==", "license": "MIT", "dependencies": { + "@pgsql/quotes": "17.1.0", "@pgsql/types": "^17.6.2" } }, diff --git a/package.json b/package.json index b15d8fb..452e22c 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@libpg-query/parser": "^17.6.3", "@opentelemetry/api": "^1.9.0", "@pgsql/types": "^17.6.2", - "@query-doctor/core": "^0.12.0", + "@query-doctor/core": "^0.13.0", "async-sema": "^3.1.1", "capnweb": "^0.7.0", "dedent": "^1.7.1", diff --git a/src/remote/api-client.ts b/src/remote/api-client.ts index 6231910..a580acb 100644 --- a/src/remote/api-client.ts +++ b/src/remote/api-client.ts @@ -1,6 +1,6 @@ import { newWebSocketRpcSession, RpcTarget } from "capnweb"; import type { RpcStub } from "capnweb"; -import type { ConnectionMode, UnauthenticatedServerApi, ClientApi, IndexDefinition, ServerApi } from "@query-doctor/core"; +import type { ConnectionMode, UnauthenticatedServerApi, ClientApi, IndexDefinition, LiveQueryOptimization, ServerApi } from "@query-doctor/core"; import type { ExportedStats } from "@query-doctor/core"; import { PgIdentifier, Statistics } from "@query-doctor/core"; import { log } from "../log.ts"; @@ -183,7 +183,10 @@ export class ApiClient extends RpcTarget implements ClientApi { ); } - async runQuery(_query: string): Promise { - log.warn("runQuery is not implemented", ApiClient.name); + async runQuery(_query: string): Promise { + // Part of the ClientApi RPC surface (core 0.13.0) but never invoked on the + // CI client — throw rather than return a fabricated optimization, so a stray + // call surfaces loudly instead of silently yielding a bogus result. + throw new Error("runQuery is not implemented on the CI ApiClient"); } } diff --git a/src/reporters/site-api.test.ts b/src/reporters/site-api.test.ts index 2973230..45bb138 100644 --- a/src/reporters/site-api.test.ts +++ b/src/reporters/site-api.test.ts @@ -245,6 +245,30 @@ describe("compareRuns", () => { expect(result.regressed).toHaveLength(1); expect(result.testOriginExcluded).toHaveLength(0); }); + + // Real SQLCommenter `file` tags carry a `:line:col` suffix + // (`…repository.spec.ts:509:10`). Before core stripped that suffix, the + // `$`-anchored `.spec.ts` pattern never matched, so a test read-back leaked + // into newQueries and phantom-blocked unrelated PRs run after run — the + // server dropped it as test-origin while the analyzer did not (Site #3606). + test("excludes a .spec.ts query whose file tag carries a :line:col suffix", async () => { + const withSuffix: CiQueryPayload = { + ...makeQuery("hash-new", 200), + tags: [ + { + key: "file", + value: + "/home/runner/work/Site/Site/apps/api/src/projects/project-queries.repository.spec.ts:509:10", + }, + ], + }; + const previousRun = makePreviousRun([]); + + const result = await compareRuns([withSuffix], previousRun, 10); + + expect(result.newQueries).toHaveLength(0); + expect(result.testOriginExcluded.map((q) => q.hash)).toEqual(["hash-new"]); + }); }); describe("changed-query detection via shape (#3367)", () => {