Skip to content

arm auto-merge as fallback when M is blocked by repo rules#26

Merged
AntonNiklasson merged 1 commit into
mainfrom
an/merge-fallback-and-ttl
May 5, 2026
Merged

arm auto-merge as fallback when M is blocked by repo rules#26
AntonNiklasson merged 1 commit into
mainfrom
an/merge-fallback-and-ttl

Conversation

@AntonNiklasson
Copy link
Copy Markdown
Owner

Summary

Pressing M on a PR with mergeStateStatus: CLEAN previously triggered a direct merge, which surfaced an unhelpful 422 ("Repository rule violations found") when GitHub rulesets imposed requirements GraphQL doesn't reflect (e.g. unresolved review threads, required deployments).

  • Fall back to enablePullRequestAutoMerge whenever the direct merge fails — the PR lands once GitHub is satisfied. Cached autoMergeAllowed is no longer gating the fallback; the server's AutoMergeNotAllowedError is the source of truth.
  • Add a 2-minute TTL to the repo-settings cache (getRepoSettings) so toggling Allow auto-merge in the GitHub UI takes effect within minutes instead of being stuck on the first cached value.
  • Forward GitHub's full multi-line merge error (joined with ) so the toast carries the actionable line, not just the header.

Test plan

  • pnpm typecheck / pnpm lint / pnpm fmt:check
  • pnpm test — added mutations.test.ts covering merge success, fallback success, and fallback-failure (AutoMergeNotAllowedError) paths
  • Manual: press M on a PR that's CLEAN but blocked by an open thread — confirm toast shows "Auto-merge enabled — direct merge blocked: …" and the PR is armed
  • Manual: toggle off Allow auto-merge on a repo, wait <2min, press M on a CLEAN PR there — confirm direct-merge error is surfaced (no fallback)

When mergeStateStatus is CLEAN, decideMergeAction picks direct merge —
but CLEAN doesn't reflect ruleset requirements (e.g. unresolved threads,
required deployments), so the merge can fail with a generic 422. Instead
of just toasting the failure, fall through to enablePullRequestAutoMerge
so the PR lands as soon as GitHub is satisfied.

The fallback always attempts toggleAutoMerge — the server's
AutoMergeNotAllowedError is the source of truth, and the cached
autoMergeAllowed flag (now 2-min TTL'd, was infinite) can lag behind a
recent repo-settings change.

Also forwards GitHub's full multi-line error message instead of dropping
everything after the first newline, so toasts carry the actionable
detail ("A conversation must be resolved…") not just the header.
@AntonNiklasson AntonNiklasson marked this pull request as ready for review May 5, 2026 06:41
Copilot AI review requested due to automatic review settings May 5, 2026 06:41
@AntonNiklasson AntonNiklasson merged commit 63f4feb into main May 5, 2026
2 checks passed
@AntonNiklasson AntonNiklasson deleted the an/merge-fallback-and-ttl branch May 5, 2026 06:41
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the “press M to merge” workflow by handling cases where GitHub repo rulesets block a direct merge even when mergeStateStatus reports CLEAN, falling back to arming auto-merge and improving surfaced error messages. It also adds a TTL to the server-side repo-settings cache so toggling “Allow auto-merge” in GitHub takes effect shortly after.

Changes:

  • Web: on direct merge failure, attempt to enable auto-merge as a fallback and show a more actionable toast.
  • Server: forward GitHub’s full multi-line merge rejection message by joining non-empty lines with .
  • Server: add a 2-minute TTL to cached getRepoSettings results (and update integration test cache mock accordingly).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/web/src/mutations.ts Adds auto-merge fallback behavior when direct merge fails and updates UI cache/toasts accordingly.
packages/web/src/mutations.test.ts Adds unit tests covering merge success, fallback success, and fallback failure paths.
packages/server/src/routes.ts Improves merge rejection message formatting by joining non-empty lines.
packages/server/src/routes.test.ts Updates tests to assert the new merged error-message format.
packages/server/src/fetchers.ts Adds a 2-minute TTL when reading cached repo settings.
packages/server/src/fetchers.integration.test.ts Extends cache mock to support TTL behavior via cacheAge.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +112 to +117
await api.toggleAutoMerge(target.instanceId, target.repo, target.number);
qc.setQueriesData<PR[]>({ queryKey: ["prs"] }, (old) =>
old?.map((pr) =>
matches(target)(pr) ? { ...pr, autoMerge: true } : pr,
),
);
Comment on lines +113 to +117
qc.setQueriesData<PR[]>({ queryKey: ["prs"] }, (old) =>
old?.map((pr) =>
matches(target)(pr) ? { ...pr, autoMerge: true } : pr,
),
);
Comment on lines +26 to 37
const cacheTimes = new Map<string, number>();
vi.mock("./cache.js", () => ({
getCached: (key: string) => cacheStore.get(key) ?? null,
setCached: (key: string, data: unknown) => {
cacheStore.set(key, data);
cacheTimes.set(key, Date.now());
},
cacheAge: (key: string) => {
const t = cacheTimes.get(key);
return t == null ? null : Date.now() - t;
},
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants