import { eq } from "drizzle-orm";
import { db } from "../db";
import { branchProtection, prReviews } from "../db/schema";
import {
matchProtection,
countHumanApprovals,
} from "./branch-protection";
export interface BranchRule {
id: string;
pattern: string;
requiredReviews: number;
requireCodeownerReview: boolean;
dismissStaleReviews: boolean;
}
export async function getBranchRules(repoId: string): Promise<BranchRule[]> {
try {
const rows = await db
.select()
.from(branchProtection)
.where(eq(branchProtection.repositoryId, repoId));
return rows.map((r) => ({
id: r.id,
pattern: r.pattern,
requiredReviews: r.requiredApprovals,
requireCodeownerReview: r.requireHumanReview,
dismissStaleReviews: r.dismissStaleReviews,
}));
} catch {
return [];
}
}
export interface MergeEligibleResult {
eligible: boolean;
reason?: string;
approvalCount: number;
requiredCount: number;
}
export async function checkMergeEligible(
prId: string,
repoId: string,
targetBranch: string
): Promise<MergeEligibleResult> {
try {
const rule = await matchProtection(repoId, targetBranch);
if (!rule || rule.requiredApprovals === 0) {
const approvalCount = await countHumanApprovals(prId);
return { eligible: true, approvalCount, requiredCount: 0 };
}
const approvalCount = await countHumanApprovals(prId);
const requiredCount = rule.requiredApprovals;
if (approvalCount < requiredCount) {
return {
eligible: false,
reason: `This PR requires ${requiredCount} approval${requiredCount !== 1 ? "s" : ""} before merging. Currently: ${approvalCount} approval${approvalCount !== 1 ? "s" : ""}.`,
approvalCount,
requiredCount,
};
}
return { eligible: true, approvalCount, requiredCount };
} catch {
return { eligible: true, approvalCount: 0, requiredCount: 0 };
}
}
|