import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
import type { RepositoryFileDiff } from "../../types";
import { AppRoute, AppRouteParams } from "../../routes.defs";
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
import { makeRepositoryService } from "../../services/repository";
import { makeUsersService } from "../../services/user";
import { buildRouteLink } from "../../utils/shared";
const postRepositoryPullRequestMergeAction: ReqHandler<
AppRouteParams,
AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION
> = async (request, reply) => {
const { orgSlug, repoSlug, pullUid } = request.params;
const { merge_message, merge_summary } = request.body;
console.log("params:", {
merge_message,
merge_summary,
});
const orgService = makeOrganizationService({ request });
const prService = makePullRequestService({ request });
const repoService = makeRepositoryService({ request });
const usersService = makeUsersService({ request });
const currentUser =
request.session.data.authenticated &&
request.session.data.curr_user_uid != null
? await usersService.getUserById(request.session.data.curr_user_uid)
: null;
const pullRequest = await prService.getPullRequestByUid(
orgSlug,
repoSlug,
pullUid,
);
if (pullRequest == null) {
return reply.status(404).callNotFound();
}
const sourceRepo = await repoService.getRepositoryById(
pullRequest.sourceRepositoryId,
);
if (sourceRepo == null) {
return reply.status(404).callNotFound();
}
const targetRepo = await repoService.getRepositoryById(
pullRequest.targetRepositoryId,
);
if (targetRepo == null) {
return reply.status(404).callNotFound();
}
const sourceParentOrg = await orgService.getOrganizationById(
sourceRepo.organizationId,
);
if (sourceParentOrg == null) {
return reply.status(404).callNotFound();
}
if (sourceRepo.visibility === ResourceVisibility.PRIVATE) {
if (currentUser == null) {
return reply.status(404).callNotFound();
} else if (
(await repoService.canUserAccessRepository(currentUser, sourceRepo)) ===
false
) {
return reply.status(404).callNotFound();
}
}
const targetParentOrg = await orgService.getOrganizationById(
targetRepo.organizationId,
);
if (targetParentOrg == null) {
return reply.status(404).callNotFound();
}
if (targetRepo.visibility === ResourceVisibility.PRIVATE) {
if (currentUser == null) {
return reply.status(404).callNotFound();
} else if (
(await repoService.canUserAccessRepository(currentUser, targetRepo)) ===
false
) {
return reply.status(404).callNotFound();
}
}
let fileDiffs = [] as RepositoryFileDiff[];
if (sourceParentOrg.slug === targetParentOrg.slug) {
fileDiffs = await repoService.getRepositoryRefDiff(
sourceRepo,
pullRequest.targetBranch,
pullRequest.sourceBranch,
);
} else {
fileDiffs = await repoService.getRepositoryRemoteRefDiff(
sourceRepo,
pullRequest.sourceBranch,
targetRepo,
pullRequest.targetBranch,
);
}
if (fileDiffs.length <= 0) {
throw new Error("Cannot merge two branches without difference.");
}
try {
const result = await prService.mergePullRequest({
pullRequestId: pullRequest.id,
mergeMessage: merge_message ?? undefined,
});
if (result.success !== true) {
return reply.status(500).send({ error: "Merge failed" });
}
const updatedPull = result.updatedPullRequest || pullRequest;
return reply.redirect(
303,
buildRouteLink(AppRoute.REPOSITORY_PULL_REQUEST_DETAILS, {
orgSlug,
repoSlug,
pullUid: updatedPull.uid,
}),
);
} catch (err) {
console.error("Merge action failed:", (err as Error).message);
return reply
.status(500)
.send({ error: "Merge action failed", detail: (err as Error).message });
}
};
export default postRepositoryPullRequestMergeAction;