Skip to content

fix(mcp): pin gittensory_propose_action to the PR current head - #2355

Merged
JSONbored merged 1 commit into
mainfrom
claude/mcp-propose-action-headsha
Jul 1, 2026
Merged

fix(mcp): pin gittensory_propose_action to the PR current head#2355
JSONbored merged 1 commit into
mainfrom
claude/mcp-propose-action-headsha

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

What

proposeAction built the staged action's params from only label/reviewBody/mergeMethod/closeComment — it never fetched or recorded the PR's head SHA. So every MCP-staged action had expectedHeadSha === undefined, and the approval-queue accept path's force-push guard (stagedHead && stagedHead !== pr.headSha) is a silent no-op on a falsy stagedHead: a maintainer or agent could propose a merge, the contributor could force-push unreviewed code, and accept would merge the new commit with no supersede/rejection — exactly the threat that guard exists to catch, just never engaged for this entrypoint.

Fix

Fetch the PR's current stored head via getPullRequest before building params and pin expectedHeadSha to it, matching the invariant the live webhook/sweep staging path (stageForApproval) already upholds. Uses the stored/DB-synced value (not a fresh live GitHub fetch), consistent with how the existing staging path resolves this — no added GitHub API load on a maintainer-facing MCP call.

Tests

  • expectedHeadSha is now staged when a PR record exists (and correctly omitted when it doesn't — matches an existing test's baseline).
  • End-to-end: propose a merge, force-push the PR, accept — the existing force-push guard now actually fires (status: "rejected", executionOutcome: "head_moved"), where before this fix it silently proceeded to execute.

Full unsharded test:coverage green; typecheck green.

Advances #1936. Closes #2255.

proposeAction built the staged action's params from only label/reviewBody/
mergeMethod/closeComment — it never fetched or recorded the PR's head SHA. So
every MCP-staged action had expectedHeadSha === undefined, and the approval-
queue accept path's force-push guard (stagedHead && stagedHead !== pr.headSha)
is a silent no-op on a falsy stagedHead: a maintainer/agent could propose a
merge, the contributor could force-push unreviewed code, and accept would
merge the new commit with no supersede/rejection — exactly the threat that
guard exists to catch, just never engaged for this entrypoint.

Fetch the PR's current stored head via getPullRequest before building params
and pin expectedHeadSha to it, matching the invariant the live webhook/sweep
staging path (stageForApproval) already upholds.

Advances #1936. Closes #2255.
@dosubot dosubot Bot added the size:XS label Jul 1, 2026
@JSONbored JSONbored self-assigned this Jul 1, 2026
@JSONbored
JSONbored merged commit ec131cf into main Jul 1, 2026
8 checks passed
@JSONbored
JSONbored deleted the claude/mcp-propose-action-headsha branch July 1, 2026 11:19
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jul 1, 2026
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.71%. Comparing base (d02fbb9) to head (b1515f7).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2355   +/-   ##
=======================================
  Coverage   95.71%   95.71%           
=======================================
  Files         222      222           
  Lines       24653    24655    +2     
  Branches     8945     8946    +1     
=======================================
+ Hits        23597    23599    +2     
  Misses        433      433           
  Partials      623      623           
Files with missing lines Coverage Δ
src/mcp/server.ts 95.72% <100.00%> (+0.01%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

fix(mcp): gittensory_propose_action stages actions with no expectedHeadSha, disabling the force-push guard

1 participant