Skip to content

Commit cb5af26

Browse files
committed
test(eligibility): close the last coverage gaps without suppressions
Codecov counts a /* v8 ignore */ line as unhit, so both suppressions are gone rather than carried: DEFAULT_PRIORITY_LABEL names the built-in value, so resolvePriorityTypeLabel returns it directly. PrTypeLabelSet is an open Record, which made DEFAULT_TYPE_LABELS.priority read as possibly-undefined and forced a fallback branch nothing could ever take. The .catch on resolvePriorityEligibilityHold is removed: that function catches its own GitHub read and cannot reject, so the guard was unreachable code that read as tested-and-fine while never running. The remaining branch is closed by an end-to-end test instead: a clean, approved, green PR that would MERGE is held because the priority issue it closes only became public a minute ago -- held, never closed.
1 parent 06c44d3 commit cb5af26

3 files changed

Lines changed: 59 additions & 8 deletions

File tree

packages/loopover-engine/src/settings/pr-type-label.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,16 @@ export type { PrTypeLabelSet } from "../types/manifest-deps-types.js";
2222
* assumption (#label-modularity): a self-hoster's `typeLabels` fully replaces the category set these
2323
* keys are drawn from. The built-in categories are mutually exclusive by default (see
2424
* `resolvePrTypeLabel`'s `removeLabels`) unless a propagation mapping is explicitly additive. */
25+
/** The built-in PRIORITY label, named on its own so it reads as `string`. `PrTypeLabelSet` is an open
26+
* `Record`, which makes `DEFAULT_TYPE_LABELS.priority` optional to the type system even though the
27+
* built-in set always defines it -- naming the value is what lets `resolvePriorityTypeLabel` return it
28+
* without a fallback branch nothing can ever take. */
29+
export const DEFAULT_PRIORITY_LABEL = "gittensor:priority";
30+
2531
export const DEFAULT_TYPE_LABELS: PrTypeLabelSet = {
2632
bug: "gittensor:bug",
2733
feature: "gittensor:feature",
28-
priority: "gittensor:priority",
34+
priority: DEFAULT_PRIORITY_LABEL,
2935
};
3036

3137
export const MAX_TYPE_LABEL_CATEGORIES = 32;
@@ -153,9 +159,7 @@ export type PrTypeLabelDecision = {
153159
export function resolvePriorityTypeLabel(labels: PrTypeLabelSet | null | undefined): string {
154160
const configured = labels?.priority;
155161
if (typeof configured === "string" && configured.trim().length > 0) return configured;
156-
/* v8 ignore next -- noUncheckedIndexedAccess: PrTypeLabelSet is a Record<string, string>, so this reads
157-
as possibly-undefined to the type system though the built-in set always defines `priority`. */
158-
return DEFAULT_TYPE_LABELS.priority ?? "gittensor:priority";
162+
return DEFAULT_PRIORITY_LABEL;
159163
}
160164

161165
export function resolvePrTypeLabel(input: {

src/queue/processors.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3479,10 +3479,10 @@ async function runAgentMaintenancePlanAndExecute(
34793479
windowMinutes: settings.priorityEligibilityWindowMinutes ?? DEFAULT_PRIORITY_ELIGIBILITY_WINDOW_MINUTES,
34803480
priorityLabel: resolvePriorityTypeLabel(settings.typeLabels),
34813481
token: ciToken,
3482-
/* v8 ignore next -- defensive: resolvePriorityEligibilityHold catches its own GitHub read, so it has no
3483-
reject path today. The guard stays so a future edit inside it degrades to "no hold" rather than
3484-
failing the whole maintenance pass -- which is the fail-open posture the rest of this rule has. */
3485-
}).catch(() => undefined);
3482+
// No `.catch` here on purpose: resolvePriorityEligibilityHold catches its own GitHub read and returns
3483+
// undefined, so it has no reject path. A guard for one that cannot happen is unreachable code that
3484+
// reads as tested-and-fine while never running.
3485+
});
34863486
const unlinkedIssueMatchClose = unlinkedIssueMatchDisposition?.kind === "close" ? unlinkedIssueMatchDisposition : undefined;
34873487

34883488
// Contributor blacklist (#1425): resolve whether the PR author is on the repo's blacklist (the shared/global

test/unit/queue-3.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2502,6 +2502,53 @@ describe("queue processors", () => {
25022502
await upsertPullRequestFromGitHub(env, "owner/repo", { number: prNumber, title: "Migration PR", state: "open", user: { login: "contributor" }, head: { sha: "sha1" }, base: { ref: "main" }, labels: [], body: "" });
25032503
}
25042504

2505+
it("holds a would-otherwise-merge PR while its linked priority issue is still inside the eligibility window (#9738)", async () => {
2506+
// The end-to-end shape of the rule: a clean, approved, green PR that would MERGE is held instead,
2507+
// because the priority issue it closes only became public minutes ago. Held, never closed -- the PR
2508+
// is early, not wrong.
2509+
const env = createTestEnv({ GITHUB_APP_PRIVATE_KEY: await generatePrivateKeyPem() });
2510+
await seedMigrationRecheckRepo(env, 61);
2511+
await upsertPullRequestFromGitHub(env, "owner/repo", {
2512+
number: 61,
2513+
title: "Fix the thing",
2514+
state: "open",
2515+
user: { login: "contributor" },
2516+
head: { sha: "sha1" },
2517+
base: { ref: "main" },
2518+
labels: [],
2519+
body: "Closes #7",
2520+
created_at: new Date(Date.now() - 60_000).toISOString(),
2521+
} as never);
2522+
const seen = { closed: false, merged: false, labels: [] as string[], comments: [] as string[], treeCalls: 0 };
2523+
stubMigrationRecheckFetch(61, { filename: "src/a.ts", status: "modified" }, [], seen);
2524+
// The one extra fact the rule needs: the priority label landed on issue #7 a minute ago, so the
2525+
// 30-minute window has not elapsed.
2526+
const inner = globalThis.fetch as typeof fetch;
2527+
vi.stubGlobal("fetch", async (input: RequestInfo | URL, init?: RequestInit) => {
2528+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
2529+
if (url === "https://api.github.com/graphql" && String(init?.body ?? "").includes("LABELED_EVENT")) {
2530+
return Response.json({
2531+
data: {
2532+
repository: {
2533+
issue: {
2534+
timelineItems: {
2535+
nodes: [{ createdAt: new Date(Date.now() - 60_000).toISOString(), label: { name: "gittensor:priority" } }],
2536+
},
2537+
},
2538+
},
2539+
},
2540+
});
2541+
}
2542+
return inner(input as never, init as never);
2543+
});
2544+
2545+
await processJob(env, { type: "agent-regate-pr", deliveryId: "priority-eligibility-hold", repoFullName: "owner/repo", prNumber: 61, installationId: 123 });
2546+
2547+
expect(seen.merged, "an unelapsed window must stop the auto-merge").toBe(false);
2548+
expect(seen.closed, "a hold is never a close -- the contributor keeps their work").toBe(false);
2549+
expect(seen.comments.some((c) => c.includes("continues normally")), "the comment reads as a wait, not a rejection").toBe(true);
2550+
});
2551+
25052552
it("holds a would-otherwise-merge PR when the live base has a colliding migration number, with the distinct label + rebase comment", async () => {
25062553
const env = createTestEnv({ GITHUB_APP_PRIVATE_KEY: await generatePrivateKeyPem() });
25072554
await seedMigrationRecheckRepo(env, 60, { premergeContentRecheck: true });

0 commit comments

Comments
 (0)