From 50f63f3286611a4de01b01549dfe19a5b8507bd8 Mon Sep 17 00:00:00 2001 From: Nathan Randall Date: Fri, 17 Apr 2026 18:15:34 -0600 Subject: [PATCH 01/10] Avoid auto-upgrade of node "@types/vscode" --- .github/dependabot.yaml | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index b6105986..85027f27 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -20,6 +20,12 @@ updates: ## Ignore all updates for 'zod' as our 'zod' version must match the ## version of 'zod' used by the '@modelcontextprotocol/sdk' dependency. - dependency-name: 'zod' + ## Ignore all updates for '@types/vscode' as its version tracks VS Code + ## minor releases and any bump would expose APIs newer than the floor + ## declared by 'engines.vscode' in 'extensions/vscode/package.json'. + ## Bump this manually together with 'engines.vscode' when raising the + ## minimum supported VS Code version. + - dependency-name: '@types/vscode' versioning-strategy: 'increase' groups: all-npm-dependencies: diff --git a/package.json b/package.json index db4dc869..ce6bead3 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "tidy": "npm run lint:fix && npm run format && npm run lint:md", "tidy:check": "npm run lint && npm run format:check", "upgrade": "npm run upgrade:node", - "upgrade:node": "npx -y npm-check-updates --color --install always --peer --reject zod --root --upgrade --workspaces" + "upgrade:node": "npx -y npm-check-updates --color --install always --peer --reject zod,@types/vscode --root --upgrade --workspaces" }, "workspaces": [ "client", From e76f456cdc20ecff4ecb7e2ca1e7ab28ca57828e Mon Sep 17 00:00:00 2001 From: Nathan Randall Date: Fri, 17 Apr 2026 19:09:47 -0600 Subject: [PATCH 02/10] ci: supply chain hardening for .github/workflows/** - Add `--ignore-scripts` to all CI `npm ci`/`npm install` invocations and set `ignore-scripts=true` in `.npmrc` so install-time scripts from transitive dependencies cannot run during PR builds. - Pin `@types/vscode` in Dependabot config and in the root `upgrade:node` script's `--reject` list so it cannot be auto-upgraded past the `engines.vscode` floor. - Add a two-workflow handoff to rebuild `server/dist/**` for Dependabot PRs without granting write tokens to untrusted PR code: * `build-server.yml` (pull_request, read-only) uploads the built `server/dist` artifact and skips the drift check for Dependabot. * `dependabot-commit-dist.yml` (workflow_run, trusted, contents:write) downloads the artifact, verifies the head SHA, and commits the rebuilt files back to the PR branch as `dependabot[bot]`. - Remove unused `workflow_dispatch:` triggers from workflows that have no inputs (lint-and-format, client-integration-tests, query-unit-tests, query-unit-tests-swift, copilot-setup-steps); keep it on `release.yml` and `update-codeql.yml` (the latter has a meaningful `target_version` input). - Update the add-language skill's `SKILL.md` and `workflow-template.yml` to match: drop `workflow_dispatch:`, pin actions to SHAs, and use `npm ci --ignore-scripts`. --- .../add-mcp-support-for-new-language/SKILL.md | 7 +- .../workflow-template.yml | 1 - .../workflows/build-and-test-extension.yml | 3 +- .github/workflows/build-server.yml | 17 ++- .../workflows/client-integration-tests.yml | 5 +- .github/workflows/copilot-setup-steps.yml | 11 +- .github/workflows/dependabot-commit-dist.yml | 130 ++++++++++++++++++ .github/workflows/lint-and-format.yml | 3 +- .github/workflows/query-unit-tests-swift.yml | 3 +- .github/workflows/query-unit-tests.yml | 3 +- .github/workflows/release-npm.yml | 2 +- .github/workflows/release-tag.yml | 2 +- .github/workflows/release-vsix.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/update-codeql.yml | 2 +- .npmrc | 1 + 16 files changed, 163 insertions(+), 31 deletions(-) create mode 100644 .github/workflows/dependabot-commit-dist.yml diff --git a/.github/skills/add-mcp-support-for-new-language/SKILL.md b/.github/skills/add-mcp-support-for-new-language/SKILL.md index 9bcb3f4f..912e5653 100644 --- a/.github/skills/add-mcp-support-for-new-language/SKILL.md +++ b/.github/skills/add-mcp-support-for-new-language/SKILL.md @@ -273,7 +273,6 @@ on: branches: ['main'] paths: # Same as above - workflow_dispatch: permissions: contents: read @@ -284,12 +283,12 @@ jobs: runs-on: {os}-latest # e.g., macos-latest, windows-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: cache: 'npm' node-version-file: '.node-version' - - run: npm ci --workspaces + - run: npm ci --workspaces --ignore-scripts - uses: ./.github/actions/setup-codeql-environment with: install-language-runtimes: false diff --git a/.github/skills/add-mcp-support-for-new-language/workflow-template.yml b/.github/skills/add-mcp-support-for-new-language/workflow-template.yml index 53c31aee..1d2d83e9 100644 --- a/.github/skills/add-mcp-support-for-new-language/workflow-template.yml +++ b/.github/skills/add-mcp-support-for-new-language/workflow-template.yml @@ -28,7 +28,6 @@ on: - 'server/scripts/extract-test-databases.sh' - 'server/scripts/install-packs.sh' - 'server/scripts/run-query-unit-tests.sh' - workflow_dispatch: # Prevent duplicate runs from push + PR on the same branch concurrency: diff --git a/.github/workflows/build-and-test-extension.yml b/.github/workflows/build-and-test-extension.yml index 4b364d05..296ba8e1 100644 --- a/.github/workflows/build-and-test-extension.yml +++ b/.github/workflows/build-and-test-extension.yml @@ -19,7 +19,6 @@ on: - 'server/dist/**' - 'server/ql/*/tools/src/**' - 'server/src/**' - workflow_dispatch: permissions: contents: read @@ -40,7 +39,7 @@ jobs: node-version-file: '.node-version' - name: Install dependencies - run: npm ci --include=optional + run: npm ci --include=optional --ignore-scripts - name: Build server (dependency) run: npm run build -w server diff --git a/.github/workflows/build-server.yml b/.github/workflows/build-server.yml index 9d150255..c9ef2d14 100644 --- a/.github/workflows/build-server.yml +++ b/.github/workflows/build-server.yml @@ -13,7 +13,6 @@ on: - '.github/workflows/build-server.yml' - '.node-version' - 'server/**' - workflow_dispatch: permissions: contents: read @@ -38,7 +37,7 @@ jobs: node-version-file: '.node-version' - name: Build Server - Install dependencies - run: npm ci --include=optional + run: npm ci --include=optional --ignore-scripts working-directory: . - name: Build Server - Clean previous build @@ -50,7 +49,21 @@ jobs: - name: Build Server - Bundle application run: npm run bundle + ## Consumed by dependabot-commit-dist.yml via workflow_run. + - name: Build Server - Upload server/dist artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: server-dist + path: | + server/dist/codeql-development-mcp-server.js + server/dist/codeql-development-mcp-server.js.map + if-no-files-found: error + retention-days: 7 + + ## Skipped for Dependabot PRs: dependabot-commit-dist.yml will push the + ## rebuilt 'server/dist' back to the PR branch. - name: Build Server - Check for uncommitted changes + if: github.actor != 'dependabot[bot]' run: | if [ -n "$(git status --porcelain)" ]; then echo "❌ Uncommitted changes detected after build:" diff --git a/.github/workflows/client-integration-tests.yml b/.github/workflows/client-integration-tests.yml index cc3066de..362d8578 100644 --- a/.github/workflows/client-integration-tests.yml +++ b/.github/workflows/client-integration-tests.yml @@ -19,7 +19,6 @@ on: - '.node-version' - 'client/**' - 'server/**' - workflow_dispatch: permissions: contents: read @@ -61,7 +60,7 @@ jobs: run: choco install jq -y - name: MCP Integration Tests - Install node dependencies for client and server workspaces - run: npm ci --workspace=client && npm ci --workspace=server + run: npm ci --workspace=client --ignore-scripts && npm ci --workspace=server --ignore-scripts - name: MCP Integration Tests - Setup CodeQL environment uses: ./.github/actions/setup-codeql-environment @@ -168,7 +167,7 @@ jobs: node-version-file: '.node-version' - name: CODEQL_PATH Tests - Install server dependencies - run: npm ci --workspace=server + run: npm ci --workspace=server --ignore-scripts - name: CODEQL_PATH Tests - Build server bundle run: npm run bundle -w server diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 0285051a..c95a3cab 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -1,31 +1,26 @@ name: 'Copilot Setup Steps' on: - # Allow manual testing through the repository's "Actions" tab - workflow_dispatch: {} - # Automatically run the setup steps when an associated workflow is changed. push: paths: - '.codeql-version' + - '.github/actions/setup-codeql-environment/action.yml' - '.github/workflows/copilot-setup-steps.yml' - '.node-version' - - '.github/actions/setup-codeql-environment/action.yml' - '**/codeql-pack.yml' - '**/codeql-pack.lock.yml' - '**/package.json' - '**/package-lock.json' - - '**/qlpack.yml' pull_request: paths: - '.codeql-version' + - '.github/actions/setup-codeql-environment/action.yml' - '.github/workflows/copilot-setup-steps.yml' - '.node-version' - - '.github/actions/setup-codeql-environment/action.yml' - '**/codeql-pack.yml' - '**/codeql-pack.lock.yml' - '**/package.json' - '**/package-lock.json' - - '**/qlpack.yml' jobs: # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. @@ -51,7 +46,7 @@ jobs: node-version-file: '.node-version' - name: Copilot Setup - Install dependencies - run: npm ci --include=optional + run: npm ci --include=optional --ignore-scripts - name: Copilot Setup - Setup CodeQL environment uses: ./.github/actions/setup-codeql-environment diff --git a/.github/workflows/dependabot-commit-dist.yml b/.github/workflows/dependabot-commit-dist.yml new file mode 100644 index 00000000..b96e9d05 --- /dev/null +++ b/.github/workflows/dependabot-commit-dist.yml @@ -0,0 +1,130 @@ +name: Dependabot Commit Dist - CodeQL Development MCP Server + +## Auto-rebuild and commit 'server/dist/**' on Dependabot PRs. +## +## Two-workflow handoff: 'build-server.yml' rebuilds with no write token +## (npm ci --ignore-scripts), uploads the 'server-dist' artifact. This +## workflow runs in the trusted default-branch context, downloads the +## artifact, and pushes it to the PR branch. No PR-supplied code executes +## here. + +on: + workflow_run: + workflows: ['Build Server - CodeQL Development MCP Server'] + types: [completed] + +permissions: + contents: read + +jobs: + commit-dist: + name: Commit Rebuilt server/dist to Dependabot PR Branch + runs-on: ubuntu-latest + + if: >- + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.actor.login == 'dependabot[bot]' + + permissions: + contents: write + actions: read + + steps: + - name: Commit Dist - Validate workflow_run head + id: pr + env: + HEAD_REPO: ${{ github.event.workflow_run.head_repository.full_name }} + HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} + HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + REPO: ${{ github.repository }} + run: | + set -euo pipefail + if [ "${HEAD_REPO}" != "${REPO}" ]; then + echo "::error::Refusing to push: head repo '${HEAD_REPO}' != '${REPO}'" + exit 1 + fi + if [ -z "${HEAD_BRANCH}" ] || [ -z "${HEAD_SHA}" ]; then + echo "::error::Missing head_branch or head_sha" + exit 1 + fi + echo "branch=${HEAD_BRANCH}" >> "${GITHUB_OUTPUT}" + echo "sha=${HEAD_SHA}" >> "${GITHUB_OUTPUT}" + + - name: Commit Dist - Checkout PR branch + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + ref: ${{ steps.pr.outputs.branch }} + persist-credentials: true + fetch-depth: 1 + + ## Abort if the branch advanced since the build started; the next + ## build-server run will re-trigger this workflow. + - name: Commit Dist - Verify checkout matches build SHA + id: verify + env: + EXPECTED_SHA: ${{ steps.pr.outputs.sha }} + run: | + set -euo pipefail + ACTUAL_SHA="$(git rev-parse HEAD)" + if [ "${ACTUAL_SHA}" != "${EXPECTED_SHA}" ]; then + echo "::warning::Branch advanced from ${EXPECTED_SHA} to ${ACTUAL_SHA}; skipping." + echo "skip=true" >> "${GITHUB_OUTPUT}" + else + echo "skip=false" >> "${GITHUB_OUTPUT}" + fi + + - name: Commit Dist - Download server-dist artifact + if: steps.verify.outputs.skip == 'false' + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + with: + name: server-dist + path: artifact/ + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + ## Defence in depth: confirm the artifact contains exactly the two + ## expected bundle files before copying into the repo. + - name: Commit Dist - Verify artifact contents + if: steps.verify.outputs.skip == 'false' + run: | + set -euo pipefail + for f in codeql-development-mcp-server.js codeql-development-mcp-server.js.map; do + if [ ! -f "artifact/${f}" ]; then + echo "::error::Missing expected artifact file: ${f}" + exit 1 + fi + done + UNEXPECTED="$(find artifact -type f \ + ! -name 'codeql-development-mcp-server.js' \ + ! -name 'codeql-development-mcp-server.js.map' \ + -print)" + if [ -n "${UNEXPECTED}" ]; then + echo "::error::Unexpected files in artifact:" + echo "${UNEXPECTED}" + exit 1 + fi + + - name: Commit Dist - Commit and push (if changed) + if: steps.verify.outputs.skip == 'false' + env: + BRANCH: ${{ steps.pr.outputs.branch }} + run: | + set -euo pipefail + cp artifact/codeql-development-mcp-server.js server/dist/ + cp artifact/codeql-development-mcp-server.js.map server/dist/ + + git config user.name 'dependabot[bot]' + git config user.email '49699333+dependabot[bot]@users.noreply.github.com' + git add server/dist/codeql-development-mcp-server.js \ + server/dist/codeql-development-mcp-server.js.map + + if git diff --cached --quiet; then + echo "::notice::server/dist already up to date." + exit 0 + fi + + git commit -m "chore(deps): rebuild server/dist after dependency update + + [dependabot skip]" + git push origin "HEAD:${BRANCH}" diff --git a/.github/workflows/lint-and-format.yml b/.github/workflows/lint-and-format.yml index 589b9ccf..abbaeb93 100644 --- a/.github/workflows/lint-and-format.yml +++ b/.github/workflows/lint-and-format.yml @@ -5,7 +5,6 @@ on: branches: ['main', 'next'] push: branches: ['main', 'next'] - workflow_dispatch: permissions: contents: read @@ -26,7 +25,7 @@ jobs: node-version-file: '.node-version' - name: Lint and Format - Install node dependencies for all workspaces - run: npm ci + run: npm ci --ignore-scripts - name: Lint and Format - Run eslint run: npm run lint diff --git a/.github/workflows/query-unit-tests-swift.yml b/.github/workflows/query-unit-tests-swift.yml index 21399672..559a954f 100644 --- a/.github/workflows/query-unit-tests-swift.yml +++ b/.github/workflows/query-unit-tests-swift.yml @@ -21,7 +21,6 @@ on: - 'server/ql/swift/**' - 'server/scripts/install-packs.sh' - 'server/scripts/run-query-unit-tests.sh' - workflow_dispatch: permissions: contents: read @@ -42,7 +41,7 @@ jobs: node-version-file: '.node-version' - name: Query Unit Tests - swift - Install node dependencies for all workspaces - run: npm ci --workspaces + run: npm ci --workspaces --ignore-scripts - name: Query Unit Tests - swift - Setup CodeQL environment uses: ./.github/actions/setup-codeql-environment diff --git a/.github/workflows/query-unit-tests.yml b/.github/workflows/query-unit-tests.yml index 9bb12813..2f631968 100644 --- a/.github/workflows/query-unit-tests.yml +++ b/.github/workflows/query-unit-tests.yml @@ -29,7 +29,6 @@ on: - 'server/ql/**' - 'server/scripts/install-packs.sh' - 'server/scripts/run-query-unit-tests.sh' - workflow_dispatch: permissions: contents: read @@ -58,7 +57,7 @@ jobs: run: sudo apt-get install -y jq - name: Query Unit Tests - ${{ matrix.language }} - Install node dependencies for all workspaces - run: npm ci --workspaces + run: npm ci --workspaces --ignore-scripts - name: Query Unit Tests - ${{ matrix.language }} - Setup CodeQL environment uses: ./.github/actions/setup-codeql-environment diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index 9060d445..74265c0a 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -66,7 +66,7 @@ jobs: registry-url: 'https://registry.npmjs.org' - name: npm - Install dependencies - run: npm ci --include=optional + run: npm ci --include=optional --ignore-scripts - name: npm - Build server run: npm run build -w server diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index e0820a0b..8c2b2b02 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -112,7 +112,7 @@ jobs: - name: Tag - Install dependencies if: steps.check-tag.outputs.tag_exists != 'true' - run: npm install --include=optional + run: npm install --include=optional --ignore-scripts - name: Tag - Install CodeQL pack dependencies if: steps.check-tag.outputs.tag_exists != 'true' diff --git a/.github/workflows/release-vsix.yml b/.github/workflows/release-vsix.yml index 97a45429..decfa9dd 100644 --- a/.github/workflows/release-vsix.yml +++ b/.github/workflows/release-vsix.yml @@ -66,7 +66,7 @@ jobs: node-version-file: '.node-version' - name: VSIX - Install dependencies - run: npm ci --include=optional + run: npm ci --include=optional --ignore-scripts - name: VSIX - Validate version consistency run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a6fb9f5a..890bade6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -225,7 +225,7 @@ jobs: - name: Release - Install production dependencies working-directory: dist-package/server - run: npm install --omit=dev --include=optional + run: npm install --omit=dev --include=optional --ignore-scripts - name: Release - Create archive run: | diff --git a/.github/workflows/update-codeql.yml b/.github/workflows/update-codeql.yml index ced6fc48..feeb1929 100644 --- a/.github/workflows/update-codeql.yml +++ b/.github/workflows/update-codeql.yml @@ -145,7 +145,7 @@ jobs: ./server/scripts/update-release-version.sh "${LATEST}" - name: Update - Install dependencies - run: npm install --include=optional + run: npm install --include=optional --ignore-scripts - name: Update - Upgrade CodeQL pack dependencies run: server/scripts/upgrade-packs.sh diff --git a/.npmrc b/.npmrc index b6f27f13..32e60127 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ engine-strict=true +ignore-scripts=true From 80111a901c52249a8b0000b859e4f68a128defb3 Mon Sep 17 00:00:00 2001 From: Nathan Randall Date: Fri, 17 Apr 2026 19:32:02 -0600 Subject: [PATCH 03/10] Fix esbuild rebuild w/ "--ignore-scripts" --- extensions/vscode/package.json | 5 +++-- server/package.json | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/extensions/vscode/package.json b/extensions/vscode/package.json index 0ce2f188..78740675 100644 --- a/extensions/vscode/package.json +++ b/extensions/vscode/package.json @@ -162,7 +162,7 @@ ] }, "scripts": { - "build": "npm run clean && npm run lint && npm run bundle", + "build": "npm run clean && npm run lint && npm run rebuild:esbuild && npm run bundle", "bundle": "node esbuild.config.js", "bundle:server": "node scripts/bundle-server.js", "clean": "rm -rf dist server .vscode-test/* *.vsix", @@ -170,12 +170,13 @@ "lint": "eslint src/ test/", "lint:fix": "eslint src/ test/ --fix", "package": "vsce package --no-dependencies --out codeql-development-mcp-server-v$(node -e 'process.stdout.write(require(`./package.json`).version)').vsix", + "rebuild:esbuild": "npm rebuild esbuild --ignore-scripts=false", "test": "npm run test:coverage && npm run test:integration", "test:coverage": "vitest --run --coverage", "test:integration": "npm run download:vscode && vscode-test", "test:integration:label": "vscode-test --label", "test:watch": "vitest --watch", - "vscode:prepublish": "npm run clean && npm run lint && npm run bundle && npm run bundle:server", + "vscode:prepublish": "npm run clean && npm run lint && npm run rebuild:esbuild && npm run bundle && npm run bundle:server", "watch": "node esbuild.config.js --watch" }, "devDependencies": { diff --git a/server/package.json b/server/package.json index ac69726d..ae689d21 100644 --- a/server/package.json +++ b/server/package.json @@ -83,9 +83,10 @@ "vitest": "^4.1.4" }, "scripts": { - "build": "npm run clean && npm run lint && npm run bundle", + "build": "npm run clean && npm run lint && npm run rebuild:esbuild && npm run bundle", "build:all": "npm run build && npm run test:ql:fail-fast", "bundle": "node esbuild.config.js", + "rebuild:esbuild": "npm rebuild esbuild --ignore-scripts=false", "clean": "rm -rf dist .tmp", "dev:stdio": "npm run build && TRANSPORT_MODE=stdio node dist/codeql-development-mcp-server.js", "dev:http": "npm run build && TRANSPORT_MODE=http node dist/codeql-development-mcp-server.js", From 76543db13aaed82b4e078da086f3931279bc9b29 Mon Sep 17 00:00:00 2001 From: Nathan Randall Date: Fri, 17 Apr 2026 19:50:03 -0600 Subject: [PATCH 04/10] More fixes for failing CI workflows --- .github/workflows/build-and-test-extension.yml | 5 +++++ .github/workflows/build-server.yml | 5 +++++ .github/workflows/client-integration-tests.yml | 10 ++++++++++ .github/workflows/copilot-setup-steps.yml | 5 +++++ client/scripts/run-integration-tests.sh | 1 + 5 files changed, 26 insertions(+) diff --git a/.github/workflows/build-and-test-extension.yml b/.github/workflows/build-and-test-extension.yml index 296ba8e1..b52e9867 100644 --- a/.github/workflows/build-and-test-extension.yml +++ b/.github/workflows/build-and-test-extension.yml @@ -41,6 +41,11 @@ jobs: - name: Install dependencies run: npm ci --include=optional --ignore-scripts + ## esbuild's optional platform binary is normally wired up by its postinstall + ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. + - name: Rebuild esbuild platform binary + run: npm rebuild esbuild --ignore-scripts=false + - name: Build server (dependency) run: npm run build -w server diff --git a/.github/workflows/build-server.yml b/.github/workflows/build-server.yml index c9ef2d14..fa40405f 100644 --- a/.github/workflows/build-server.yml +++ b/.github/workflows/build-server.yml @@ -40,6 +40,11 @@ jobs: run: npm ci --include=optional --ignore-scripts working-directory: . + ## esbuild's optional platform binary is normally wired up by its postinstall + ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. + - name: Build Server - Rebuild esbuild platform binary + run: npm rebuild esbuild --ignore-scripts=false + - name: Build Server - Clean previous build run: npm run clean diff --git a/.github/workflows/client-integration-tests.yml b/.github/workflows/client-integration-tests.yml index 362d8578..ebd7c706 100644 --- a/.github/workflows/client-integration-tests.yml +++ b/.github/workflows/client-integration-tests.yml @@ -62,6 +62,11 @@ jobs: - name: MCP Integration Tests - Install node dependencies for client and server workspaces run: npm ci --workspace=client --ignore-scripts && npm ci --workspace=server --ignore-scripts + ## esbuild's optional platform binary is normally wired up by its postinstall + ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. + - name: MCP Integration Tests - Rebuild esbuild platform binary + run: npm rebuild esbuild --ignore-scripts=false + - name: MCP Integration Tests - Setup CodeQL environment uses: ./.github/actions/setup-codeql-environment with: @@ -169,6 +174,11 @@ jobs: - name: CODEQL_PATH Tests - Install server dependencies run: npm ci --workspace=server --ignore-scripts + ## esbuild's optional platform binary is normally wired up by its postinstall + ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. + - name: CODEQL_PATH Tests - Rebuild esbuild platform binary + run: npm rebuild esbuild --ignore-scripts=false + - name: CODEQL_PATH Tests - Build server bundle run: npm run bundle -w server diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index c95a3cab..2889731d 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -48,6 +48,11 @@ jobs: - name: Copilot Setup - Install dependencies run: npm ci --include=optional --ignore-scripts + ## esbuild's optional platform binary is normally wired up by its postinstall + ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. + - name: Copilot Setup - Rebuild esbuild platform binary + run: npm rebuild esbuild --ignore-scripts=false + - name: Copilot Setup - Setup CodeQL environment uses: ./.github/actions/setup-codeql-environment with: diff --git a/client/scripts/run-integration-tests.sh b/client/scripts/run-integration-tests.sh index 6ff77b2f..1d20d9d8 100755 --- a/client/scripts/run-integration-tests.sh +++ b/client/scripts/run-integration-tests.sh @@ -86,6 +86,7 @@ fi # Step 1: Build and bundle the server code echo "📦 Building CodeQL MCP server bundle..." cd "$SERVER_DIR" +npm run rebuild:esbuild npm run bundle # Step 2: Install CodeQL packs (only once for both modes, skip if --no-install-packs) From 563ed1d95bceacc45d0efdf1beaeaa7e20e239b8 Mon Sep 17 00:00:00 2001 From: Nathan Randall Date: Fri, 17 Apr 2026 19:53:14 -0600 Subject: [PATCH 05/10] Fix download path in dependabot-commit-dist.yml --- .github/workflows/dependabot-commit-dist.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dependabot-commit-dist.yml b/.github/workflows/dependabot-commit-dist.yml index b96e9d05..cba8b634 100644 --- a/.github/workflows/dependabot-commit-dist.yml +++ b/.github/workflows/dependabot-commit-dist.yml @@ -84,20 +84,23 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} ## Defence in depth: confirm the artifact contains exactly the two - ## expected bundle files before copying into the repo. + ## expected bundle files before copying into the repo. The upload + ## step in 'build-server.yml' preserves the 'server/dist/' prefix + ## relative to the workspace root, so files land under that path. - name: Commit Dist - Verify artifact contents if: steps.verify.outputs.skip == 'false' run: | set -euo pipefail - for f in codeql-development-mcp-server.js codeql-development-mcp-server.js.map; do + for f in server/dist/codeql-development-mcp-server.js \ + server/dist/codeql-development-mcp-server.js.map; do if [ ! -f "artifact/${f}" ]; then echo "::error::Missing expected artifact file: ${f}" exit 1 fi done UNEXPECTED="$(find artifact -type f \ - ! -name 'codeql-development-mcp-server.js' \ - ! -name 'codeql-development-mcp-server.js.map' \ + ! -path 'artifact/server/dist/codeql-development-mcp-server.js' \ + ! -path 'artifact/server/dist/codeql-development-mcp-server.js.map' \ -print)" if [ -n "${UNEXPECTED}" ]; then echo "::error::Unexpected files in artifact:" @@ -111,8 +114,8 @@ jobs: BRANCH: ${{ steps.pr.outputs.branch }} run: | set -euo pipefail - cp artifact/codeql-development-mcp-server.js server/dist/ - cp artifact/codeql-development-mcp-server.js.map server/dist/ + cp artifact/server/dist/codeql-development-mcp-server.js server/dist/ + cp artifact/server/dist/codeql-development-mcp-server.js.map server/dist/ git config user.name 'dependabot[bot]' git config user.email '49699333+dependabot[bot]@users.noreply.github.com' From 34d88c372c77f1e8a87723f841e3e50008783eb1 Mon Sep 17 00:00:00 2001 From: Nathan Randall Date: Sat, 18 Apr 2026 10:44:37 -0600 Subject: [PATCH 06/10] Address review feedback for PR #258 --- extensions/vscode/package.json | 8 ++++---- server/package.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/vscode/package.json b/extensions/vscode/package.json index 78740675..5fe4750d 100644 --- a/extensions/vscode/package.json +++ b/extensions/vscode/package.json @@ -162,8 +162,8 @@ ] }, "scripts": { - "build": "npm run clean && npm run lint && npm run rebuild:esbuild && npm run bundle", - "bundle": "node esbuild.config.js", + "build": "npm run clean && npm run lint && npm run bundle", + "bundle": "npm run rebuild:esbuild && node esbuild.config.js", "bundle:server": "node scripts/bundle-server.js", "clean": "rm -rf dist server .vscode-test/* *.vsix", "download:vscode": "node scripts/download-vscode.js", @@ -176,8 +176,8 @@ "test:integration": "npm run download:vscode && vscode-test", "test:integration:label": "vscode-test --label", "test:watch": "vitest --watch", - "vscode:prepublish": "npm run clean && npm run lint && npm run rebuild:esbuild && npm run bundle && npm run bundle:server", - "watch": "node esbuild.config.js --watch" + "vscode:prepublish": "npm run clean && npm run lint && npm run bundle && npm run bundle:server", + "watch": "npm run rebuild:esbuild && node esbuild.config.js --watch" }, "devDependencies": { "@eslint/js": "^10.0.1", diff --git a/server/package.json b/server/package.json index ae689d21..c83ce6b6 100644 --- a/server/package.json +++ b/server/package.json @@ -83,9 +83,9 @@ "vitest": "^4.1.4" }, "scripts": { - "build": "npm run clean && npm run lint && npm run rebuild:esbuild && npm run bundle", + "build": "npm run clean && npm run lint && npm run bundle", "build:all": "npm run build && npm run test:ql:fail-fast", - "bundle": "node esbuild.config.js", + "bundle": "npm run rebuild:esbuild && node esbuild.config.js", "rebuild:esbuild": "npm rebuild esbuild --ignore-scripts=false", "clean": "rm -rf dist .tmp", "dev:stdio": "npm run build && TRANSPORT_MODE=stdio node dist/codeql-development-mcp-server.js", From ca534c0283173042dc84f95a8eb0ec9b6b87d546 Mon Sep 17 00:00:00 2001 From: Nathan Randall Date: Sat, 18 Apr 2026 10:48:22 -0600 Subject: [PATCH 07/10] ci: drop dependabot-commit-dist workflow handoff Avoid Code Scanning alert for newly added workflow. To be revisited in future work. Removes the workflow_run-based handoff that rebuilt and pushed 'server/dist/**' back to Dependabot PR branches, along with the upload-artifact step and Dependabot-specific dirty-tree guard in 'build-server.yml' that fed it. - Delete '.github/workflows/dependabot-commit-dist.yml' - Remove 'server-dist' upload-artifact step from build-server.yml - Drop 'if: github.actor != dependabot[bot]' on the dirty-tree check so it now fails loudly for all PRs, including Dependabot --- .github/workflows/build-server.yml | 14 -- .github/workflows/dependabot-commit-dist.yml | 133 ------------------- 2 files changed, 147 deletions(-) delete mode 100644 .github/workflows/dependabot-commit-dist.yml diff --git a/.github/workflows/build-server.yml b/.github/workflows/build-server.yml index fa40405f..45e56580 100644 --- a/.github/workflows/build-server.yml +++ b/.github/workflows/build-server.yml @@ -54,21 +54,7 @@ jobs: - name: Build Server - Bundle application run: npm run bundle - ## Consumed by dependabot-commit-dist.yml via workflow_run. - - name: Build Server - Upload server/dist artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 - with: - name: server-dist - path: | - server/dist/codeql-development-mcp-server.js - server/dist/codeql-development-mcp-server.js.map - if-no-files-found: error - retention-days: 7 - - ## Skipped for Dependabot PRs: dependabot-commit-dist.yml will push the - ## rebuilt 'server/dist' back to the PR branch. - name: Build Server - Check for uncommitted changes - if: github.actor != 'dependabot[bot]' run: | if [ -n "$(git status --porcelain)" ]; then echo "❌ Uncommitted changes detected after build:" diff --git a/.github/workflows/dependabot-commit-dist.yml b/.github/workflows/dependabot-commit-dist.yml deleted file mode 100644 index cba8b634..00000000 --- a/.github/workflows/dependabot-commit-dist.yml +++ /dev/null @@ -1,133 +0,0 @@ -name: Dependabot Commit Dist - CodeQL Development MCP Server - -## Auto-rebuild and commit 'server/dist/**' on Dependabot PRs. -## -## Two-workflow handoff: 'build-server.yml' rebuilds with no write token -## (npm ci --ignore-scripts), uploads the 'server-dist' artifact. This -## workflow runs in the trusted default-branch context, downloads the -## artifact, and pushes it to the PR branch. No PR-supplied code executes -## here. - -on: - workflow_run: - workflows: ['Build Server - CodeQL Development MCP Server'] - types: [completed] - -permissions: - contents: read - -jobs: - commit-dist: - name: Commit Rebuilt server/dist to Dependabot PR Branch - runs-on: ubuntu-latest - - if: >- - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'success' && - github.event.workflow_run.actor.login == 'dependabot[bot]' - - permissions: - contents: write - actions: read - - steps: - - name: Commit Dist - Validate workflow_run head - id: pr - env: - HEAD_REPO: ${{ github.event.workflow_run.head_repository.full_name }} - HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} - HEAD_SHA: ${{ github.event.workflow_run.head_sha }} - REPO: ${{ github.repository }} - run: | - set -euo pipefail - if [ "${HEAD_REPO}" != "${REPO}" ]; then - echo "::error::Refusing to push: head repo '${HEAD_REPO}' != '${REPO}'" - exit 1 - fi - if [ -z "${HEAD_BRANCH}" ] || [ -z "${HEAD_SHA}" ]; then - echo "::error::Missing head_branch or head_sha" - exit 1 - fi - echo "branch=${HEAD_BRANCH}" >> "${GITHUB_OUTPUT}" - echo "sha=${HEAD_SHA}" >> "${GITHUB_OUTPUT}" - - - name: Commit Dist - Checkout PR branch - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - ref: ${{ steps.pr.outputs.branch }} - persist-credentials: true - fetch-depth: 1 - - ## Abort if the branch advanced since the build started; the next - ## build-server run will re-trigger this workflow. - - name: Commit Dist - Verify checkout matches build SHA - id: verify - env: - EXPECTED_SHA: ${{ steps.pr.outputs.sha }} - run: | - set -euo pipefail - ACTUAL_SHA="$(git rev-parse HEAD)" - if [ "${ACTUAL_SHA}" != "${EXPECTED_SHA}" ]; then - echo "::warning::Branch advanced from ${EXPECTED_SHA} to ${ACTUAL_SHA}; skipping." - echo "skip=true" >> "${GITHUB_OUTPUT}" - else - echo "skip=false" >> "${GITHUB_OUTPUT}" - fi - - - name: Commit Dist - Download server-dist artifact - if: steps.verify.outputs.skip == 'false' - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - with: - name: server-dist - path: artifact/ - run-id: ${{ github.event.workflow_run.id }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - ## Defence in depth: confirm the artifact contains exactly the two - ## expected bundle files before copying into the repo. The upload - ## step in 'build-server.yml' preserves the 'server/dist/' prefix - ## relative to the workspace root, so files land under that path. - - name: Commit Dist - Verify artifact contents - if: steps.verify.outputs.skip == 'false' - run: | - set -euo pipefail - for f in server/dist/codeql-development-mcp-server.js \ - server/dist/codeql-development-mcp-server.js.map; do - if [ ! -f "artifact/${f}" ]; then - echo "::error::Missing expected artifact file: ${f}" - exit 1 - fi - done - UNEXPECTED="$(find artifact -type f \ - ! -path 'artifact/server/dist/codeql-development-mcp-server.js' \ - ! -path 'artifact/server/dist/codeql-development-mcp-server.js.map' \ - -print)" - if [ -n "${UNEXPECTED}" ]; then - echo "::error::Unexpected files in artifact:" - echo "${UNEXPECTED}" - exit 1 - fi - - - name: Commit Dist - Commit and push (if changed) - if: steps.verify.outputs.skip == 'false' - env: - BRANCH: ${{ steps.pr.outputs.branch }} - run: | - set -euo pipefail - cp artifact/server/dist/codeql-development-mcp-server.js server/dist/ - cp artifact/server/dist/codeql-development-mcp-server.js.map server/dist/ - - git config user.name 'dependabot[bot]' - git config user.email '49699333+dependabot[bot]@users.noreply.github.com' - git add server/dist/codeql-development-mcp-server.js \ - server/dist/codeql-development-mcp-server.js.map - - if git diff --cached --quiet; then - echo "::notice::server/dist already up to date." - exit 0 - fi - - git commit -m "chore(deps): rebuild server/dist after dependency update - - [dependabot skip]" - git push origin "HEAD:${BRANCH}" From a30be1db61acd1cc3ae9ed521122eeda933348a2 Mon Sep 17 00:00:00 2001 From: Nathan Randall <70299490+data-douser@users.noreply.github.com> Date: Sat, 18 Apr 2026 11:05:32 -0600 Subject: [PATCH 08/10] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Nathan Randall <70299490+data-douser@users.noreply.github.com> --- .github/workflows/build-server.yml | 5 ----- .github/workflows/client-integration-tests.yml | 5 ----- .github/workflows/copilot-setup-steps.yml | 5 ----- client/scripts/run-integration-tests.sh | 1 - 4 files changed, 16 deletions(-) diff --git a/.github/workflows/build-server.yml b/.github/workflows/build-server.yml index 45e56580..acaf06a1 100644 --- a/.github/workflows/build-server.yml +++ b/.github/workflows/build-server.yml @@ -40,11 +40,6 @@ jobs: run: npm ci --include=optional --ignore-scripts working-directory: . - ## esbuild's optional platform binary is normally wired up by its postinstall - ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. - - name: Build Server - Rebuild esbuild platform binary - run: npm rebuild esbuild --ignore-scripts=false - - name: Build Server - Clean previous build run: npm run clean diff --git a/.github/workflows/client-integration-tests.yml b/.github/workflows/client-integration-tests.yml index ebd7c706..a73d23fd 100644 --- a/.github/workflows/client-integration-tests.yml +++ b/.github/workflows/client-integration-tests.yml @@ -62,11 +62,6 @@ jobs: - name: MCP Integration Tests - Install node dependencies for client and server workspaces run: npm ci --workspace=client --ignore-scripts && npm ci --workspace=server --ignore-scripts - ## esbuild's optional platform binary is normally wired up by its postinstall - ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. - - name: MCP Integration Tests - Rebuild esbuild platform binary - run: npm rebuild esbuild --ignore-scripts=false - - name: MCP Integration Tests - Setup CodeQL environment uses: ./.github/actions/setup-codeql-environment with: diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 2889731d..c95a3cab 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -48,11 +48,6 @@ jobs: - name: Copilot Setup - Install dependencies run: npm ci --include=optional --ignore-scripts - ## esbuild's optional platform binary is normally wired up by its postinstall - ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. - - name: Copilot Setup - Rebuild esbuild platform binary - run: npm rebuild esbuild --ignore-scripts=false - - name: Copilot Setup - Setup CodeQL environment uses: ./.github/actions/setup-codeql-environment with: diff --git a/client/scripts/run-integration-tests.sh b/client/scripts/run-integration-tests.sh index 1d20d9d8..6ff77b2f 100755 --- a/client/scripts/run-integration-tests.sh +++ b/client/scripts/run-integration-tests.sh @@ -86,7 +86,6 @@ fi # Step 1: Build and bundle the server code echo "📦 Building CodeQL MCP server bundle..." cd "$SERVER_DIR" -npm run rebuild:esbuild npm run bundle # Step 2: Install CodeQL packs (only once for both modes, skip if --no-install-packs) From 1cfaf0f502832168872573b14de00a3ab9da5c21 Mon Sep 17 00:00:00 2001 From: Nathan Randall <70299490+data-douser@users.noreply.github.com> Date: Sat, 18 Apr 2026 11:07:31 -0600 Subject: [PATCH 09/10] Update .github/workflows/build-and-test-extension.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Nathan Randall <70299490+data-douser@users.noreply.github.com> --- .github/workflows/build-and-test-extension.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build-and-test-extension.yml b/.github/workflows/build-and-test-extension.yml index b52e9867..296ba8e1 100644 --- a/.github/workflows/build-and-test-extension.yml +++ b/.github/workflows/build-and-test-extension.yml @@ -41,11 +41,6 @@ jobs: - name: Install dependencies run: npm ci --include=optional --ignore-scripts - ## esbuild's optional platform binary is normally wired up by its postinstall - ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. - - name: Rebuild esbuild platform binary - run: npm rebuild esbuild --ignore-scripts=false - - name: Build server (dependency) run: npm run build -w server From 48e979192949e1ad19722265cc063accf2912b7a Mon Sep 17 00:00:00 2001 From: Nathan Randall <70299490+data-douser@users.noreply.github.com> Date: Sat, 18 Apr 2026 11:15:35 -0600 Subject: [PATCH 10/10] Update .github/workflows/client-integration-tests.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Nathan Randall <70299490+data-douser@users.noreply.github.com> --- .github/workflows/client-integration-tests.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/client-integration-tests.yml b/.github/workflows/client-integration-tests.yml index a73d23fd..362d8578 100644 --- a/.github/workflows/client-integration-tests.yml +++ b/.github/workflows/client-integration-tests.yml @@ -169,11 +169,6 @@ jobs: - name: CODEQL_PATH Tests - Install server dependencies run: npm ci --workspace=server --ignore-scripts - ## esbuild's optional platform binary is normally wired up by its postinstall - ## script; .npmrc 'ignore-scripts=true' suppresses that, so rebuild here. - - name: CODEQL_PATH Tests - Rebuild esbuild platform binary - run: npm rebuild esbuild --ignore-scripts=false - - name: CODEQL_PATH Tests - Build server bundle run: npm run bundle -w server