From 2c5b44cfd1f3ac07e0af32c3182371ec0310b712 Mon Sep 17 00:00:00 2001 From: Pybsama <294532706+Pybsama@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:29:48 +0800 Subject: [PATCH 1/2] Fix standard query lockfile detection --- .../src/local-queries/standard-queries.ts | 13 ++-- .../local-queries/standard-queries.test.ts | 61 +++++++++---------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/extensions/ql-vscode/src/local-queries/standard-queries.ts b/extensions/ql-vscode/src/local-queries/standard-queries.ts index 6288cb05247..16fe4fdf065 100644 --- a/extensions/ql-vscode/src/local-queries/standard-queries.ts +++ b/extensions/ql-vscode/src/local-queries/standard-queries.ts @@ -2,7 +2,7 @@ import type { CodeQLCliServer } from "../codeql-cli/cli"; import { QLPACK_FILENAMES, QLPACK_LOCK_FILENAMES } from "../common/ql"; import { basename, dirname, resolve } from "path"; import { extLogger } from "../common/logging/vscode"; -import { promises } from "fs-extra"; +import { pathExists, promises } from "fs-extra"; import type { BaseLogger } from "../common/logging"; type LockFileForStandardQueryResult = { @@ -36,9 +36,14 @@ export async function createLockFileForStandardQuery( ); } const packPath = dirname(packFilePath); - const lockFilePath = packContents.find((p) => - QLPACK_LOCK_FILENAMES.includes(basename(p)), - ); + let lockFilePath: string | undefined; + for (const lockFileName of QLPACK_LOCK_FILENAMES) { + const candidateLockFilePath = resolve(packPath, lockFileName); + if (await pathExists(candidateLockFilePath)) { + lockFilePath = candidateLockFilePath; + break; + } + } let cleanup: (() => Promise) | undefined = undefined; diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/local-queries/standard-queries.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/local-queries/standard-queries.test.ts index f0464c97419..40a49839584 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/local-queries/standard-queries.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/local-queries/standard-queries.test.ts @@ -4,7 +4,7 @@ import type { DirectoryResult } from "tmp-promise"; import { dir } from "tmp-promise"; import { join } from "path"; import { createLockFileForStandardQuery } from "../../../../src/local-queries/standard-queries"; -import { outputFile, pathExists } from "fs-extra"; +import { outputFile, pathExists, readFile } from "fs-extra"; describe("createLockFileForStandardQuery", () => { let tmpDir: DirectoryResult; @@ -41,37 +41,34 @@ describe("createLockFileForStandardQuery", () => { }); describe("when the lock file exists", () => { - let lockfilePath: string; - - beforeEach(async () => { - lockfilePath = join(packPath, "qlpack.lock.yml"); - - packPacklist.mockResolvedValue([qlpackPath, lockfilePath, queryPath]); - }); - - it("does not resolve or install dependencies", async () => { - expect(await createLockFileForStandardQuery(mockCli, queryPath)).toEqual({ - cleanup: undefined, - }); - - expect(packResolveDependencies).not.toHaveBeenCalled(); - expect(clearCache).not.toHaveBeenCalled(); - expect(packInstall).not.toHaveBeenCalled(); - }); - - it("does not resolve or install dependencies with a codeql-pack.lock.yml", async () => { - lockfilePath = join(packPath, "codeql-pack.lock.yml"); - - packPacklist.mockResolvedValue([qlpackPath, lockfilePath, queryPath]); - - expect(await createLockFileForStandardQuery(mockCli, queryPath)).toEqual({ - cleanup: undefined, - }); - - expect(packResolveDependencies).not.toHaveBeenCalled(); - expect(clearCache).not.toHaveBeenCalled(); - expect(packInstall).not.toHaveBeenCalled(); - }); + it.each(["qlpack.lock.yml", "codeql-pack.lock.yml"])( + "does not resolve or install dependencies with %s", + async (lockFileName) => { + const lockFilePath = join(packPath, lockFileName); + const lockFileContents = `${lockFileName} contents`; + await outputFile(lockFilePath, lockFileContents); + + const { cleanup } = await createLockFileForStandardQuery( + mockCli, + queryPath, + ); + + expect({ + cleanup, + packResolveDependenciesCallCount: + packResolveDependencies.mock.calls.length, + clearCacheCallCount: clearCache.mock.calls.length, + packInstallCallCount: packInstall.mock.calls.length, + lockFileContents: await readFile(lockFilePath, "utf8"), + }).toEqual({ + cleanup: undefined, + packResolveDependenciesCallCount: 0, + clearCacheCallCount: 0, + packInstallCallCount: 0, + lockFileContents, + }); + }, + ); }); describe("when the lock file does not exist", () => { From 3818600a1d766b70410db7d228125fe4a628a9eb Mon Sep 17 00:00:00 2001 From: Pybsama <294532706+Pybsama@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:43:40 +0800 Subject: [PATCH 2/2] Document standard query lockfile fix --- extensions/ql-vscode/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/ql-vscode/CHANGELOG.md b/extensions/ql-vscode/CHANGELOG.md index 5bfed122e1d..4ad246d23cf 100644 --- a/extensions/ql-vscode/CHANGELOG.md +++ b/extensions/ql-vscode/CHANGELOG.md @@ -2,6 +2,8 @@ ## [UNRELEASED] +- Avoid reinstalling dependencies for standard queries when their query pack already has a lock file. [#4471](https://github.com/github/vscode-codeql/issues/4471) + ## 1.17.8 - 17 July 2026 - Fix a bug where installing or updating the CodeQL CLI could hang indefinitely while extracting the downloaded archive. Extraction now reports an error if a file cannot be written, and aborts with a clear message if no progress is made within the download timeout (for example due to slow or networked storage, or security software). [#4455](https://github.com/github/vscode-codeql/pull/4455)