github-issue-tower-defence-management 2.63.4 → 2.63.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adapter/repositories/GitHubIssueCommentRepository.js +77 -34
- package/bin/adapter/repositories/GitHubIssueCommentRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +16 -9
- package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/RestIssueRepository.js +107 -29
- package/bin/adapter/repositories/issue/RestIssueRepository.js.map +1 -1
- package/bin/adapter/repositories/issue/githubRateLimitRetry.js +148 -3
- package/bin/adapter/repositories/issue/githubRateLimitRetry.js.map +1 -1
- package/bin/adapter/repositories/issue/githubSecondaryRateLimitBreaker.js +126 -0
- package/bin/adapter/repositories/issue/githubSecondaryRateLimitBreaker.js.map +1 -0
- package/bin/domain/usecases/CliErrorReportUseCase.js +1 -1
- package/bin/domain/usecases/CliErrorReportUseCase.js.map +1 -1
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +2 -5
- package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
- package/package.json +1 -1
- package/types/adapter/repositories/GitHubIssueCommentRepository.d.ts +2 -2
- package/types/adapter/repositories/GitHubIssueCommentRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +7 -0
- package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/RestIssueRepository.d.ts +12 -0
- package/types/adapter/repositories/issue/RestIssueRepository.d.ts.map +1 -1
- package/types/adapter/repositories/issue/githubRateLimitRetry.d.ts +53 -1
- package/types/adapter/repositories/issue/githubRateLimitRetry.d.ts.map +1 -1
- package/types/adapter/repositories/issue/githubSecondaryRateLimitBreaker.d.ts +49 -0
- package/types/adapter/repositories/issue/githubSecondaryRateLimitBreaker.d.ts.map +1 -0
- package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
|
@@ -2,18 +2,22 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GitHubIssueCommentRepository = void 0;
|
|
4
4
|
const commentDeduplication_1 = require("./commentDeduplication");
|
|
5
|
+
const githubSecondaryRateLimitBreaker_1 = require("./issue/githubSecondaryRateLimitBreaker");
|
|
6
|
+
const githubRateLimitRetry_1 = require("./issue/githubRateLimitRetry");
|
|
5
7
|
function isRestCommentPayloadArray(value) {
|
|
6
8
|
if (!Array.isArray(value))
|
|
7
9
|
return false;
|
|
8
10
|
return true;
|
|
9
11
|
}
|
|
10
|
-
function
|
|
12
|
+
function isPageCacheEntry(value) {
|
|
11
13
|
if (typeof value !== 'object' || value === null)
|
|
12
14
|
return false;
|
|
13
15
|
if (!('etag' in value) || typeof value.etag !== 'string')
|
|
14
16
|
return false;
|
|
15
17
|
if (!('comments' in value) || !Array.isArray(value.comments))
|
|
16
18
|
return false;
|
|
19
|
+
if (!('hasNextPage' in value) || typeof value.hasNextPage !== 'boolean')
|
|
20
|
+
return false;
|
|
17
21
|
return value.comments.every((c) => typeof c === 'object' &&
|
|
18
22
|
c !== null &&
|
|
19
23
|
'author' in c &&
|
|
@@ -23,6 +27,15 @@ function isCommentCacheEntry(value) {
|
|
|
23
27
|
'createdAt' in c &&
|
|
24
28
|
typeof c.createdAt === 'string');
|
|
25
29
|
}
|
|
30
|
+
function isCommentPageCache(value) {
|
|
31
|
+
if (typeof value !== 'object' || value === null)
|
|
32
|
+
return false;
|
|
33
|
+
if (!('pages' in value) ||
|
|
34
|
+
typeof value.pages !== 'object' ||
|
|
35
|
+
value.pages === null)
|
|
36
|
+
return false;
|
|
37
|
+
return Object.values(value.pages).every(isPageCacheEntry);
|
|
38
|
+
}
|
|
26
39
|
class GitHubIssueCommentRepository {
|
|
27
40
|
constructor(token, commentCacheRepository = null) {
|
|
28
41
|
this.token = token;
|
|
@@ -43,71 +56,88 @@ class GitHubIssueCommentRepository {
|
|
|
43
56
|
commentCacheKey(owner, repo, issueNumber) {
|
|
44
57
|
return `comments/${owner}/${repo}/${issueNumber}`;
|
|
45
58
|
}
|
|
46
|
-
async
|
|
59
|
+
async readCommentPageCache(owner, repo, issueNumber) {
|
|
47
60
|
if (!this.commentCacheRepository)
|
|
48
61
|
return null;
|
|
49
62
|
const raw = await this.commentCacheRepository.getSingle(this.commentCacheKey(owner, repo, issueNumber));
|
|
50
|
-
return
|
|
63
|
+
return isCommentPageCache(raw) ? raw : null;
|
|
51
64
|
}
|
|
52
|
-
async
|
|
65
|
+
async writeCommentPageCache(owner, repo, issueNumber, pages) {
|
|
53
66
|
if (!this.commentCacheRepository)
|
|
54
67
|
return;
|
|
55
|
-
await this.commentCacheRepository.setSingle(this.commentCacheKey(owner, repo, issueNumber), {
|
|
56
|
-
etag,
|
|
57
|
-
comments: comments.map((c) => ({
|
|
58
|
-
author: c.author,
|
|
59
|
-
content: c.content,
|
|
60
|
-
createdAt: c.createdAt.toISOString(),
|
|
61
|
-
})),
|
|
62
|
-
});
|
|
68
|
+
await this.commentCacheRepository.setSingle(this.commentCacheKey(owner, repo, issueNumber), { pages });
|
|
63
69
|
}
|
|
64
70
|
async getCommentsFromIssue(issue) {
|
|
65
71
|
const { owner, repo, issueNumber } = this.parseIssueUrl(issue);
|
|
66
|
-
const
|
|
72
|
+
const existingCache = await this.readCommentPageCache(owner, repo, issueNumber);
|
|
73
|
+
const cachedPages = existingCache
|
|
74
|
+
? { ...existingCache.pages }
|
|
75
|
+
: {};
|
|
76
|
+
const PER_PAGE = 100;
|
|
67
77
|
const comments = [];
|
|
78
|
+
const updatedPages = { ...cachedPages };
|
|
79
|
+
let cacheWasUpdated = false;
|
|
68
80
|
let page = 1;
|
|
69
81
|
let hasNextPage = true;
|
|
70
|
-
let newEtag = null;
|
|
71
82
|
while (hasNextPage) {
|
|
72
|
-
const
|
|
83
|
+
const pageKey = String(page);
|
|
84
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}/comments?per_page=${PER_PAGE}&page=${page}`;
|
|
73
85
|
const headers = {
|
|
74
86
|
Authorization: `Bearer ${this.token}`,
|
|
75
87
|
Accept: 'application/vnd.github+json',
|
|
76
88
|
};
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
const cachedPage = cachedPages[pageKey];
|
|
90
|
+
if (cachedPage) {
|
|
91
|
+
headers['If-None-Match'] = cachedPage.etag;
|
|
79
92
|
}
|
|
80
93
|
const response = await fetch(url, { headers });
|
|
81
|
-
if (response.status === 304 &&
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
94
|
+
if (response.status === 304 && cachedPage) {
|
|
95
|
+
for (const c of cachedPage.comments) {
|
|
96
|
+
comments.push({
|
|
97
|
+
author: c.author,
|
|
98
|
+
content: c.content,
|
|
99
|
+
createdAt: new Date(c.createdAt),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
hasNextPage =
|
|
103
|
+
cachedPage.hasNextPage || cachedPage.comments.length >= PER_PAGE;
|
|
104
|
+
page++;
|
|
105
|
+
continue;
|
|
87
106
|
}
|
|
88
107
|
if (!response.ok) {
|
|
89
108
|
throw new Error(`Failed to fetch comments from GitHub REST API: ${response.status} ${response.statusText}`);
|
|
90
109
|
}
|
|
91
|
-
if (page === 1) {
|
|
92
|
-
newEtag = response.headers.get('ETag');
|
|
93
|
-
}
|
|
94
110
|
const responseData = await response.json();
|
|
95
111
|
if (!isRestCommentPayloadArray(responseData)) {
|
|
96
112
|
throw new Error('Unexpected response shape when fetching comments from GitHub REST API');
|
|
97
113
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
114
|
+
const pageComments = responseData.map((payload) => ({
|
|
115
|
+
author: payload.user?.login ?? '',
|
|
116
|
+
content: payload.body,
|
|
117
|
+
createdAt: new Date(payload.created_at),
|
|
118
|
+
}));
|
|
119
|
+
for (const c of pageComments) {
|
|
120
|
+
comments.push(c);
|
|
104
121
|
}
|
|
105
122
|
const linkHeader = response.headers.get('Link') ?? '';
|
|
106
123
|
hasNextPage = linkHeader.includes('rel="next"');
|
|
124
|
+
const etag = response.headers.get('ETag');
|
|
125
|
+
if (etag) {
|
|
126
|
+
updatedPages[pageKey] = {
|
|
127
|
+
etag,
|
|
128
|
+
comments: pageComments.map((c) => ({
|
|
129
|
+
author: c.author,
|
|
130
|
+
content: c.content,
|
|
131
|
+
createdAt: c.createdAt.toISOString(),
|
|
132
|
+
})),
|
|
133
|
+
hasNextPage,
|
|
134
|
+
};
|
|
135
|
+
cacheWasUpdated = true;
|
|
136
|
+
}
|
|
107
137
|
page++;
|
|
108
138
|
}
|
|
109
|
-
if (
|
|
110
|
-
await this.
|
|
139
|
+
if (cacheWasUpdated) {
|
|
140
|
+
await this.writeCommentPageCache(owner, repo, issueNumber, updatedPages);
|
|
111
141
|
}
|
|
112
142
|
return comments;
|
|
113
143
|
}
|
|
@@ -155,6 +185,12 @@ class GitHubIssueCommentRepository {
|
|
|
155
185
|
return;
|
|
156
186
|
}
|
|
157
187
|
}
|
|
188
|
+
const stateFilePath = (0, githubSecondaryRateLimitBreaker_1.secondaryRateLimitStateFilePath)();
|
|
189
|
+
const nowMsBeforePost = Date.now();
|
|
190
|
+
const breaker = (0, githubSecondaryRateLimitBreaker_1.checkSecondaryRateLimitBreaker)(nowMsBeforePost, stateFilePath);
|
|
191
|
+
if (breaker.isBlocked && breaker.resetTimeMs !== null) {
|
|
192
|
+
throw new githubRateLimitRetry_1.GitHubRateLimitError(`GitHub secondary rate limit is active until ${new Date(breaker.resetTimeMs).toISOString()}`, new Date(breaker.resetTimeMs).toISOString());
|
|
193
|
+
}
|
|
158
194
|
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}/comments`, {
|
|
159
195
|
method: 'POST',
|
|
160
196
|
headers: {
|
|
@@ -165,6 +201,13 @@ class GitHubIssueCommentRepository {
|
|
|
165
201
|
body: JSON.stringify({ body: commentContent }),
|
|
166
202
|
});
|
|
167
203
|
if (!response.ok) {
|
|
204
|
+
const bodyText = await response.text().catch(() => '');
|
|
205
|
+
const nowMs = Date.now();
|
|
206
|
+
if ((0, githubRateLimitRetry_1.isSecondaryRateLimit)(response.headers, bodyText)) {
|
|
207
|
+
const backoffMs = (0, githubRateLimitRetry_1.computeSecondaryRateLimitBackoffMs)(response.headers, nowMs);
|
|
208
|
+
(0, githubSecondaryRateLimitBreaker_1.writeSecondaryRateLimitState)(nowMs + backoffMs, nowMs, stateFilePath);
|
|
209
|
+
throw new githubRateLimitRetry_1.GitHubRateLimitError(`HTTP ${response.status} GitHub API secondary rate limit exceeded`, new Date(nowMs + backoffMs).toISOString());
|
|
210
|
+
}
|
|
168
211
|
throw new Error(`Failed to create comment via GitHub REST API: ${response.status} ${response.statusText}`);
|
|
169
212
|
}
|
|
170
213
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GitHubIssueCommentRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubIssueCommentRepository.ts"],"names":[],"mappings":";;;AAGA,iEAGgC;
|
|
1
|
+
{"version":3,"file":"GitHubIssueCommentRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/GitHubIssueCommentRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -230,6 +230,13 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
230
230
|
this.lastIssuesFetchedAtByProjectId = new Map();
|
|
231
231
|
this.getLastIssuesFetchedAt = (projectId) => this.lastIssuesFetchedAtByProjectId.get(projectId) ?? null;
|
|
232
232
|
this.fetchWithRateLimitRetry = (request) => (0, githubRateLimitRetry_1.fetchWithGitHubRateLimitRetry)(request, this.sleep);
|
|
233
|
+
/**
|
|
234
|
+
* Variant for content-creating requests (POST / PUT / PATCH / DELETE).
|
|
235
|
+
* Checks the shared secondary rate limit circuit breaker before issuing
|
|
236
|
+
* the request so that a block discovered by one process immediately
|
|
237
|
+
* silences all other processes on the host.
|
|
238
|
+
*/
|
|
239
|
+
this.fetchWithRateLimitRetryForWrite = (request) => (0, githubRateLimitRetry_1.fetchWithGitHubRateLimitRetry)(request, this.sleep, Date.now, false, true);
|
|
233
240
|
this.throwGitHubError = async (prefix, response) => {
|
|
234
241
|
const bodyText = await response.clone().text();
|
|
235
242
|
const isRateLimit = (0, githubRateLimitRetry_1.hasRateLimitSignals)(response.status, response.headers, bodyText);
|
|
@@ -1695,7 +1702,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
1695
1702
|
};
|
|
1696
1703
|
this.closePullRequest = async (prUrl) => {
|
|
1697
1704
|
const { owner, repo, issueNumber: prNumber } = this.parseIssueUrl(prUrl);
|
|
1698
|
-
const response = await this.
|
|
1705
|
+
const response = await this.fetchWithRateLimitRetryForWrite(() => fetch(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${prNumber}`, {
|
|
1699
1706
|
method: 'PATCH',
|
|
1700
1707
|
headers: {
|
|
1701
1708
|
Authorization: `Bearer ${this.ghToken}`,
|
|
@@ -1712,7 +1719,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
1712
1719
|
const { owner, repo, issueNumber } = this.parseIssueUrl(issueUrl);
|
|
1713
1720
|
const ownerSegment = encodeURIComponent(owner);
|
|
1714
1721
|
const repoSegment = encodeURIComponent(repo);
|
|
1715
|
-
const response = await this.
|
|
1722
|
+
const response = await this.fetchWithRateLimitRetryForWrite(() => fetch(`https://api.github.com/repos/${ownerSegment}/${repoSegment}/issues/${issueNumber}`, {
|
|
1716
1723
|
method: 'PATCH',
|
|
1717
1724
|
headers: {
|
|
1718
1725
|
Authorization: `Bearer ${this.ghToken}`,
|
|
@@ -1779,7 +1786,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
1779
1786
|
};
|
|
1780
1787
|
this.approvePullRequest = async (prUrl) => {
|
|
1781
1788
|
const { owner, repo, issueNumber: prNumber } = this.parseIssueUrl(prUrl);
|
|
1782
|
-
const response = await this.
|
|
1789
|
+
const response = await this.fetchWithRateLimitRetryForWrite(() => fetch(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${prNumber}/reviews`, {
|
|
1783
1790
|
method: 'POST',
|
|
1784
1791
|
headers: {
|
|
1785
1792
|
Authorization: `Bearer ${this.ghToken}`,
|
|
@@ -1801,7 +1808,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
1801
1808
|
'Content-Type': 'application/json',
|
|
1802
1809
|
Accept: 'application/vnd.github+json',
|
|
1803
1810
|
};
|
|
1804
|
-
const mergeWith = (mergeMethod) => this.
|
|
1811
|
+
const mergeWith = (mergeMethod) => this.fetchWithRateLimitRetryForWrite(() => fetch(mergeUrl, {
|
|
1805
1812
|
method: 'PUT',
|
|
1806
1813
|
headers,
|
|
1807
1814
|
body: JSON.stringify(mergeMethod ? { merge_method: mergeMethod } : {}),
|
|
@@ -1865,7 +1872,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
1865
1872
|
body: commentBody,
|
|
1866
1873
|
comments: [inlineComment],
|
|
1867
1874
|
};
|
|
1868
|
-
const response = await this.
|
|
1875
|
+
const response = await this.fetchWithRateLimitRetryForWrite(() => fetch(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${prNumber}/reviews`, {
|
|
1869
1876
|
method: 'POST',
|
|
1870
1877
|
headers: {
|
|
1871
1878
|
Authorization: `Bearer ${this.ghToken}`,
|
|
@@ -1918,7 +1925,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
1918
1925
|
const commitId = await this.fetchPullRequestHeadSha(owner, repo, prNumber, prUrl);
|
|
1919
1926
|
const ownerSegment = encodeURIComponent(owner);
|
|
1920
1927
|
const repoSegment = encodeURIComponent(repo);
|
|
1921
|
-
const response = await this.
|
|
1928
|
+
const response = await this.fetchWithRateLimitRetryForWrite(() => fetch(`https://api.github.com/repos/${ownerSegment}/${repoSegment}/pulls/${prNumber}/comments`, {
|
|
1922
1929
|
method: 'POST',
|
|
1923
1930
|
headers: {
|
|
1924
1931
|
Authorization: `Bearer ${this.ghToken}`,
|
|
@@ -1988,7 +1995,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
1988
1995
|
};
|
|
1989
1996
|
this.updateBranch = async (prUrl) => {
|
|
1990
1997
|
const { owner, repo, issueNumber: prNumber } = this.parseIssueUrl(prUrl);
|
|
1991
|
-
const response = await this.
|
|
1998
|
+
const response = await this.fetchWithRateLimitRetryForWrite(() => fetch(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${prNumber}/update-branch`, {
|
|
1992
1999
|
method: 'PUT',
|
|
1993
2000
|
headers: {
|
|
1994
2001
|
Authorization: `Bearer ${this.ghToken}`,
|
|
@@ -2006,7 +2013,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
2006
2013
|
};
|
|
2007
2014
|
this.deletePullRequestBranch = async (prUrl, branchName) => {
|
|
2008
2015
|
const { owner, repo } = this.parseIssueUrl(prUrl);
|
|
2009
|
-
const response = await this.
|
|
2016
|
+
const response = await this.fetchWithRateLimitRetryForWrite(() => fetch(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/git/refs/heads/${encodeURIComponent(branchName)}`, {
|
|
2010
2017
|
method: 'DELETE',
|
|
2011
2018
|
headers: {
|
|
2012
2019
|
Authorization: `Bearer ${this.ghToken}`,
|
|
@@ -2301,7 +2308,7 @@ class ApiV3CheerioRestIssueRepository extends BaseGitHubRepository_1.BaseGitHubR
|
|
|
2301
2308
|
throw new Error(`Unexpected response shape when fetching comments for ${issueOrPrUrl}`);
|
|
2302
2309
|
}
|
|
2303
2310
|
for (const comment of body) {
|
|
2304
|
-
const deleteResponse = await this.
|
|
2311
|
+
const deleteResponse = await this.fetchWithRateLimitRetryForWrite(() => fetch(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/issues/comments/${comment.id}`, {
|
|
2305
2312
|
method: 'DELETE',
|
|
2306
2313
|
headers: {
|
|
2307
2314
|
Authorization: `Bearer ${this.ghToken}`,
|