Show merge-conflict badge on PR cards via GraphQL mergeable field

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DgBEW6qAwgn2fcQbA2f4ZQ
This commit is contained in:
Joshua Coles 2026-07-29 10:10:53 +00:00
parent 5aa6f3367d
commit ab6e3bbe3a
5 changed files with 17 additions and 0 deletions

View File

@ -11,6 +11,7 @@ export const LIST_QUERY = /* GraphQL */ `
title title
url url
isDraft isDraft
mergeable
updatedAt updatedAt
author { login } author { login }
headRefName headRefName
@ -34,6 +35,7 @@ export interface ListPr {
title: string; title: string;
url: string; url: string;
isDraft: boolean; isDraft: boolean;
mergeable: 'MERGEABLE' | 'CONFLICTING' | 'UNKNOWN';
updatedAt: string; updatedAt: string;
author: { login: string } | null; author: { login: string } | null;
headRefName: string; headRefName: string;

View File

@ -37,6 +37,7 @@ function signature(pr: ListPr): string {
pr.reviews.totalCount, pr.reviews.totalCount,
pr.latestReviews.nodes.map((r) => `${r.author?.login}:${r.state}`), pr.latestReviews.nodes.map((r) => `${r.author?.login}:${r.state}`),
pr.labels.nodes.map((l) => l.name).sort(), pr.labels.nodes.map((l) => l.name).sort(),
pr.mergeable,
]), ]),
) )
.digest('hex'); .digest('hex');
@ -82,6 +83,7 @@ function buildSnapshot(config: AppConfig, pr: ListPr, detail: DetailPr | undefin
url: pr.url, url: pr.url,
author: pr.author?.login ?? 'ghost', author: pr.author?.login ?? 'ghost',
isDraft: pr.isDraft, isDraft: pr.isDraft,
mergeable: pr.mergeable,
branch: pr.headRefName, branch: pr.headRefName,
updatedAt: pr.updatedAt, updatedAt: pr.updatedAt,
labels, labels,

View File

@ -34,6 +34,8 @@ export interface PrSnapshot {
url: string; url: string;
author: string; author: string;
isDraft: boolean; isDraft: boolean;
/** GitHub's merge-conflict state; UNKNOWN while GitHub is still computing it. */
mergeable: 'MERGEABLE' | 'CONFLICTING' | 'UNKNOWN';
branch: string; branch: string;
updatedAt: string; updatedAt: string;
labels: string[]; labels: string[];

View File

@ -38,6 +38,7 @@ export default function PrCard({
</div> </div>
<div className="meta-row"> <div className="meta-row">
{pr.isDraft && <span className="draft-tag">draft</span>} {pr.isDraft && <span className="draft-tag">draft</span>}
{pr.mergeable === 'CONFLICTING' && <span className="conflict-tag"> conflicts</span>}
<span>{pr.author}</span> <span>{pr.author}</span>
<span className="branch" title={pr.branch}> <span className="branch" title={pr.branch}>
{pr.branch} {pr.branch}

View File

@ -308,6 +308,16 @@ button {
color: var(--ink-secondary); color: var(--ink-secondary);
} }
.conflict-tag {
border: 1px solid var(--status-fail);
border-radius: 4px;
padding: 0 5px;
font-size: 11px;
font-weight: 600;
color: var(--status-fail-text);
background: var(--chip-fail-bg);
}
.branch { .branch {
font-family: ui-monospace, monospace; font-family: ui-monospace, monospace;
font-size: 11px; font-size: 11px;