From 1a2ef21b068a67b5a12363502ba9c8548eaa93f7 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 12:22:51 -0400 Subject: [PATCH 01/14] fix(workflows): add packages: read permission to update-codeql-version.yml Fixes a live failure hit during the first real end-to-end test of this workflow (dispatched with codeql_version: 2.21.4): the 'Upgrade every pack's dependencies' step failed resolving codeql/namebinding ('not found in the registry') while running codeql pack upgrade on ruby/src. The job's default GITHUB_TOKEN lacked packages: read, matching what ci.yml already grants for the same kind of pack resolution. Tracked in issue #162. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/update-codeql-version.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index a4c31693..08c87ff0 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -23,6 +23,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read # PR creation uses a scoped GitHub App token (SECLABS_APP_ID/SECLABS_APP_KEY), not GITHUB_TOKEN + packages: read # `codeql pack upgrade` resolves codeql/* library deps from GHCR (see ci.yml) steps: - name: Checkout From 3fa6f799afd1079d61e3ad792165b6eb90ead27c Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 12:51:30 -0400 Subject: [PATCH 02/14] debug: temporary step to inspect codeql resolve qlpacks output --- .github/workflows/update-codeql-version.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index 08c87ff0..c0501032 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -49,6 +49,15 @@ jobs: - name: Setup CodeQL uses: ./.github/actions/install-codeql + - name: DEBUG resolve qlpacks + run: | + set -x + codeql version + echo "--- codeql resolve qlpacks --format=json ---" + codeql resolve qlpacks --format=json || true + echo "--- find bundled qlpacks dir ---" + find "$(dirname "$(command -v codeql)")" -maxdepth 6 -iname "qlpack.yml" -path "*qlpacks*codeql*" 2>/dev/null | head -50 || true + - name: Upgrade every pack's dependencies env: GITHUB_TOKEN: ${{ github.token }} From ad7dac7221fb4696c284f280a1ba4c90a3bfe06e Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 12:54:45 -0400 Subject: [PATCH 03/14] debug: test gh-codeql bundle install + qlpacks disk layout --- .github/workflows/update-codeql-version.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index c0501032..c6ae493b 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -49,14 +49,18 @@ jobs: - name: Setup CodeQL uses: ./.github/actions/install-codeql - - name: DEBUG resolve qlpacks + - name: DEBUG gh-codeql bundle qlpacks + env: + GH_TOKEN: ${{ github.token }} run: | set -x - codeql version - echo "--- codeql resolve qlpacks --format=json ---" - codeql resolve qlpacks --format=json || true - echo "--- find bundled qlpacks dir ---" - find "$(dirname "$(command -v codeql)")" -maxdepth 6 -iname "qlpack.yml" -path "*qlpacks*codeql*" 2>/dev/null | head -50 || true + gh extension install github/gh-codeql + gh codeql set-version "${{ steps.version.outputs.version }}" + gh codeql version --format=terse + BUNDLE_CODEQL="$(gh codeql home 2>/dev/null || true)" + echo "gh codeql home: $BUNDLE_CODEQL" + find "$BUNDLE_CODEQL" -maxdepth 4 -iname "qlpacks" -type d 2>/dev/null || true + find "$BUNDLE_CODEQL" -maxdepth 6 -path "*qlpacks/codeql*" -iname "qlpack.yml" 2>/dev/null | sort | head -80 || true - name: Upgrade every pack's dependencies env: From 711dcf91ffd933ba8fe3049f4bb4f3a67443106b Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 12:56:50 -0400 Subject: [PATCH 04/14] debug: point directly at gh-codeql bundle unpack dir --- .github/workflows/update-codeql-version.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index c6ae493b..e8e5131e 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -57,10 +57,12 @@ jobs: gh extension install github/gh-codeql gh codeql set-version "${{ steps.version.outputs.version }}" gh codeql version --format=terse - BUNDLE_CODEQL="$(gh codeql home 2>/dev/null || true)" - echo "gh codeql home: $BUNDLE_CODEQL" - find "$BUNDLE_CODEQL" -maxdepth 4 -iname "qlpacks" -type d 2>/dev/null || true - find "$BUNDLE_CODEQL" -maxdepth 6 -path "*qlpacks/codeql*" -iname "qlpack.yml" 2>/dev/null | sort | head -80 || true + BUNDLE_DIR="$HOME/.local/share/gh/extensions/gh-codeql/dist/release/v${{ steps.version.outputs.version }}" + echo "bundle dir: $BUNDLE_DIR" + ls -la "$BUNDLE_DIR" || true + find "$BUNDLE_DIR" -maxdepth 2 -iname "qlpacks*" 2>/dev/null || true + find "$BUNDLE_DIR" -maxdepth 8 -path "*qlpacks/codeql/go-all*" -iname "qlpack.yml" 2>/dev/null || true + find "$BUNDLE_DIR" -maxdepth 8 -path "*qlpacks/codeql/*-all*" -iname "qlpack.yml" 2>/dev/null | sort || true - name: Upgrade every pack's dependencies env: From 216b117c975ad78cbc933cf90c1973b9c62d0590 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 12:58:32 -0400 Subject: [PATCH 05/14] debug: search go dir + resolve qlpacks with bundle codeql binary --- .github/workflows/update-codeql-version.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index e8e5131e..aee182c3 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -59,10 +59,11 @@ jobs: gh codeql version --format=terse BUNDLE_DIR="$HOME/.local/share/gh/extensions/gh-codeql/dist/release/v${{ steps.version.outputs.version }}" echo "bundle dir: $BUNDLE_DIR" - ls -la "$BUNDLE_DIR" || true - find "$BUNDLE_DIR" -maxdepth 2 -iname "qlpacks*" 2>/dev/null || true - find "$BUNDLE_DIR" -maxdepth 8 -path "*qlpacks/codeql/go-all*" -iname "qlpack.yml" 2>/dev/null || true - find "$BUNDLE_DIR" -maxdepth 8 -path "*qlpacks/codeql/*-all*" -iname "qlpack.yml" 2>/dev/null | sort || true + find "$BUNDLE_DIR" -maxdepth 3 -type d -iname "go*" 2>/dev/null || true + echo "--- all qlpack.yml under go dir ---" + find "$BUNDLE_DIR/go" -iname "qlpack.yml" 2>/dev/null | sort || true + echo "--- resolve qlpacks using bundle codeql binary ---" + "$BUNDLE_DIR/codeql" resolve qlpacks --format=json --search-path "$BUNDLE_DIR" 2>&1 | head -c 4000 || true - name: Upgrade every pack's dependencies env: From 426b42d218336928dff69c7b1c75bda2d58c4a18 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:00:10 -0400 Subject: [PATCH 06/14] debug: try codeql-action codeql-bundle release asset --- .github/workflows/update-codeql-version.yml | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index aee182c3..4372a552 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -49,21 +49,21 @@ jobs: - name: Setup CodeQL uses: ./.github/actions/install-codeql - - name: DEBUG gh-codeql bundle qlpacks + - name: DEBUG codeql-action bundle qlpacks env: GH_TOKEN: ${{ github.token }} run: | set -x - gh extension install github/gh-codeql - gh codeql set-version "${{ steps.version.outputs.version }}" - gh codeql version --format=terse - BUNDLE_DIR="$HOME/.local/share/gh/extensions/gh-codeql/dist/release/v${{ steps.version.outputs.version }}" - echo "bundle dir: $BUNDLE_DIR" - find "$BUNDLE_DIR" -maxdepth 3 -type d -iname "go*" 2>/dev/null || true - echo "--- all qlpack.yml under go dir ---" - find "$BUNDLE_DIR/go" -iname "qlpack.yml" 2>/dev/null | sort || true - echo "--- resolve qlpacks using bundle codeql binary ---" - "$BUNDLE_DIR/codeql" resolve qlpacks --format=json --search-path "$BUNDLE_DIR" 2>&1 | head -c 4000 || true + BUNDLE_TAG="codeql-bundle-v${{ steps.version.outputs.version }}" + mkdir -p /tmp/bundle + gh release download "$BUNDLE_TAG" --repo github/codeql-action --pattern "codeql-bundle-linux64.tar.gz" --dir /tmp/bundle + echo "--- listing top-level tar entries (first 40) ---" + tar tzf /tmp/bundle/codeql-bundle-linux64.tar.gz | head -40 + echo "--- extracting only qlpacks/codeql/go-all and qlpacks/codeql/java-all ---" + tar xzf /tmp/bundle/codeql-bundle-linux64.tar.gz -C /tmp/bundle --wildcards \ + 'codeql/qlpacks/codeql/go-all/*/qlpack.yml' \ + 'codeql/qlpacks/codeql/java-all/*/qlpack.yml' 2>&1 | head -20 || true + find /tmp/bundle -iname "qlpack.yml" | sort - name: Upgrade every pack's dependencies env: From ebfb97fde9c086c610804ecd2ab9b6d0162096ca Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:04:04 -0400 Subject: [PATCH 07/14] debug: list all qlpacks dir entries via tar tzf without extraction --- .github/workflows/update-codeql-version.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index 4372a552..1b3339f0 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -57,13 +57,8 @@ jobs: BUNDLE_TAG="codeql-bundle-v${{ steps.version.outputs.version }}" mkdir -p /tmp/bundle gh release download "$BUNDLE_TAG" --repo github/codeql-action --pattern "codeql-bundle-linux64.tar.gz" --dir /tmp/bundle - echo "--- listing top-level tar entries (first 40) ---" - tar tzf /tmp/bundle/codeql-bundle-linux64.tar.gz | head -40 - echo "--- extracting only qlpacks/codeql/go-all and qlpacks/codeql/java-all ---" - tar xzf /tmp/bundle/codeql-bundle-linux64.tar.gz -C /tmp/bundle --wildcards \ - 'codeql/qlpacks/codeql/go-all/*/qlpack.yml' \ - 'codeql/qlpacks/codeql/java-all/*/qlpack.yml' 2>&1 | head -20 || true - find /tmp/bundle -iname "qlpack.yml" | sort + echo "--- listing all codeql/qlpacks/codeql/// dir entries (no extraction) ---" + tar tzf /tmp/bundle/codeql-bundle-linux64.tar.gz | grep -E '^codeql/qlpacks/codeql/[^/]+/[^/]+/$' | sort -u - name: Upgrade every pack's dependencies env: From 3d531e595a596a4c59ab1304325b9f777b2cd367 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:12:49 -0400 Subject: [PATCH 08/14] fix(workflows): pin codeql/* library deps to the CLI-bundle version before upgrade codeql pack upgrade resolves unconstrained '*' dependencies to the latest-ever-published registry version, completely independent of the CLI version pinned in .codeqlversion. This caused e.g. codeql/go-all to jump to 7.2.0 (registry-latest) instead of 4.2.6 (the version actually shipped with/tested against CLI 2.21.4), and caused 'codeql/namebinding not found in the registry' fatal errors for other languages since registry-latest go-all depends on packages not present at the versions being resolved. Add .github/scripts/pin-codeql-library-versions.sh, which downloads the official CodeQL Bundle (github/codeql-action release codeql-bundle-v) for the target CLI version and rewrites every codeql/-all / codeql/-queries dependency across all qlpack.yml files from '*' to that exact bundled version, before codeql pack upgrade runs. Internal githubsecuritylab/* cross-pack dependencies are left untouched (they intentionally track our own latest published versions). --- .../scripts/pin-codeql-library-versions.sh | 97 +++++++++++++++++++ .github/workflows/update-codeql-version.yml | 16 +-- 2 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 .github/scripts/pin-codeql-library-versions.sh diff --git a/.github/scripts/pin-codeql-library-versions.sh b/.github/scripts/pin-codeql-library-versions.sh new file mode 100644 index 00000000..6bc8f5a1 --- /dev/null +++ b/.github/scripts/pin-codeql-library-versions.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# Pins every `codeql/: '*'` dependency in this repo's qlpack.yml files to +# the exact library version shipped in the official CodeQL Bundle for a given +# CLI release. +# +# Why this exists: `codeql pack upgrade` resolves an unconstrained `'*'` +# dependency to the *latest-ever-published* version in the configured +# registry (GHCR) - completely independent of whatever CodeQL CLI version is +# pinned in `.codeqlversion`. That mismatch can jump `codeql/-all` +# several major versions ahead of what the pinned CLI actually ships/tests +# against, which can silently break analyses (see CONTRIBUTING.md's +# "Updating the pinned CodeQL CLI/library version" section for a worked +# example). Pinning these `codeql/*` deps to the exact bundle-paired version +# before running `codeql pack upgrade` makes that resolution deterministic +# and keeps every pack's declared library dependency in lockstep with the +# CLI version this repo says it supports. +# +# Usage: pin-codeql-library-versions.sh +# e.g. pin-codeql-library-versions.sh 2.21.4 +# +# Requires: gh (authenticated), tar, sed, find. Run from the repo root. +set -euo pipefail + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +VERSION="$1" +BUNDLE_TAG="codeql-bundle-v${VERSION}" +WORKDIR="$(mktemp -d)" +trap 'rm -rf "$WORKDIR"' EXIT + +echo "Determining codeql/* library versions bundled with CodeQL CLI ${VERSION}..." +echo "(source of truth: github/codeql-action release '${BUNDLE_TAG}', asset codeql-bundle-linux64.tar.gz)" + +if ! gh release download "$BUNDLE_TAG" --repo github/codeql-action \ + --pattern "codeql-bundle-linux64.tar.gz" --dir "$WORKDIR" --clobber; then + echo "::error::Could not download the CodeQL Bundle for tag '${BUNDLE_TAG}' from github/codeql-action releases." >&2 + echo "Every CLI release published to github/codeql-cli-binaries should have a matching 'codeql-bundle-v' release in github/codeql-action - check that the tag exists." >&2 + exit 1 +fi + +# List every bundled `codeql/` qlpack and its exact version WITHOUT +# extracting any file contents - the bundle is large (~500MB) and we only +# need the directory listing (name + version are encoded in the path). +VERSIONS_FILE="$WORKDIR/versions.txt" +tar tzf "$WORKDIR/codeql-bundle-linux64.tar.gz" \ + | grep -E '^codeql/qlpacks/codeql/[^/]+/[^/]+/$' \ + | sed -E 's#^codeql/qlpacks/codeql/([^/]+)/([^/]+)/$#\1 \2#' \ + | sort -u > "$VERSIONS_FILE" + +echo "Discovered $(wc -l < "$VERSIONS_FILE") bundled codeql/* packages for CLI ${VERSION}." + +# Every real qlpack.yml in the repo, excluding gitignored local build +# artifacts (.codeql/ pack caches, the /codeql cloned-repo checkout dir). +mapfile -t QLPACK_FILES < <(find . -name qlpack.yml -not -path "*/.codeql/*" -not -path "./codeql/*") + +declare -A PINNED_COUNT=() +while read -r pkg ver; do + [[ -z "$pkg" ]] && continue + count=0 + for file in "${QLPACK_FILES[@]}"; do + # Only touch lines declaring an unconstrained `codeql/: '*'` (or + # unquoted / double-quoted `*`) dependency; any trailing comment is left + # untouched since the substitution only replaces the matched quote-star-quote. + if grep -qE "^[[:space:]]*codeql/${pkg}:[[:space:]]*[\"']?\\*[\"']?[[:space:]]*(#.*)?\$" "$file"; then + sed -i -E "s#^([[:space:]]*codeql/${pkg}:[[:space:]]*)([\"']?)\\*\\2#\\1\\2${ver}\\2#" "$file" + count=$((count + 1)) + fi + done + if [[ $count -gt 0 ]]; then + PINNED_COUNT["$pkg@$ver"]=$count + fi +done < "$VERSIONS_FILE" + +echo +echo "Pinned codeql/* dependencies:" +for key in "${!PINNED_COUNT[@]}"; do + echo " - ${key} (${PINNED_COUNT[$key]} file(s))" +done | sort + +# Surface any remaining unconstrained codeql/* dependency that this script +# did NOT pin (e.g. it isn't one of the standard per-language bundle +# packages) so it doesn't silently keep resolving to registry-latest. +echo +echo "codeql/* dependencies left unpinned (not found in the CodeQL Bundle):" +REMAINING=0 +for file in "${QLPACK_FILES[@]}"; do + if grep -qE "^[[:space:]]*codeql/[A-Za-z0-9_.-]+:[[:space:]]*[\"']?\*[\"']?[[:space:]]*(#.*)?\$" "$file"; then + grep -nE "^[[:space:]]*codeql/[A-Za-z0-9_.-]+:[[:space:]]*[\"']?\*[\"']?[[:space:]]*(#.*)?\$" "$file" | sed "s#^# ${file}:#" + REMAINING=1 + fi +done +if [[ "$REMAINING" -eq 0 ]]; then + echo " (none)" +fi diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index 1b3339f0..d4f3a529 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -49,16 +49,11 @@ jobs: - name: Setup CodeQL uses: ./.github/actions/install-codeql - - name: DEBUG codeql-action bundle qlpacks + - name: Pin codeql/* library dependencies to the CodeQL Bundle version env: GH_TOKEN: ${{ github.token }} run: | - set -x - BUNDLE_TAG="codeql-bundle-v${{ steps.version.outputs.version }}" - mkdir -p /tmp/bundle - gh release download "$BUNDLE_TAG" --repo github/codeql-action --pattern "codeql-bundle-linux64.tar.gz" --dir /tmp/bundle - echo "--- listing all codeql/qlpacks/codeql/// dir entries (no extraction) ---" - tar tzf /tmp/bundle/codeql-bundle-linux64.tar.gz | grep -E '^codeql/qlpacks/codeql/[^/]+/[^/]+/$' | sort -u + .github/scripts/pin-codeql-library-versions.sh "${{ steps.version.outputs.version }}" - name: Upgrade every pack's dependencies env: @@ -98,8 +93,13 @@ jobs: This PR: - Updates `.codeqlversion` to `${{ steps.version.outputs.version }}`. + - Pins every `codeql/-all` / `codeql/-queries` dependency across all + `qlpack.yml` files to the exact version shipped in the official CodeQL Bundle + for this CLI release (see `.github/scripts/pin-codeql-library-versions.sh`) - + this keeps `codeql pack upgrade` from jumping those libraries to + registry-latest instead of the version this CLI actually ships/tests against. - Runs `codeql pack upgrade ` for every pack directory to refresh its - `codeql-pack.lock.yml` against the new CLI. + `codeql-pack.lock.yml` against the new CLI and pinned library versions. **This PR does not publish anything by itself** - no pack `version:` field is bumped here, so `publish.yml`'s version-diff trigger won't fire for it yet. From 4ec3a990ed75ac2cfee422a6d6791888b345ad88 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:13:06 -0400 Subject: [PATCH 09/14] chore: mark pin-codeql-library-versions.sh executable --- .github/scripts/pin-codeql-library-versions.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .github/scripts/pin-codeql-library-versions.sh diff --git a/.github/scripts/pin-codeql-library-versions.sh b/.github/scripts/pin-codeql-library-versions.sh old mode 100644 new mode 100755 From 3835f0607b5a7abd4c4161a6794c32484dcca93b Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:15:52 -0400 Subject: [PATCH 10/14] fix(workflows): exclude ql/hotspots from the pack-upgrade loop ql/hotspots is a standalone local dev tool (see ql/hotspots/README.md and hotspots.yml), not one of the per-language src/lib/ext packs that ci.yml/publish.yml operate on. Its codeql/ql: '*' dependency isn't a real resolvable GHCR package, so it always fails codeql pack upgrade regardless of CLI version - a pre-existing, unrelated latent bug this workflow's blanket 'find . -name qlpack.yml' loop was hitting for the first time now that the codeql/*-all resolution bug is fixed and the loop can actually reach this directory. --- .github/workflows/update-codeql-version.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index d4f3a529..93aed99b 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -60,7 +60,12 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: | set -euo pipefail - for dir in $(find . -name qlpack.yml -exec dirname {} \;); do + # ql/hotspots is excluded: it's a standalone local dev tool (see + # ql/hotspots/README.md and .github/workflows/hotspots.yml), not one of + # the per-language src/lib/ext/ext-library-sources packs that ci.yml and + # publish.yml operate on. Its `codeql/ql: '*'` dependency isn't a real + # resolvable GHCR package, so it always fails `codeql pack upgrade`. + for dir in $(find . -name qlpack.yml -not -path "./ql/hotspots/*" -exec dirname {} \;); do echo "::group::codeql pack upgrade $dir" codeql pack upgrade "$dir" echo "::endgroup::" From ee26fcc0b0e0d9b9138ebd37e71522968dac7209 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:24:20 -0400 Subject: [PATCH 11/14] fix(workflows): gitignore the downloaded codeql_home CLI install dir The install-codeql composite action downloads/extracts the CodeQL CLI into github.workspace/codeql_home, i.e. inside the repository checkout, but this directory was never gitignored. update-codeql-version.yml is the first workflow to both install CodeQL AND commit/push changes (via peter-evans/create-pull-request), and its push was rejected by GitHub's 100MB file size limit because codeql_home/codeql-linux64.zip (~474MB) and several 50+MB extractor binaries got staged as untracked files alongside the real qlpack.yml/lock-file changes. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 9b5eeee6..3048acd2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ */*.class # Cloned repository of codeql /codeql +# Downloaded/extracted CodeQL CLI (see .github/actions/install-codeql), cached +# by actions/cache between CI runs - never meant to be committed. +/codeql_home # Test files / folders test.ql From 4e14bb4e5aa3f22ef26b173fc6b0e35cd02fb309 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:31:55 -0400 Subject: [PATCH 12/14] docs(contributing): document exact-pinning of codeql/* dependencies Explains why codeql/-all / codeql/-queries dependencies in qlpack.yml are now pinned to an exact version (matching the official CodeQL Bundle for the target CLI release) instead of left as an unconstrained '*' range: codeql pack upgrade resolves '*' to the latest-ever-published registry version, independent of .codeqlversion, which previously let a routine CLI bump silently jump a library several major versions ahead of anything that CLI actually ships/tests against. Also documents: - How the pin values are derived (github/codeql-action bundle release listing via tar tzf, not gh-codeql or a web scrape) and why those two alternatives were rejected. - The new pin-codeql-library-versions.sh step in the update-codeql-version.yml process (as step 2.1, before codeql pack upgrade). - Why ql/hotspots is excluded from the pack-upgrade loop (standalone dev tool, not a real per-language pack, codeql/ql is not a real registry/bundle package). - That this is a go-forward convention: existing qlpack.yml files stay unpinned until their next CLI-bump run, not retroactively true today. --- CONTRIBUTING.md | 83 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2640df08..0eaa7c11 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,18 +66,56 @@ Every query pack in this repository is compiled and tested against a specific ve The pinning is codified per language across: - [`.codeqlversion`][codeqlversion] (repo root): the CodeQL **CLI** version CI installs and compiles/tests against. -- `/src/codeql-pack.lock.yml` **and** `/lib/codeql-pack.lock.yml`: the exact resolved - (locked) version of `codeql/-all` (and, for `src`, `codeql/-queries` where used), - generated by `codeql pack install`/`codeql pack upgrade` against the CLI above. The `qlpack.yml` files - themselves only declare an unpinned `'*'` range, so the lock files, not the `qlpack.yml`, are the real - source of truth. **`src` and `lib` each have their own independently-resolved lock file** - nothing - keeps them in sync automatically, so it's possible (if `codeql pack upgrade` is run against one - directory but not the other) for them to drift apart. Always upgrade both when bumping +- `/{src,lib}/qlpack.yml`: **every `codeql/-all` / `codeql/-queries` + dependency is pinned to an exact version** (e.g. `codeql/go-all: '4.2.6'`), not left as an + unconstrained `'*'` range. This is deliberate, not incidental — see the warning box below for why. + Internal `githubsecuritylab/*` cross-pack dependencies (e.g. `/lib` depending on + `/ext`) are unaffected and still use whatever range/pin a maintainer set by hand. +- `/src/codeql-pack.lock.yml` **and** `/lib/codeql-pack.lock.yml`: the exact + resolved (locked) version tree generated by `codeql pack install`/`codeql pack upgrade` against the + CLI and the pinned `qlpack.yml` dependency above. **`src` and `lib` each have their own + independently-resolved lock file** - nothing keeps them in sync automatically, so it's possible (if + `codeql pack upgrade` is run against one directory but not the other, or one `qlpack.yml` pin is + hand-edited without the other) for them to drift apart. Always upgrade both when bumping `.codeqlversion` (the [automated workflow](#updating-the-pinned-codeql-clilibrary-version) does this for every pack directory in one pass); the table below only shows `src` for brevity, but the auto-generated table in every publish summary (see [Cutting a release](#cutting-a-release)) checks both and will flag drift between them. +> [!WARNING] +> **Why `codeql/*` dependencies are pinned to an exact version instead of left as `'*'`:** they used +> to be unconstrained (`codeql/go-all: '*'`, etc.). The problem: `codeql pack upgrade` resolves an +> unconstrained `'*'` dependency to the **latest-ever-published** version in the configured registry +> (GHCR) - completely independent of whatever CodeQL CLI version is pinned in `.codeqlversion`. In +> practice this let a routine `.codeqlversion` bump silently jump `codeql/go-all` from the version +> actually bundled/tested with the target CLI (e.g. `4.2.6`, bundled with CLI `v2.21.4`) to whatever +> was newest in the registry at that moment (e.g. `7.2.0`) - a library several major versions ahead of +> anything that CLI version ships or has ever been tested against, which can silently break analyses +> or fail outright with errors like `'codeql/namebinding' not found in the registry`. +> +> The fix: [`.github/scripts/pin-codeql-library-versions.sh`][pin-codeql-library-versions-script] runs +> before `codeql pack upgrade` (as part of +> [`update-codeql-version.yml`](#updating-the-pinned-codeql-clilibrary-version)) and rewrites every +> `codeql/: '*'` dependency to the *exact* version shipped in the **official CodeQL Bundle** for +> the target CLI release - i.e. the same library versions GitHub itself builds, tests, and ships +> together with that CLI. It determines these by downloading the bundle release asset +> (`codeql-bundle-linux64.tar.gz`, tag `codeql-bundle-v`) from +> [github/codeql-action releases](https://github.com/github/codeql-action/releases) and listing its +> `codeql/qlpacks/codeql///` directory entries (via `tar tzf`, no extraction needed) - +> this is the CLI-native source of truth, not a web scrape of any documentation page. (Two other +> approaches were considered and rejected: the [`gh-codeql`](https://github.com/github/gh-codeql) +> extension's `gh codeql set-version` only installs the bare CLI without any bundled library packs, so +> it can't answer this question; and `codeql resolve packs`/`codeql pack upgrade` themselves are what's +> *being* fixed, so they can't be used to validate their own input.) Any `codeql/*` dependency the +> script can't find in the bundle (there's exactly one, see the note on [`ql/hotspots`](#ql-hotspots) +> below) is left untouched and surfaced as a warning rather than silently skipped. +> +> Every `qlpack.yml` becomes pinned this way starting with the next CLI bump run through +> [`update-codeql-version.yml`](#updating-the-pinned-codeql-clilibrary-version) - if you're reading +> this shortly after this pinning behavior was introduced and a pack's `qlpack.yml` still shows +> `codeql/: '*'`, that just means its dependencies haven't been re-resolved since, not that the +> convention doesn't apply to it. + CodeQL CLI: `v2.21.1` (released 2025-04-16) ([Bundle](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.21.1) / [Binary](https://github.com/github/codeql-cli-binaries/releases/tag/v2.21.1)) | Language | Query pack | Standard library (`*-all`) | Upstream query pack (`*-queries`) | Lock file | @@ -159,13 +197,21 @@ coding agent) in the loop for the hard part — fixing whatever the new CLI brea when to actually take the upgrade (and deal with any breakage) is a deliberate call, not something to run unattended. 2. **Dependency refresh** — run [`update-codeql-version.yml`][update-codeql-version-workflow] - (`workflow_dispatch`, input the new CLI version, e.g. `2.22.0`). It updates `.codeqlversion`, - runs `codeql pack upgrade ` for every pack directory to refresh each - `codeql-pack.lock.yml`, and opens a PR (via the same GitHub App token as + (`workflow_dispatch`, input the new CLI version, e.g. `2.22.0`). It updates `.codeqlversion`, then: + 1. Pins every `codeql/: '*'` dependency across every `qlpack.yml` to the exact version shipped + in the official CodeQL Bundle for that CLI release (see the warning box under + [Supported CodeQL versions](#supported-codeql-versions) above for why this step exists), via + [`pin-codeql-library-versions.sh`][pin-codeql-library-versions-script]. + 2. Runs `codeql pack upgrade ` for every pack directory (except + [`ql/hotspots`](#ql-hotspots), see below) to refresh each `codeql-pack.lock.yml` against the + newly-pinned dependencies. + + It then opens a PR (via the same GitHub App token as [`update-release.yml`][update-release-workflow], so CI actually runs on it — a plain - `GITHUB_TOKEN`-authored PR would not trigger downstream workflows). This is the automated - version of [#118][pr-118]'s original proposal, extended to also own the `.codeqlversion` bump - itself (not just the `codeql pack upgrade` loop) and to use a token that triggers CI. + `GITHUB_TOKEN`-authored PR would not trigger downstream workflows). This is the automated version + of [#118][pr-118]'s original proposal, extended to also own the `.codeqlversion` bump and the + exact-version pinning (not just a bare `codeql pack upgrade` loop) and to use a token that triggers + CI. 3. **Fix breakage and finish the checklist** — this PR does **not** publish anything by itself (no pack `version:` field is touched), so there's no rush, but it still needs: - [ ] Fix any compilation/test errors CI surfaces from upstream API changes (usually the @@ -177,6 +223,16 @@ coding agent) in the loop for the hard part — fixing whatever the new CLI brea [Cutting a release](#cutting-a-release) below to bump every pack's `version:` in lockstep and trigger the real batch publish. +> [!NOTE] +> **Why `ql/hotspots` is excluded from the `codeql pack upgrade` loop:** +> `ql/hotspots` is a standalone local dev tool (a QL-4-QL hotspot query generator, see +> `ql/hotspots/README.md` and `.github/workflows/hotspots.yml`) that patches a freshly-cloned +> `github/codeql` checkout — it's not one of the per-language `src`/`lib`/`ext`/`ext-library-sources` +> packs `ci.yml`/`publish.yml` operate on. Its `qlpack.yml` declares `codeql/ql: '*'`, but +> `codeql/ql` isn't a real package published to the registry or shipped in the CodeQL Bundle, so +> `codeql pack upgrade`/the pinning script can never resolve it. This is a pre-existing, unrelated +> quirk of that tool, not something the version-bump automation needs to (or can) fix. + > [!WARNING] > The `.codeqlversion` bump and the pack version bumps don't have to land in the same PR, but > splitting them is risky: [#124][pr-124] refreshed `.codeqlversion` and every language's @@ -282,6 +338,7 @@ Please do get in touch (privacy@github.com) if you have any questions about this [update-release-workflow]: ./.github/workflows/update-release.yml [update-codeql-version-workflow]: ./.github/workflows/update-codeql-version.yml [detect-codeql-release-workflow]: ./.github/workflows/detect-codeql-release.yml +[pin-codeql-library-versions-script]: ./.github/scripts/pin-codeql-library-versions.sh [codeql-cli-binaries]: https://github.com/github/codeql-cli-binaries/releases [release-config]: ./.release.yml [patch-release-me]: https://github.com/42ByteLabs/patch-release-me From 315fd0b072cc16e9ea089ea49f8df7729fa24094 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:53:16 -0400 Subject: [PATCH 13/14] fix(workflows): exclude codeql_home from qlpack.yml discovery loops Copilot review caught this on PR #163: .github/actions/install-codeql downloads/extracts the CodeQL CLI into ./codeql_home (inside the repo checkout), and the bare CLI ships its own small vendored qlpack.yml packs (codeql//downgrades, codeql/legacy-upgrades) that have nothing to do with this repo's packs. Confirmed via the live test run (29110858206) log: both the pin script and the upgrade loop's `find . -name qlpack.yml` picked up and ran `codeql pack upgrade` against 10 of these vendored packs under ./codeql_home/codeql/*/downgrades and ./codeql_home/codeql/legacy-upgrades, in addition to this repo's real 47 pack directories. It happened to succeed silently this time and was invisible in the resulting PR diff only because codeql_home is now gitignored (fixed in ee26fcc) - but it was still real wasted work, and a future CLI version's vendored pack could just as easily hit the same "not found in the registry" failure mode as ql/hotspots did, for the same underlying reason (a `codeql/*: */ dependency that isn't a real resolvable package). --- .github/scripts/pin-codeql-library-versions.sh | 7 +++++-- .github/workflows/update-codeql-version.yml | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/scripts/pin-codeql-library-versions.sh b/.github/scripts/pin-codeql-library-versions.sh index 6bc8f5a1..138953d2 100755 --- a/.github/scripts/pin-codeql-library-versions.sh +++ b/.github/scripts/pin-codeql-library-versions.sh @@ -53,8 +53,11 @@ tar tzf "$WORKDIR/codeql-bundle-linux64.tar.gz" \ echo "Discovered $(wc -l < "$VERSIONS_FILE") bundled codeql/* packages for CLI ${VERSION}." # Every real qlpack.yml in the repo, excluding gitignored local build -# artifacts (.codeql/ pack caches, the /codeql cloned-repo checkout dir). -mapfile -t QLPACK_FILES < <(find . -name qlpack.yml -not -path "*/.codeql/*" -not -path "./codeql/*") +# artifacts (.codeql/ pack caches, the /codeql cloned-repo checkout dir, and +# /codeql_home, where .github/actions/install-codeql downloads/extracts the +# CodeQL CLI - which ships its own small vendored qlpack.yml packs, e.g. +# codeql//downgrades, that have nothing to do with this repo). +mapfile -t QLPACK_FILES < <(find . -name qlpack.yml -not -path "*/.codeql/*" -not -path "./codeql/*" -not -path "./codeql_home/*") declare -A PINNED_COUNT=() while read -r pkg ver; do diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index 93aed99b..5ad1ead0 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -60,12 +60,18 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: | set -euo pipefail - # ql/hotspots is excluded: it's a standalone local dev tool (see - # ql/hotspots/README.md and .github/workflows/hotspots.yml), not one of - # the per-language src/lib/ext/ext-library-sources packs that ci.yml and - # publish.yml operate on. Its `codeql/ql: '*'` dependency isn't a real - # resolvable GHCR package, so it always fails `codeql pack upgrade`. - for dir in $(find . -name qlpack.yml -not -path "./ql/hotspots/*" -exec dirname {} \;); do + # Exclusions: + # - ./ql/hotspots is a standalone local dev tool (see + # ql/hotspots/README.md and .github/workflows/hotspots.yml), not + # one of the per-language src/lib/ext/ext-library-sources packs + # that ci.yml and publish.yml operate on. Its `codeql/ql: '*'` + # dependency isn't a real resolvable GHCR package, so it always + # fails `codeql pack upgrade`. + # - ./codeql_home is where .github/actions/install-codeql + # downloads/extracts the CodeQL CLI; it ships its own small + # vendored qlpack.yml packs (e.g. codeql//downgrades) that + # have nothing to do with this repo and shouldn't be touched. + for dir in $(find . -name qlpack.yml -not -path "./ql/hotspots/*" -not -path "./codeql_home/*" -exec dirname {} \;); do echo "::group::codeql pack upgrade $dir" codeql pack upgrade "$dir" echo "::endgroup::" From 970be4dc21492852b97761d4177ebd00073b589f Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:07:11 -0400 Subject: [PATCH 14/14] fix(pin-script): make library-version pinning idempotent across CLI bumps The pin script previously only matched dependency lines with a literal '*' value. Once a qlpack.yml dependency got pinned to an exact version by one run, that regex would never match again on subsequent runs - meaning every CLI bump after the first would silently fail to re-pin codeql/* dependencies to the new bundle version, permanently desyncing .codeqlversion from the actual pins. Rewrite the match/rewrite logic to match ANY current value for a recognized codeql/ dependency (unquoted/quoted '*', or an already- pinned exact version) and unconditionally overwrite it to the target bundle version, preserving quote style and trailing comments. Verified locally against a mock qlpack.yml simulating a post-first-run state: an existing pinned version and a double-quoted pinned version were both correctly overwritten to new target versions, while unrelated/unknown dependencies were left untouched. Also add the ./codeql/* and */.codeql/* path exclusions to update-codeql-version.yml's upgrade loop for parity with the pin script's existing exclusions (defense in depth, per review feedback). Update CONTRIBUTING.md's two spots describing the pinning step to reflect this unconditional-overwrite/idempotent behavior instead of "only rewrites literal *". Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../scripts/pin-codeql-library-versions.sh | 34 ++++++++++++++----- .github/workflows/update-codeql-version.yml | 8 +++-- CONTRIBUTING.md | 23 ++++++++----- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/.github/scripts/pin-codeql-library-versions.sh b/.github/scripts/pin-codeql-library-versions.sh index 138953d2..8c36d7b8 100755 --- a/.github/scripts/pin-codeql-library-versions.sh +++ b/.github/scripts/pin-codeql-library-versions.sh @@ -1,7 +1,9 @@ #!/usr/bin/env bash -# Pins every `codeql/: '*'` dependency in this repo's qlpack.yml files to -# the exact library version shipped in the official CodeQL Bundle for a given -# CLI release. +# Pins every `codeql/` dependency in this repo's qlpack.yml files to the +# exact library version shipped in the official CodeQL Bundle for a given CLI +# release - overwriting whatever value is currently there (an unconstrained +# `'*'`, or an exact version pinned by a previous run of this script against +# an older CLI). # # Why this exists: `codeql pack upgrade` resolves an unconstrained `'*'` # dependency to the *latest-ever-published* version in the configured @@ -15,6 +17,15 @@ # and keeps every pack's declared library dependency in lockstep with the # CLI version this repo says it supports. # +# This script is idempotent and must be re-run (with a new target version) +# on every subsequent CLI bump: once a dependency is pinned to an exact +# version, it no longer matches an "unconstrained" pattern, so this script +# unconditionally overwrites any `codeql/: ` line for every +# package it finds in the target bundle, regardless of what value (if any) +# is already there - otherwise the pin would only ever get set once, and +# every later `.codeqlversion` bump would silently keep resolving against +# the stale version from the first run. +# # Usage: pin-codeql-library-versions.sh # e.g. pin-codeql-library-versions.sh 2.21.4 # @@ -64,11 +75,12 @@ while read -r pkg ver; do [[ -z "$pkg" ]] && continue count=0 for file in "${QLPACK_FILES[@]}"; do - # Only touch lines declaring an unconstrained `codeql/: '*'` (or - # unquoted / double-quoted `*`) dependency; any trailing comment is left - # untouched since the substitution only replaces the matched quote-star-quote. - if grep -qE "^[[:space:]]*codeql/${pkg}:[[:space:]]*[\"']?\\*[\"']?[[:space:]]*(#.*)?\$" "$file"; then - sed -i -E "s#^([[:space:]]*codeql/${pkg}:[[:space:]]*)([\"']?)\\*\\2#\\1\\2${ver}\\2#" "$file" + # Match a `codeql/: ` dependency line regardless of its + # current value - unquoted or quoted `*`, or an already-pinned exact + # version from a previous run - and overwrite it to the target bundle + # version, preserving quote style and any trailing comment. + if grep -qE "^[[:space:]]*codeql/${pkg}:[[:space:]]*[\"']?[^\"'#[:space:]]+[\"']?[[:space:]]*(#.*)?\$" "$file"; then + sed -i -E "s#^([[:space:]]*codeql/${pkg}:[[:space:]]*)([\"']?)[^\"'#[:space:]]+\\2#\\1\\2${ver}\\2#" "$file" count=$((count + 1)) fi done @@ -85,7 +97,11 @@ done | sort # Surface any remaining unconstrained codeql/* dependency that this script # did NOT pin (e.g. it isn't one of the standard per-language bundle -# packages) so it doesn't silently keep resolving to registry-latest. +# packages, like ql/hotspots' `codeql/ql`) so it doesn't silently keep +# resolving to registry-latest. Since every package the loop above finds in +# the bundle gets its value unconditionally overwritten (see the loop +# comment), anything still showing a literal `'*'` here was never found in +# any bundle this script has been run against. echo echo "codeql/* dependencies left unpinned (not found in the CodeQL Bundle):" REMAINING=0 diff --git a/.github/workflows/update-codeql-version.yml b/.github/workflows/update-codeql-version.yml index 5ad1ead0..819c9418 100644 --- a/.github/workflows/update-codeql-version.yml +++ b/.github/workflows/update-codeql-version.yml @@ -60,7 +60,8 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: | set -euo pipefail - # Exclusions: + # Exclusions (kept in sync with the same exclusions in + # .github/scripts/pin-codeql-library-versions.sh): # - ./ql/hotspots is a standalone local dev tool (see # ql/hotspots/README.md and .github/workflows/hotspots.yml), not # one of the per-language src/lib/ext/ext-library-sources packs @@ -71,7 +72,10 @@ jobs: # downloads/extracts the CodeQL CLI; it ships its own small # vendored qlpack.yml packs (e.g. codeql//downgrades) that # have nothing to do with this repo and shouldn't be touched. - for dir in $(find . -name qlpack.yml -not -path "./ql/hotspots/*" -not -path "./codeql_home/*" -exec dirname {} \;); do + # - ./codeql and */.codeql are a locally-cloned github/codeql + # checkout (used by ql/hotspots) and CodeQL's own per-pack build + # caches, respectively - neither is a repo pack either. + for dir in $(find . -name qlpack.yml -not -path "./ql/hotspots/*" -not -path "./codeql_home/*" -not -path "./codeql/*" -not -path "*/.codeql/*" -exec dirname {} \;); do echo "::group::codeql pack upgrade $dir" codeql pack upgrade "$dir" echo "::endgroup::" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0eaa7c11..1f5b7472 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -95,10 +95,13 @@ The pinning is codified per language across: > > The fix: [`.github/scripts/pin-codeql-library-versions.sh`][pin-codeql-library-versions-script] runs > before `codeql pack upgrade` (as part of -> [`update-codeql-version.yml`](#updating-the-pinned-codeql-clilibrary-version)) and rewrites every -> `codeql/: '*'` dependency to the *exact* version shipped in the **official CodeQL Bundle** for -> the target CLI release - i.e. the same library versions GitHub itself builds, tests, and ships -> together with that CLI. It determines these by downloading the bundle release asset +> [`update-codeql-version.yml`](#updating-the-pinned-codeql-clilibrary-version)) and unconditionally +> overwrites every `codeql/` dependency it recognizes - whether currently `'*'` or an exact +> version pinned by a previous run against an older CLI - to the *exact* version shipped in the +> **official CodeQL Bundle** for the target CLI release - i.e. the same library versions GitHub +> itself builds, tests, and ships together with that CLI. It's re-run (with a new target version) +> on every subsequent CLI bump, so pins are always re-enforced against the bundle, not just set once. +> It determines these versions by downloading the bundle release asset > (`codeql-bundle-linux64.tar.gz`, tag `codeql-bundle-v`) from > [github/codeql-action releases](https://github.com/github/codeql-action/releases) and listing its > `codeql/qlpacks/codeql///` directory entries (via `tar tzf`, no extraction needed) - @@ -198,10 +201,14 @@ coding agent) in the loop for the hard part — fixing whatever the new CLI brea something to run unattended. 2. **Dependency refresh** — run [`update-codeql-version.yml`][update-codeql-version-workflow] (`workflow_dispatch`, input the new CLI version, e.g. `2.22.0`). It updates `.codeqlversion`, then: - 1. Pins every `codeql/: '*'` dependency across every `qlpack.yml` to the exact version shipped - in the official CodeQL Bundle for that CLI release (see the warning box under - [Supported CodeQL versions](#supported-codeql-versions) above for why this step exists), via - [`pin-codeql-library-versions.sh`][pin-codeql-library-versions-script]. + 1. Unconditionally re-pins every `codeql/` dependency it recognizes across every + `qlpack.yml` to the exact version shipped in the official CodeQL Bundle for that CLI release + (see the warning box under [Supported CodeQL versions](#supported-codeql-versions) above for + why this step exists), via + [`pin-codeql-library-versions.sh`][pin-codeql-library-versions-script] - this overwrites + whatever value is currently there, whether that's an unconstrained `'*'` or an exact version + pinned by an earlier run of this same workflow, so pins always stay in lockstep with + `.codeqlversion` on every bump, not just the first one. 2. Runs `codeql pack upgrade ` for every pack directory (except [`ql/hotspots`](#ql-hotspots), see below) to refresh each `codeql-pack.lock.yml` against the newly-pinned dependencies.