@jsenv/github-pull-request-impact 1.6.4 → 1.6.5

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-pull-request-impact",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
4
4
  "description": "Report pull request impact on something",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -10,10 +10,11 @@
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "https://github.com/jsenv/github-pull-request-impact"
13
+ "url": "https://github.com/jsenv/workflow",
14
+ "directory": "packages/jsenv-github-pull-request-impact"
14
15
  },
15
16
  "engines": {
16
- "node": ">=14.17.0"
17
+ "node": ">=16.13.0"
17
18
  },
18
19
  "publishConfig": {
19
20
  "access": "public"
@@ -25,42 +26,31 @@
25
26
  },
26
27
  "./*": "./*"
27
28
  },
29
+ "main": "./main.js",
28
30
  "files": [
29
31
  "/src/",
30
32
  "/main.js"
31
33
  ],
32
34
  "scripts": {
33
- "eslint-check": "node ./node_modules/eslint/bin/eslint.js .",
34
- "test": "node ./script/test/test.js",
35
- "generate-import-map": "node ./script/generate-import-map/generate-import-map.js",
35
+ "eslint": "npx eslint . --ext=.js,.mjs",
36
+ "importmap": "node ./script/importmap/importmap.mjs",
37
+ "test": "node --experimental-json-modules ./script/test/test.mjs",
36
38
  "test-with-coverage": "npm run test -- --coverage",
37
- "prettier-format": "node ./script/prettier-format/prettier-format.js",
38
- "prettier-format-stage": "npm run prettier-format -- --staged",
39
- "prettier-check": "npm run prettier-format -- --dry-run",
40
- "log-performance-report": "node .github/workflows/performance_impact/generate_performance_report.js --log",
41
- "upload-coverage": "node ./script/upload-coverage/upload-coverage.js",
42
- "prepublishOnly": "node ./script/transform-package/remove-postinstall.js",
43
- "postpublish": "node ./script/transform-package/restore-postinstall.js"
39
+ "prettier": "prettier --write ."
44
40
  },
45
41
  "dependencies": {
46
- "@jsenv/cancellation": "3.0.0",
42
+ "@jsenv/filesystem": "2.7.1",
47
43
  "@jsenv/logger": "4.0.1",
48
- "@jsenv/server": "6.1.0",
49
- "@jsenv/util": "4.1.1"
44
+ "@jsenv/server": "12.4.0"
50
45
  },
51
46
  "devDependencies": {
52
- "@jsenv/assert": "2.2.5",
53
- "@jsenv/codecov-upload": "3.5.0",
54
- "@jsenv/core": "19.0.2",
55
- "@jsenv/eslint-config": "15.0.1",
56
- "@jsenv/github-release-package": "1.2.3",
57
- "@jsenv/importmap-eslint-resolver": "5.0.0",
58
- "@jsenv/node-module-import-map": "13.6.1",
59
- "@jsenv/package-publish": "1.6.2",
60
- "@jsenv/performance-impact": "1.2.1",
61
- "@jsenv/prettier-check-project": "5.6.1",
62
- "eslint": "7.31.0",
63
- "eslint-plugin-import": "2.23.4",
64
- "prettier": "2.3.2"
47
+ "@jsenv/assert": "2.4.1",
48
+ "@jsenv/core": "25.3.0",
49
+ "@jsenv/eslint-config": "16.0.9",
50
+ "@jsenv/importmap-eslint-resolver": "5.2.5",
51
+ "@jsenv/importmap-node-module": "5.1.2",
52
+ "eslint": "8.7.0",
53
+ "eslint-plugin-import": "2.25.4",
54
+ "prettier": "2.5.1"
65
55
  }
66
- }
56
+ }
@@ -6,11 +6,9 @@
6
6
 
7
7
  import { createLogger } from "@jsenv/logger"
