feat(pr): allow to delete branch after merge@@ -21,11 +21,14 @@ const postRepositoryPullRequestMergeAction: ReqHandler<
AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION
> = async (request, reply) => {
const { orgSlug, repoSlug, pullUid } = request.params;
- const { merge_message, merge_summary } = request.body;
+ const { merge_message, merge_summary, delete_source_branch } = request.body;
+
+ const shouldDeleteSourceBranch = delete_source_branch != null; // treat any presence as request to delete
console.log("params:", {
merge_message,
merge_summary,
+ delete_source_branch,
});
const orgService = makeOrganizationService({ request });
@@ -131,6 +134,7 @@ const postRepositoryPullRequestMergeAction: ReqHandler<
const result = await prService.mergePullRequest({
pullRequestId: pullRequest.id,
mergeMessage: merge_message ?? undefined,
+ deleteSourceBranch: shouldDeleteSourceBranch,
});
if (result.success !== true) {
@@ -312,6 +312,7 @@ export interface AppRouteParams {
body: {
merge_summary: string;
merge_message: string;
+ delete_source_branch?: boolean;
};
};
[AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]: {
@@ -40,13 +40,13 @@ const makeRepositoryResolver: ServiceMethodFactory<
if (repo == null) {
throw new Error(
- `Unknown repository "${repo}" in (known) organization "${org}".`
+ `Unknown repository "${repoSlug}" in (known) organization "${org.slug}".`,
);
}
// /!\ Notice how it use db's data instead of user's input to build path.
const gitRepositoryDir = resolve(
- join(Env.GIT_REPOSITORIES_ROOT, org.slug, repo.slug)
+ join(Env.GIT_REPOSITORIES_ROOT, org.slug, repo.slug),
);
if (
@@ -85,6 +85,35 @@ export const makeMergePullRequest: ServiceMethodFactory<
);
});
+ // setup committer identity
+ await new Promise<void>((resolve, reject) => {
+ const c = spawn(
+ "git",
+ ["config", "user.name", "GitFOSS Agent (system)"],
+ {
+ cwd: tmpDir,
+ env: { LANG: "C" },
+ },
+ );
+ let err = "";
+ c.stderr.on("data", (d) => (err += d.toString()));
+ c.on("close", (code) =>
+ code === 0 ? resolve() : reject(new Error(err)),
+ );
+ });
+
+ await new Promise<void>((resolve, reject) => {
+ const c = spawn("git", ["config", "user.email", "git@gitfoss.dev"], {
+ cwd: tmpDir,
+ env: { LANG: "C" },
+ });
+ let err = "";
+ c.stderr.on("data", (d) => (err += d.toString()));
+ c.on("close", (code) =>
+ code === 0 ? resolve() : reject(new Error(err)),
+ );
+ });
+
// add source as remote
await new Promise<void>((resolve, reject) => {
const c = spawn("git", ["remote", "add", "source", sourceBarePath], {
@@ -156,6 +185,25 @@ export const makeMergePullRequest: ServiceMethodFactory<
);
});
+ // Optional: delete source branch on the source repo if requested
+ if (dto.deleteSourceBranch === true) {
+ await new Promise<void>((resolve, reject) => {
+ const c = spawn(
+ "git",
+ ["push", sourceBarePath, "--delete", pr.sourceBranch],
+ {
+ cwd: tmpDir,
+ env: { LANG: "C" },
+ },
+ );
+ let err = "";
+ c.stderr.on("data", (d) => (err += d.toString()));
+ c.on("close", (code) =>
+ code === 0 ? resolve() : reject(new Error(err || "delete source branch failed")),
+ );
+ });
+ }
+
// update PR as merged
const updatedPR = await request.prisma.pullRequest.update({
where: { id: pr.id },
@@ -170,17 +218,6 @@ export const makeMergePullRequest: ServiceMethodFactory<
success: true,
updatedPullRequest: updatedPR,
};
- } catch (err) {
- throw err;
- } finally {
- // cleanup
- try {
- await rm(tmpDir, { recursive: true, force: true });
- } catch {
- // ignore cleanup errors
- }
- }
- };
-};
+
export default makeMergePullRequest;
@@ -26,6 +26,8 @@ export type PullRequestSelectOrIncludes =
export interface MergePullRequestDTO {
pullRequestId: string;
mergeMessage?: string;
+ // delete the source branch in the source repository after merge if requested
+ deleteSourceBranch?: boolean;
// could extend with mergeStrategy in future (e.g., merge, squash, rebase)
}
@@ -244,6 +244,20 @@ const RepositoryPullRequestDetailsView: ReactView<
>
<button type={"submit"}>Merge</button>
</Grid.Row>
+ {/* Delete source branch after merge checkbox */}
+ <Grid.Col fluid style={{ marginTop: 8 }}>
+ <label
+ htmlFor={"delete_source_branch"}
+ style={{ display: "block" }}
+ >
+ <input
+ type={"checkbox"}
+ id={"delete_source_branch"}
+ name={"delete_source_branch"}
+ />
+ {" Delete source branch after merge"}
+ </label>
+ </Grid.Col>
</Grid.Col>
</form>
</Grid.Col>