From 2011738c5ea84c525090d44039dd0012d93ab6e4 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Fri, 10 Jul 2026 18:43:37 -0400 Subject: [PATCH] fix(release): stop patch-release-me double-bumping ql/hotspots `ql/hotspots/` is deliberately excluded from `.release.yml`'s "CodeQL Pack Versions" location (added in #158/d0b969e: it's a separate package published by its own manual workflow_dispatch, not part of the per-language pack family) - yet it kept getting bumped in lockstep with every release anyway (most recently 0.2.4 -> 0.3.0 in PR #173, and 0.2.1 -> 0.2.4 in PR #169 before that). Root cause, confirmed by running the exact pinned patch-release-me image locally with --debug against both a minimal repro and a full copy of this repo's real qlpack.yml files: 1. patch-release-me ships its own hardcoded default location for the "CodeQL" ecosystem, literally named "CodeQL Packs" (see its src/defaults.yml), matching **/qlpack.yml with only `excludes: [/.codeql/]`. Our own custom location was named "CodeQL Pack Versions" - a different name - so patch-release-me's config loader (src/config.rs) adds its built-in default *alongside* ours instead of treating ours as an override (it only skips adding the default when a location with the exact same `name` already exists). The built-in default has no idea about our `ql/hotspots/` exclude, so it bumps that file regardless. 2. Our own location's pattern (`^version:\s*{version}$`) has never actually matched anything, on any pack, since the day it was anchored in d0b969e - the `^`/`$` anchor to the whole file, not each line, without a `(?m)` multiline flag, and `version:` is never the literal first/last byte of a real multi-line qlpack.yml. All real bumping has silently been done by the built-in default this whole time, which is exactly why our exclude never took effect. Fix (both verified together, locally, against all 28 real qlpack.yml files in this repo with their actual LF line endings): - Rename our location to exactly "CodeQL Packs" so patch-release-me's default-merge logic skips adding its own conflicting built-in default instead of running both. - Add the `(?m)` flag so the anchor actually works per-line, keeping the original anti-partial-match protection (e.g. bumping "0.2.2" from correctly matching inside "0.2.20") while working at all. Verified: all 20 real packs bump correctly, `ql/hotspots/qlpack.yml` stays untouched, `.release.yml` itself still bumps. Also documents this in CONTRIBUTING.md's "Cutting a release" section so the location's name/pattern requirements aren't silently broken again by a future edit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .release.yml | 4 ++-- CONTRIBUTING.md | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.release.yml b/.release.yml index 009c027e..c35ed756 100644 --- a/.release.yml +++ b/.release.yml @@ -9,13 +9,13 @@ excludes: - "/codeql_home/" # only present when run alongside update-codeql-version.yml, which downloads the CLI here locations: - - name: "CodeQL Pack Versions" + - name: "CodeQL Packs" # must match patch-release-me's built-in default location name for the "CodeQL" ecosystem (see defaults.yml upstream) - otherwise BOTH run, and the built-in one bumps every qlpack.yml with no knowledge of our excludes below paths: - "**/qlpack.yml" excludes: - "ql/hotspots/" patterns: - - '^version:\s*{version}$' + - '(?m)^version:\s*{version}$' # (?m) is required: without it ^/$ anchor to the whole file, not each line, so this would never match a real multi-line qlpack.yml - name: "CodeQL Configurations" paths: - "configs/*.yml" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9661e801..b424d44d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -305,11 +305,23 @@ supported way to bump `.release.yml`: [`42ByteLabs/patch-release-me`][patch-release-me] tool, which reads `.release.yml`'s current `version:`, computes the bump, and opens a PR that: - bumps `.release.yml`'s `version:` to the new value, and - - patches **every** matching pack's own `version:` field to match (the "CodeQL Pack Versions" + - patches **every** matching pack's own `version:` field to match (the "CodeQL Packs" location in `.release.yml`, added in [#158][pr-158] — this is what makes `.release.yml` a real lever over publishing today, not just a changelog label), and - writes a `prerelease: true|false` field into `.release.yml` reflecting the `prerelease` input (default `false`/unchecked, i.e. a full release) - see the note below. + +> [!IMPORTANT] +> `ql/hotspots/` is deliberately excluded from that "CodeQL Packs" location (it's a separate +> package published by its own manual `workflow_dispatch`, not part of the per-language pack +> family - see `.github/workflows/hotspots.yml`). That location's `name:` **must stay exactly +> `"CodeQL Packs"`**, matching `patch-release-me`'s own built-in default location for the +> `CodeQL` ecosystem - if it's ever renamed, the built-in default silently reactivates +> alongside it and re-bumps `ql/hotspots/qlpack.yml` regardless of the exclude, since the +> built-in default doesn't know about it. Its pattern also needs the `(?m)` multiline flag +> (`(?m)^version:\s*{version}$`) - without it, `^`/`$` anchor to the whole file rather than each +> line and the pattern silently never matches anything. Both were real, live bugs discovered +> while landing the CodeQL 2.22.4/v0.3.0 bump (see PR #173). - [ ] Review and merge that PR like any other. - [ ] Merging it is what changes `.release.yml` on `main`, which auto-triggers [`publish.yml`][publish-workflow] for a real batch publish: every pack whose version actually