@remogram/provider-gitlab-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 +89 -24
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -7,9 +7,21 @@ 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
|
|
|
15
27
|
const PUBLIC_GITLAB_HOST = 'gitlab.com';
|
|
@@ -17,12 +29,14 @@ const PUBLIC_GITLAB_API = 'https://gitlab.com/api/v4';
|
|
|
17
29
|
const AUTH_CAPABILITIES = [
|
|
18
30
|
'repo_status',
|
|
19
31
|
'ref_compare',
|
|
32
|
+
'ref_inventory',
|
|
33
|
+
'cr_inventory',
|
|
20
34
|
'pr_status',
|
|
21
35
|
'pr_checks',
|
|
22
36
|
'merge_plan',
|
|
23
37
|
'sync_plan',
|
|
24
38
|
];
|
|
25
|
-
const STRUCTURED_COMMANDS =
|
|
39
|
+
const STRUCTURED_COMMANDS = apiProviderCommands();
|
|
26
40
|
|
|
27
41
|
export function gitlabToken() {
|
|
28
42
|
return process.env.GITLAB_TOKEN || null;
|
|
@@ -115,35 +129,39 @@ export async function gitlabFetch(config, parsed, path, options = {}) {
|
|
|
115
129
|
});
|
|
116
130
|
}
|
|
117
131
|
|
|
118
|
-
const MAX_CHECK_PAGES =
|
|
132
|
+
const MAX_CHECK_PAGES = MAX_CHECK_STATUS_PAGES;
|
|
119
133
|
const GITLAB_PAGE_SIZE = 100;
|
|
120
134
|
|
|
121
135
|
export async function gitlabFetchPaginated(config, parsed, path) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
return all;
|
|
136
|
+
return paginateCheckStatusPages({
|
|
137
|
+
fetchPage: async ({ page, limit }) => {
|
|
138
|
+
const separator = path.includes('?') ? '&' : '?';
|
|
139
|
+
const body = await gitlabFetch(
|
|
140
|
+
config,
|
|
141
|
+
parsed,
|
|
142
|
+
`${path}${separator}per_page=${limit}&page=${page}`,
|
|
143
|
+
);
|
|
144
|
+
return Array.isArray(body) ? body : [];
|
|
145
|
+
},
|
|
146
|
+
});
|
|
135
147
|
}
|
|
136
148
|
|
|
137
149
|
export function providerCapabilities() {
|
|
150
|
+
const check_sources = ['commit_statuses', 'pipelines'];
|
|
138
151
|
return {
|
|
139
152
|
commands: STRUCTURED_COMMANDS,
|
|
140
153
|
auth_envs: ['GITLAB_TOKEN'],
|
|
141
|
-
check_sources
|
|
154
|
+
check_sources,
|
|
142
155
|
mergeability_confidence: 'derived',
|
|
143
156
|
host_binding: 'verified_remote_host',
|
|
144
157
|
pagination: 'supported',
|
|
145
158
|
write_support: false,
|
|
146
159
|
...forgeIngestCapabilityFacts(),
|
|
160
|
+
...checkPaginationCapabilityFacts({
|
|
161
|
+
strategy: 'offset_limit',
|
|
162
|
+
pageSizeParam: 'per_page',
|
|
163
|
+
sourceCount: check_sources.length,
|
|
164
|
+
}),
|
|
147
165
|
};
|
|
148
166
|
}
|
|
149
167
|
|
|
@@ -259,7 +277,7 @@ export async function prChecks(ctx, opts) {
|
|
|
259
277
|
});
|
|
260
278
|
}
|
|
261
279
|
|
|
262
|
-
const [
|
|
280
|
+
const [statusResult, pipelineResult] = await Promise.all([
|
|
263
281
|
gitlabFetchPaginated(
|
|
264
282
|
ctx.config,
|
|
265
283
|
ctx.parsed,
|
|
@@ -271,6 +289,8 @@ export async function prChecks(ctx, opts) {
|
|
|
271
289
|
`${projectApiPath(ctx.config, 'pipelines')}?sha=${encodeURIComponent(sha)}`,
|
|
272
290
|
),
|
|
273
291
|
]);
|
|
292
|
+
const statusRecords = statusResult.items;
|
|
293
|
+
const pipelineRecords = pipelineResult.items;
|
|
274
294
|
const mappedStatuses = statusRecords.map((status) => ({
|
|
275
295
|
context: sanitizeField(status.name || status.context),
|
|
276
296
|
state: normalizeStatusState(status.status),
|
|
@@ -282,18 +302,19 @@ export async function prChecks(ctx, opts) {
|
|
|
282
302
|
description: sanitizeField(pipeline.status),
|
|
283
303
|
}));
|
|
284
304
|
const mapped = [...mappedStatuses, ...mappedPipelines];
|
|
285
|
-
|
|
305
|
+
const checks_truncated = statusResult.truncated || pipelineResult.truncated;
|
|
306
|
+
return {
|
|
307
|
+
head_sha: sha,
|
|
308
|
+
check_conclusion: summarizeChecks(mapped),
|
|
309
|
+
checks_truncated,
|
|
310
|
+
statuses: mapped,
|
|
311
|
+
};
|
|
286
312
|
}
|
|
287
313
|
|
|
288
314
|
export async function mergePlan(ctx, opts) {
|
|
289
315
|
const view = await prView(ctx, opts);
|
|
290
316
|
const checks = await prChecks(ctx, { number: view.pr_number });
|
|
291
|
-
const blockers =
|
|
292
|
-
if (view.mergeability === 'conflicted') blockers.push('merge_conflict');
|
|
293
|
-
if (view.state !== 'open') blockers.push('pr_not_open');
|
|
294
|
-
if (checks.check_conclusion === 'failure') blockers.push('checks_failed');
|
|
295
|
-
if (checks.check_conclusion === 'missing') blockers.push('checks_missing');
|
|
296
|
-
if (checks.check_conclusion === 'pending') blockers.push('checks_pending');
|
|
317
|
+
const blockers = mergeBlockersFromFacts(view, checks);
|
|
297
318
|
return {
|
|
298
319
|
pr_number: view.pr_number,
|
|
299
320
|
mergeability: view.mergeability,
|
|
@@ -302,6 +323,47 @@ export async function mergePlan(ctx, opts) {
|
|
|
302
323
|
};
|
|
303
324
|
}
|
|
304
325
|
|
|
326
|
+
export async function listOpenPullsWithMeta(ctx, opts = {}) {
|
|
327
|
+
apiBase(ctx.config, ctx.parsed);
|
|
328
|
+
requireToken();
|
|
329
|
+
const listLimit =
|
|
330
|
+
opts.limit != null && Number.isInteger(Number(opts.limit)) && Number(opts.limit) > 0
|
|
331
|
+
? Number(opts.limit)
|
|
332
|
+
: null;
|
|
333
|
+
const path = `${projectApiPath(ctx.config, 'merge_requests')}?state=opened`;
|
|
334
|
+
const separator = path.includes('?') ? '&' : '?';
|
|
335
|
+
const { items: all, list_truncated: listTruncated } = await paginateOffsetListPages({
|
|
336
|
+
pageSize: GITLAB_PAGE_SIZE,
|
|
337
|
+
listLimit,
|
|
338
|
+
...(listLimit != null ? { maxPagesTruncatesWithLimit: true } : {}),
|
|
339
|
+
fetchPage: async ({ page, limit }) => {
|
|
340
|
+
const body = await gitlabFetch(
|
|
341
|
+
ctx.config,
|
|
342
|
+
ctx.parsed,
|
|
343
|
+
`${path}${separator}per_page=${limit}&page=${page}`,
|
|
344
|
+
);
|
|
345
|
+
return Array.isArray(body) ? body : [];
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
let numbers = all
|
|
349
|
+
.map((mr) => mr.iid)
|
|
350
|
+
.filter((number) => Number.isInteger(number))
|
|
351
|
+
.sort((a, b) => a - b);
|
|
352
|
+
if (listLimit != null && numbers.length > listLimit) {
|
|
353
|
+
numbers = numbers.slice(0, listLimit);
|
|
354
|
+
}
|
|
355
|
+
return { numbers, list_truncated: listTruncated };
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export async function listOpenPulls(ctx, opts = {}) {
|
|
359
|
+
const meta = await listOpenPullsWithMeta(ctx, opts);
|
|
360
|
+
return meta.numbers;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export async function crInventorySlice(ctx, opts = {}) {
|
|
364
|
+
return crInventory(ctx, { listOpenPulls, listOpenPullsWithMeta, prView, prChecks }, opts);
|
|
365
|
+
}
|
|
366
|
+
|
|
305
367
|
export async function syncPlan(ctx, remoteName = 'origin') {
|
|
306
368
|
assertGitRemote(remoteName, 'remote');
|
|
307
369
|
apiBase(ctx.config, ctx.parsed);
|
|
@@ -335,6 +397,9 @@ export const provider = {
|
|
|
335
397
|
providerCapabilities,
|
|
336
398
|
repoStatus,
|
|
337
399
|
refsCompare,
|
|
400
|
+
refsInventory,
|
|
401
|
+
listOpenPulls,
|
|
402
|
+
crInventory: crInventorySlice,
|
|
338
403
|
prView,
|
|
339
404
|
prChecks,
|
|
340
405
|
mergePlan,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remogram/provider-gitlab-api",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
4
|
"description": "GitLab API 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
|
}
|