@goodfellow-cms/gitlab 0.8.0 → 0.9.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 +34 -0
- package/dist/testing.d.ts +3 -0
- package/dist/testing.js +33 -2
- package/package.json +7 -3
package/dist/index.js
CHANGED
|
@@ -143,6 +143,11 @@ function gitlabEditors(api, project, branch, username) {
|
|
|
143
143
|
await gitlabRequest(api, editor.id.startsWith(INVITATION) ? `${base}/invitations/${encodeURIComponent(editor.id.slice(11))}` : `${base}/members/${editor.id.slice(7)}`, { method: "DELETE" }).catch(notAllowed$2);
|
|
144
144
|
},
|
|
145
145
|
async letEditorsPublish() {
|
|
146
|
+
const read = async () => {
|
|
147
|
+
const answer = await gitlabRequest(api, protectedPath, { allow: [404] }).catch(notAllowed$2);
|
|
148
|
+
return answer.ok ? await answer.json() : void 0;
|
|
149
|
+
};
|
|
150
|
+
const developersMay = (protection) => !protection || ["push_access_levels", "merge_access_levels"].every((kind) => (protection[kind] ?? []).some((level) => level.access_level !== null && level.access_level <= DEVELOPER));
|
|
146
151
|
const protect = (level) => gitlabRequest(api, `${base}/protected_branches`, {
|
|
147
152
|
method: "POST",
|
|
148
153
|
body: {
|
|
@@ -152,6 +157,30 @@ function gitlabEditors(api, project, branch, username) {
|
|
|
152
157
|
allow_force_push: false
|
|
153
158
|
}
|
|
154
159
|
});
|
|
160
|
+
const current = await read();
|
|
161
|
+
if (!current) {
|
|
162
|
+
await protect(DEVELOPER).catch(notAllowed$2);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (developersMay(current)) return;
|
|
166
|
+
const swap = (levels = []) => [{ access_level: DEVELOPER }, ...levels.flatMap((level) => level.id === void 0 ? [] : [{
|
|
167
|
+
id: level.id,
|
|
168
|
+
_destroy: true
|
|
169
|
+
}])];
|
|
170
|
+
if ((await gitlabRequest(api, protectedPath, {
|
|
171
|
+
method: "PATCH",
|
|
172
|
+
body: {
|
|
173
|
+
allow_force_push: false,
|
|
174
|
+
allowed_to_push: swap(current.push_access_levels),
|
|
175
|
+
allowed_to_merge: swap(current.merge_access_levels)
|
|
176
|
+
},
|
|
177
|
+
allow: [
|
|
178
|
+
400,
|
|
179
|
+
404,
|
|
180
|
+
405,
|
|
181
|
+
422
|
|
182
|
+
]
|
|
183
|
+
}).catch(notAllowed$2)).ok && developersMay(await read())) return;
|
|
155
184
|
await gitlabRequest(api, protectedPath, {
|
|
156
185
|
method: "DELETE",
|
|
157
186
|
allow: [404]
|
|
@@ -162,6 +191,11 @@ function gitlabEditors(api, project, branch, username) {
|
|
|
162
191
|
await protect(MAINTAINER).catch(() => void 0);
|
|
163
192
|
notAllowed$2(error);
|
|
164
193
|
}
|
|
194
|
+
const after = await read();
|
|
195
|
+
if (!after || !developersMay(after)) {
|
|
196
|
+
if (!after) await protect(MAINTAINER).catch(() => void 0);
|
|
197
|
+
throw new Error("GitLab didn't keep the main branch's new protection. Try again.");
|
|
198
|
+
}
|
|
165
199
|
}
|
|
166
200
|
};
|
|
167
201
|
}
|
package/dist/testing.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export interface FakeGitLabOptions {
|
|
|
50
50
|
* artifact, or nothing for a job that fails. Without it, task pipelines fail.
|
|
51
51
|
*/
|
|
52
52
|
tasks?: (variables: Record<string, string>) => string | undefined | Promise<string | undefined>;
|
|
53
|
+
/** GitLab before 15.6, which can't change a protected branch's access levels, only remove and add it. */
|
|
54
|
+
noProtectionChanges?: boolean;
|
|
53
55
|
}
|
|
54
56
|
/** A pipeline schedule, such as the nightly one or one the admin panel adds for a scheduled change. */
|
|
55
57
|
export interface FakeSchedule {
|
|
@@ -120,6 +122,7 @@ export declare function fakeGitLab(options: FakeGitLabOptions): {
|
|
|
120
122
|
merge: number;
|
|
121
123
|
forcePush: boolean;
|
|
122
124
|
}>;
|
|
125
|
+
protectionChanges: string[];
|
|
123
126
|
failBuild: (sha: string, failure?: {
|
|
124
127
|
job?: string;
|
|
125
128
|
failureReason?: string;
|
package/dist/testing.js
CHANGED
|
@@ -53,6 +53,8 @@ function fakeGitLab(options) {
|
|
|
53
53
|
merge: 40,
|
|
54
54
|
forcePush: false
|
|
55
55
|
}]]);
|
|
56
|
+
/** Each change to a protected branch, in order: `DELETE main`, `POST main`, `PATCH main`. */
|
|
57
|
+
const protectionChanges = [];
|
|
56
58
|
/** The project's members and invitations, and its protected branches. */
|
|
57
59
|
async function handleMembers(request, url, rest, accessLevel) {
|
|
58
60
|
const forbidden = () => json({ message: "403 Forbidden" }, 403);
|
|
@@ -134,20 +136,48 @@ function fakeGitLab(options) {
|
|
|
134
136
|
if (!found) return json({ message: "404 Not found" }, 404);
|
|
135
137
|
if (request.method === "GET") return json({
|
|
136
138
|
name,
|
|
137
|
-
push_access_levels: [{
|
|
138
|
-
|
|
139
|
+
push_access_levels: [{
|
|
140
|
+
id: 1,
|
|
141
|
+
access_level: found.push
|
|
142
|
+
}],
|
|
143
|
+
merge_access_levels: [{
|
|
144
|
+
id: 2,
|
|
145
|
+
access_level: found.merge
|
|
146
|
+
}],
|
|
139
147
|
allow_force_push: found.forcePush
|
|
140
148
|
});
|
|
141
149
|
if (request.method === "DELETE") {
|
|
142
150
|
if (accessLevel < 40) return forbidden();
|
|
143
151
|
protectedBranches.delete(name);
|
|
152
|
+
protectionChanges.push(`DELETE ${name}`);
|
|
144
153
|
return new Response(null, { status: 204 });
|
|
145
154
|
}
|
|
155
|
+
if (request.method === "PATCH" && !options.noProtectionChanges) {
|
|
156
|
+
if (accessLevel < 40) return forbidden();
|
|
157
|
+
const body = await request.json();
|
|
158
|
+
const levelFrom = (levels, id, now) => {
|
|
159
|
+
if (!levels) return now;
|
|
160
|
+
const kept = levels.some((level) => level.id === id && level._destroy) ? [] : [now];
|
|
161
|
+
const added = levels.flatMap((level) => level.access_level === void 0 ? [] : [level.access_level]);
|
|
162
|
+
return kept.length + added.length === 1 ? kept[0] ?? added[0] ?? now : void 0;
|
|
163
|
+
};
|
|
164
|
+
const push = levelFrom(body.allowed_to_push, 1, found.push);
|
|
165
|
+
const merge = levelFrom(body.allowed_to_merge, 2, found.merge);
|
|
166
|
+
if (push === void 0 || merge === void 0) return json({ message: "Only one access level allowed" }, 422);
|
|
167
|
+
protectedBranches.set(name, {
|
|
168
|
+
push,
|
|
169
|
+
merge,
|
|
170
|
+
forcePush: body.allow_force_push ?? found.forcePush
|
|
171
|
+
});
|
|
172
|
+
protectionChanges.push(`PATCH ${name}`);
|
|
173
|
+
return json({ name });
|
|
174
|
+
}
|
|
146
175
|
}
|
|
147
176
|
if (rest === "/protected_branches" && request.method === "POST") {
|
|
148
177
|
if (accessLevel < 40) return forbidden();
|
|
149
178
|
const body = await request.json();
|
|
150
179
|
if (protectedBranches.has(body.name)) return json({ message: "Protected branch already exists" }, 409);
|
|
180
|
+
protectionChanges.push(`POST ${body.name}`);
|
|
151
181
|
protectedBranches.set(body.name, {
|
|
152
182
|
push: body.push_access_level ?? 40,
|
|
153
183
|
merge: body.merge_access_level ?? 40,
|
|
@@ -898,6 +928,7 @@ function fakeGitLab(options) {
|
|
|
898
928
|
members,
|
|
899
929
|
invitations,
|
|
900
930
|
protectedBranches,
|
|
931
|
+
protectionChanges,
|
|
901
932
|
failBuild,
|
|
902
933
|
cancelBuild,
|
|
903
934
|
/** The project's update settings, and the pipelines the update ran in, which tests add with `addUpdateRun()`. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodfellow-cms/gitlab",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Edit a Goodfellow site stored on GitLab, straight from the browser.",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Edit a Goodfellow CMS site stored on GitLab, straight from the browser.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"goodfellow",
|
|
7
7
|
"cms",
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
],
|
|
13
13
|
"homepage": "https://goodfellow-cms.github.io/goodfellow-cms/docs/hosts",
|
|
14
14
|
"bugs": "https://github.com/goodfellow-cms/goodfellow-cms/issues",
|
|
15
|
+
"funding": {
|
|
16
|
+
"type": "github",
|
|
17
|
+
"url": "https://github.com/sponsors/goodfellow-cms"
|
|
18
|
+
},
|
|
15
19
|
"license": "MIT",
|
|
16
20
|
"repository": {
|
|
17
21
|
"type": "git",
|
|
@@ -35,7 +39,7 @@
|
|
|
35
39
|
"dist"
|
|
36
40
|
],
|
|
37
41
|
"dependencies": {
|
|
38
|
-
"@goodfellow-cms/core": "0.
|
|
42
|
+
"@goodfellow-cms/core": "0.9.0"
|
|
39
43
|
},
|
|
40
44
|
"devDependencies": {
|
|
41
45
|
"@puckeditor/core": "0.23.0"
|