Merge a pull request marked ready at its head once its checks pass (issue 722)
mesh/merge-gate out of date: judged against trunk 482232e8c51c, the trunk is now 7e3e62062bef; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk 482232e8c51c, the trunk is now 7e3e62062bef; judged again on a recheck or when it is merged
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate out of date: judged against trunk 482232e8c51c, the trunk is now 7e3e62062bef; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk 482232e8c51c, the trunk is now 7e3e62062bef; judged again on a recheck or when it is merged
mesh/delivery superseded: a newer head of the same pull request
The operator wants a reviewed pull request merged without a session calling the merge tool again after every recheck. The reviewer marks it ready (label mesh/ready and a comment "ready at <full head sha>"); the forge's open-pulls read carries the mark, and mesh-delivery merges through gitea_merge_pull_request at that head, in a group's order once its composed check passed. A push after the mark clears it; a failed check is said on the pull request and as a stalled line.
This commit is contained in:
@@ -137,3 +137,52 @@ test("a merged pull request whose branch was deleted is announced with its branc
|
||||
assert.equal(headBranchOf({ ref: "refs/pull/7/head" }), "refs/pull/7/head");
|
||||
assert.equal(headBranchOf(undefined), undefined);
|
||||
});
|
||||
|
||||
// **A pull request marked ready says the head it is marked at** (novox/hq issue 722): the label mesh/ready and the
|
||||
// newest comment "ready at <full head sha>". mesh-delivery merges on it; without the label no comment is read.
|
||||
test("a pull request's ready mark is read: the label and the head the newest ready comment names", async () => {
|
||||
const { GiteaClient } = await import("../client.ts");
|
||||
const head = "c".repeat(40), older = "d".repeat(40);
|
||||
const asked: string[] = [];
|
||||
const server = createServer((req, res) => {
|
||||
const url = req.url ?? "";
|
||||
asked.push(url);
|
||||
const send = (v: unknown) => res.end(JSON.stringify(v));
|
||||
if (url.startsWith("/api/v1/repos/issues/search")) {
|
||||
return send(url.includes("page=1") ? [
|
||||
{ number: 7, repository: { owner: "novox", name: "hq", full_name: "novox/hq" },
|
||||
labels: [{ id: 31, name: "mesh/ready" }, { id: 2, name: "bug" }] },
|
||||
{ number: 8, repository: { owner: "novox", name: "hq", full_name: "novox/hq" }, labels: [] },
|
||||
] : []);
|
||||
}
|
||||
if (url.startsWith("/api/v1/repos/novox/hq/pulls/7")) {
|
||||
return send({ number: 7, state: "open", base: { ref: "main" }, head: { ref: "x", sha: head }, html_url: "h" });
|
||||
}
|
||||
if (url.startsWith("/api/v1/repos/novox/hq/pulls/8")) {
|
||||
return send({ number: 8, state: "open", base: { ref: "main" }, head: { ref: "y", sha: older }, html_url: "h" });
|
||||
}
|
||||
if (url.startsWith("/api/v1/repos/novox/hq/issues/7/comments")) {
|
||||
return send([
|
||||
{ id: 1, user: { login: "mesh" }, body: `ready at ${older}`, created_at: "2026-10-14T10:00:00Z" },
|
||||
{ id: 2, user: { login: "mesh" }, body: `Reviewed: approve.\nready at ${head}\n`, created_at: "2026-10-14T11:00:00Z" },
|
||||
{ id: 3, user: { login: "jochen" }, body: "thanks", created_at: "2026-10-14T12:00:00Z" },
|
||||
]);
|
||||
}
|
||||
if (url.includes("/branch_protections")) return send([]);
|
||||
if (url.includes("/status")) return send({ statuses: [] });
|
||||
res.statusCode = 404;
|
||||
res.end("{}");
|
||||
});
|
||||
await new Promise<void>((r) => server.listen(0, r));
|
||||
const client = new GiteaClient(`http://127.0.0.1:${(server.address() as any).port}`, "t");
|
||||
try {
|
||||
const open = await client.openPulls();
|
||||
assert.deepEqual(open[0].labels, ["mesh/ready", "bug"]);
|
||||
assert.deepEqual(open[0].ready, { head, by: "mesh", at: "2026-10-14T11:00:00Z", label_id: 31 },
|
||||
"the newest comment that names a head");
|
||||
assert.equal(open[1].ready, undefined, "no label, no mark");
|
||||
assert.ok(!asked.some((u) => u.includes("/issues/8/comments")), "no comment read without the label");
|
||||
} finally {
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user