@jsenv/lighthouse-impact 2.1.1 → 2.1.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Lighthouse impact [![npm package](https://img.shields.io/npm/v/@jsenv/lighthouse-impact.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/lighthouse-impact) [![github main](https://github.com/jsenv/lighthouse-impact/workflows/main/badge.svg)](https://github.com/jsenv/lighthouse-impact/actions?workflow=main) [![codecov coverage](https://codecov.io/gh/jsenv/lighthouse-impact/branch/main/graph/badge.svg)](https://codecov.io/gh/jsenv/lighthouse-impact)
1
+ # Lighthouse impact [![npm package](https://img.shields.io/npm/v/@jsenv/lighthouse-impact.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/lighthouse-impact)
2
2
 
3
3
  `@jsenv/lighthouse-impact` analyses a pull request impact on lighthouse score. This analysis is posted in a comment of the pull request on GitHub.
4
4
 
@@ -24,7 +24,7 @@ The first thing you need is a script capable to generate a lighthouse report.
24
24
  npm install --save-dev @jsenv/lighthouse-impact
25
25
  ```
26
26
 
27
- _generate_lighthouse_report.mjs_
27
+ _lighthouse.mjs_
28
28
 
29
29
  ```js
30
30
  /*
@@ -69,7 +69,7 @@ _index.html_
69
69
  </html>
70
70
  ```
71
71
 
72
- At this stage, you could generate a lighthouse report on your machine. For an example, see [package.json#L36](./package.json#L36) and [script/lighthouse/generate_lighthouse_report.mjs#L37](./script/lighthouse/generate_lighthouse_report.mjs#L37).
72
+ At this stage, you could generate a lighthouse report on your machine. For an example, see [package.json#L37](./package.json#L37) and [script/lighthouse/lighthouse.mjs#L19](./script/lighthouse/lighthouse.mjs#L19).
73
73
 
74
74
  Now it's time to configure a workflow to compare lighthouse reports before and after merging a pull request.
75
75
 
@@ -99,10 +99,10 @@ jobs:
99
99
  - name: Setup git
100
100
  uses: actions/checkout@v2
101
101
  - name: Setup node
102
- uses: actions/setup-node@v1
102
+ uses: actions/setup-node@v2
103
103
  with:
104
- node-version: "16.x"
105
- - name: Setup npm
104
+ node-version: "16.13.0"
105
+ - name: Install node modules
106
106
  run: npm install
107
107
  - name: Report lighthouse impact
108
108
  run: node ./report_lighthouse_impact.mjs
@@ -123,9 +123,9 @@ import {
123
123
  readGitHubWorkflowEnv,
124
124
  } from "@jsenv/lighthouse-impact"
125
125
 
126
- reportLighthouseImpact({
126
+ await reportLighthouseImpact({
127
127
  ...readGitHubWorkflowEnv(),
128
- lighthouseReportPath: "./generate_lighthouse_report.mjs#lighthouseReport",
128
+ lighthouseReportPath: "./lighthouse.mjs#lighthouseReport",
129
129
  })
130
130
  ```
131
131
 
@@ -167,7 +167,7 @@ reportLighthouseImpact({
167
167
  + repositoryName: process.env.TRAVIS_REPO_SLUG.split("/")[1],
168
168
  + pullRequestNumber: process.env.TRAVIS_PULL_REQUEST,
169
169
  + githubToken: process.env.GITHUB_TOKEN, // see next step
170
- lighthouseReportPath: "./generate_lighthouse_report.mjs#lighthouseReport",
170
+ lighthouseReportPath: "./lighthouse.mjs#lighthouseReport",
171
171
  })
172
172
  ```
173
173
 
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/lighthouse-impact",
3
- "version": "2.1.1",
3
+ "version": "2.1.5",
4
4
  "description": "Package description",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -10,7 +10,8 @@
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "https://github.com/jsenv/lighthouse-impact"
13
+ "url": "https://github.com/jsenv/workflow",
14
+ "directory": "packages/jsenv-lighthouse-impact"
14
15
  },
15
16
  "engines": {
16
17
  "node": ">=16.13.0"
@@ -32,37 +33,30 @@
32
33
  "/main.js"
33
34
  ],
34
35
  "scripts": {
35
- "eslint": "node ./node_modules/eslint/bin/eslint.js . --ext=.js,.mjs",
36
+ "eslint": "npx eslint . --ext=.js,.mjs",
36
37
  "importmap": "node ./script/importmap/importmap.mjs",
37
- "performance": "node --expose-gc ./script/performance/performance.mjs --log",
38
- "lighthouse": "node ./script/lighthouse/lighthouse.mjs --local",
39
- "generate-comment-snapshot-file": "node ./test/comment/generate_comment_snapshot_file.mjs",
38
+ "snapshot": "node ./test/comment/generate_comment_snapshot_file.mjs",
40
39
  "test": "node ./script/test/test.mjs",
41
40
  "test-with-coverage": "npm run test -- --coverage",
42
41
  "prettier": "prettier --write ."
43
42
  },
44
43
  "dependencies": {
45
- "@jsenv/cancellation": "3.0.0",
46
- "@jsenv/dynamic-import-worker": "1.0.0",
47
- "@jsenv/filesystem": "2.3.1",
48
- "@jsenv/github-pull-request-impact": "1.6.4",
44
+ "@jsenv/abort": "4.1.2",
45
+ "@jsenv/dynamic-import-worker": "1.0.1",
46
+ "@jsenv/filesystem": "2.7.1",
47
+ "@jsenv/github-pull-request-impact": "1.6.7",
49
48
  "@jsenv/logger": "4.0.1",
50
- "chrome-launcher": "0.14.0",
51
- "lighthouse": "8.2.0"
49
+ "chrome-launcher": "0.15.0",
50
+ "lighthouse": "9.2.0"
52
51
  },
53
52
  "devDependencies": {
54
- "@jsenv/assert": "2.4.0",
55
- "@jsenv/core": "24.5.8",
53
+ "@jsenv/assert": "2.4.1",
54
+ "@jsenv/core": "25.3.0",
56
55
  "@jsenv/eslint-config": "16.0.9",
57
- "@jsenv/github-release-package": "1.2.3",
58
- "@jsenv/importmap-eslint-resolver": "5.2.1",
59
- "@jsenv/importmap-node-module": "2.8.0",
60
- "@jsenv/package-publish": "1.6.2",
61
- "@jsenv/performance-impact": "2.2.1",
62
- "@jsenv/server": "12.2.0",
63
- "eslint": "8.4.1",
64
- "eslint-plugin-import": "2.25.3",
65
- "eslint-plugin-html": "6.2.0",
56
+ "@jsenv/importmap-eslint-resolver": "5.2.5",
57
+ "@jsenv/importmap-node-module": "5.1.3",
58
+ "eslint": "8.7.0",
59
+ "eslint-plugin-import": "2.25.4",
66
60
  "prettier": "2.5.1"
67
61
  }
68
62
  }
@@ -2,19 +2,13 @@
2
2
 
3
3
  import { createRequire } from "node:module"
4
4
 
5
- import { createLogger } from "@jsenv/logger"
6
- import {
7
- createCancellationToken,
8
- createCancellationSource,
9
- composeCancellationToken,
10
- createOperation,
11
- executeAsyncFunction,
12
- } from "@jsenv/cancellation"
13
5
  import {
14
6
  writeFile,
15
7
  resolveUrl,
16
8
  assertAndNormalizeDirectoryUrl,
17
9
  } from "@jsenv/filesystem"
10
+ import { createLogger } from "@jsenv/logger"
11
+ import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
18
12
 
19
13
  import { formatLighthouseReportForLog } from "./internal/formatLighthouseReportForLog.js"
20
14
 
@@ -23,8 +17,8 @@ const require = createRequire(import.meta.url)
23
17
  export const generateLighthouseReport = async (
24
18
  url,
25
19
  {
26
- cancellationToken = createCancellationToken(),
27
- cancelOnSIGINT = true,
20
+ signal = new AbortController().signal,
21
+ handleSIGINT = true,
28
22
  logLevel,
29
23
 
30
24
  headless = true,
@@ -47,31 +41,23 @@ export const generateLighthouseReport = async (
47
41
  htmlFileLog = true,
48
42
  } = {},
49
43
  ) => {
50
- // eslint-disable-next-line import/no-unresolved
51
- const ReportGenerator = require("lighthouse/report/report-generator")
44
+ const ReportGenerator = require("lighthouse/report/generator/report-generator.js")
52
45
  const {
53
46
  computeMedianRun,
54
47
  } = require("lighthouse/lighthouse-core/lib/median-run.js")
55
48
  const chromeLauncher = require("chrome-launcher")
56
49
 
57
- let cleanup = () => {}
58
-
59
- if (cancelOnSIGINT) {
60
- const processCancellationSource = createCancellationSource()
61
- const processCancellationToken = processCancellationSource.token
62
- cancellationToken = composeCancellationToken(
63
- cancellationToken,
64
- processCancellationToken,
65
- )
66
- const SIGINTCallback = () => {
67
- processCancellationSource.cancel("process SIGINT")
68
- }
69
- process.once("SIGINT", SIGINTCallback)
70
- // beware if someday something do things on cleanup
71
- // to call the old cleanup function
72
- cleanup = () => {
73
- process.removeListener("SIGINT", SIGINTCallback)
74
- }
50
+ const generateReportOperation = Abort.startOperation()
51
+ generateReportOperation.addAbortSignal(signal)
52
+ if (handleSIGINT) {
53
+ generateReportOperation.addAbortSource((abort) => {
54
+ return raceProcessTeardownEvents(
55
+ {
56
+ SIGINT: true,
57
+ },
58
+ abort,
59
+ )
60
+ })
75
61
  }
76
62
 
77
63
  const jsenvGenerateLighthouseReport = async () => {
@@ -86,32 +72,42 @@ export const generateLighthouseReport = async (
86
72
  "--disk-cache-size=1",
87
73
  // "--disk-cache-dir=/dev/null",
88
74
  ]
89
- const chrome = await createOperation({
90
- cancellationToken,
91
- start: () => chromeLauncher.launch({ chromeFlags }),
92
- })
75
+ const chrome = await chromeLauncher.launch({ chromeFlags })
76
+ if (generateReportOperation.signal.aborted) {
77
+ return { aborted: true }
78
+ }
79
+
93
80
  const lighthouseOptions = {
94
81
  chromeFlags,
95
82
  port: chrome.port,
96
83
  }
97
84
 
98
85
  const reports = []
99
- await Array(runCount)
100
- .fill()
101
- .reduce(async (previous, _, index) => {
102
- await previous
103
- if (index > 0 && delayBetweenEachRunInSeconds) {
104
- await new Promise((resolve) =>
105
- setTimeout(resolve, delayBetweenEachRunInSeconds * 1000),
106
- )
107
- }
108
- const report = await generateOneLighthouseReport(url, {
109
- cancellationToken,
110
- lighthouseOptions,
111
- config,
112
- })
113
- reports.push(report)
114
- }, Promise.resolve())
86
+ try {
87
+ await Array(runCount)
88
+ .fill()
89
+ .reduce(async (previous, _, index) => {
90
+ generateReportOperation.throwIfAborted()
91
+ await previous
92
+
93
+ if (index > 0 && delayBetweenEachRunInSeconds) {
94
+ await new Promise((resolve) =>
95
+ setTimeout(resolve, delayBetweenEachRunInSeconds * 1000),
96
+ )
97
+ }
98
+ generateReportOperation.throwIfAborted()
99
+ const report = await generateOneLighthouseReport(url, {
100
+ lighthouseOptions,
101
+ config,
102
+ })
103
+ reports.push(report)
104
+ }, Promise.resolve())
105
+ } catch (e) {
106
+ if (Abort.isAbortError(e)) {
107
+ return { aborted: true }
108
+ }
109
+ throw e
110
+ }
115
111
 
116
112
  const lighthouseReport = computeMedianRun(reports)
117
113
 
@@ -161,30 +157,19 @@ export const generateLighthouseReport = async (
161
157
  return lighthouseReport
162
158
  }
163
159
 
164
- return executeAsyncFunction(
165
- async () => {
166
- try {
167
- return await jsenvGenerateLighthouseReport()
168
- } finally {
169
- cleanup()
170
- }
171
- },
172
- {
173
- catchCancellation: true,
174
- considerUnhandledRejectionsAsExceptions: true,
175
- },
176
- )
160
+ try {
161
+ return await jsenvGenerateLighthouseReport()
162
+ } finally {
163
+ await generateReportOperation.end()
164
+ }
177
165
  }
178
166
 
179
167
  const generateOneLighthouseReport = async (
180
168
  url,
181
- { cancellationToken, lighthouseOptions, config },
169
+ { lighthouseOptions, config },
182
170
  ) => {
183
171
  const lighthouse = require("lighthouse")
184
- const results = await createOperation({
185
- cancellationToken,
186
- start: () => lighthouse(url, lighthouseOptions, config),
187
- })
172
+ const results = await lighthouse(url, lighthouseOptions, config)
188
173
 
189
174
  // use results.lhr for the JS-consumeable output
190
175
  // https://github.com/GoogleChrome/lighthouse/blob/master/types/lhr.d.ts
@@ -1,15 +1,9 @@
1
- /* eslint-disable new-cap */
1
+ import * as githubRESTAPI from "@jsenv/github-pull-request-impact/src/internal/github_rest_api.js"
2
2
  import { createDetailedMessage } from "@jsenv/logger"
3
- import {
4
- GET,
5
- POST,
6
- PATCH,
7
- } from "@jsenv/github-pull-request-impact/src/internal/git_hub_api.js"
8
3
 
9
4
  // https://developer.github.com/v3/gists/#create-a-gist
10
5
 
11
6
  export const patchOrPostGists = async ({
12
- cancellationToken,
13
7
  logger,
14
8
 
15
9
  githubToken,
@@ -45,14 +39,14 @@ export const patchOrPostGists = async ({
45
39
  logger.debug(`update or create both gists.`)
46
40
  let [beforeMergeGist, afterMergeGist] = await Promise.all([
47
41
  beforeMergeGistId
48
- ? GET(`https://api.github.com/gists/${beforeMergeGistId}`, {
49
- cancellationToken,
42
+ ? githubRESTAPI.GET({
43
+ url: `https://api.github.com/gists/${beforeMergeGistId}`,
50
44
  githubToken,
51
45
  })
52
46
  : null,
53
47
  afterMergeGistId
54
- ? GET(`https://api.github.com/gists/${afterMergeGistId}`, {
55
- cancellationToken,
48
+ ? githubRESTAPI.GET({
49
+ url: `https://api.github.com/gists/${afterMergeGistId}`,
56
50
  githubToken,
57
51
  })
58
52
  : null,
@@ -66,25 +60,19 @@ export const patchOrPostGists = async ({
66
60
  })
67
61
  if (beforeMergeGist) {
68
62
  logger.info(`updating base gist at ${gistIdToUrl(beforeMergeGist.id)}`)
69
- beforeMergeGist = await PATCH(
70
- `https://api.github.com/gists/${beforeMergeGist.id}`,
71
- beforeMergeGistBody,
72
- {
73
- cancellationToken,
74
- githubToken,
75
- },
76
- )
63
+ beforeMergeGist = await githubRESTAPI.PATCH({
64
+ url: `https://api.github.com/gists/${beforeMergeGist.id}`,
65
+ githubToken,
66
+ body: beforeMergeGistBody,
67
+ })
77
68
  logger.info(`base gist updated`)
78
69
  } else {
79
70
  logger.info(`creating base gist`)
80
- beforeMergeGist = await POST(
81
- `https://api.github.com/gists`,
82
- beforeMergeGistBody,
83
- {
84
- cancellationToken,
85
- githubToken,
86
- },
87
- )
71
+ beforeMergeGist = await githubRESTAPI.POST({
72
+ url: `https://api.github.com/gists`,
73
+ githubToken,
74
+ body: beforeMergeGistBody,
75
+ })
88
76
  logger.info(`base gist created at ${gistIdToUrl(beforeMergeGist.id)}`)
89
77
  }
90
78
 
@@ -98,25 +86,19 @@ export const patchOrPostGists = async ({
98
86
  logger.info(
99
87
  `updating after merge gist at ${gistIdToUrl(afterMergeGist.id)}`,
100
88
  )
101
- afterMergeGist = await PATCH(
102
- `https://api.github.com/gists/${afterMergeGist.id}`,
103
- afterMergeGistBody,
104
- {
105
- cancellationToken,
106
- githubToken,
107
- },
108
- )
89
+ afterMergeGist = await githubRESTAPI.PATCH({
90
+ url: `https://api.github.com/gists/${afterMergeGist.id}`,
91
+ githubToken,
92
+ body: afterMergeGistBody,
93
+ })
109
94
  logger.info(`after merge gist updated`)
110
95
  } else {
111
96
  logger.info(`creating after merge gist`)
112
- afterMergeGist = await POST(
113
- `https://api.github.com/gists`,
114
- afterMergeGistBody,
115
- {
116
- cancellationToken,
117
- githubToken,
118
- },
119
- )
97
+ afterMergeGist = await githubRESTAPI.POST({
98
+ url: `https://api.github.com/gists`,
99
+ githubToken,
100
+ body: afterMergeGistBody,
101
+ })
120
102
  logger.info(`after merge gist created at ${gistIdToUrl(afterMergeGist.id)}`)
121
103
  }
122
104
 
@@ -1,5 +1,5 @@
1
- import { commentGitHubPullRequestImpact } from "@jsenv/github-pull-request-impact"
2
1
  import { assertAndNormalizeDirectoryUrl, resolveUrl } from "@jsenv/filesystem"
2
+ import { commentGitHubPullRequestImpact } from "@jsenv/github-pull-request-impact"
3
3
  import { importOneExportFromFile } from "@jsenv/dynamic-import-worker"
4
4
 
5
5
  import { patchOrPostGists } from "./internal/patchOrPostGists.js"
@@ -8,7 +8,6 @@ import { createLighthouseImpactComment } from "./internal/createLighthouseImpact
8
8
  export const reportLighthouseImpact = async ({
9
9
  logLevel,
10
10
  commandLogs = false,
11
- cancellationToken,
12
11
  cancelOnSIGINT,
13
12
  projectDirectoryUrl,
14
13
 
@@ -41,7 +40,6 @@ export const reportLighthouseImpact = async ({
41
40
  commandLogs,
42
41
  // lighthouse report are super verbose, do not log them
43
42
  infoLogs: false,
44
- cancellationToken,
45
43
  cancelOnSIGINT,
46
44
  projectDirectoryUrl,
47
45
 
@@ -59,7 +57,6 @@ export const reportLighthouseImpact = async ({
59
57
  },
60
58
  commentIdentifier: `<!-- Generated by @jsenv/lighthouse-impact -->`,
61
59
  createCommentForComparison: async ({
62
- cancellationToken,
63
60
  logger,
64
61
 
65
62
  pullRequestBase,
@@ -74,7 +71,6 @@ export const reportLighthouseImpact = async ({
74
71
  let afterMergeGist
75
72
  try {
76
73
  const gistResult = await patchOrPostGists({
77
- cancellationToken,
78
74
  logger,
79
75
 
80
76
  githubToken,