@remogram/provider-gitea-api 0.1.0-beta.1 → 0.1.0-beta.3
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/index.js +118 -29
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -7,22 +7,36 @@ import {
|
|
|
7
7
|
gitRevParse,
|
|
8
8
|
gitCurrentBranch,
|
|
9
9
|
gitAheadBehind,
|
|
10
|
+
refsInventory,
|
|
11
|
+
crInventory,
|
|
12
|
+
mergeBlockersFromFacts,
|
|
10
13
|
ERROR_CODES,
|
|
11
14
|
forgeError,
|
|
12
15
|
forgeIngestCapabilityFacts,
|
|
16
|
+
checkPaginationCapabilityFacts,
|
|
17
|
+
DEFAULT_CHECK_STATUS_PAGE_SIZE,
|
|
18
|
+
MAX_CHECK_STATUS_PAGES,
|
|
19
|
+
paginateCheckStatusPages,
|
|
20
|
+
paginateOffsetListPages,
|
|
21
|
+
fetchWithIngestPageBackoff,
|
|
22
|
+
fetchPageWithIngestBackoff,
|
|
23
|
+
withPerPageParam,
|
|
24
|
+
apiProviderCommands,
|
|
13
25
|
} from '@remogram/core';
|
|
14
26
|
const PUBLIC_GITEA_HOST = 'gitea.com';
|
|
15
27
|
const PUBLIC_GITEA_API = 'https://gitea.com/api/v1';
|
|
16
28
|
const AUTH_CAPABILITIES = [
|
|
17
29
|
'repo_status',
|
|
18
30
|
'ref_compare',
|
|
31
|
+
'ref_inventory',
|
|
32
|
+
'cr_inventory',
|
|
19
33
|
'pr_status',
|
|
20
34
|
'pr_checks',
|
|
21
35
|
'merge_plan',
|
|
22
36
|
'sync_plan',
|
|
23
37
|
];
|
|
24
38
|
|
|
25
|
-
const STRUCTURED_COMMANDS =
|
|
39
|
+
const STRUCTURED_COMMANDS = apiProviderCommands();
|
|
26
40
|
|
|
27
41
|
export function giteaToken() {
|
|
28
42
|
return process.env.GITEA_TOKEN || null;
|
|
@@ -118,23 +132,21 @@ export async function giteaFetch(config, parsed, path, options = {}) {
|
|
|
118
132
|
});
|
|
119
133
|
}
|
|
120
134
|
|
|
121
|
-
const MAX_CHECK_PAGES =
|
|
135
|
+
const MAX_CHECK_PAGES = MAX_CHECK_STATUS_PAGES;
|
|
122
136
|
const GITEA_PAGE_SIZE = 100;
|
|
123
137
|
|
|
124
138
|
export async function giteaFetchPaginated(config, parsed, path) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
return all;
|
|
139
|
+
return paginateCheckStatusPages({
|
|
140
|
+
fetchPage: async ({ page, limit }) => {
|
|
141
|
+
const separator = path.includes('?') ? '&' : '?';
|
|
142
|
+
const body = await giteaFetch(
|
|
143
|
+
config,
|
|
144
|
+
parsed,
|
|
145
|
+
`${path}${separator}limit=${limit}&page=${page}`,
|
|
146
|
+
);
|
|
147
|
+
return Array.isArray(body) ? body : [];
|
|
148
|
+
},
|
|
149
|
+
});
|
|
138
150
|
}
|
|
139
151
|
|
|
140
152
|
export function normalizeGiteaStatusState(state) {
|
|
@@ -149,6 +161,36 @@ export function normalizeGiteaStatusState(state) {
|
|
|
149
161
|
return 'unknown';
|
|
150
162
|
}
|
|
151
163
|
|
|
164
|
+
function giteaStatusRecordOrder(a, b) {
|
|
165
|
+
const aUpdated = Date.parse(a.updated_at ?? '') || 0;
|
|
166
|
+
const bUpdated = Date.parse(b.updated_at ?? '') || 0;
|
|
167
|
+
if (aUpdated !== bUpdated) return aUpdated - bUpdated;
|
|
168
|
+
const aId = Number(a.id) || 0;
|
|
169
|
+
const bId = Number(b.id) || 0;
|
|
170
|
+
return aId - bId;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function dedupeGiteaStatusRecords(records) {
|
|
174
|
+
const latestByContext = new Map();
|
|
175
|
+
for (const record of records) {
|
|
176
|
+
const context = record?.context;
|
|
177
|
+
if (context == null || context === '') continue;
|
|
178
|
+
const existing = latestByContext.get(context);
|
|
179
|
+
if (!existing || giteaStatusRecordOrder(record, existing) > 0) {
|
|
180
|
+
latestByContext.set(context, record);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return Array.from(latestByContext.values());
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function mapGiteaCommitStatuses(records) {
|
|
187
|
+
return dedupeGiteaStatusRecords(records).map((s) => ({
|
|
188
|
+
context: sanitizeField(s.context),
|
|
189
|
+
state: normalizeGiteaStatusState(s.status ?? s.state),
|
|
190
|
+
description: sanitizeField(s.description),
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
|
|
152
194
|
export function normalizeGiteaPrState(state) {
|
|
153
195
|
const normalized = String(state ?? '').toLowerCase();
|
|
154
196
|
if (normalized === 'open') return 'open';
|
|
@@ -172,15 +214,21 @@ export async function repoStatus(ctx) {
|
|
|
172
214
|
}
|
|
173
215
|
|
|
174
216
|
export function providerCapabilities() {
|
|
217
|
+
const check_sources = ['commit_statuses'];
|
|
175
218
|
return {
|
|
176
219
|
commands: STRUCTURED_COMMANDS,
|
|
177
220
|
auth_envs: ['GITEA_TOKEN'],
|
|
178
|
-
check_sources
|
|
221
|
+
check_sources,
|
|
179
222
|
mergeability_confidence: 'direct',
|
|
180
223
|
host_binding: 'verified_remote_host',
|
|
181
224
|
pagination: 'supported',
|
|
182
225
|
write_support: false,
|
|
183
226
|
...forgeIngestCapabilityFacts(),
|
|
227
|
+
...checkPaginationCapabilityFacts({
|
|
228
|
+
strategy: 'offset_limit',
|
|
229
|
+
pageSizeParam: 'limit',
|
|
230
|
+
sourceCount: check_sources.length,
|
|
231
|
+
}),
|
|
184
232
|
};
|
|
185
233
|
}
|
|
186
234
|
|
|
@@ -213,6 +261,48 @@ export async function getPull(ctx, { number }) {
|
|
|
213
261
|
return giteaFetch(ctx.config, ctx.parsed, repoApiPath(ctx.config, 'pulls', number));
|
|
214
262
|
}
|
|
215
263
|
|
|
264
|
+
export async function listOpenPullsWithMeta(ctx, opts = {}) {
|
|
265
|
+
requireToken();
|
|
266
|
+
const listLimit =
|
|
267
|
+
opts.limit != null && Number.isInteger(Number(opts.limit)) && Number(opts.limit) > 0
|
|
268
|
+
? Number(opts.limit)
|
|
269
|
+
: null;
|
|
270
|
+
const pageSize =
|
|
271
|
+
listLimit != null ? Math.min(listLimit, GITEA_PAGE_SIZE) : GITEA_PAGE_SIZE;
|
|
272
|
+
const path = `${repoApiPath(ctx.config, 'pulls')}?state=open`;
|
|
273
|
+
const pageSep = path.includes('?') ? '&' : '?';
|
|
274
|
+
const { items: all, list_truncated: listTruncated } = await paginateOffsetListPages({
|
|
275
|
+
pageSize,
|
|
276
|
+
listLimit,
|
|
277
|
+
...(listLimit != null && pageSize < listLimit ? { maxPagesTruncatesWithLimit: true } : {}),
|
|
278
|
+
fetchPage: async ({ page, limit }) => {
|
|
279
|
+
const body = await giteaFetch(
|
|
280
|
+
ctx.config,
|
|
281
|
+
ctx.parsed,
|
|
282
|
+
`${path}${pageSep}limit=${limit}&page=${page}`,
|
|
283
|
+
);
|
|
284
|
+
return Array.isArray(body) ? body : [];
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
let numbers = all
|
|
288
|
+
.map((pr) => pr.number)
|
|
289
|
+
.filter((number) => Number.isInteger(number))
|
|
290
|
+
.sort((a, b) => a - b);
|
|
291
|
+
if (listLimit != null && numbers.length > listLimit) {
|
|
292
|
+
numbers = numbers.slice(0, listLimit);
|
|
293
|
+
}
|
|
294
|
+
return { numbers, list_truncated: listTruncated };
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export async function listOpenPulls(ctx, opts = {}) {
|
|
298
|
+
const meta = await listOpenPullsWithMeta(ctx, opts);
|
|
299
|
+
return meta.numbers;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export async function crInventorySlice(ctx, opts = {}) {
|
|
303
|
+
return crInventory(ctx, { listOpenPulls, listOpenPullsWithMeta, prView, prChecks }, opts);
|
|
304
|
+
}
|
|
305
|
+
|
|
216
306
|
function mergeability(pr) {
|
|
217
307
|
if (pr.mergeable === true) return 'clean';
|
|
218
308
|
if (pr.mergeable === false) return 'conflicted';
|
|
@@ -254,18 +344,19 @@ export async function prChecks(ctx, opts) {
|
|
|
254
344
|
forgeError: forgeError(ERROR_CODES.MISSING_REF, 'Could not determine head SHA for checks'),
|
|
255
345
|
});
|
|
256
346
|
}
|
|
257
|
-
const statusRecords = await giteaFetchPaginated(
|
|
347
|
+
const { items: statusRecords, truncated: checks_truncated } = await giteaFetchPaginated(
|
|
258
348
|
ctx.config,
|
|
259
349
|
ctx.parsed,
|
|
260
350
|
repoApiPath(ctx.config, 'commits', sha, 'statuses'),
|
|
261
351
|
);
|
|
262
|
-
const mapped = statusRecords
|
|
263
|
-
context: sanitizeField(s.context),
|
|
264
|
-
state: normalizeGiteaStatusState(s.state),
|
|
265
|
-
description: sanitizeField(s.description),
|
|
266
|
-
}));
|
|
352
|
+
const mapped = mapGiteaCommitStatuses(statusRecords);
|
|
267
353
|
const conclusion = summarizeChecks(mapped);
|
|
268
|
-
return {
|
|
354
|
+
return {
|
|
355
|
+
head_sha: sha,
|
|
356
|
+
check_conclusion: conclusion,
|
|
357
|
+
checks_truncated,
|
|
358
|
+
statuses: mapped,
|
|
359
|
+
};
|
|
269
360
|
}
|
|
270
361
|
|
|
271
362
|
export function summarizeChecks(statuses) {
|
|
@@ -279,12 +370,7 @@ export function summarizeChecks(statuses) {
|
|
|
279
370
|
export async function mergePlan(ctx, opts) {
|
|
280
371
|
const view = await prView(ctx, opts);
|
|
281
372
|
const checks = await prChecks(ctx, { number: view.pr_number });
|
|
282
|
-
const blockers =
|
|
283
|
-
if (view.mergeability === 'conflicted') blockers.push('merge_conflict');
|
|
284
|
-
if (view.state !== 'open') blockers.push('pr_not_open');
|
|
285
|
-
if (checks.check_conclusion === 'failure') blockers.push('checks_failed');
|
|
286
|
-
if (checks.check_conclusion === 'missing') blockers.push('checks_missing');
|
|
287
|
-
if (checks.check_conclusion === 'pending') blockers.push('checks_pending');
|
|
373
|
+
const blockers = mergeBlockersFromFacts(view, checks);
|
|
288
374
|
return {
|
|
289
375
|
pr_number: view.pr_number,
|
|
290
376
|
mergeability: view.mergeability,
|
|
@@ -325,6 +411,9 @@ export const provider = {
|
|
|
325
411
|
providerCapabilities,
|
|
326
412
|
repoStatus,
|
|
327
413
|
refsCompare,
|
|
414
|
+
refsInventory,
|
|
415
|
+
listOpenPulls,
|
|
416
|
+
crInventory: crInventorySlice,
|
|
328
417
|
prView,
|
|
329
418
|
prChecks,
|
|
330
419
|
mergePlan,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remogram/provider-gitea-api",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
4
|
"description": "Gitea REST API forge provider for remogram",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,6 +22,6 @@
|
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@remogram/core": "0.1.0-beta.
|
|
25
|
+
"@remogram/core": "0.1.0-beta.3"
|
|
26
26
|
}
|
|
27
27
|
}
|