@percy/core 1.28.3-beta.1 → 1.28.4-beta.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/discovery.js +55 -43
- package/dist/percy.js +79 -42
- package/dist/secretPatterns.yml +7024 -0
- package/dist/timing.js +21 -0
- package/dist/utils.js +26 -0
- package/package.json +10 -8
- package/test/helpers/index.js +1 -0
package/dist/discovery.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import logger from '@percy/logger';
|
|
2
2
|
import Queue from './queue.js';
|
|
3
3
|
import { normalizeURL, hostnameMatches, createResource, createRootResource, createPercyCSSResource, createLogResource, yieldAll, snapshotLogName, withRetries } from './utils.js';
|
|
4
|
+
import { sha256hash } from '@percy/client/utils';
|
|
5
|
+
import Pako from 'pako';
|
|
6
|
+
import TimeIt from './timing.js';
|
|
4
7
|
|
|
5
8
|
// Logs verbose debug logs detailing various snapshot options.
|
|
6
9
|
function debugSnapshotOptions(snapshot) {
|
|
@@ -143,6 +146,12 @@ function processSnapshotResources({
|
|
|
143
146
|
var _log$meta$snapshot, _log$meta$snapshot2;
|
|
144
147
|
return ((_log$meta$snapshot = log.meta.snapshot) === null || _log$meta$snapshot === void 0 ? void 0 : _log$meta$snapshot.testCase) === snapshot.meta.snapshot.testCase && ((_log$meta$snapshot2 = log.meta.snapshot) === null || _log$meta$snapshot2 === void 0 ? void 0 : _log$meta$snapshot2.name) === snapshot.meta.snapshot.name;
|
|
145
148
|
})));
|
|
149
|
+
if (process.env.PERCY_GZIP) {
|
|
150
|
+
for (let index = 0; index < resources.length; index++) {
|
|
151
|
+
resources[index].content = Pako.gzip(resources[index].content);
|
|
152
|
+
resources[index].sha = sha256hash(resources[index].content);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
146
155
|
return {
|
|
147
156
|
...snapshot,
|
|
148
157
|
resources
|
|
@@ -304,6 +313,7 @@ export function createDiscoveryQueue(percy) {
|
|
|
304
313
|
concurrency
|
|
305
314
|
} = percy.config.discovery;
|
|
306
315
|
let queue = new Queue('discovery');
|
|
316
|
+
let timeit = new TimeIt();
|
|
307
317
|
let cache;
|
|
308
318
|
return queue.set({
|
|
309
319
|
concurrency
|
|
@@ -334,54 +344,56 @@ export function createDiscoveryQueue(percy) {
|
|
|
334
344
|
})
|
|
335
345
|
// discovery resources for snapshots and call the callback for each discovered snapshot
|
|
336
346
|
.handle('task', async function* (snapshot, callback) {
|
|
337
|
-
|
|
347
|
+
await timeit.measure('asset-discovery', snapshot.name, async () => {
|
|
348
|
+
percy.log.debug(`Discovering resources: ${snapshot.name}`, snapshot.meta);
|
|
338
349
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
350
|
+
// expectation explained in tests
|
|
351
|
+
/* istanbul ignore next: tested, but coverage is stripped */
|
|
352
|
+
let assetDiscoveryPageEnableJS = snapshot.cliEnableJavaScript && !snapshot.domSnapshot || (snapshot.enableJavaScript ?? !snapshot.domSnapshot);
|
|
353
|
+
percy.log.debug(`Asset discovery Browser Page enable JS: ${assetDiscoveryPageEnableJS}`);
|
|
354
|
+
await withRetries(async function* () {
|
|
355
|
+
// create a new browser page
|
|
356
|
+
let page = yield percy.browser.page({
|
|
357
|
+
enableJavaScript: assetDiscoveryPageEnableJS,
|
|
358
|
+
networkIdleTimeout: snapshot.discovery.networkIdleTimeout,
|
|
359
|
+
requestHeaders: snapshot.discovery.requestHeaders,
|
|
360
|
+
authorization: snapshot.discovery.authorization,
|
|
361
|
+
userAgent: snapshot.discovery.userAgent,
|
|
362
|
+
captureMockedServiceWorker: snapshot.discovery.captureMockedServiceWorker,
|
|
363
|
+
meta: snapshot.meta,
|
|
364
|
+
// enable network inteception
|
|
365
|
+
intercept: {
|
|
366
|
+
enableJavaScript: snapshot.enableJavaScript,
|
|
367
|
+
disableCache: snapshot.discovery.disableCache,
|
|
368
|
+
allowedHostnames: snapshot.discovery.allowedHostnames,
|
|
369
|
+
disallowedHostnames: snapshot.discovery.disallowedHostnames,
|
|
370
|
+
getResource: u => snapshot.resources.get(u) || cache.get(u),
|
|
371
|
+
saveResource: r => {
|
|
372
|
+
snapshot.resources.set(r.url, r);
|
|
373
|
+
if (!r.root) {
|
|
374
|
+
cache.set(r.url, r);
|
|
375
|
+
}
|
|
364
376
|
}
|
|
365
377
|
}
|
|
378
|
+
});
|
|
379
|
+
try {
|
|
380
|
+
yield* captureSnapshotResources(page, snapshot, {
|
|
381
|
+
captureWidths: !snapshot.domSnapshot && percy.deferUploads,
|
|
382
|
+
capture: callback,
|
|
383
|
+
captureForDevices: percy.deviceDetails || []
|
|
384
|
+
});
|
|
385
|
+
} finally {
|
|
386
|
+
// always close the page when done
|
|
387
|
+
await page.close();
|
|
366
388
|
}
|
|
389
|
+
}, {
|
|
390
|
+
count: snapshot.discovery.retry ? 3 : 1,
|
|
391
|
+
onRetry: () => {
|
|
392
|
+
percy.log.info(`Retrying snapshot: ${snapshotLogName(snapshot.name, snapshot.meta)}`, snapshot.meta);
|
|
393
|
+
},
|
|
394
|
+
signal: snapshot._ctrl.signal,
|
|
395
|
+
throwOn: ['AbortError']
|
|
367
396
|
});
|
|
368
|
-
try {
|
|
369
|
-
yield* captureSnapshotResources(page, snapshot, {
|
|
370
|
-
captureWidths: !snapshot.domSnapshot && percy.deferUploads,
|
|
371
|
-
capture: callback,
|
|
372
|
-
captureForDevices: percy.deviceDetails || []
|
|
373
|
-
});
|
|
374
|
-
} finally {
|
|
375
|
-
// always close the page when done
|
|
376
|
-
await page.close();
|
|
377
|
-
}
|
|
378
|
-
}, {
|
|
379
|
-
count: snapshot.discovery.retry ? 3 : 1,
|
|
380
|
-
onRetry: () => {
|
|
381
|
-
percy.log.info(`Retrying snapshot: ${snapshotLogName(snapshot.name, snapshot.meta)}`, snapshot.meta);
|
|
382
|
-
},
|
|
383
|
-
signal: snapshot._ctrl.signal,
|
|
384
|
-
throwOn: ['AbortError']
|
|
385
397
|
});
|
|
386
398
|
}).handle('error', ({
|
|
387
399
|
name,
|
package/dist/percy.js
CHANGED
|
@@ -2,10 +2,11 @@ import PercyClient from '@percy/client';
|
|
|
2
2
|
import PercyConfig from '@percy/config';
|
|
3
3
|
import logger from '@percy/logger';
|
|
4
4
|
import Browser from './browser.js';
|
|
5
|
+
import Pako from 'pako';
|
|
6
|
+
import { base64encode, generatePromise, yieldAll, yieldTo, redactSecrets } from './utils.js';
|
|
5
7
|
import { createPercyServer, createStaticServer } from './api.js';
|
|
6
8
|
import { gatherSnapshots, createSnapshotsQueue, validateSnapshotOptions } from './snapshot.js';
|
|
7
9
|
import { discoverSnapshotResources, createDiscoveryQueue } from './discovery.js';
|
|
8
|
-
import { generatePromise, yieldAll, yieldTo } from './utils.js';
|
|
9
10
|
import { WaitForJob } from './wait-for-job.js';
|
|
10
11
|
|
|
11
12
|
// A Percy instance will create a new build when started, handle snapshot creation, asset discovery,
|
|
@@ -146,6 +147,7 @@ export class Percy {
|
|
|
146
147
|
this.readyState = 0;
|
|
147
148
|
try {
|
|
148
149
|
var _this$build;
|
|
150
|
+
this.log.warn('Notice: Percy collects CI logs for service improvement, stored for 14 days. Opt-out anytime with export PERCY_CLIENT_ERROR_LOGS=false');
|
|
149
151
|
// start the snapshots queue immediately when not delayed or deferred
|
|
150
152
|
if (!this.delayUploads && !this.deferUploads) yield this.#snapshots.start();
|
|
151
153
|
// do not start the discovery queue when not needed
|
|
@@ -206,54 +208,61 @@ export class Percy {
|
|
|
206
208
|
// Stops the local API server and closes the browser and internal queues once snapshots have
|
|
207
209
|
// completed. Does nothing if not running. When `force` is true, any queued snapshots are cleared.
|
|
208
210
|
async *stop(force) {
|
|
209
|
-
var _this$server3;
|
|
210
211
|
// not started, but the browser was launched
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
212
|
+
try {
|
|
213
|
+
var _this$server3;
|
|
214
|
+
if (!this.readyState && this.browser.isConnected()) {
|
|
215
|
+
await this.browser.close();
|
|
216
|
+
}
|
|
217
|
+
if (this.syncQueue) this.syncQueue.stop();
|
|
218
|
+
// not started or already stopped
|
|
219
|
+
if (!this.readyState || this.readyState > 2) return;
|
|
220
|
+
|
|
221
|
+
// close queues asap
|
|
222
|
+
if (force) {
|
|
223
|
+
this.#discovery.close(true);
|
|
224
|
+
this.#snapshots.close(true);
|
|
225
|
+
}
|
|
223
226
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
+
// already stopping
|
|
228
|
+
if (this.readyState === 2) return;
|
|
229
|
+
this.readyState = 2;
|
|
227
230
|
|
|
228
|
-
|
|
229
|
-
|
|
231
|
+
// log when force stopping
|
|
232
|
+
if (force) this.log.info('Stopping percy...');
|
|
230
233
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
234
|
+
// used to log snapshot count information
|
|
235
|
+
let info = (state, size) => `${state} ` + `${size} snapshot${size !== 1 ? 's' : ''}`;
|
|
236
|
+
try {
|
|
237
|
+
// flush discovery and snapshot queues
|
|
238
|
+
yield* this.yield.flush((state, size) => {
|
|
239
|
+
this.log.progress(`${info(state, size)}...`, !!size);
|
|
240
|
+
});
|
|
241
|
+
} catch (error) {
|
|
242
|
+
// reset ready state when aborted
|
|
243
|
+
/* istanbul ignore else: all errors bubble */
|
|
244
|
+
if (error.name === 'AbortError') this.readyState = 1;
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
244
247
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
248
|
+
// if dry-running, log the total number of snapshots
|
|
249
|
+
if (this.dryRun && this.#snapshots.size) {
|
|
250
|
+
this.log.info(info('Found', this.#snapshots.size));
|
|
251
|
+
}
|
|
249
252
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
253
|
+
// close server and end queues
|
|
254
|
+
await ((_this$server3 = this.server) === null || _this$server3 === void 0 ? void 0 : _this$server3.close());
|
|
255
|
+
await this.#discovery.end();
|
|
256
|
+
await this.#snapshots.end();
|
|
254
257
|
|
|
255
|
-
|
|
256
|
-
|
|
258
|
+
// mark instance as stopped
|
|
259
|
+
this.readyState = 3;
|
|
260
|
+
} catch (err) {
|
|
261
|
+
this.log.error(err);
|
|
262
|
+
throw err;
|
|
263
|
+
} finally {
|
|
264
|
+
await this.sendBuildLogs();
|
|
265
|
+
}
|
|
257
266
|
}
|
|
258
267
|
|
|
259
268
|
// Takes one or more snapshots of a page while discovering resources to upload with the resulting
|
|
@@ -412,5 +421,33 @@ export class Percy {
|
|
|
412
421
|
if (syncMode) options.sync = syncMode;
|
|
413
422
|
return syncMode;
|
|
414
423
|
}
|
|
424
|
+
async sendBuildLogs() {
|
|
425
|
+
if (!process.env.PERCY_TOKEN) return;
|
|
426
|
+
try {
|
|
427
|
+
var _this$build3, _this$build4, _this$build5, _this$build6;
|
|
428
|
+
const logsObject = {
|
|
429
|
+
clilogs: logger.query(() => true)
|
|
430
|
+
};
|
|
431
|
+
// Only add CI logs if not disabled voluntarily.
|
|
432
|
+
if (process.env.PERCY_CLIENT_ERROR_LOGS !== 'false') {
|
|
433
|
+
const redactedContent = redactSecrets(logger.query(() => true, true));
|
|
434
|
+
logsObject.cilogs = redactedContent;
|
|
435
|
+
}
|
|
436
|
+
const content = base64encode(Pako.gzip(JSON.stringify(logsObject)));
|
|
437
|
+
const referenceId = (_this$build3 = this.build) !== null && _this$build3 !== void 0 && _this$build3.id ? `build_${(_this$build4 = this.build) === null || _this$build4 === void 0 ? void 0 : _this$build4.id}` : (_this$build5 = this.build) === null || _this$build5 === void 0 ? void 0 : _this$build5.id;
|
|
438
|
+
const eventObject = {
|
|
439
|
+
content: content,
|
|
440
|
+
build_id: (_this$build6 = this.build) === null || _this$build6 === void 0 ? void 0 : _this$build6.id,
|
|
441
|
+
reference_id: referenceId,
|
|
442
|
+
service_name: 'cli',
|
|
443
|
+
base64encoded: true
|
|
444
|
+
};
|
|
445
|
+
// Ignore this will update once I implement logs controller.
|
|
446
|
+
const logsSHA = await this.client.sendBuildLogs(eventObject);
|
|
447
|
+
this.log.info(`Build logs sent successfully. Please share this log ID with Percy team in case of any issues - ${logsSHA}`);
|
|
448
|
+
} catch (err) {
|
|
449
|
+
this.log.warn('Could not send the builds logs');
|
|
450
|
+
}
|
|
451
|
+
}
|
|
415
452
|
}
|
|
416
453
|
export default Percy;
|