@goodfellow-cms/github 0.8.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.d.ts +6 -6
- package/dist/index.js +19 -13
- package/dist/testing.d.ts +8 -0
- package/dist/testing.js +24 -2
- package/package.json +7 -3
package/dist/index.d.ts
CHANGED
|
@@ -134,19 +134,19 @@ export declare class GitHubBackend implements GitBackend {
|
|
|
134
134
|
readAt(path: string, revision: string): Promise<string | undefined>;
|
|
135
135
|
changedPaths(from: string, to: string): Promise<string[]>;
|
|
136
136
|
/**
|
|
137
|
-
* Reads the deployment GitHub Pages or
|
|
138
|
-
* Cloudflare Pages reports on it, and for GitHub Actions, the workflow run
|
|
137
|
+
* Reads the deployment GitHub Pages, Vercel or Netlify created for a commit,
|
|
138
|
+
* or what Cloudflare Pages or Netlify reports on it, and for GitHub Actions, the workflow run
|
|
139
139
|
* that builds it: a build that fails never creates a deployment. Before any
|
|
140
140
|
* exists, the site counts as building if it has ever been deployed, or if
|
|
141
141
|
* Cloudflare reported on the commit before.
|
|
142
142
|
*/
|
|
143
143
|
deployStatus(revision: string): Promise<DeployStatus>;
|
|
144
144
|
/**
|
|
145
|
-
* What Cloudflare Pages reports on a commit: a check run of its
|
|
146
|
-
* or a commit status, which fine-grained tokens can read where
|
|
147
|
-
* need a GitHub App's permission. `undefined` if it reported nothing.
|
|
145
|
+
* What Cloudflare Pages or Netlify reports on a commit: a check run of its
|
|
146
|
+
* GitHub App, or a commit status, which fine-grained tokens can read where
|
|
147
|
+
* check runs need a GitHub App's permission. `undefined` if it reported nothing.
|
|
148
148
|
*/
|
|
149
|
-
private
|
|
149
|
+
private hostBuild;
|
|
150
150
|
/** The commit a commit was made on top of, if the token can see it. */
|
|
151
151
|
private parentOf;
|
|
152
152
|
/** The site's deploy workflow run for a commit, or `undefined` if there's none or the token can't see Actions. */
|
package/dist/index.js
CHANGED
|
@@ -860,8 +860,14 @@ function githubCodeUpdates(options) {
|
|
|
860
860
|
}
|
|
861
861
|
//#endregion
|
|
862
862
|
//#region src/backend.ts
|
|
863
|
-
/**
|
|
864
|
-
|
|
863
|
+
/**
|
|
864
|
+
* The check runs and commit statuses of hosts that build the site themselves
|
|
865
|
+
* and report to GitHub: Cloudflare Pages (its GitHub App is "Cloudflare Workers
|
|
866
|
+
* and Pages") and Netlify's deploys (`netlify/<site>/deploy…`), but not its
|
|
867
|
+
* other checks, such as "Header rules", which finish before the deploy does.
|
|
868
|
+
* Netlify's GitHub App also creates a deployment, which `deployStatus()` reads first.
|
|
869
|
+
*/
|
|
870
|
+
const HOST_BUILDS = /cloudflare|netlify\/\S+\/deploy/i;
|
|
865
871
|
/** How many files one GraphQL request reads. */
|
|
866
872
|
const GRAPHQL_BATCH = 100;
|
|
867
873
|
/** The most files GitHub's compare lists. */
|
|
@@ -1301,8 +1307,8 @@ var GitHubBackend = class GitHubBackend {
|
|
|
1301
1307
|
return [...new Set(files.flatMap((file) => [file.filename, file.previous_filename ?? []].flat()))];
|
|
1302
1308
|
}
|
|
1303
1309
|
/**
|
|
1304
|
-
* Reads the deployment GitHub Pages or
|
|
1305
|
-
* Cloudflare Pages reports on it, and for GitHub Actions, the workflow run
|
|
1310
|
+
* Reads the deployment GitHub Pages, Vercel or Netlify created for a commit,
|
|
1311
|
+
* or what Cloudflare Pages or Netlify reports on it, and for GitHub Actions, the workflow run
|
|
1306
1312
|
* that builds it: a build that fails never creates a deployment. Before any
|
|
1307
1313
|
* exists, the site counts as building if it has ever been deployed, or if
|
|
1308
1314
|
* Cloudflare reported on the commit before.
|
|
@@ -1334,8 +1340,8 @@ var GitHubBackend = class GitHubBackend {
|
|
|
1334
1340
|
};
|
|
1335
1341
|
}
|
|
1336
1342
|
}
|
|
1337
|
-
const
|
|
1338
|
-
if (
|
|
1343
|
+
const hosted = await this.hostBuild(revision);
|
|
1344
|
+
if (hosted) return hosted;
|
|
1339
1345
|
const run = await this.workflowRun(revision);
|
|
1340
1346
|
if (run?.status === "completed" && run.conclusion === "cancelled") {
|
|
1341
1347
|
const head = await this.head();
|
|
@@ -1352,22 +1358,22 @@ var GitHubBackend = class GitHubBackend {
|
|
|
1352
1358
|
};
|
|
1353
1359
|
if ((await githubJson(this.api, `/repos/${this.repo}/deployments?per_page=1`)).length > 0) return { state: "building" };
|
|
1354
1360
|
const parent = await this.parentOf(revision);
|
|
1355
|
-
return { state: parent && await this.
|
|
1361
|
+
return { state: parent && await this.hostBuild(parent) ? "building" : "unknown" };
|
|
1356
1362
|
} catch (error) {
|
|
1357
1363
|
if (error instanceof GitApiError) return { state: "unknown" };
|
|
1358
1364
|
throw error;
|
|
1359
1365
|
}
|
|
1360
1366
|
}
|
|
1361
1367
|
/**
|
|
1362
|
-
* What Cloudflare Pages reports on a commit: a check run of its
|
|
1363
|
-
* or a commit status, which fine-grained tokens can read where
|
|
1364
|
-
* need a GitHub App's permission. `undefined` if it reported nothing.
|
|
1368
|
+
* What Cloudflare Pages or Netlify reports on a commit: a check run of its
|
|
1369
|
+
* GitHub App, or a commit status, which fine-grained tokens can read where
|
|
1370
|
+
* check runs need a GitHub App's permission. `undefined` if it reported nothing.
|
|
1365
1371
|
*/
|
|
1366
|
-
async
|
|
1372
|
+
async hostBuild(revision) {
|
|
1367
1373
|
const checks = await githubRequest(this.api, `/repos/${this.repo}/commits/${revision}/check-runs?per_page=50`, { allow: [403, 404] });
|
|
1368
1374
|
if (checks.ok) {
|
|
1369
1375
|
const { check_runs: found = [] } = await checks.json();
|
|
1370
|
-
const run = found.find((candidate) =>
|
|
1376
|
+
const run = found.find((candidate) => HOST_BUILDS.test(`${candidate.app?.slug ?? ""} ${candidate.name}`));
|
|
1371
1377
|
if (run) {
|
|
1372
1378
|
const detailsUrl = run.details_url ?? run.html_url ?? void 0;
|
|
1373
1379
|
if (run.status !== "completed") return {
|
|
@@ -1390,7 +1396,7 @@ var GitHubBackend = class GitHubBackend {
|
|
|
1390
1396
|
}
|
|
1391
1397
|
const statuses = await githubRequest(this.api, `/repos/${this.repo}/commits/${revision}/statuses?per_page=50`, { allow: [403, 404] });
|
|
1392
1398
|
if (!statuses.ok) return void 0;
|
|
1393
|
-
const status = (await statuses.json()).find((candidate) =>
|
|
1399
|
+
const status = (await statuses.json()).find((candidate) => HOST_BUILDS.test(candidate.context));
|
|
1394
1400
|
if (!status) return void 0;
|
|
1395
1401
|
const detailsUrl = status.target_url ?? void 0;
|
|
1396
1402
|
if (status.state === "success") return {
|
package/dist/testing.d.ts
CHANGED
|
@@ -87,6 +87,14 @@ export interface FakeGitHubOptions {
|
|
|
87
87
|
afterChecks: number;
|
|
88
88
|
report?: "check-runs" | "statuses";
|
|
89
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
* Simulates Netlify, as `cloudflare` does Cloudflare Pages: its GitHub App's
|
|
92
|
+
* "Header rules" check run, which finishes at once, and a commit status for
|
|
93
|
+
* the deploy, which reports success after being checked this many times.
|
|
94
|
+
*/
|
|
95
|
+
netlify?: {
|
|
96
|
+
afterChecks: number;
|
|
97
|
+
};
|
|
90
98
|
/** Answers 403 to reading check runs, as GitHub does for fine-grained tokens, which can't have the permission. */
|
|
91
99
|
checkRunsForbidden?: boolean;
|
|
92
100
|
/** Organizations the users belong to, which new repositories can be created in. */
|
package/dist/testing.js
CHANGED
|
@@ -623,7 +623,7 @@ function fakeGitHub(options) {
|
|
|
623
623
|
}
|
|
624
624
|
}
|
|
625
625
|
function deploy(sha) {
|
|
626
|
-
if (options.cloudflare) cloudflareBuilds.set(sha, { checks: 0 });
|
|
626
|
+
if (options.cloudflare || options.netlify) cloudflareBuilds.set(sha, { checks: 0 });
|
|
627
627
|
if (options.deployAfterChecks === void 0) return;
|
|
628
628
|
deployments.unshift({
|
|
629
629
|
id: nextDeployment++,
|
|
@@ -638,7 +638,7 @@ function fakeGitHub(options) {
|
|
|
638
638
|
if (!build) return void 0;
|
|
639
639
|
build.checks += 1;
|
|
640
640
|
if (build.failed) return "failure";
|
|
641
|
-
return build.checks > (options.cloudflare?.afterChecks ?? 0) ? "success" : "building";
|
|
641
|
+
return build.checks > (options.cloudflare?.afterChecks ?? options.netlify?.afterChecks ?? 0) ? "success" : "building";
|
|
642
642
|
}
|
|
643
643
|
function failCloudflare(sha) {
|
|
644
644
|
cloudflareBuilds.set(sha, {
|
|
@@ -1261,6 +1261,19 @@ function fakeGitHub(options) {
|
|
|
1261
1261
|
const checkRunsSha = rest.match(/^\/commits\/([0-9a-f]{40})\/check-runs$/)?.[1];
|
|
1262
1262
|
if (checkRunsSha) {
|
|
1263
1263
|
if (options.checkRunsForbidden) return json({ message: "Resource not accessible by personal access token" }, 403);
|
|
1264
|
+
if (options.netlify) {
|
|
1265
|
+
const known = cloudflareBuilds.has(checkRunsSha);
|
|
1266
|
+
return json({
|
|
1267
|
+
total_count: known ? 1 : 0,
|
|
1268
|
+
check_runs: known ? [{
|
|
1269
|
+
id: 1,
|
|
1270
|
+
name: "Header rules - parish",
|
|
1271
|
+
app: { slug: "netlify" },
|
|
1272
|
+
status: "completed",
|
|
1273
|
+
conclusion: "neutral"
|
|
1274
|
+
}] : []
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1264
1277
|
const state = options.cloudflare?.report === "statuses" ? void 0 : cloudflareState(checkRunsSha);
|
|
1265
1278
|
const runsFound = state ? [{
|
|
1266
1279
|
id: 1,
|
|
@@ -1278,6 +1291,15 @@ function fakeGitHub(options) {
|
|
|
1278
1291
|
}
|
|
1279
1292
|
const statusesSha = rest.match(/^\/commits\/([0-9a-f]{40})\/statuses$/)?.[1];
|
|
1280
1293
|
if (statusesSha) {
|
|
1294
|
+
if (options.netlify) {
|
|
1295
|
+
const deploy = cloudflareState(statusesSha);
|
|
1296
|
+
return json(deploy ? [{
|
|
1297
|
+
context: "netlify/parish/deploy-preview",
|
|
1298
|
+
state: deploy === "building" ? "pending" : deploy,
|
|
1299
|
+
target_url: `https://app.netlify.com/sites/parish/deploys/${statusesSha}`,
|
|
1300
|
+
description: deploy === "failure" ? "Deploy failed" : "Deploy is ready!"
|
|
1301
|
+
}] : []);
|
|
1302
|
+
}
|
|
1281
1303
|
const state = options.cloudflare?.report === "statuses" ? cloudflareState(statusesSha) : void 0;
|
|
1282
1304
|
return json(state ? [{
|
|
1283
1305
|
context: "Cloudflare Pages",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodfellow-cms/github",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Edit a Goodfellow site stored on GitHub, straight from the browser.",
|
|
3
|
+
"version": "0.10.0",
|
|
4
|
+
"description": "Edit a Goodfellow CMS site stored on GitHub, 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.10.0",
|
|
39
43
|
"@noble/ciphers": "2.4.0",
|
|
40
44
|
"@noble/hashes": "2.4.0"
|
|
41
45
|
},
|