Skip to content

fix(ci): clear stale query-count label/comment when snapshots match base#1583

Merged
ascorbic merged 1 commit into
mainfrom
fix/query-count-comment-catch22
Jun 22, 2026
Merged

fix(ci): clear stale query-count label/comment when snapshots match base#1583
ascorbic merged 1 commit into
mainfrom
fix/query-count-comment-catch22

Conversation

@ascorbic

Copy link
Copy Markdown
Collaborator

What does this PR do?

Fixes a catch-22 in the Query Counts — Label workflow that leaves a stale "query counts dropped" comment on PRs whose net diff no longer changes any counts.

The workflow was path-filtered on the snapshot files:

on:
  pull_request_target:
    paths:
      - scripts/query-counts.snapshot.sqlite.json
      - scripts/query-counts.snapshot.d1.json

The script already self-heals (removes the label / deletes the comment when base and head match), but the paths: filter means it only runs when the PR diff touches the snapshot files. Once a previously-changed snapshot matches base again — reverted, or base caught up via a merge — the PR diff no longer touches those files, so the workflow never runs and the self-heal can never fire. The stale comment lingers.

Real-world trigger: #1579 (Astro 7 upgrade). Its early CI run committed a snapshot delta (16->9) and posted a -28 queries comment. After #1580 fixed the harness and the branch merged main, the head snapshots matched base again — net diff: zero snapshot changes — but the path-filtered workflow couldn't run to clear the now-wrong comment.

Fix: drop the paths: filter and let the script decide from the actual base/head diff on every run — add the label + upsert the comment when snapshots differ, remove the label + delete the comment when they match. The job only reads snapshot files via the API and manages labels/comments; it never checks out or executes PR code, so removing the filter doesn't change the pull_request_target security posture.

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes (n/a — CI YAML only, no source changed)
  • pnpm lint passes (n/a — CI YAML only)
  • pnpm test passes (n/a — CI YAML only)
  • pnpm format has been run (prettier-clean)
  • I have added/updated tests for my changes (n/a — workflow change, not unit-testable here)
  • User-visible strings in the admin UI are wrapped for translation (n/a)
  • I have added a changeset (n/a — no published package changed)
  • New features link to an approved Discussion (n/a — bug fix)

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: Claude Opus 4.8

Notes

The stale comment already on #1579 won't clear until this lands on main (pull_request_target uses the base branch's workflow definition) and #1579 gets another push. It can also be deleted by hand in the meantime.

…ch base

The Query Counts label workflow was path-filtered on the snapshot files, so
it only ran when a PR's diff touched them. That created a catch-22: once a
previously-changed snapshot matched base again (reverted, or base caught up
via a merge), the PR diff no longer touched the files, so the workflow never
ran and its self-heal (remove label, delete comment) could never fire. The
result was a stale "query counts dropped" comment lingering on a PR whose net
diff no longer changes any counts.

Drop the paths filter and let the script decide from the actual base/head
diff on every run: add the label and upsert the comment when snapshots
differ, remove the label and delete the comment when they match. The job
only reads the snapshot files via the API and manages labels/comments, so it
never executes PR code despite pull_request_target.
@changeset-bot

changeset-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 38cab83

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
emdash-demo-cache 38cab83 Jun 22 2026, 03:16 PM

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
docs 38cab83 Jun 22 2026, 03:16 PM

@github-actions github-actions Bot added review/needs-review No maintainer or bot review yet area/ci size/M labels Jun 22, 2026
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
emdash-playground 38cab83 Jun 22 2026, 03:18 PM

@pkg-pr-new

pkg-pr-new Bot commented Jun 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@1583

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@1583

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@1583

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@1583

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@1583

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@1583

emdash

npm i https://pkg.pr.new/emdash@1583

create-emdash

npm i https://pkg.pr.new/create-emdash@1583

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@1583

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@1583

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@1583

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@1583

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@1583

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@1583

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@1583

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@1583

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@1583

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@1583

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@1583

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@1583

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@1583

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@1583

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@1583

commit: 38cab83

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach — correct, solves the right problem. The paths: filter on a pull_request_target workflow whose entire purpose is to self-heal (drop a stale label/comment when snapshots match base again) is self-defeating: once a snapshot delta is reverted or neutralized, the PR diff stops touching the snapshot files, so the workflow can never run to clear the now-wrong label/comment. That is exactly the catch-22 described. Dropping paths: and letting the script decide from the actual base/head diff on every run is the right, minimal fix — the script already had the self-heal branch; the filter was the only thing preventing it from firing. This fits the existing design (the sibling Measure/Apply workflows are untouched) and EmDash's "fewer queries is right; more needs a conversation" stance is preserved.

Security posture — verified, claim holds. I checked the new file end-to-end: no actions/checkout, no run: step, no secrets consumed. It only fetches snapshot JSON via repos.getContent at base/head SHAs and manages labels/comments with GITHUB_TOKEN (pull-requests: write). Removing paths: does not change what the workflow can touch. pull_request_target runs the base branch's workflow file, so (as the PR notes) this only takes effect after merge to main.

Implementation — clean.

  • hasChange = sections.length > 0 drives both the label and the comment consistently. The old two-step split (unconditional addLabels in step 1 + conditional comment delete in step 2) is replaced by a single step that adds label+comment when changed and removes both when not — strictly more correct; the old code could leave a stale label when snapshots were touched-but-identical.
  • createLabel 422 and removeLabel 404 are caught correctly; addLabels is idempotent.
  • Traced the lifecycle with the Measure (pull_request) and Apply (workflow_run) workflows: after Apply pushes regenerated snapshots, the resulting synchronize re-runs Label against the new head and converges (upsert in place). No spurious flapping.
  • Event types (opened, synchronize, reopened, edited) are appropriate; running on edited is harmless (same SHAs → same hasChange → no-op or re-confirm). The "base caught up via a merge" case works because merging main into the PR head fires synchronize.
  • CI YAML only → no published package changed, so no changeset is needed; i18n/typecheck/lint are n/a as the PR states.

Conclusion: No findings. Genuinely clean — I'd sign off.

Non-blocking, pre-existing (not introduced by this diff, flagged only for the record):

  1. No concurrency: group, so rapid pushes can overlap on the label/comment mutations; the ops are idempotent and converge, so this is cosmetic.
  2. Snapshot keys are interpolated into the comment markdown unescaped (rows.push(\| `${key}` …``)); on a fork PR the head snapshot is author-controlled. GitHub sanitizes script handlers, so this is low-severity (markup, not script execution), and the realistic keys are generated route names — but a future hardening pass could escape keys/cells. Neither is touched by this PR.

@github-actions github-actions Bot added review/approved Approved; no new commits since and removed review/needs-review No maintainer or bot review yet labels Jun 22, 2026
@ascorbic ascorbic merged commit fff7315 into main Jun 22, 2026
46 of 47 checks passed
@ascorbic ascorbic deleted the fix/query-count-comment-catch22 branch June 22, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci review/approved Approved; no new commits since size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant