@goodfellow-cms/gitlab 0.9.0 → 0.10.0
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/dist/index.js +71 -25
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +4 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1368,27 +1368,77 @@ function gitlabSetup(options = {}) {
|
|
|
1368
1368
|
async function isAvailable(owner, name) {
|
|
1369
1369
|
return (await gitlabRequest(api, `/projects/${encodeURIComponent(`${owner.path}/${name}`)}`, { allow: [404] })).status === 404;
|
|
1370
1370
|
}
|
|
1371
|
+
const projectPath = (path) => `/projects/${encodeURIComponent(path)}`;
|
|
1372
|
+
/**
|
|
1373
|
+
* Makes one connection between a site's projects, giving what's left to do
|
|
1374
|
+
* by hand where GitLab refuses it, with what it answered.
|
|
1375
|
+
*/
|
|
1376
|
+
async function attempt(unmade, request, left) {
|
|
1377
|
+
try {
|
|
1378
|
+
await request();
|
|
1379
|
+
} catch (error) {
|
|
1380
|
+
if (!(error instanceof GitApiError)) throw error;
|
|
1381
|
+
left.push({
|
|
1382
|
+
...unmade,
|
|
1383
|
+
reason: error.message
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1371
1387
|
/**
|
|
1372
1388
|
* Lets each project's pipelines reach the other, as their setup files say:
|
|
1373
1389
|
* a job token is refused by a project whose job token allowlist doesn't
|
|
1374
1390
|
* name its project, even a public one. Also lets the code project's job
|
|
1375
|
-
* token publish updates
|
|
1376
|
-
*
|
|
1391
|
+
* token publish updates. Runs before the project's files are written,
|
|
1392
|
+
* since their first pipeline reads the other project. Each is tried on its
|
|
1393
|
+
* own, so one GitLab refuses doesn't keep the others from being made.
|
|
1377
1394
|
*/
|
|
1378
|
-
async function connectProjects(link) {
|
|
1379
|
-
const
|
|
1380
|
-
try {
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1395
|
+
async function connectProjects(link, left) {
|
|
1396
|
+
const ids = /* @__PURE__ */ new Map();
|
|
1397
|
+
for (const which of ["code", "content"]) try {
|
|
1398
|
+
ids.set(which, (await gitlabJson(api, projectPath(link[which]))).id);
|
|
1399
|
+
} catch (error) {
|
|
1400
|
+
if (!(error instanceof GitApiError)) throw error;
|
|
1401
|
+
}
|
|
1402
|
+
for (const { reader, read } of link.links.reads) {
|
|
1403
|
+
const target = ids.get(reader);
|
|
1404
|
+
await attempt({
|
|
1405
|
+
kind: "read",
|
|
1406
|
+
reader: link[reader],
|
|
1407
|
+
read: link[read],
|
|
1408
|
+
reason: ""
|
|
1409
|
+
}, async () => {
|
|
1410
|
+
if (target === void 0) throw new GitApiError(404, `GitLab couldn't find ${link[reader]}.`);
|
|
1411
|
+
await gitlabRequest(api, `${projectPath(link[read])}/job_token_scope/allowlist`, {
|
|
1412
|
+
method: "POST",
|
|
1413
|
+
body: { target_project_id: target }
|
|
1414
|
+
});
|
|
1415
|
+
}, left);
|
|
1416
|
+
}
|
|
1417
|
+
if (link.links.updates) {
|
|
1418
|
+
const repo = link[link.links.updates];
|
|
1419
|
+
await attempt({
|
|
1420
|
+
kind: "push",
|
|
1421
|
+
repo,
|
|
1422
|
+
reason: ""
|
|
1423
|
+
}, () => gitlabRequest(api, projectPath(repo), {
|
|
1388
1424
|
method: "PUT",
|
|
1389
1425
|
body: { ci_push_repository_for_job_token_allowed: true }
|
|
1390
|
-
});
|
|
1391
|
-
|
|
1426
|
+
}), left);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Runs the pipelines that need it each night. After the project's files
|
|
1431
|
+
* are written, since a schedule names the main branch, which an empty
|
|
1432
|
+
* project doesn't have yet.
|
|
1433
|
+
*/
|
|
1434
|
+
async function scheduleNightly(link, left) {
|
|
1435
|
+
for (const which of link.links.nightly) {
|
|
1436
|
+
const repo = link[which];
|
|
1437
|
+
await attempt({
|
|
1438
|
+
kind: "nightly",
|
|
1439
|
+
repo,
|
|
1440
|
+
reason: ""
|
|
1441
|
+
}, () => gitlabRequest(api, `${projectPath(repo)}/pipeline_schedules`, {
|
|
1392
1442
|
method: "POST",
|
|
1393
1443
|
body: {
|
|
1394
1444
|
description: which === link.links.updates ? "Rebuild the site and install Goodfellow's fixes each night" : "Rebuild the site each night",
|
|
@@ -1397,15 +1447,7 @@ function gitlabSetup(options = {}) {
|
|
|
1397
1447
|
cron_timezone: "UTC",
|
|
1398
1448
|
active: true
|
|
1399
1449
|
}
|
|
1400
|
-
});
|
|
1401
|
-
return true;
|
|
1402
|
-
} catch (error) {
|
|
1403
|
-
if (error instanceof GitApiError && [
|
|
1404
|
-
400,
|
|
1405
|
-
403,
|
|
1406
|
-
404
|
|
1407
|
-
].includes(error.status)) return false;
|
|
1408
|
-
throw error;
|
|
1450
|
+
}), left);
|
|
1409
1451
|
}
|
|
1410
1452
|
}
|
|
1411
1453
|
return {
|
|
@@ -1446,9 +1488,10 @@ function gitlabSetup(options = {}) {
|
|
|
1446
1488
|
throw error;
|
|
1447
1489
|
}
|
|
1448
1490
|
const warnings = [];
|
|
1491
|
+
const unconnected = [];
|
|
1449
1492
|
if (site.link) {
|
|
1450
1493
|
onStep?.("connect");
|
|
1451
|
-
|
|
1494
|
+
await connectProjects(site.link, unconnected);
|
|
1452
1495
|
}
|
|
1453
1496
|
let siteUrl;
|
|
1454
1497
|
if (site.pages && site.domain) {
|
|
@@ -1491,13 +1534,16 @@ function gitlabSetup(options = {}) {
|
|
|
1491
1534
|
}])
|
|
1492
1535
|
}
|
|
1493
1536
|
});
|
|
1537
|
+
if (site.link) await scheduleNightly(site.link, unconnected);
|
|
1538
|
+
if (unconnected.length) warnings.push("connect-unavailable");
|
|
1494
1539
|
return {
|
|
1495
1540
|
repo: project.path_with_namespace,
|
|
1496
1541
|
webUrl: project.web_url,
|
|
1497
1542
|
...siteUrl && { siteUrl },
|
|
1498
1543
|
buildsUrl: `${project.web_url}/-/pipelines`,
|
|
1499
1544
|
pagesUrl: site.pages ? `${project.web_url}/pages` : void 0,
|
|
1500
|
-
warnings
|
|
1545
|
+
warnings,
|
|
1546
|
+
...unconnected.length && { unconnected }
|
|
1501
1547
|
};
|
|
1502
1548
|
}
|
|
1503
1549
|
};
|
package/dist/testing.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export interface FakeGitLabOptions {
|
|
|
40
40
|
};
|
|
41
41
|
/** Domains another GitLab Pages site already uses. */
|
|
42
42
|
takenDomains?: string[];
|
|
43
|
+
/** What connecting created projects GitLab refuses, as a plan or a sign-in might: job token allowlists, job token pushes or pipeline schedules. */
|
|
44
|
+
refuseConnections?: Array<"allowlist" | "push" | "schedule">;
|
|
43
45
|
/** Other GitLab accounts that exist, which can be added to the project. Every token's user exists and is a member. */
|
|
44
46
|
accounts?: string[];
|
|
45
47
|
/** Who can see the project. Private by default. */
|
package/dist/testing.js
CHANGED
|
@@ -375,6 +375,7 @@ function fakeGitLab(options) {
|
|
|
375
375
|
});
|
|
376
376
|
if (rest === "" && request.method === "PUT") {
|
|
377
377
|
const body = await request.json();
|
|
378
|
+
if (options.refuseConnections?.includes("push")) return json({ message: "403 Forbidden" }, 403);
|
|
378
379
|
if (body.ci_push_repository_for_job_token_allowed !== void 0) project.jobTokenPush = body.ci_push_repository_for_job_token_allowed;
|
|
379
380
|
return json({
|
|
380
381
|
id: project.id,
|
|
@@ -383,6 +384,7 @@ function fakeGitLab(options) {
|
|
|
383
384
|
}
|
|
384
385
|
if (rest === "/job_token_scope/allowlist" && request.method === "POST") {
|
|
385
386
|
const body = await request.json();
|
|
387
|
+
if (options.refuseConnections?.includes("allowlist")) return json({ message: "403 Forbidden" }, 403);
|
|
386
388
|
if (![...created.values()].some((candidate) => candidate.id === body.target_project_id)) return json({ message: "404 Project Not Found" }, 404);
|
|
387
389
|
if (!project.jobTokenAllowlist.includes(body.target_project_id)) project.jobTokenAllowlist.push(body.target_project_id);
|
|
388
390
|
return json({
|
|
@@ -401,6 +403,8 @@ function fakeGitLab(options) {
|
|
|
401
403
|
}
|
|
402
404
|
if (rest === "/pipeline_schedules" && request.method === "POST") {
|
|
403
405
|
const body = await request.json();
|
|
406
|
+
if (options.refuseConnections?.includes("schedule")) return json({ message: { ref: ["is ambiguous"] } }, 400);
|
|
407
|
+
if (project.repo.files().size === 0) return json({ message: { ref: ["is ambiguous"] } }, 400);
|
|
404
408
|
project.schedules.push({
|
|
405
409
|
...body,
|
|
406
410
|
active: body.active !== false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodfellow-cms/gitlab",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Edit a Goodfellow CMS site stored on GitLab, straight from the browser.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"goodfellow",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"dist"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@goodfellow-cms/core": "0.
|
|
42
|
+
"@goodfellow-cms/core": "0.10.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@puckeditor/core": "0.23.0"
|