Skip to content

Commit d3199ad

Browse files
authored
Optionally run onSuccess (#558)
Reworks internal logic to allow running against either onPostBuild, or onSuccess
1 parent b2383d5 commit d3199ad

File tree

13 files changed

+297
-121
lines changed

13 files changed

+297
-121
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ node_modules
22
.env
33
.vscode
44
yarn-error.log
5+
.DS_Store
6+
57
# Local Netlify folder
68
.netlify
79
reports

manifest.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: netlify-plugin-lighthouse
22
inputs:
3+
- name: audits
4+
required: false
5+
description: A list of audits to perform. Each list item is an object with either a url/path to scan and an optional thresholds mapping.
6+
37
# Deprecated, use audits
48
- name: audit_url
59
required: false
@@ -13,10 +17,10 @@ inputs:
1317
required: false
1418
description: Path to save the generated HTML Lighthouse report
1519

16-
- name: audits
17-
required: false
18-
description: A list of audits to perform. Each list item is an object with either a url/path to scan and an optional thresholds mapping.
19-
2020
- name: settings
2121
required: false
2222
description: Lighthouse-specific settings, used to modify reporting criteria
23+
24+
- name: run_on_success
25+
required: false
26+
description: (Beta) Run Lighthouse against the deployed site

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"description": "Netlify Plugin to run Lighthouse on each build",
55
"main": "src/index.js",
66
"scripts": {
7-
"local": "node -e 'import(\"./src/index.js\").then(index => index.onPostBuild());'",
7+
"local": "node -e 'import(\"./src/index.js\").then(index => index.default()).then(events => events.onPostBuild());'",
8+
"local-onsuccess": "RUN_ON_SUCCESS=true node -e 'import(\"./src/index.js\").then(index => index.default()).then(events => events.onSuccess());'",
89
"lint": "eslint 'src/**/*.js'",
910
"format": "prettier --write 'src/**/*.js'",
1011
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --collect-coverage",

src/index.js

Lines changed: 38 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,46 @@
1-
import chalk from 'chalk';
21
import * as dotenv from 'dotenv';
32

4-
import processResults from './lib/process-results/index.js';
3+
import runEvent from './lib/run-event/index.js';
54
import getUtils from './lib/get-utils/index.js';
6-
import getConfiguration from './lib/get-configuration/index.js';
7-
import getSettings from './lib/get-settings/index.js';
8-
import runAudit from './lib/run-audit/index.js';
95

106
dotenv.config();
117

12-
export const onPostBuild = async ({ constants, utils, inputs } = {}) => {
13-
const { failBuild, show } = getUtils({ utils });
14-
let errorMetadata = [];
15-
16-
try {
17-
const { audits } = getConfiguration({
18-
constants,
19-
inputs,
20-
});
21-
22-
const settings = getSettings(inputs?.settings);
23-
24-
const allErrors = [];
25-
const data = [];
26-
for (const { serveDir, path, url, thresholds, output_path } of audits) {
27-
const { errors, summary, shortSummary, details, report, runtimeError } =
28-
await runAudit({
29-
serveDir,
30-
path,
31-
url,
32-
thresholds,
33-
output_path,
34-
settings,
8+
export default function lighthousePlugin(inputs) {
9+
// Run onPostBuild by default, unless RUN_ON_SUCCESS is set to true
10+
const defaultEvent =
11+
inputs?.run_on_success === 'true' || process.env.RUN_ON_SUCCESS === 'true'
12+
? 'onSuccess'
13+
: 'onPostBuild';
14+
15+
if (defaultEvent === 'onSuccess') {
16+
return {
17+
onSuccess: async ({ constants, utils, inputs } = {}) => {
18+
// Mock the required `utils` functions if running locally
19+
const { failPlugin, show } = getUtils({ utils });
20+
21+
await runEvent({
22+
event: 'onSuccess',
23+
constants,
24+
inputs,
25+
onComplete: show,
26+
onFail: failPlugin,
3527
});
36-
37-
if (summary && !runtimeError) {
38-
console.log({ results: summary });
39-
}
40-
if (runtimeError) {
41-
console.log({ runtimeError });
42-
}
43-
44-
const fullPath = [serveDir, path].join('/');
45-
if (report) {
46-
const size = Buffer.byteLength(JSON.stringify(report));
47-
console.log(
48-
`Report collected: audited_uri: '${chalk.magenta(
49-
url || fullPath,
50-
)}', html_report_size: ${chalk.magenta(
51-
+(size / 1024).toFixed(2),
52-
)} KiB`,
53-
);
54-
}
55-
56-
if (Array.isArray(errors) && errors.length > 0) {
57-
allErrors.push({ serveDir, url, errors });
58-
}
59-
data.push({
60-
path: fullPath,
61-
url,
62-
summary,
63-
shortSummary,
64-
details,
65-
report,
66-
runtimeError,
67-
});
68-
}
69-
70-
const { error, summary, extraData } = processResults({
71-
data,
72-
errors: allErrors,
73-
show,
74-
});
75-
errorMetadata.push(...extraData);
76-
77-
if (error && Object.keys(error).length !== 0) {
78-
throw error;
79-
}
80-
81-
show({ summary, extraData });
82-
} catch (error) {
83-
if (error.details) {
84-
console.error(error.details);
85-
failBuild(`${chalk.red('Failed with error:\n')}${error.message}`, {
86-
errorMetadata,
87-
});
88-
} else {
89-
failBuild(`${chalk.red('Failed with error:\n')}`, {
90-
error,
91-
errorMetadata,
92-
});
93-
}
28+
},
29+
};
30+
} else {
31+
return {
32+
onPostBuild: async ({ constants, utils, inputs } = {}) => {
33+
// Mock the required `utils` functions if running locally
34+
const { failBuild, show } = getUtils({ utils });
35+
36+
await runEvent({
37+
event: 'onPostBuild',
38+
constants,
39+
inputs,
40+
onComplete: show,
41+
onFail: failBuild,
42+
});
43+
},
44+
};
9445
}
95-
};
46+
}

src/lib/get-configuration/get-configuration.test.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('config', () => {
2323
const config = getConfiguration();
2424

2525
expect(config).toEqual({
26-
audits: [
26+
auditConfigs: [
2727
{
2828
serveDir: undefined,
2929
url: undefined,
@@ -40,7 +40,7 @@ describe('config', () => {
4040
const config = getConfiguration();
4141

4242
expect(config).toEqual({
43-
audits: [
43+
auditConfigs: [
4444
{
4545
serveDir: 'PUBLISH_DIR',
4646
url: 'AUDIT_URL',
@@ -59,7 +59,7 @@ describe('config', () => {
5959
const config = getConfiguration();
6060

6161
expect(config).toEqual({
62-
audits: [
62+
auditConfigs: [
6363
{
6464
url: 'https://www.test.com',
6565
thresholds: { performance: 0.9 },
@@ -93,7 +93,7 @@ describe('config', () => {
9393
const config = getConfiguration({ constants, inputs });
9494

9595
expect(config).toEqual({
96-
audits: [
96+
auditConfigs: [
9797
{
9898
serveDir: 'PUBLISH_DIR',
9999
url: 'url',
@@ -106,11 +106,15 @@ describe('config', () => {
106106

107107
it('should append audits serveDir to PUBLISH_DIR', () => {
108108
const constants = { PUBLISH_DIR: 'PUBLISH_DIR' };
109-
const inputs = { audits: [{ serveDir: 'route1', thresholds: { seo: 1 } }] };
109+
const inputs = {
110+
audits: [{ serveDir: 'route1', thresholds: { seo: 1 } }],
111+
};
110112
const config = getConfiguration({ constants, inputs });
111113

112114
expect(config).toEqual({
113-
audits: [{ serveDir: 'PUBLISH_DIR/route1', thresholds: { seo: 1 } }],
115+
auditConfigs: [
116+
{ serveDir: 'PUBLISH_DIR/route1', thresholds: { seo: 1 } },
117+
],
114118
});
115119
});
116120

@@ -126,7 +130,7 @@ describe('config', () => {
126130
const config = getConfiguration({ constants, inputs });
127131

128132
expect(config).toEqual({
129-
audits: [
133+
auditConfigs: [
130134
{ serveDir: 'PUBLISH_DIR/route1', thresholds: { seo: 1 } },
131135
{ serveDir: 'PUBLISH_DIR/route2', thresholds: { performance: 1 } },
132136
],
@@ -156,7 +160,7 @@ describe('config', () => {
156160
const config = getConfiguration({ constants, inputs });
157161

158162
expect(config).toEqual({
159-
audits: [{ serveDir: 'PUBLISH_DIR/a/b', thresholds: {} }],
163+
auditConfigs: [{ serveDir: 'PUBLISH_DIR/a/b', thresholds: {} }],
160164
});
161165
});
162166

@@ -196,7 +200,7 @@ describe('config', () => {
196200
const config = getConfiguration({ constants, inputs });
197201

198202
expect(config).toEqual({
199-
audits: [
203+
auditConfigs: [
200204
{
201205
serveDir: 'PUBLISH_DIR/route1',
202206
output_path: 'reports/lighthouse.html',

src/lib/get-configuration/index.js

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import chalk from 'chalk';
22

33
import getServePath from '../get-serve-path/index.js';
44

5-
const getConfiguration = ({ constants, inputs } = {}) => {
5+
const getConfiguration = ({ constants, inputs, deployUrl } = {}) => {
6+
const useDeployUrl = !!deployUrl;
7+
68
const serveDir =
79
(constants && constants.PUBLISH_DIR) || process.env.PUBLISH_DIR;
810

911
const auditUrl = (inputs && inputs.audit_url) || process.env.AUDIT_URL;
1012

11-
const output_path = (inputs && inputs.output_path) || process.env.OUTPUT_PATH;
12-
1313
if (auditUrl) {
1414
console.warn(
1515
`${chalk.yellow(
@@ -18,6 +18,8 @@ const getConfiguration = ({ constants, inputs } = {}) => {
1818
);
1919
}
2020

21+
const output_path = (inputs && inputs.output_path) || process.env.OUTPUT_PATH;
22+
2123
let thresholds =
2224
(inputs && inputs.thresholds) || process.env.THRESHOLDS || {};
2325

@@ -38,20 +40,37 @@ const getConfiguration = ({ constants, inputs } = {}) => {
3840
}
3941
}
4042

43+
let auditConfigs = [];
44+
45+
/** TODO: Simplify this…
46+
* When using a deployUrl (testing against the live deployed site), we don't
47+
* need to serve the site, so we can skip the serveDir and output_path
48+
*/
49+
4150
if (!Array.isArray(audits)) {
42-
audits = [{ serveDir, url: auditUrl, thresholds, output_path }];
51+
auditConfigs = [
52+
{
53+
serveDir: useDeployUrl ? undefined : serveDir,
54+
url: useDeployUrl ? deployUrl : auditUrl,
55+
thresholds,
56+
output_path: useDeployUrl ? undefined : output_path,
57+
},
58+
];
4359
} else {
44-
audits = audits.map((a) => {
60+
auditConfigs = audits.map((a) => {
4561
return {
4662
...a,
4763
thresholds: a.thresholds || thresholds,
48-
output_path: a.output_path || output_path,
49-
...getServePath(serveDir, a.serveDir ?? ''),
64+
output_path: useDeployUrl ? undefined : a.output_path || output_path,
65+
url: useDeployUrl ? deployUrl : a.url,
66+
serveDir: useDeployUrl
67+
? undefined
68+
: getServePath(serveDir, a.serveDir ?? ''),
5069
};
5170
});
5271
}
5372

54-
return { audits };
73+
return { auditConfigs };
5574
};
5675

5776
export default getConfiguration;

src/lib/get-serve-path/get-serve-path.test.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@ import getServePath from '.';
22

33
describe('getServePath', () => {
44
it('returns undefined for dir thats not a string', () => {
5-
expect(getServePath(2)).toEqual({ serveDir: undefined });
5+
expect(getServePath(2)).toEqual(undefined);
66
});
77

88
it('returns undefined for subdir thats not a string', () => {
9-
expect(getServePath(2, 2)).toEqual({ serveDir: undefined });
9+
expect(getServePath(2, 2)).toEqual(undefined);
1010
});
1111

1212
it('returns joined path for serveDir', () => {
13-
expect(getServePath('example', 'path')).toEqual({
14-
serveDir: 'example/path',
15-
});
13+
expect(getServePath('example', 'path')).toEqual('example/path');
1614
});
1715
});

src/lib/get-serve-path/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import chalk from 'chalk';
44

55
const getServePath = (dir, subDir) => {
66
if (typeof subDir !== 'string' || typeof dir !== 'string') {
7-
return { serveDir: undefined };
7+
return undefined;
88
}
99

1010
const resolvedPath = join(dir, subDir);
@@ -18,7 +18,7 @@ const getServePath = (dir, subDir) => {
1818
);
1919
}
2020

21-
return { serveDir: resolvedPath };
21+
return resolvedPath;
2222
};
2323

2424
export default getServePath;

0 commit comments

Comments
 (0)