Skip to content

Commit 8298195

Browse files
committed
use github api to find pull request for commit
throttle octokit requests
1 parent 09b536c commit 8298195

16 files changed

+927
-632
lines changed

package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
},
4242
"dependencies": {
4343
"@manypkg/get-packages": "^2.2.0",
44+
"@octokit/plugin-throttling": "^9.4.0",
45+
"@octokit/rest": "^21.1.0",
4446
"chalk": "^4.0.0",
4547
"cli-highlight": "^2.1.11",
4648
"execa": "^5.0.0",
@@ -51,7 +53,10 @@
5153
"yargs": "^17.1.0"
5254
},
5355
"devDependencies": {
56+
"@types/fs-extra": "^11.0.4",
57+
"@types/hosted-git-info": "^3.0.5",
5458
"@types/node": "22.10.10",
59+
"@types/yargs": "^17.0.33",
5560
"@typescript-eslint/eslint-plugin": "5.62.0",
5661
"@typescript-eslint/parser": "5.62.0",
5762
"eslint": "8.55.0",
@@ -62,7 +67,7 @@
6267
"release-plan": "^0.11.0",
6368
"rimraf": "3.0.2",
6469
"typescript": "5.0.4",
65-
"vitest": "^3.0.4"
70+
"vitest": "^3.0.7"
6671
},
6772
"packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af",
6873
"engines": {

pnpm-lock.yaml

+401-243
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__mocks__/@octokit/rest.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { vi } from "vitest";
2+
3+
let responses = {
4+
prs: {} as Record<string, any[]>,
5+
users: {} as Record<string, any>,
6+
};
7+
8+
function throwError(status: number) {
9+
const e = new Error();
10+
(e as any).status = status;
11+
throw e;
12+
}
13+
14+
export const octokit = {
15+
args: [] as any,
16+
repos: {
17+
listPullRequestsAssociatedWithCommit: vi.fn(({ commit_sha }) => ({
18+
data: responses.prs[commit_sha] || throwError(404),
19+
})),
20+
},
21+
users: {
22+
getByUsername: vi.fn(({ username }) => ({ data: responses.users[username] || throwError(404) })),
23+
},
24+
};
25+
export const Octokit = function (...args: any[]) {
26+
octokit.args = args;
27+
return octokit;
28+
};
29+
Octokit.plugin = () => Octokit;
30+
Octokit.octokit = octokit;
31+
export const __setMockResponses = (res: any) => (responses = res);
32+
export const __resetMockResponses = () => (responses = { prs: {}, users: {} });

src/__snapshots__/changelog.spec.js.snap

+9-21
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
exports[`Changelog > getCommitInfos > parse commits with different tags 1`] = `
44
[
5+
{
6+
"commitSHA": "a0000006",
7+
"date": "2017-01-01",
8+
"issueNumber": null,
9+
"message": "Merge pull request #3 from my-feature-3",
10+
"packages": [],
11+
"tags": undefined,
12+
},
513
{
614
"commitSHA": "a0000005",
715
"date": "2017-01-01",
@@ -41,29 +49,9 @@ exports[`Changelog > getCommitInfos > parse commits with different tags 1`] = `
4149
"tags": undefined,
4250
},
4351
{
44-
"categories": [
45-
":rocket: New Feature",
46-
],
4752
"commitSHA": "a0000003",
4853
"date": "2017-01-01",
49-
"githubIssue": {
50-
"labels": [
51-
{
52-
"name": "Type: New Feature",
53-
},
54-
{
55-
"name": "Status: In Progress",
56-
},
57-
],
58-
"number": 2,
59-
"title": "This is the commit title for the issue (#2)",
60-
"user": {
61-
"html_url": "https://github.com/test-user",
62-
"login": "test-user",
63-
"name": "Test User",
64-
},
65-
},
66-
"issueNumber": "2",
54+
"issueNumber": null,
6755
"message": "feat(module) Add new module (#2)",
6856
"packages": [],
6957
"tags": undefined,

src/changelog.spec.js

+53-40
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
2-
2+
import * as MockedOctokit from "./__mocks__/@octokit/rest";
3+
import { Octokit } from "@octokit/rest";
34
import Changelog from "./changelog";
4-
import * as fetch from "./fetch";
55
import * as git from "./git";
66

7+
vi.mock("@octokit/rest");
78
vi.mock("../src/progress-bar");
89
vi.mock("../src/changelog");
910
vi.mock("../src/github-api");
1011
vi.mock("./git");
11-
vi.mock("./fetch");
1212

1313
describe("Changelog", () => {
14+
beforeEach(() => {
15+
Octokit.mockImplementation((...args) => MockedOctokit.Octokit(...args));
16+
Octokit.plugin.mockImplementation(() => MockedOctokit.Octokit);
17+
});
18+
afterEach(() => {
19+
vi.resetAllMocks();
20+
});
1421
describe("packageFromPath", () => {
1522
const TESTS = [
1623
["", ""],
@@ -89,7 +96,7 @@ describe("Changelog", () => {
8996

9097
describe("getCommitInfos", () => {
9198
beforeEach(() => {
92-
fetch.__resetMockResponses();
99+
MockedOctokit.__resetMockResponses();
93100

94101
git.listCommits.mockImplementation(() => [
95102
{
@@ -135,35 +142,47 @@ describe("Changelog", () => {
135142
git.changedPaths.mockImplementation(() => []);
136143

137144
const usersCache = {
138-
"https://api.github.com/users/test-user": {
145+
"test-user": {
139146
body: {
140147
login: "test-user",
141148
html_url: "https://github.com/test-user",
142149
name: "Test User",
143150
},
144151
},
145152
};
146-
const issuesCache = {
147-
"https://api.github.com/repos/embroider-build/github-changelog/issues/2": {
148-
body: {
153+
const prCache = {
154+
a0000001: [],
155+
a0000002: [],
156+
a0000003: [
157+
{
158+
number: 2,
159+
title: "feat(module) Add new module (#2)",
160+
labels: [{ name: "Type: New Feature" }, { name: "Status: In Progress" }],
161+
user: usersCache["test-user"].body,
162+
},
163+
],
164+
a0000004: [
165+
{
149166
number: 2,
150167
title: "This is the commit title for the issue (#2)",
151168
labels: [{ name: "Type: New Feature" }, { name: "Status: In Progress" }],
152-
user: usersCache["https://api.github.com/users/test-user"].body,
169+
user: usersCache["test-user"].body,
153170
},
154-
},
171+
],
172+
a0000005: [],
173+
a0000006: [],
155174
"https://api.github.com/repos/embroider-build/github-changelog/issues/3": {
156175
body: {
157176
number: 2,
158177
title: "This is the commit title for the issue (#2)",
159178
labels: [{ name: "ignore" }, { name: "Status: In Progress" }],
160-
user: usersCache["https://api.github.com/users/test-user"].body,
179+
user: usersCache["test-user"].body,
161180
},
162181
},
163182
};
164-
fetch.__setMockResponses({
165-
...usersCache,
166-
...issuesCache,
183+
MockedOctokit.__setMockResponses({
184+
users: { ...usersCache },
185+
prs: { ...prCache },
167186
});
168187
});
169188

@@ -181,39 +200,33 @@ describe("Changelog", () => {
181200

182201
describe("getCommitters", () => {
183202
beforeEach(() => {
184-
fetch.__resetMockResponses();
203+
MockedOctokit.__resetMockResponses();
185204

186205
const usersCache = {
187-
"https://api.github.com/users/test-user": {
188-
body: {
189-
login: "test-user",
190-
html_url: "https://github.com/test-user",
191-
name: "Test User",
192-
},
206+
"test-user": {
207+
login: "test-user",
208+
html_url: "https://github.com/test-user",
209+
name: "Test User",
193210
},
194-
"https://api.github.com/users/test-user-1": {
195-
body: {
196-
login: "test-user-1",
197-
html_url: "https://github.com/test-user-1",
198-
name: "Test User 1",
199-
},
211+
"test-user-1": {
212+
login: "test-user-1",
213+
html_url: "https://github.com/test-user-1",
214+
name: "Test User 1",
200215
},
201-
"https://api.github.com/users/test-user-2": {
202-
body: {
203-
login: "test-user-2",
204-
html_url: "https://github.com/test-user-2",
205-
name: "Test User 2",
206-
},
216+
"test-user-2": {
217+
login: "test-user-2",
218+
html_url: "https://github.com/test-user-2",
219+
name: "Test User 2",
207220
},
208-
"https://api.github.com/users/user-bot": {
209-
body: {
210-
login: "user-bot",
211-
html_url: "https://github.com/user-bot",
212-
name: "User Bot",
213-
},
221+
"user-bot": {
222+
login: "user-bot",
223+
html_url: "https://github.com/user-bot",
224+
name: "User Bot",
214225
},
215226
};
216-
fetch.__setMockResponses(usersCache);
227+
MockedOctokit.__setMockResponses({
228+
users: { ...usersCache },
229+
});
217230
});
218231

219232
it("get list of valid commiters", async () => {

src/changelog.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ const { resolve, sep } = require("path");
33

44
import progressBar from "./progress-bar";
55
import { Configuration } from "./configuration";
6-
import findPullRequestId from "./find-pull-request-id";
76
import * as Git from "./git";
87
import GithubAPI, { GitHubUserResponse } from "./github-api";
98
import { CommitInfo, Release } from "./interfaces";
@@ -161,27 +160,30 @@ export default class Changelog {
161160
.map(ref => ref.substr(TAG_PREFIX.length));
162161
}
163162

164-
const issueNumber = findPullRequestId(message);
165-
166163
return {
167164
commitSHA: sha,
168165
message,
169166
// Note: Only merge commits or commits referencing an issue / PR
170167
// will be kept in the changelog.
171168
tags: tagsInCommit,
172-
issueNumber,
169+
issueNumber: null,
173170
date,
174171
} as CommitInfo;
175172
});
176173
}
177174

178175
private async downloadIssueData(commitInfos: CommitInfo[]) {
179176
progressBar.init("Downloading issue information…", commitInfos.length);
177+
const PRs = new Set();
180178
await pMap(
181179
commitInfos,
182180
async (commitInfo: CommitInfo) => {
183-
if (commitInfo.issueNumber) {
184-
commitInfo.githubIssue = await this.github.getIssueData(this.config.repo, commitInfo.issueNumber);
181+
const issueData = await this.github.getPullRequest(this.config.repo, commitInfo.commitSHA);
182+
183+
if (issueData && !PRs.has(issueData.number)) {
184+
PRs.add(issueData.number);
185+
commitInfo.issueNumber = issueData.number.toString();
186+
commitInfo.githubIssue = issueData;
185187
}
186188

187189
progressBar.tick();
@@ -214,7 +216,7 @@ export default class Changelog {
214216
releaseMap[currentTag] = { name: currentTag, date, commits: [] };
215217
}
216218

217-
let prUserLogin = commit.githubIssue?.user.login;
219+
let prUserLogin = commit.githubIssue?.user!!.login;
218220
if (prUserLogin && !this.ignoreCommitter(prUserLogin)) {
219221
releaseMap[currentTag].commits.push(commit);
220222
}

0 commit comments

Comments
 (0)