223 lines · 8.9 KB
import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { requireViewer, viewerMiddleware } from "./middleware";
import { pullInput, requirePull, requirePullMutation } from "~/server/pull-access";
import { limitHeavy, limitWrite } from "~/server/limits";
import { assertNotArchived, requireRepoAccess } from "~/server/repos";
import { addIssueEvent, MergeError } from "~/server/pulls";
import { headBranchConflicts, requireHeadPush, updateHeadBranch } from "~/server/pull-merge";
import { applySuggestions, MAX_BATCHED_SUGGESTIONS } from "~/server/suggestions";
import { linkIssue, unlinkIssue } from "~/server/pull-links";
import { loadIssue } from "~/server/issues";
import { readPullTemplate } from "~/server/pull-templates";
import { badRequest, conflict, notFoundError } from "~/server/errors";
import { repoRef } from "~/lib/validation";
import { setCodeOwnerRequirement as setRuleCodeOwnerRequirement } from "~/server/protection-write";
import { setAutoMerge as setPullAutoMerge, setMergeQueue as setPullMergeQueue } from "~/server/pull-automation";
import { dismissReview as dismissPullReview, rerequestPullReview as rerequestReviewFor } from "~/server/reviews-write";

const MAX_RESOLVED_FILE_CHARS = 1024 * 1024;

function rethrowMerge(error: unknown): never {
  if (error instanceof MergeError) throw conflict(error.message);
  throw error;
}

export const updatePullBranch = createServerFn({ method: "POST" })
  .middleware([viewerMiddleware])
  .validator(pullInput)
  .handler(async ({ data, context }) => {
    const viewer = requireViewer(context.viewer);
    await limitWrite(viewer);
    const { pull, headRepo } = await requirePullMutation(data.owner, data.repo, data.number, viewer, "read");
    if (pull.state !== "open") throw badRequest("Pull request is not open");
    await requireHeadPush(headRepo, pull.head_ref, viewer);
    const outcome = await updateHeadBranch(pull, viewer).catch(rethrowMerge);
    if (outcome.conflicts) return { sha: null, conflicts: outcome.conflicts.length };
    return { sha: outcome.sha, conflicts: 0 };
  });

export const getPullConflicts = createServerFn({ method: "GET" })