@jsenv/github-check-run 0.0.12 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/github-check-run",
3
- "version": "0.0.12",
3
+ "version": "0.1.0",
4
4
  "description": "Interact with GitHub check rest API",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -34,7 +34,7 @@
34
34
  "test": "node ./scripts/test.mjs"
35
35
  },
36
36
  "dependencies": {
37
- "@jsenv/fetch": "1.1.40",
37
+ "@jsenv/fetch": "1.1.41",
38
38
  "@jsenv/log": "3.4.1"
39
39
  }
40
40
  }
@@ -14,10 +14,10 @@ export const startGithubCheckRun = async ({
14
14
  repositoryOwner,
15
15
  repositoryName,
16
16
  commitSha,
17
- checkStatus = "in_progress",
18
17
  checkName,
19
18
  checkTitle,
20
19
  checkSummary,
20
+ checkStatus = "in_progress",
21
21
  }) => {
22
22
  if (typeof githubToken !== "string") {
23
23
  throw new TypeError(
@@ -74,37 +74,30 @@ export const startGithubCheckRun = async ({
74
74
  return { progress: () => {}, fail: () => {}, pass: () => {} };
75
75
  }
76
76
 
77
- const update = async ({
77
+ const updateState = async ({
78
78
  status,
79
79
  conclusion,
80
- title,
81
- summary,
80
+ title = check.title,
81
+ summary = check.summary,
82
82
  annotations = [],
83
83
  }) => {
84
- if (typeof title !== "string") {
85
- throw new TypeError(`title must be a string, got ${title}`);
86
- }
87
- if (typeof summary !== "string") {
88
- throw new TypeError(`summary must be a string, got ${summary}`);
89
- }
90
-
91
84
  let annotationsSent = 0;
92
85
  const annotationsBatch = annotations.slice(annotationsSent, 50);
86
+ const body = {
87
+ ...(status ? { status } : {}),
88
+ ...(conclusion ? { conclusion } : {}),
89
+ output: {
90
+ title: title === undefined ? check.title : title,
91
+ summary: summary === undefined ? check.summary : summary,
92
+ ...(annotationsBatch.length ? { annotations: annotationsBatch } : {}),
93
+ },
94
+ };
93
95
 
94
96
  try {
95
- const body = {
96
- ...(status ? { status } : {}),
97
- ...(conclusion ? { conclusion } : {}),
98
- output: {
99
- title,
100
- summary,
101
- ...(annotationsBatch.length ? { annotations: annotationsBatch } : {}),
102
- },
103
- };
104
97
  logger.debug(`PATCH check ${check.html_url}
105
98
  --- body ---
106
99
  ${JSON.stringify(body, null, " ")}`);
107
- await PATCH({
100
+ check = await PATCH({
108
101
  url: check.url,
109
102
  githubToken,
110
103
  body,
@@ -118,20 +111,11 @@ ${JSON.stringify(body, null, " ")}`);
118
111
  );
119
112
  return;
120
113
  }
121
- if (status) {
122
- checkStatus = status;
123
- }
124
- if (title) {
125
- checkTitle = title;
126
- }
127
- if (summary) {
128
- checkSummary = summary;
129
- }
130
114
 
131
115
  annotationsSent += annotationsBatch.length;
132
116
  while (annotationsSent < annotations.length) {
133
117
  const annotationsBatch = annotations.slice(annotationsSent, 50);
134
- await PATCH({
118
+ check = await PATCH({
135
119
  url: check.url,
136
120
  githubToken,
137
121
  body: {
@@ -148,65 +132,76 @@ ${JSON.stringify(body, null, " ")}`);
148
132
  let lastProgressCall;
149
133
  let pendingAnnotations = [];
150
134
  let pendingAbortController;
135
+ let pendingProgressPromise = Promise.resolve();
151
136
  let msBetweenProgressCalls = 500;
152
137
 
153
138
  return {
154
139
  progress: async ({ title, summary, annotations = [] }) => {
155
- const nowMs = Date.now();
156
- const isFirstCall = !lastProgressCall;
157
- lastProgressCall = nowMs;
158
- if (isFirstCall) {
159
- await update({
160
- title,
161
- summary,
162
- annotations,
163
- });
164
- return;
140
+ if (check.conclusion === "failure") {
141
+ throw new Error(`cannot progress() after fail()`);
165
142
  }
166
- if (pendingAbortController) {
167
- pendingAbortController.abort();
143
+ if (check.conclusion === "success") {
144
+ throw new Error(`cannot progress() after pass()`);
168
145
  }
169
- const msEllapsedSinceLastProgressCall = nowMs - lastProgressCall;
170
- const msEllapsedIsBigEnough =
171
- msEllapsedSinceLastProgressCall > msBetweenProgressCalls;
172
- if (msEllapsedIsBigEnough) {
173
- annotations = [...pendingAnnotations, ...annotations];
174
- pendingAnnotations.length = 0;
175
- await update({
146
+ pendingProgressPromise = (async () => {
147
+ const nowMs = Date.now();
148
+ const isFirstCall = !lastProgressCall;
149
+ lastProgressCall = nowMs;
150
+ if (isFirstCall) {
151
+ await updateState({
152
+ title,
153
+ summary,
154
+ annotations,
155
+ });
156
+ return;
157
+ }
158
+ if (pendingAbortController) {
159
+ pendingAbortController.abort();
160
+ }
161
+ const msEllapsedSinceLastProgressCall = nowMs - lastProgressCall;
162
+ const msEllapsedIsBigEnough =
163
+ msEllapsedSinceLastProgressCall > msBetweenProgressCalls;
164
+ if (msEllapsedIsBigEnough) {
165
+ annotations = [...pendingAnnotations, ...annotations];
166
+ pendingAnnotations.length = 0;
167
+ await updateState({
168
+ title,
169
+ summary,
170
+ annotations,
171
+ });
172
+ return;
173
+ }
174
+ pendingAnnotations.push(...annotations);
175
+ pendingAbortController = new AbortController();
176
+ await new Promise((resolve) => {
177
+ pendingAbortController.signal.onabort = resolve;
178
+ setTimeout(resolve, msBetweenProgressCalls);
179
+ });
180
+ if (pendingAbortController && pendingAbortController.signal.aborted) {
181
+ return;
182
+ }
183
+ pendingAbortController = null;
184
+ await updateState({
176
185
  title,
177
186
  summary,
178
187
  annotations,
179
188
  });
180
- return;
181
- }
182
- pendingAnnotations.push(...annotations);
183
- pendingAbortController = new AbortController();
184
- await new Promise((resolve) => {
185
- pendingAbortController.signal.onabort = resolve;
186
- setTimeout(resolve, msBetweenProgressCalls);
187
- });
188
- if (pendingAbortController && pendingAbortController.signal.aborted) {
189
- return;
190
- }
191
- pendingAbortController = null;
192
- await update({
193
- title,
194
- summary,
195
- annotations,
196
- });
189
+ })();
190
+ await pendingProgressPromise;
191
+ pendingProgressPromise = Promise.resolve();
197
192
  },
198
- fail: ({ title, summary, annotations } = {}) => {
199
- if (checkStatus !== "in_progress") {
200
- throw new Error(
201
- `fail() must be called while checkStatus is "in_progress", got ${checkStatus}`,
202
- );
203
- }
204
-
193
+ fail: async ({ title, summary, annotations } = {}) => {
194
+ await pendingProgressPromise;
205
195
  if (pendingAbortController) {
206
196
  pendingAbortController.abort();
207
197
  }
208
- // TODO: wait to any update before PATCH
209
- return update({
198
+ if (check.conclusion === "failure") {
199
+ throw new Error(`already failed`);
200
+ }
201
+ if (check.conclusion === "success") {
202
+ throw new Error(`cannot fail() after pass()`);
203
+ }
204
+ return updateState({
210
205
  status: "completed",
211
206
  conclusion: "failure",
212
207
  title,
@@ -214,17 +209,18 @@ ${JSON.stringify(body, null, " ")}`);
214
209
  annotations,
215
210
  });
216
211
  },
217
- pass: ({ title, summary, annotations } = {}) => {
218
- if (checkStatus !== "in_progress") {
219
- throw new Error(
220
- `pass() must be called while checkStatus is "in_progress", got ${checkStatus}`,
221
- );
222
- }
212
+ pass: async ({ title, summary, annotations } = {}) => {
213
+ await pendingProgressPromise;
223
214
  if (pendingAbortController) {
224
215
  pendingAbortController.abort();
225
216
  }
226
- // TODO: wait to any pending update before PATCH
227
- return update({
217
+ if (check.conclusion === "failure") {
218
+ throw new Error(`cannot pass() after fail()`);
219
+ }
220
+ if (check.conclusion === "success") {
221
+ throw new Error(`already passed`);
222
+ }
223
+ return updateState({
228
224
  status: "completed",
229
225
  conclusion: "success",
230
226
  title,