@bakers-build/addon-forge-github 0.9.1-next.8 → 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/src/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // shortly before it expires; or, with `auth: 'gh'`, the conductor's own `gh`
4
4
  // login. The repository comes from config, never from a clone's `origin`.
5
5
  import { createSign } from 'node:crypto';
6
- import { cliToken, requestJson, requestText, tail, } from '@bakers-build/addon-forge/backend';
6
+ import { cliToken, requestJson, } from '@bakers-build/addon-forge/backend';
7
7
  const API = 'https://api.github.com';
8
8
  const REFRESH_MS = 60_000;
9
9
  function settingsOf(raw) {
@@ -64,7 +64,6 @@ function stateStatus(state) {
64
64
  return 'success';
65
65
  return state === 'pending' ? 'pending' : 'failure';
66
66
  }
67
- const NO_RUN = { run_id: null, job_id: null, run_started_at: null };
68
67
  const basic = (token) => Buffer.from(`x-access-token:${token}`).toString('base64');
69
68
  const factory = async (raw, context) => {
70
69
  const s = settingsOf(raw);
@@ -102,7 +101,7 @@ const factory = async (raw, context) => {
102
101
  };
103
102
  return out.token;
104
103
  };
105
- const api = async (path, init = {}) => (init.text ? requestText : requestJson)(doFetch, `${repo}${path}`, {
104
+ const api = async (path, init = {}) => requestJson(doFetch, `${repo}${path}`, {
106
105
  method: init.method ?? 'GET',
107
106
  headers: {
108
107
  authorization: `Bearer ${await accessToken()}`,
@@ -136,11 +135,11 @@ const factory = async (raw, context) => {
136
135
  openPrsWithBase: async (base) => (await api(`/pulls?state=open&base=${encodeURIComponent(base)}&per_page=100`))
137
136
  .filter((p) => p.base.ref === base)
138
137
  .map(prOf),
139
- checks: async (ref, base, opts = {}) => {
138
+ checks: async (ref, base) => {
140
139
  const at = encodeURIComponent(ref);
141
140
  const b = encodeURIComponent(base);
142
141
  const [runs, status, rules, branch] = await Promise.all([
143
- api(`/commits/${at}/check-runs?filter=all&per_page=100`),
142
+ api(`/commits/${at}/check-runs?per_page=100`),
144
143
  api(`/commits/${at}/status`),
145
144
  api(`/rules/branches/${b}`, { allow404: true }),
146
145
  api(`/branches/${b}`, { allow404: true }),
@@ -152,67 +151,21 @@ const factory = async (raw, context) => {
152
151
  .map((c) => c.context),
153
152
  ...(branch?.protection?.required_status_checks?.contexts ?? []),
154
153
  ]);
155
- // shortcut: one page only; a partial list could hide a newer attempt, so refuse it; paginate when this trips.
156
- if ((runs.total_count ?? 0) > runs.check_runs.length)
157
- throw new Error(`${ref} has ${runs.total_count} check runs, more than the ${runs.check_runs.length} one page holds; the result would be partial`);
158
- // `ref` may be a branch: the runs lookup needs the commit the check runs report.
159
- const sha = runs.check_runs[0]?.head_sha;
160
- const workflowRuns = sha
161
- ? (await api(`/actions/runs?head_sha=${encodeURIComponent(sha)}&per_page=100`)).workflow_runs
162
- : [];
163
- const bySuite = new Map(workflowRuns.map((w) => [w.check_suite_id, w]));
164
- const newest = new Map();
165
- for (const w of workflowRuns) {
166
- const kept = newest.get(w.workflow_id);
167
- if (!kept ||
168
- w.run_started_at > kept.run_started_at ||
169
- (w.run_started_at === kept.run_started_at && w.id > kept.id))
170
- newest.set(w.workflow_id, w);
171
- }
172
- let jobs = runs.check_runs.map((r) => ({
173
- r,
174
- w: r.check_suite ? bySuite.get(r.check_suite.id) : undefined,
175
- }));
176
- if (!opts.allRuns) {
177
- // An Actions check run without a listed run belongs to an earlier attempt.
178
- jobs = jobs.filter(({ r, w }) => w
179
- ? newest.get(w.workflow_id) === w
180
- : r.app?.slug !== 'github-actions');
181
- // A re-run attempt is a newer check run of the same name in the same run.
182
- const latest = new Map();
183
- const key = (j) => `${j.w?.id ?? ''}\0${j.r.name}`;
184
- for (const j of jobs)
185
- latest.set(key(j), Math.max(latest.get(key(j)) ?? 0, j.r.id));
186
- jobs = jobs.filter((j) => latest.get(key(j)) === j.r.id);
187
- }
188
154
  const rows = [
189
- ...jobs.map(({ r, w }) => ({
155
+ ...runs.check_runs.map((r) => ({
190
156
  name: r.name,
191
157
  status: runStatus(r),
192
158
  required: required.has(r.name),
193
- conclusion: r.conclusion,
194
- run_id: w?.id ?? null,
195
- // An Actions job's id is its check run's id.
196
- job_id: w ? r.id : null,
197
- run_started_at: w?.run_started_at ?? null,
198
159
  })),
199
160
  ...status.statuses.map((st) => ({
200
161
  name: st.context,
201
162
  status: stateStatus(st.state),
202
163
  required: required.has(st.context),
203
- conclusion: st.state,
204
- ...NO_RUN,
205
164
  })),
206
165
  ];
207
166
  for (const name of required)
208
167
  if (!rows.some((r) => r.name === name))
209
- rows.push({
210
- name,
211
- status: 'missing',
212
- required: true,
213
- conclusion: null,
214
- ...NO_RUN,
215
- });
168
+ rows.push({ name, status: 'missing', required: true });
216
169
  return rows;
217
170
  },
218
171
  mergeBlocker: async (pr) => {
@@ -237,16 +190,6 @@ const factory = async (raw, context) => {
237
190
  });
238
191
  },
239
192
  isMerged: async (pr) => (await pull(pr.number)).merged === true,
240
- // The API redirects to a signed download URL; fetch follows it.
241
- jobLog: async (jobId, maxBytes) => {
242
- const log = (await api(`/actions/jobs/${jobId}/logs`, {
243
- allow404: true,
244
- text: true,
245
- }));
246
- if (log === undefined)
247
- throw new Error(`job ${jobId} is not a job of ${s.repository}`);
248
- return tail(log, maxBytes);
249
- },
250
193
  };
251
194
  return backend;
252
195
  };
@@ -5,7 +5,9 @@
5
5
  "description": "The forge entry's with.backend.with: a GitHub App, or the conductor's gh login with auth 'gh'.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
- "required": ["repository"],
8
+ "required": [
9
+ "repository"
10
+ ],
9
11
  "properties": {
10
12
  "repository": {
11
13
  "type": "string",
@@ -17,12 +19,18 @@
17
19
  "description": "Use the conductor's own gh login instead of a GitHub App."
18
20
  },
19
21
  "app_id": {
20
- "type": ["integer", "string"],
22
+ "type": [
23
+ "integer",
24
+ "string"
25
+ ],
21
26
  "minLength": 1,
22
27
  "description": "The GitHub App's ID; required unless `auth` is set."
23
28
  },
24
29
  "installation_id": {
25
- "type": ["integer", "string"],
30
+ "type": [
31
+ "integer",
32
+ "string"
33
+ ],
26
34
  "minLength": 1,
27
35
  "description": "The App's installation on the repository; required unless `auth` is set."
28
36
  },
@@ -38,9 +46,14 @@
38
46
  }
39
47
  },
40
48
  "if": {
41
- "required": ["auth"]
49
+ "required": [
50
+ "auth"
51
+ ]
42
52
  },
43
53
  "else": {
44
- "required": ["app_id", "installation_id"]
54
+ "required": [
55
+ "app_id",
56
+ "installation_id"
57
+ ]
45
58
  }
46
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bakers-build/addon-forge-github",
3
- "version": "0.9.1-next.8",
3
+ "version": "0.10.0",
4
4
  "description": "bakers.build forge backend for GitHub: a GitHub App installation token scoped to one repository. Implements @bakers-build/addon-forge's ForgeBackend contract.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -21,11 +21,11 @@
21
21
  "directory": "bakers-cli/addons/forge-github"
22
22
  },
23
23
  "peerDependencies": {
24
- "@bakers-build/addon-forge": "^0.9.1-next.8",
25
- "@bakers-build/core": "^0.9.1-next.8"
24
+ "@bakers-build/addon-forge": "^0.10.0",
25
+ "@bakers-build/core": "^0.10.0"
26
26
  },
27
27
  "bakersBuild": {
28
- "commit": "41eb5631e4ddf107b0b7a5ce2ffe2ed2a6052b5e",
29
- "channel": "next"
28
+ "commit": "5857b00008bc0926fd52fdc8d9366d6d52444e35",
29
+ "channel": "latest"
30
30
  }
31
31
  }