Skip to content

Commit 3a7a0d6

Browse files
authored
fix: resolve PR branch issues (#415)
1 parent 89953af commit 3a7a0d6

3 files changed

Lines changed: 106 additions & 4 deletions

File tree

lib/modules/repository.js

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,23 @@ class Repository {
192192
await Promise.all(createOrUpdateFilesMultiple);
193193
}
194194

195+
async getPullRequestsBy({ branchName, state }) {
196+
try {
197+
return await this.octokit.pulls.list({
198+
owner: this.owner,
199+
repo: this.repo,
200+
state,
201+
head: `${this.owner}:${branchName}`,
202+
});
203+
} catch(error) {
204+
return { data: [] }
205+
}
206+
}
207+
195208
async getPullRequestURL({ branchName }) {
196-
const results = await this.octokit.pulls.list({
197-
owner: this.owner,
198-
repo: this.repo,
209+
const results = await this.getPullRequestsBy({
210+
branchName,
199211
state: "open",
200-
head: `${this.owner}:${branchName}`,
201212
});
202213
return results.data[0].html_url;
203214
}
@@ -259,6 +270,23 @@ class Repository {
259270
branchName,
260271
});
261272
}
273+
274+
async deleteBranch({branchName}) {
275+
try {
276+
await this.octokit.git.deleteRef({
277+
owner: this.owner,
278+
repo: this.repo,
279+
ref: `heads/${branchName}`
280+
});
281+
} catch (error) {
282+
// /* istanbul ignore if */
283+
// if (error.status !== 404) {
284+
// throw error;
285+
// }
286+
287+
// throw new BranchNotFoundError(branchName);
288+
}
289+
}
262290
}
263291

264292
module.exports = Repository;

lib/setup-repository.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,28 @@ const { BranchNotFoundError } = require("./modules/errors");
66
async function setupRepository({ context, branchName }) {
77
const repository = new Repository(context);
88

9+
const hasOpenPullRequest = async ({branchName}) => {
10+
const result = await repository.getPullRequestsBy({
11+
branchName,
12+
state: "open"
13+
});
14+
15+
// TODO: Possibly make sure the existing pull request is created by the bot?
16+
return result.data.length > 0;
17+
};
18+
919
try {
1020
await repository.getRef(branchName);
21+
const openPrExists = await hasOpenPullRequest(branchName)
22+
1123
context.log.debug(
1224
`Branch "${branchName}" exists, will work from this branch`
1325
);
26+
27+
if (!openPrExists) {
28+
repository.deleteBranch(branchName);
29+
}
30+
1431
repository.setBaseBranch(branchName);
1532
} catch (error) {
1633
const isBranchNotFoundError = error instanceof BranchNotFoundError;

test/unit/setup-repository.test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const Repository = require("../../lib/modules/repository");
2+
const { BranchNotFoundError } = require("../../lib/modules/errors");
3+
const setupRepository = require("../../lib/setup-repository");
4+
5+
jest.mock("../../lib/modules/repository");
6+
7+
describe("Setup Repository", () => {
8+
const mockBranchName = "all-contributors/add-hertzg-tenshiAMD";
9+
const mockContext = {
10+
log: {
11+
debug() {},
12+
},
13+
};
14+
15+
afterEach(() => jest.clearAllMocks());
16+
17+
it("should base off latest on first time request", async () => {
18+
Repository.prototype.getRef.mockReturnValue(
19+
Promise.reject(new BranchNotFoundError(mockBranchName))
20+
);
21+
22+
await setupRepository({ branchName: mockBranchName, context: mockContext });
23+
24+
expect(Repository.prototype.getRef).toBeCalledWith(mockBranchName);
25+
expect(Repository.prototype.deleteBranch).not.toBeCalled();
26+
expect(Repository.prototype.getPullRequestsBy).not.toBeCalled();
27+
expect(Repository.prototype.setBaseBranch).not.toBeCalled();
28+
});
29+
30+
it("should delete existing dangling (already merged) branches then recreate new pr", async () => {
31+
Repository.prototype.getRef.mockReturnValue(Promise.resolve());
32+
Repository.prototype.getPullRequestsBy.mockReturnValue(
33+
Promise.resolve({ data: [] })
34+
);
35+
36+
await setupRepository({ branchName: mockBranchName, context: mockContext });
37+
38+
expect(Repository.prototype.getRef).toBeCalledWith(mockBranchName);
39+
expect(Repository.prototype.deleteBranch).toBeCalledTimes(1);
40+
expect(Repository.prototype.setBaseBranch).toBeCalledTimes(1);
41+
expect(Repository.prototype.getPullRequestsBy).toBeCalledTimes(1);
42+
});
43+
44+
it("should use existing branch only if pr for it was not merged yet", async () => {
45+
Repository.prototype.getRef.mockReturnValue(Promise.resolve());
46+
Repository.prototype.getPullRequestsBy.mockReturnValue(
47+
Promise.resolve({ data: [{}] })
48+
);
49+
50+
await setupRepository({ branchName: mockBranchName, context: mockContext });
51+
52+
expect(Repository.prototype.getRef).toBeCalledWith(mockBranchName);
53+
expect(Repository.prototype.deleteBranch).not.toBeCalled();
54+
expect(Repository.prototype.getPullRequestsBy).toBeCalledTimes(1);
55+
expect(Repository.prototype.setBaseBranch).toBeCalledTimes(1);
56+
});
57+
});

0 commit comments

Comments
 (0)