Vectrum
Sign In
68 lines · 2.8 KB · TypeScript
"use server";

import { revalidatePath } from "next/cache";
import { AGENT_PUSH_CHOICES, type AgentPush } from "@/lib/branch-rules";
import { GitError, setDefaultBranch } from "@/lib/git";
import { deleteBranchRule, ProtectionError, saveBranchRule } from "@/lib/protection";
import { setAgentPush } from "@/lib/repos";
import { ActionError, repoForAction } from "./guard";
import type { FormState } from "./types";

const settingsPath = (owner: string, name: string) => `/${owner}/${name}/settings/branches`;

export async function saveBranchRuleAction(owner: string, name: string, ruleId: string | null, _prev: FormState, formData: FormData): Promise<FormState> {
  try {
    const { repo } = await repoForAction(owner, name, "admin");
    const on = (key: string) => formData.get(key) === "on";
    await saveBranchRule(
      repo.id,
      {
        pattern: String(formData.get("pattern") ?? ""),
        requirePr: on("requirePr"),
        requiredApprovals: Number(formData.get("requiredApprovals") ?? 0) || 0,
        requireCi: on("requireCi"),
        blockForcePush: on("blockForcePush"),
        blockDeletion: on("blockDeletion"),
        agentsMayMerge: on("agentsMayMerge"),
      },
      ruleId ?? undefined,
    );
    revalidatePath(settingsPath(repo.owner, repo.name));
    return { success: ruleId ? "Rule saved." : "Rule added." };
  } catch (e) {
    if (e instanceof ActionError || e instanceof ProtectionError) return { error: e.message };
    throw e;
  }
}

export async function deleteBranchRuleAction(owner: string, name: string, ruleId: string) {
  const { repo } = await repoForAction(owner, name, "admin");
  await deleteBranchRule(repo.id, ruleId);
  revalidatePath(settingsPath(repo.owner, repo.name));
}

export async function setAgentPushAction(owner: string, name: string, _prev: FormState, formData: FormData): Promise<FormState> {
  try {
    const { repo } = await repoForAction(owner, name, "admin");
    const value = String(formData.get("agentPush") ?? "") as AgentPush;
    if (!AGENT_PUSH_CHOICES.some((c) => c.value === value)) throw new ActionError("Choose where agents may push.");
    await setAgentPush(repo.id, value);
    revalidatePath(`/${repo.owner}/${repo.name}`, "layout");
    return { success: "Saved." };
  } catch (e) {
    if (e instanceof ActionError) return { error: e.message };
    throw e;
  }
}

export async function setDefaultBranchAction(owner: string, name: string, _prev: FormState, formData: FormData): Promise<FormState> {
  try {
    const { repo } = await repoForAction(owner, name, "admin");
    await setDefaultBranch(repo.dir, String(formData.get("branch") ?? ""));
    revalidatePath(`/${repo.owner}/${repo.name}`, "layout");
    return { success: "Saved." };
  } catch (e) {
    if (e instanceof ActionError || e instanceof GitError) return { error: e.message };
    throw e;
  }
}