53 lines · 2.7 KB
#!/usr/bin/env bun
/**
 * End-to-end check that the merge queue hands a conflicting pull to an AI fix and re-enqueues it after
 * CI passes on the fix commit. Needs a dev server with MERGEFIX_PROVIDER=mock; takes several minutes
 * because the Workflow polls CI every two minutes. Queues the pull through `PUT /pulls/:n/merge_queue`.
 *
 *   D1_CWD=$PWD bun scripts/e2e-mergefix-queue.ts
 */
import { api, assert, d1, fixStatus, poll, prepareConflict } from "./mergefix-harness";

const REQUEUE_TIMEOUT_MS = 15 * 60 * 1000;
const FIX_TIMEOUT_MS = 5 * 60 * 1000;

const user = await api<{ login: string }>("GET", "/user");
const name = `mergefix-queue-${Date.now().toString(36)}`;
const line = (middle: string) => `header\none\n${middle}\nthree\nfooter\n`;
const prepared = await prepareConflict(user.login, name, [
  { path: "app.txt", base: line("two"), head: line("two (head wording)"), main: line("two (main wording)") },
]);
try {
  const repoId = String(d1(`SELECT id FROM repos WHERE name = '${name}'`)[0]?.id);
  d1(
    `INSERT INTO repo_mergefix_settings (repo_id, queue_enabled, allow_private, min_confidence, min_margin, updated_at)
     VALUES ('${repoId}', 1, 0, 0.8, 0.3, ${Date.now()})`,
  );
  await api(
    "PUT",
    `/repos/${user.login}/${name}/pulls/${prepared.pull.number}/merge_queue`,
    { method: "merge", expected_head: prepared.before },
    [200, 202, 204],
  );
  const applied = await poll("the queue-triggered fix to land", FIX_TIMEOUT_MS, async () => {
    const fix = await fixStatus(user.login, name, prepared.pull.number);
    return fix && !["queued", "running", "applying"].includes(fix.status) ? fix : null;
  });
  assert(applied.status === "applied", `expected applied, got ${applied.status}: ${applied.error}`);
  assert(prepared.remoteHead() === applied.commit_sha, "head branch moved to the fix commit");
  console.log(`fix ${applied.commit_sha?.slice(0, 7)} applied; waiting for CI and re-enqueue`);
  const requeued = await poll("the pull to rejoin the queue", REQUEUE_TIMEOUT_MS, async () => {
    const fix = await fixStatus(user.login, name, prepared.pull.number);