@remogram/provider-gitlab-api 0.1.0-beta.6 → 0.1.0-beta.9

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.
@@ -0,0 +1,13 @@
1
+ /** @type {((ctx: object, opts: { branchRef: string }) => Promise<object>) | null} */
2
+ let branchProtectionImpl = null;
3
+
4
+ export function setBranchProtectionImpl(fn) {
5
+ branchProtectionImpl = fn;
6
+ }
7
+
8
+ export async function resolveBranchProtection(ctx, opts) {
9
+ if (typeof branchProtectionImpl !== 'function') {
10
+ throw new Error('branch protection impl not registered');
11
+ }
12
+ return branchProtectionImpl(ctx, opts);
13
+ }
package/index.js CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  buildMergePlanFromProviderFacts,
14
14
  ERROR_CODES,
15
15
  forgeError,
16
+ LIVE_REACHABILITY_TIMEOUT_MS,
16
17
  forgeIngestCapabilityFacts,
17
18
  checkPaginationCapabilityFacts,
18
19
  openPullListCapabilityFacts,
@@ -39,6 +40,7 @@ import {
39
40
  appendSortQuery,
40
41
  buildProviderIdentityFromGitLabUser,
41
42
  buildBranchProtectionFromGitLabProtection,
43
+ buildPrChecksBody,
42
44
  buildCrFilesFromGitLabChanges,
43
45
  buildCrCommentsBody,
44
46
  buildCrCommentsFromGitLabDiscussions,
@@ -48,11 +50,16 @@ import {
48
50
  appendForgeChangeEvents,
49
51
  parseStatusSetArgs,
50
52
  buildCommitStatusSetBody,
53
+ idempotencyPacketFields,
51
54
  normalizeStatusSetState,
52
55
  MAX_OPEN_PULL_IDEMPOTENCY_PAGES,
53
56
  statusSetIdempotencyScanCapabilityFacts,
54
57
  assertWriteCommandConfigured,
55
58
  } from '@remogram/core';
59
+ import {
60
+ resolveBranchProtection,
61
+ setBranchProtectionImpl,
62
+ } from './branch-protection-internal.js';
56
63
 
57
64
  const PUBLIC_GITLAB_HOST = 'gitlab.com';
58
65
  const PUBLIC_GITLAB_API = 'https://gitlab.com/api/v4';
@@ -177,6 +184,22 @@ export async function gitlabFetchWithMeta(config, parsed, path, options = {}) {
177
184
  });
178
185
  }
179
186
 
187
+ export async function apiReachability(ctx) {
188
+ if (!gitlabToken()) {
189
+ throw Object.assign(new Error('GITLAB_TOKEN not set'), {
190
+ forgeError: forgeError(ERROR_CODES.UNAUTHENTICATED_PROVIDER, 'GITLAB_TOKEN not set'),
191
+ });
192
+ }
193
+ const token = requireToken();
194
+ const url = `${apiBase(ctx.config, ctx.parsed)}${projectApiPath(ctx.config)}`;
195
+ await fetchJson(
196
+ url,
197
+ { headers: authHeaders(token) },
198
+ LIVE_REACHABILITY_TIMEOUT_MS,
199
+ );
200
+ return { repo_accessible: true };
201
+ }
202
+
180
203
  const MAX_CHECK_PAGES = MAX_CHECK_STATUS_PAGES;
181
204
  const GITLAB_PAGE_SIZE = 100;
182
205
 
@@ -246,10 +269,10 @@ export async function refsCompare(ctx, baseRef, headRef) {
246
269
  });
247
270
  }
248
271
  return {
249
- base_ref: sanitizeField(baseRef),
250
- base_sha: baseSha,
251
- head_ref: sanitizeField(headRef),
252
- head_sha: headSha,
272
+ compare_base_ref: sanitizeField(baseRef),
273
+ compare_base_sha: baseSha,
274
+ compare_head_ref: sanitizeField(headRef),
275
+ compare_head_sha: headSha,
253
276
  ...gitAheadBehind(ctx.cwd, baseSha, headSha),
254
277
  };
255
278
  }
@@ -286,10 +309,10 @@ export async function prView(ctx, opts) {
286
309
  url: sanitizeUrl(mr.web_url ?? mr.url),
287
310
  title: sanitizeField(mr.title),
288
311
  state: normalizeMrState(mr.state),
289
- base_ref: sanitizeField(mr.target_branch),
290
- base_sha: sanitizeField(mr.diff_refs?.base_sha),
291
- head_ref: sanitizeField(mr.source_branch),
292
- head_sha: sanitizeField(mr.sha ?? mr.diff_refs?.head_sha),
312
+ forge_target_branch_ref: sanitizeField(mr.target_branch),
313
+ forge_target_sha: sanitizeField(mr.diff_refs?.base_sha),
314
+ forge_source_branch_ref: sanitizeField(mr.source_branch),
315
+ forge_source_sha: sanitizeField(mr.sha ?? mr.diff_refs?.head_sha),
293
316
  mergeability: mergeability(mr),
294
317
  };
295
318
  }
