@goodfellow-cms/gitlab 0.9.0 → 0.10.1
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 +73 -25
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +5 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1368,27 +1368,79 @@ 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
|
+
const source = ids.get(read);
|
|
1405
|
+
await attempt({
|
|
1406
|
+
kind: "read",
|
|
1407
|
+
reader: link[reader],
|
|
1408
|
+
read: link[read],
|
|
1409
|
+
reason: ""
|
|
1410
|
+
}, async () => {
|
|
1411
|
+
if (target === void 0) throw new GitApiError(404, `GitLab couldn't find ${link[reader]}.`);
|
|
1412
|
+
if (source === void 0) throw new GitApiError(404, `GitLab couldn't find ${link[read]}.`);
|
|
1413
|
+
await gitlabRequest(api, `/projects/${source}/job_token_scope/allowlist`, {
|
|
1414
|
+
method: "POST",
|
|
1415
|
+
body: { target_project_id: target }
|
|
1416
|
+
});
|
|
1417
|
+
}, left);
|
|
1418
|
+
}
|
|
1419
|
+
if (link.links.updates) {
|
|
1420
|
+
const repo = link[link.links.updates];
|
|
1421
|
+
await attempt({
|
|
1422
|
+
kind: "push",
|
|
1423
|
+
repo,
|
|
1424
|
+
reason: ""
|
|
1425
|
+
}, () => gitlabRequest(api, projectPath(repo), {
|
|
1388
1426
|
method: "PUT",
|
|
1389
1427
|
body: { ci_push_repository_for_job_token_allowed: true }
|
|
1390
|
-
});
|
|
1391
|
-
|
|
1428
|
+
}), left);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
/**
|
|
1432
|
+
* Runs the pipelines that need it each night. After the project's files
|
|
1433
|
+
* are written, since a schedule names the main branch, which an empty
|
|
1434
|
+
* project doesn't have yet.
|
|
1435
|
+
*/
|
|
1436
|
+
async function scheduleNightly(link, left) {
|
|
1437
|
+
for (const which of link.links.nightly) {
|
|
1438
|
+
const repo = link[which];
|
|
1439
|
+
await attempt({
|
|
1440
|
+
kind: "nightly",
|
|
1441
|
+
repo,
|
|
1442
|
+
reason: ""
|
|
1443
|
+
}, () => gitlabRequest(api, `${projectPath(repo)}/pipeline_schedules`, {
|
|
1392
1444
|
method: "POST",
|
|
1393
1445
|
body: {
|
|
1394
1446
|
description: which === link.links.updates ? "Rebuild the site and install Goodfellow's fixes each night" : "Rebuild the site each night",
|
|
@@ -1397,15 +1449,7 @@ function gitlabSetup(options = {}) {
|
|
|
1397
1449
|
cron_timezone: "UTC",
|
|
1398
1450
|
active: true
|
|
1399
1451
|
}
|
|
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;
|
|
1452
|
+
}), left);
|
|
1409
1453
|
}
|
|
1410
1454
|
}
|
|
1411
1455
|
return {
|
|
@@ -1446,9 +1490,10 @@ function gitlabSetup(options = {}) {
|
|
|
1446
1490
|
throw error;
|
|
1447
1491
|
}
|
|
1448
1492
|
const warnings = [];
|
|
1493
|
+
const unconnected = [];
|
|
1449
1494
|
if (site.link) {
|
|
1450
1495
|
onStep?.("connect");
|
|
1451
|
-
|
|
1496
|
+
await connectProjects(site.link, unconnected);
|
|
1452
1497
|
}
|
|
1453
1498
|
let siteUrl;
|
|
1454
1499
|
if (site.pages && site.domain) {
|
|
@@ -1491,13 +1536,16 @@ function gitlabSetup(options = {}) {
|
|
|
1491
1536
|
}])
|
|
1492
1537
|
}
|
|
1493
1538
|
});
|
|
1539
|
+
if (site.link) await scheduleNightly(site.link, unconnected);
|
|
1540
|
+
if (unconnected.length) warnings.push("connect-unavailable");
|
|
1494
1541
|
return {
|
|
1495
1542
|
repo: project.path_with_namespace,
|
|
1496
1543
|
webUrl: project.web_url,
|
|
1497
1544
|
...siteUrl && { siteUrl },
|
|
1498
1545
|
buildsUrl: `${project.web_url}/-/pipelines`,
|
|
1499
1546
|
pagesUrl: site.pages ? `${project.web_url}/pages` : void 0,
|
|
1500
|
-
warnings
|
|
1547
|
+
warnings,
|
|
1548
|
+
...unconnected.length && { unconnected }
|
|
1501
1549
|
};
|
|
1502
1550
|
}
|
|
1503
1551
|
};
|
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,
|
|
@@ -382,7 +383,9 @@ function fakeGitLab(options) {
|
|
|
382
383
|
});
|
|
383
384
|
}
|
|
384
385
|
if (rest === "/job_token_scope/allowlist" && request.method === "POST") {
|
|
386
|
+
if (!/^\d+$/.test(key)) return json({ error: "id is invalid" }, 400);
|
|
385
387
|
const body = await request.json();
|
|
388
|
+
if (options.refuseConnections?.includes("allowlist")) return json({ message: "403 Forbidden" }, 403);
|
|
386
389
|
if (![...created.values()].some((candidate) => candidate.id === body.target_project_id)) return json({ message: "404 Project Not Found" }, 404);
|
|
387
390
|
if (!project.jobTokenAllowlist.includes(body.target_project_id)) project.jobTokenAllowlist.push(body.target_project_id);
|
|
388
391
|
return json({
|
|
@@ -401,6 +404,8 @@ function fakeGitLab(options) {
|
|
|
401
404
|
}
|
|
402
405
|
if (rest === "/pipeline_schedules" && request.method === "POST") {
|
|
403
406
|
const body = await request.json();
|
|
407
|
+
if (options.refuseConnections?.includes("schedule")) return json({ message: { ref: ["is ambiguous"] } }, 400);
|
|
408
|
+
if (project.repo.files().size === 0) return json({ message: { ref: ["is ambiguous"] } }, 400);
|
|
404
409
|
project.schedules.push({
|
|
405
410
|
...body,
|
|
406
411
|
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.1",
|
|
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.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@puckeditor/core": "0.23.0"
|