8
8
  import {
9
- createCancellationToken,
10
- createCancellationSource,
11
- composeCancellationToken,
12
- } from "@jsenv/cancellation"
13
- import { assertAndNormalizeDirectoryUrl, urlToFileSystemPath } from "@jsenv/util"
9
+ assertAndNormalizeDirectoryUrl,
10
+ urlToFileSystemPath,
11
+ } from "@jsenv/filesystem"
14
12
 
15
13
  import { exec } from "./internal/exec.js"
16
14
  import { GET, POST, PATCH } from "./internal/git_hub_api.js"
@@ -21,8 +19,6 @@ export const commentGitHubPullRequestImpact = async ({
21
19
  logLevel,
22
20
  commandLogs = false,
23
21
  infoLogs = true,
24
- cancellationToken = createCancellationToken(),
25
- cancelOnSIGINT = true,
26
22
  projectDirectoryUrl,
27
23
 
28
24
  githubToken,
@@ -47,51 +43,46 @@ export const commentGitHubPullRequestImpact = async ({
47
43
  }) => {
48
44
  projectDirectoryUrl = assertAndNormalizeDirectoryUrl(projectDirectoryUrl)
49
45
  if (typeof collectInfo !== "function") {
50
- throw new TypeError(`collectInfo must be a function but received ${collectInfo}`)
46
+ throw new TypeError(
47
+ `collectInfo must be a function but received ${collectInfo}`,
48
+ )
51
49
  }
52
50
  if (typeof commentIdentifier !== "string") {
53
- throw new TypeError(`commentIdentifier must be a string but received ${commentIdentifier}`)
51
+ throw new TypeError(
52
+ `commentIdentifier must be a string but received ${commentIdentifier}`,
53
+ )
54
54
  }
55
55
  if (typeof githubToken !== "string") {
56
- throw new TypeError(`githubToken must be a string but received ${githubToken}`)
56
+ throw new TypeError(
57
+ `githubToken must be a string but received ${githubToken}`,
58
+ )
57
59
  }
58
60
  if (typeof repositoryOwner !== "string") {
59
- throw new TypeError(`repositoryOwner must be a string but received ${repositoryOwner}`)
61
+ throw new TypeError(
62
+ `repositoryOwner must be a string but received ${repositoryOwner}`,
63
+ )
60
64
  }
61
65
  if (typeof repositoryName !== "string") {
62
- throw new TypeError(`repositoryName must be a string but received ${repositoryName}`)
66
+ throw new TypeError(
67
+ `repositoryName must be a string but received ${repositoryName}`,
68
+ )
63
69
  }
64
70
  pullRequestNumber = String(pullRequestNumber)
65
71
  if (typeof pullRequestNumber !== "string") {
66
- throw new TypeError(`pullRequestNumber must be a string but received ${pullRequestNumber}`)
72
+ throw new TypeError(
73
+ `pullRequestNumber must be a string but received ${pullRequestNumber}`,
74
+ )
67
75
  }
68
76
 
69
77
  const logger = createLogger({ logLevel })
70
78
 
71
79
  let cleanup = () => {}
72
80
 
73
- if (cancelOnSIGINT) {
74
- const processCancellationSource = createCancellationSource()
75
- const processCancellationToken = processCancellationSource.token
76
- cancellationToken = composeCancellationToken(cancellationToken, processCancellationToken)
77
- const SIGINTCallback = () => {
78
- processCancellationSource.cancel("process SIGINT")
79
- }
80
- process.once("SIGINT", SIGINTCallback)
81
-
82
- // beware if someday something do things on cleanup
83
- // to call the old cleanup function
84
- cleanup = () => {
85
- process.removeListener("SIGINT", SIGINTCallback)
86
- }
87
- }
88
-
89
81
  try {
90
82
  return await commentPrImpact({
91
83
  logger,
92
84
  commandLogs,
93
85
  infoLogs,
94
- cancellationToken,
95
86
  projectDirectoryUrl,
96
87
 
97
88
  githubToken,
@@ -120,7 +111,6 @@ const commentPrImpact = async ({
120
111
  logger,
121
112
  infoLogs,
122
113
  commandLogs,
123
- cancellationToken,
124
114
  projectDirectoryUrl,
125
115
 
126
116
  githubToken,
@@ -157,7 +147,6 @@ const commentPrImpact = async ({
157
147
  // https://developer.github.com/v3/pulls/#get-a-pull-request
158
148
  logger.debug(`get pull request ${pullApiUrl}`)
159
149
  const pullRequest = await GET(pullApiUrl, {
160
- cancellationToken,
161
150
  githubToken,
162
151
  })
163
152
  const pullRequestHtmlUrl = pullRequest.html_url
@@ -189,9 +178,10 @@ const commentPrImpact = async ({
189
178
  const pullRequestCommentApiUrl = pullRequest.comments_url
190
179
  const comments = await GET(pullRequestCommentApiUrl, {
191
180
  githubToken,
192
- cancellationToken,
193
181
  })
194
- const existingComment = comments.find(({ body }) => body.includes(commentIdentifier))
182
+ const existingComment = comments.find(({ body }) =>
183
+ body.includes(commentIdentifier),
184
+ )
195
185
  if (existingComment) {
196
186
  logger.debug(`comment found at ${existingComment.html_url}.`)
197
187
  } else {
@@ -227,7 +217,7 @@ const commentPrImpact = async ({
227
217
  const comment = await PATCH(
228
218
  `https://api.github.com/repos/${repositoryOwner}/${repositoryName}/issues/comments/${existingComment.id}`,
229
219
  { body: commentBody },
230
- { githubToken, cancellationToken },
220
+ { githubToken },
231
221
  )
232
222
  logger.info("comment updated")
233
223
  return comment
@@ -237,14 +227,16 @@ const commentPrImpact = async ({
237
227
  const comment = await POST(
238
228
  `https://api.github.com/repos/${repositoryOwner}/${repositoryName}/issues/${pullRequestNumber}/comments`,
239
229
  { body: commentBody },
240
- { githubToken, cancellationToken },
230
+ { githubToken },
241
231
  )
242
232
  logger.info(`comment created at ${comment.html_url}`)
243
233
  return comment
244
234
  }
245
235
 
246
- const isFork = pullRequest.base.repo.full_name !== pullRequest.head.repo.full_name
247
- const isInPullRequestWorkflow = process.env.GITHUB_EVENT_NAME === "pull_request"
236
+ const isFork =
237
+ pullRequest.base.repo.full_name !== pullRequest.head.repo.full_name
238
+ const isInPullRequestWorkflow =
239
+ process.env.GITHUB_EVENT_NAME === "pull_request"
248
240
  if (isFork && isInPullRequestWorkflow) {
249
241
  logger.warn(formatGithubTokenNotAllowedToCommentWarning())
250
242
  }
@@ -260,10 +252,13 @@ const commentPrImpact = async ({
260
252
  let beforeMergeInfo
261
253
  try {
262
254
  // cannot use depth=1 arg otherwise git merge might have merge conflicts
263
- await execCommandInProjectDirectory(`git fetch --no-tags --prune origin ${pullRequestBase}`)
264
- await execCommandInProjectDirectory(`git reset --hard origin/${pullRequestBase}`)
255
+ await execCommandInProjectDirectory(
256
+ `git fetch --no-tags --prune origin ${pullRequestBase}`,
257
+ )
258
+ await execCommandInProjectDirectory(
259
+ `git reset --hard origin/${pullRequestBase}`,
260
+ )
265
261
  beforeMergeInfo = await collectInfo({
266
- cancellationToken,
267
262
  beforeMerge: true,
268
263
  execCommandInProjectDirectory,
269
264
  })
@@ -273,7 +268,10 @@ const commentPrImpact = async ({
273
268
  } catch (error) {
274
269
  logger.error(error.stack)
275
270
  const comment = await patchOrPostComment(
276
- createCommentForBeforeMergeError(error, { pullRequestHead, pullRequestBase }),
271
+ createCommentForBeforeMergeError(error, {
272
+ pullRequestHead,
273
+ pullRequestBase,
274
+ }),
277
275
  )
278
276
  if (catchError) {
279
277
  return { error, comment }
@@ -285,11 +283,15 @@ const commentPrImpact = async ({
285
283
  try {
286
284
  // buildCommand might generate files that could conflict when doing the merge
287
285
  // reset to avoid potential merge conflicts
288
- await execCommandInProjectDirectory(`git reset --hard origin/${pullRequestBase}`)
286
+ await execCommandInProjectDirectory(
287
+ `git reset --hard origin/${pullRequestBase}`,
288
+ )
289
289
  // Avoid "The following untracked working tree files would be overwritten by merge" error
290
290
  await execCommandInProjectDirectory(`git clean -d -f .`)
291
291
  // cannot use depth=1 arg otherwise git merge might have merge conflicts
292
- await execCommandInProjectDirectory(`git fetch --no-tags --prune origin ${headRef}`)
292
+ await execCommandInProjectDirectory(
293
+ `git fetch --no-tags --prune origin ${headRef}`,
294
+ )
293
295
  // ensure there is user.email + user.name required to perform git merge command
294
296
  // without them git would complain that it does not know who we are
295
297
 
@@ -301,11 +303,12 @@ const commentPrImpact = async ({
301
303
  valueIfMissing: "Your Name",
302
304
  execCommandInProjectDirectory,
303
305
  })
304
- await execCommandInProjectDirectory(`git merge FETCH_HEAD --allow-unrelated-histories`)
306
+ await execCommandInProjectDirectory(
307
+ `git merge FETCH_HEAD --allow-unrelated-histories`,
308
+ )
305
309
  await restoreGitUserEmail()
306
310
  await restoreGitUserName()
307
311
  afterMergeInfo = await collectInfo({
308
- cancellationToken,
309
312
  afterMerge: true,
310
313
  execCommandInProjectDirectory,
311
314
  })
@@ -315,7 +318,10 @@ const commentPrImpact = async ({
315
318
  } catch (error) {
316
319
  logger.error(error.stack)
317
320
  const gitHubComment = await patchOrPostComment(
318
- createCommentForAfterMergeError(error, { pullRequestHead, pullRequestBase }),
321
+ createCommentForAfterMergeError(error, {
322
+ pullRequestHead,
323
+ pullRequestBase,
324
+ }),
319
325
  )
320
326
  if (catchError) {
321
327
  return { error, gitHubComment }
@@ -336,7 +342,6 @@ const commentPrImpact = async ({
336
342
  }
337
343
 
338
344
  const commentForComparison = await createCommentForComparison({
339
- cancellationToken,
340
345
  logger,
341
346
 
342
347
  pullRequestBase,
@@ -350,12 +355,17 @@ const commentPrImpact = async ({
350
355
  return { gitHubComment }
351
356
  }
352
357
 
353
- const ensureGitConfig = async (name, { execCommandInProjectDirectory, valueIfMissing }) => {
358
+ const ensureGitConfig = async (
359
+ name,
360
+ { execCommandInProjectDirectory, valueIfMissing },
361
+ ) => {
354
362
  try {
355
363
  await execCommandInProjectDirectory(`git config ${name}`)
356
364
  return () => {}
357
365
  } catch (e) {
358
- await execCommandInProjectDirectory(`git config ${name} "${valueIfMissing}"`)
366
+ await execCommandInProjectDirectory(
367
+ `git config ${name} "${valueIfMissing}"`,
368
+ )
359
369
  return async () => {
360
370
  await execCommandInProjectDirectory(`git config --unset ${name}`)
361
371
  }
@@ -391,7 +401,10 @@ To fix this, change "pull_request" for "pull_request_target" in your workflow fi
391
401
  See https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request_target`
392
402
  }
393
403
 
394
- const jsenvCreateBeforeMergeErrorComment = (error, { pullRequestBase, pullRequestHead }) => {
404
+ const jsenvCreateBeforeMergeErrorComment = (
405
+ error,
406
+ { pullRequestBase, pullRequestHead },
407
+ ) => {
395
408
  return `---
396
409
 
397
410
  **Error:** Error while trying to collect info before merging ${pullRequestHead} into ${pullRequestBase}.
@@ -401,7 +414,10 @@ const jsenvCreateBeforeMergeErrorComment = (error, { pullRequestBase, pullReques
401
414
  ---`
402
415
  }
403
416
 
404
- const jsenvCreateCommentForAfterMergeError = (error, { pullRequestBase, pullRequestHead }) => {
417
+ const jsenvCreateCommentForAfterMergeError = (
418
+ error,
419
+ { pullRequestBase, pullRequestHead },
420
+ ) => {
405
421
  return `---
406
422
 
407
423
  **Error:** Error while trying to collect info after merging ${pullRequestHead} into ${pullRequestBase}.
@@ -411,7 +427,10 @@ const jsenvCreateCommentForAfterMergeError = (error, { pullRequestBase, pullRequ
411
427
  ---`
412
428
  }
413
429
 
414
- const jsenvCreateCommentForVersionMismatch = ({ beforeMergeVersion, afterMergeversion }) => {
430
+ const jsenvCreateCommentForVersionMismatch = ({
431
+ beforeMergeVersion,
432
+ afterMergeversion,
433
+ }) => {
415
434
  return `---
416
435
 
417
436
  **Error:** Cannot compare before and after merge data because the version are different.
@@ -423,7 +442,10 @@ After merge data version: ${afterMergeversion}
423
442
  ---`
424
443
  }
425
444
 
426
- const jsenvCreateCommentForComparison = ({ beforeMergeInfo, afterMergeInfo }) => {
445
+ const jsenvCreateCommentForComparison = ({
446
+ beforeMergeInfo,
447
+ afterMergeInfo,
448
+ }) => {
427
449
  return `--- before merge ---
428
450
  ${JSON.stringify(beforeMergeInfo, null, " ")}
429
451
  --- after merge ---
@@ -1,8 +1,7 @@
1
1
  import { fetchUrl } from "@jsenv/server"
2
2
 
3
- export const GET = async (url, { githubToken, cancellationToken } = {}) => {
3
+ export const GET = async (url, { githubToken } = {}) => {
4
4
  return sendHttpRequest(url, {
5
- cancellationToken,
6
5
  method: "GET",
7
6
  headers: tokenToHeaders(githubToken),
8
7
  responseStatusMap: {
@@ -15,9 +14,8 @@ export const GET = async (url, { githubToken, cancellationToken } = {}) => {
15
14
  })
16
15
  }
17
16
 
18
- export const POST = (url, body, { cancellationToken, githubToken } = {}) => {
17
+ export const POST = (url, body, { githubToken } = {}) => {
19
18
  return sendHttpRequest(url, {
20
- cancellationToken,
21
19
  method: "POST",
22
20
  headers: tokenToHeaders(githubToken),
23
21
  body: JSON.stringify(body),
@@ -30,9 +28,8 @@ export const POST = (url, body, { cancellationToken, githubToken } = {}) => {
30
28
  })
31
29
  }
32
30
 
33
- export const PATCH = async (url, body, { cancellationToken, githubToken } = {}) => {
31
+ export const PATCH = async (url, body, { githubToken } = {}) => {
34
32
  return sendHttpRequest(url, {
35
- cancellationToken,
36
33
  method: "PATCH",
37
34
  headers: tokenToHeaders(githubToken),
38
35
  body: JSON.stringify(body),
@@ -56,15 +53,16 @@ const tokenToHeaders = (token) => {
56
53
 
57
54
  const sendHttpRequest = async (
58
55
  url,
59
- { cancellationToken, method, headers, body, responseStatusMap },
56
+ { method, headers, body, responseStatusMap },
60
57
  ) => {
61
58
  let response
62
59
  try {
63
60
  response = await fetchUrl(url, {
64
- cancellationToken,
65
61
  method,
66
62
  headers: {
67
- ...(typeof body === "undefined" ? {} : { "content-length": Buffer.byteLength(body) }),
63
+ ...(typeof body === "undefined"
64
+ ? {}
65
+ : { "content-length": Buffer.byteLength(body) }),
68
66
  ...headers,
69
67
  },
70
68
  body,
@@ -1,28 +1,25 @@
1
- import { readFileSync } from "fs"
1
+ import { readFileSync } from "node:fs"
2
2
 
3
3
  export const readGitHubWorkflowEnv = () => {
4
4
  const eventName = process.env.GITHUB_EVENT_NAME
5
5
  if (!eventName) {
6
- throw new Error(`missing process.env.GITHUB_EVENT_NAME, we are not in a github workflow`)
6
+ throw new Error(
7
+ `missing process.env.GITHUB_EVENT_NAME, we are not in a github workflow`,
8
+ )
7
9
  }
8
10
  if (eventName !== "pull_request" && eventName !== "pull_request_target") {
9
11
  throw new Error(`must be called only in a pull request`)
10
12
  }
11
-
12
13
  const githubToken = process.env.GITHUB_TOKEN
13
-
14
14
  if (!githubToken) {
15
15
  throw new Error(`missing githubToken`)
16
16
  }
17
-
18
17
  const githubRepository = process.env.GITHUB_REPOSITORY
19
18
  if (!githubRepository) {
20
19
  throw new Error(`missing process.env.GITHUB_REPOSITORY`)
21
20
  }
22
-
23
21
  const [repositoryOwner, repositoryName] = githubRepository.split("/")
24
22
  const pullRequestNumber = readPullRequestNumber()
25
-
26
23
  const runId = process.env.GITHUB_RUN_ID
27
24
  const runLink = runId
28
25
  ? {
@@ -30,7 +27,6 @@ export const readGitHubWorkflowEnv = () => {
30
27
  text: `${process.env.GITHUB_WORKFLOW || "workflow"}#${runId}`,
31
28
  }
32
29
  : undefined
33
-
34
30
  return {
35
31
  projectDirectoryUrl: process.env.GITHUB_WORKSPACE,
36
32
  githubToken,
@@ -46,10 +42,8 @@ const readPullRequestNumber = () => {
46
42
  if (!githubRef) {
47
43
  throw new Error(`missing process.env.GITHUB_REF`)
48
44
  }
49
-
50
45
  const pullRequestNumber = githubRefToPullRequestNumber(githubRef)
51
46
  if (pullRequestNumber) return pullRequestNumber
52
-
53
47
  // https://github.com/actions/checkout/issues/58#issuecomment-589447479
54
48
  const githubEventFilePath = process.env.GITHUB_EVENT_PATH
55
49
  if (githubEventFilePath) {
@@ -67,7 +61,6 @@ ${githubEventFilePath}
67
61
  return pullRequestNumber
68
62
  }
69
63
  }
70
-
71
64
  throw new Error(`cannot get pull request number from process.env.GITHUB_REF
72
65
  --- process.env.GITHUB_REF ---
73
66
  ${githubRef}`)
@@ -77,7 +70,9 @@ const githubRefToPullRequestNumber = (githubRef) => {
77
70
  const pullPrefix = "refs/pull/"
78
71
  const pullRequestNumberStartIndex = githubRef.indexOf(pullPrefix)
79
72
  if (pullRequestNumberStartIndex === -1) return undefined
80
- const afterPull = githubRef.slice(pullRequestNumberStartIndex + pullPrefix.length)
73
+ const afterPull = githubRef.slice(
74
+ pullRequestNumberStartIndex + pullPrefix.length,
75
+ )
81
76
  const slashAfterPullIndex = afterPull.indexOf("/")
82
77
  if (slashAfterPullIndex === -1) return undefined
83
78
  const pullRequestNumberString = afterPull.slice(0, slashAfterPullIndex)