@@ -313,6 +336,7 @@ export async function prChecks(ctx, opts) {
313
336
  apiBase(ctx.config, ctx.parsed);
314
337
  requireToken();
315
338
  let sha;
339
+ let requiredContexts = [];
316
340
  if (opts.ref) {
317
341
  assertGitRef(opts.ref, 'ref');
318
342
  sha = gitRevParse(ctx.cwd, opts.ref);
@@ -324,6 +348,11 @@ export async function prChecks(ctx, opts) {
324
348
  } else {
325
349
  const mr = await getMergeRequest(ctx, opts);
326
350
  sha = mr.sha ?? mr.diff_refs?.head_sha;
351
+ const targetBranch = mr.target_branch;
352
+ if (targetBranch) {
353
+ const protection = await resolveBranchProtection(ctx, { branchRef: targetBranch });
354
+ requiredContexts = protection.required_status_contexts ?? [];
355
+ }
327
356
  }
328
357
  if (!sha) {
329
358
  throw Object.assign(new Error('No SHA'), {
@@ -349,20 +378,26 @@ export async function prChecks(ctx, opts) {
349
378
  context: sanitizeField(status.name || status.context),
350
379
  state: normalizeStatusState(status.status),
351
380
  description: sanitizeField(status.description || status.status),
381
+ ...(status.target_url ? { target_url: sanitizeField(status.target_url) } : {}),
382
+ sha,
383
+ source: 'commit_status',
352
384
  }));
353
385
  const mappedPipelines = pipelineRecords.map((pipeline) => ({
354
386
  context: sanitizeField(pipeline.name || `pipeline:${pipeline.id}`),
355
387
  state: normalizeStatusState(pipeline.status),
356
388
  description: sanitizeField(pipeline.status),
389
+ sha,
390
+ source: 'pipeline',
357
391
  }));
358
392
  const mapped = [...mappedStatuses, ...mappedPipelines];
359
393
  const checks_truncated = statusResult.truncated || pipelineResult.truncated;
360
- return {
361
- head_sha: sha,
394
+ return buildPrChecksBody({
395
+ forge_source_sha: sha,
362
396
  check_conclusion: summarizeChecks(mapped),
363
397
  checks_truncated,
364
398
  statuses: mapped,
365
- };
399
+ required_contexts: requiredContexts,
400
+ });
366
401
  }
367
402
 
368
403
  export async function mergePlan(ctx, opts) {
@@ -857,7 +892,8 @@ export async function findCommitStatusByContext(ctx, sha, context) {
857
892
 
858
893
  export async function statusSet(ctx, args) {
859
894
  assertWriteCommandConfigured(ctx.config, 'status_set');
860
- const parsed = parseStatusSetArgs(args);
895
+ const { idempotencyFingerprint = null, ...rest } = args;
896
+ const parsed = parseStatusSetArgs(rest);
861
897
  const existing = await findCommitStatusByContext(ctx, parsed.sha, parsed.context);
862
898
  if (existing) {
863
899
  const requestedGitlabState = remogramStateToGitlabPostState(parsed.state);
@@ -867,7 +903,12 @@ export async function statusSet(ctx, args) {
867
903
  return buildCommitStatusSetBody(
868
904
  { ...existing, status: remogramState },
869
905
  parsed,
870
- { reusedExisting: true },
906
+ {
907
+ reusedExisting: true,
908
+ idempotencyFields: idempotencyFingerprint
909
+ ? idempotencyPacketFields(idempotencyFingerprint, { reusedExisting: true })
910
+ : null,
911
+ },
871
912
  );
872
913
  }
873
914
  }
@@ -893,12 +934,18 @@ export async function statusSet(ctx, args) {
893
934
  status: gitlabStatusAsRemogramState(response?.status ?? response?.state ?? parsed.state),
894
935
  },
895
936
  parsed,
937
+ {
938
+ idempotencyFields: idempotencyFingerprint
939
+ ? idempotencyPacketFields(idempotencyFingerprint, { reusedExisting: false })
940
+ : null,
941
+ },
896
942
  );
897
943
  }
898
944
 
899
945
  export const provider = {
900
946
  id: 'gitlab-api',
901
947
  providerCapabilities,
948
+ apiReachability,
902
949
  repoStatus,
903
950
  refsCompare,
904
951
  refsInventory,
@@ -915,3 +962,5 @@ export const provider = {
915
962
  forgeChanges,
916
963
  statusSet,
917
964
  };
965
+
966
+ setBranchProtectionImpl(branchProtection);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remogram/provider-gitlab-api",
3
- "version": "0.1.0-beta.6",
3
+ "version": "0.1.0-beta.9",
4
4
  "description": "GitLab API provider for remogram",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -16,12 +16,13 @@
16
16
  "*.js"
17
17
  ],
18
18
  "exports": {
19
- ".": "./index.js"
19
+ ".": "./index.js",
20
+ "./branch-protection-internal.js": "./branch-protection-internal.js"
20
21
  },
21
22
  "engines": {
22
23
  "node": ">=20"
23
24
  },
24
25
  "dependencies": {
25
- "@remogram/core": "0.1.0-beta.6"
26
+ "@remogram/core": "0.1.0-beta.9"
26
27
  }
27
28
  }