@percy/cli-build 1.0.0-beta.8 → 1.0.1

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
@@ -7,44 +7,45 @@ Commands for interacting with Percy builds
7
7
  * [`percy build:finalize`](#percy-buildfinalize)
8
8
  * [`percy build:wait`](#percy-buildwait)
9
9
 
10
- ## `percy build:finalize`
10
+ ### `percy build:finalize`
11
11
 
12
- Finalize parallel Percy builds where PERCY_PARALLEL_TOTAL=-1
12
+ Finalize parallel Percy builds
13
13
 
14
14
  ```
15
- USAGE
16
- $ percy build:finalize
17
-
18
- OPTIONS
19
- -q, --quiet log errors only
20
- -v, --verbose log everything
21
- --silent log nothing
22
-
23
- EXAMPLE
24
- $ percy build:finalize
15
+ Usage:
16
+ $ percy build:finalize [options]
17
+
18
+ Global options:
19
+ -v, --verbose Log everything
20
+ -q, --quiet Log errors only
21
+ -s, --silent Log nothing
22
+ -h, --help Display command help
25
23
  ```
26
24
 
27
- ## `percy build:wait`
25
+ ### `percy build:wait`
28
26
 
29
- Wait for a build to be finished. Requires a full access PERCY_TOKEN
27
+ Wait for a build to be finished
30
28
 
31
29
  ```
32
- USAGE
33
- $ percy build:wait
34
-
35
- OPTIONS
36
- -b, --build=build build id
37
- -c, --commit=commit build's commit sha for a project
38
- -f, --fail-on-changes exits with an error when diffs are found in snapshots
39
- -i, --interval=interval interval, in milliseconds, at which to poll for updates, defaults to 1000
40
- -p, --project=project build's project slug, required with --commit
41
- -q, --quiet log errors only
42
- -t, --timeout=timeout timeout, in milliseconds, to exit when there are no updates, defaults to 10 minutes
43
- -v, --verbose log everything
44
- --silent log nothing
45
-
46
- EXAMPLES
47
- $ percy build:wait --build 123
48
- $ percy build:wait --project test --commit HEAD
30
+ Usage:
31
+ $ percy build:wait [options]
32
+
33
+ Options:
34
+ -b, --build <id> Build ID
35
+ -p, --project <slug> Build project slug, requires '--commit'
36
+ -c, --commit <sha> Build commit sha, requires '--project'
37
+ -t, --timeout <ms> Timeout before exiting without updates, defaults to 10 minutes
38
+ -i, --interval <ms> Interval at which to poll for updates, defaults to 1 second
39
+ -f, --fail-on-changes Exit with an error when diffs are found
40
+
41
+ Global options:
42
+ -v, --verbose Log everything
43
+ -q, --quiet Log errors only
44
+ -s, --silent Log nothing
45
+ -h, --help Display command help
46
+
47
+ Examples:
48
+ $ percy build:wait --build 2222222
49
+ $ percy build:wait --project org/project --commit HEAD
49
50
  ```
50
51
  <!-- commandsstop -->
package/dist/build.js ADDED
@@ -0,0 +1,8 @@
1
+ import command from '@percy/cli-command';
2
+ import finalize from './finalize.js';
3
+ import wait from './wait.js';
4
+ export const build = command('build', {
5
+ description: 'Finalize and wait on Percy builds',
6
+ commands: [finalize, wait]
7
+ });
8
+ export default build;
@@ -0,0 +1,35 @@
1
+ import command from '@percy/cli-command';
2
+ export const finalize = command('finalize', {
3
+ description: 'Finalize parallel Percy builds',
4
+ percy: true
5
+ }, async ({
6
+ env,
7
+ percy,
8
+ log,
9
+ exit
10
+ }) => {
11
+ if (!percy) exit(0, 'Percy is disabled'); // automatically set parallel total to -1
12
+
13
+ env.PERCY_PARALLEL_TOTAL || (env.PERCY_PARALLEL_TOTAL = '-1'); // ensure that this command is not used for other parallel totals
14
+
15
+ if (env.PERCY_PARALLEL_TOTAL !== '-1') {
16
+ log.error('This command should only be used with PERCY_PARALLEL_TOTAL=-1');
17
+ log.error(`Current value is "${env.PERCY_PARALLEL_TOTAL}"`);
18
+ exit(1);
19
+ }
20
+
21
+ log.info('Finalizing parallel build...'); // rely on the parallel nonce to cause the API to return the current running build for the nonce
22
+
23
+ let {
24
+ data: build
25
+ } = await percy.client.createBuild();
26
+ await percy.client.finalizeBuild(build.id, {
27
+ all: true
28
+ });
29
+ let {
30
+ 'build-number': number,
31
+ 'web-url': url
32
+ } = build.attributes;
33
+ log.info(`Finalized build #${number}: ${url}`);
34
+ });
35
+ export default finalize;
package/dist/index.js CHANGED
@@ -1,8 +1,3 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _default = {};
8
- exports.default = _default;
1
+ export { default, build } from './build.js';
2
+ export { finalize } from './finalize.js';
3
+ export { wait } from './wait.js';
package/dist/wait.js ADDED
@@ -0,0 +1,137 @@
1
+ import command from '@percy/cli-command';
2
+ export const wait = command('wait', {
3
+ description: 'Wait for a build to be finished',
4
+ flags: [{
5
+ name: 'build',
6
+ description: 'Build ID',
7
+ exclusive: ['project', 'commit'],
8
+ type: 'id',
9
+ short: 'b'
10
+ }, {
11
+ name: 'project',
12
+ description: 'Build project slug, requires \'--commit\'',
13
+ requires: ['commit'],
14
+ type: 'slug',
15
+ short: 'p'
16
+ }, {
17
+ name: 'commit',
18
+ description: 'Build commit sha, requires \'--project\'',
19
+ requires: ['project'],
20
+ type: 'sha',
21
+ short: 'c'
22
+ }, {
23
+ name: 'timeout',
24
+ description: 'Timeout before exiting without updates, defaults to 10 minutes',
25
+ type: 'ms',
26
+ parse: Number,
27
+ short: 't'
28
+ }, {
29
+ name: 'interval',
30
+ description: 'Interval at which to poll for updates, defaults to 1 second',
31
+ type: 'ms',
32
+ parse: Number,
33
+ short: 'i'
34
+ }, {
35
+ name: 'fail-on-changes',
36
+ description: 'Exit with an error when diffs are found',
37
+ short: 'f'
38
+ }],
39
+ examples: ['$0 --build 2222222', '$0 --project org/project --commit HEAD'],
40
+ percy: true
41
+ }, async function* ({
42
+ flags,
43
+ percy,
44
+ log,
45
+ exit
46
+ }) {
47
+ if (!percy) exit(0, 'Percy is disabled'); // do not wait directly on the promise as to not block the event loop
48
+
49
+ let waiting = percy.client.waitForBuild(flags, build => {
50
+ logProgress(build, log);
51
+ if (isFailing(build, flags)) exit(1);
52
+ }); // wait between event loops to allow process termination
53
+
54
+ let handleDone = () => waiting.done = true;
55
+
56
+ waiting.then(handleDone, handleDone);
57
+
58
+ while (!waiting.done) {
59
+ yield new Promise(r => setImmediate(r));
60
+ } // bubble errors
61
+
62
+
63
+ yield waiting;
64
+ }); // Log build progress
65
+
66
+ function logProgress({
67
+ attributes: {
68
+ state,
69
+ 'web-url': url,
70
+ 'build-number': number,
71
+ 'failure-reason': failReason,
72
+ 'failure-details': failDetails,
73
+ 'total-snapshots': count,
74
+ 'total-comparisons': total,
75
+ 'total-comparisons-diff': diffs,
76
+ 'total-comparisons-finished': finished
77
+ }
78
+ }, log) {
79
+ switch (state) {
80
+ case 'pending':
81
+ return log.progress('Recieving snapshots...');
82
+
83
+ case 'processing':
84
+ return log.progress(`Processing ${count} snapshots - ` + (finished === total ? 'finishing up...' : `${finished} of ${total} comparisons finished...`));
85
+
86
+ case 'finished':
87
+ log.info(`Build #${number} finished! ${url}`);
88
+ return log.info(`Found ${diffs} changes`);
89
+
90
+ case 'failed':
91
+ log.error(`Build #${number} failed! ${url}`);
92
+ return log.error(failureMessage(failReason, failDetails));
93
+
94
+ default:
95
+ return log.error(`Build #${number} is ${state}. ${url}`);
96
+ }
97
+ } // Create failure messages
98
+
99
+
100
+ function failureMessage(type, {
101
+ missing_parallel_builds: missingParallel,
102
+ parallel_builds_received: parallelCount,
103
+ parallel_builds_expected: parallelTotal
104
+ } = {}) {
105
+ switch (type) {
106
+ case 'render_timeout':
107
+ return 'Some snapshots in this build took too long ' + 'to render even after multiple retries.';
108
+
109
+ case 'no_snapshots':
110
+ return 'No snapshots were uploaded to this build.';
111
+
112
+ case 'missing_finalize':
113
+ return 'Failed to correctly finalize.';
114
+
115
+ case 'missing_resources':
116
+ return missingParallel ? `Only ${parallelCount} of ${parallelTotal} parallel builds were received.` : 'Some build or snapshot resources failed to correctly upload.';
117
+
118
+ default:
119
+ return `Error: ${type}`;
120
+ }
121
+ } // Return true or false if a build is considered failing or not
122
+
123
+
124
+ function isFailing({
125
+ attributes: {
126
+ state,
127
+ 'total-comparisons-diff': diffs
128
+ }
129
+ }, {
130
+ failOnChanges
131
+ }) {
132
+ // not pending and not processing
133
+ return state !== 'pending' && state !== 'processing' && ( // not finished or finished with diffs
134
+ state !== 'finished' || failOnChanges && !!diffs);
135
+ }
136
+
137
+ export default wait;
package/package.json CHANGED
@@ -1,40 +1,38 @@
1
1
  {
2
2
  "name": "@percy/cli-build",
3
- "version": "1.0.0-beta.8",
3
+ "version": "1.0.1",
4
4
  "license": "MIT",
5
- "main": "dist/index.js",
6
- "files": [
7
- "dist",
8
- "oclif.manifest.json"
9
- ],
10
- "scripts": {
11
- "build": "babel --root-mode upward src --out-dir dist",
12
- "lint": "eslint --ignore-path ../../.gitignore .",
13
- "postbuild": "oclif-dev manifest",
14
- "readme": "oclif-dev readme",
15
- "test": "cross-env NODE_ENV=test mocha",
16
- "test:coverage": "nyc yarn test"
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/percy/cli",
8
+ "directory": "packages/cli-build"
17
9
  },
18
10
  "publishConfig": {
19
11
  "access": "public"
20
12
  },
21
- "mocha": {
22
- "require": "../../scripts/babel-register"
13
+ "engines": {
14
+ "node": ">=14"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "main": "./dist/index.js",
20
+ "type": "module",
21
+ "exports": "./dist/index.js",
22
+ "scripts": {
23
+ "build": "node ../../scripts/build",
24
+ "lint": "eslint --ignore-path ../../.gitignore .",
25
+ "readme": "percy-cli-readme",
26
+ "test": "node ../../scripts/test",
27
+ "test:coverage": "yarn test --coverage"
23
28
  },
24
- "oclif": {
25
- "bin": "percy",
26
- "commands": "./dist/commands",
27
- "topics": {
28
- "build": {
29
- "description": "interact with Percy builds"
30
- }
31
- }
29
+ "@percy/cli": {
30
+ "commands": [
31
+ "./dist/build.js"
32
+ ]
32
33
  },
33
34
  "dependencies": {
34
- "@percy/cli-command": "^1.0.0-beta.8",
35
- "@percy/client": "^1.0.0-beta.8",
36
- "@percy/env": "^1.0.0-beta.8",
37
- "@percy/logger": "^1.0.0-beta.8"
35
+ "@percy/cli-command": "1.0.1"
38
36
  },
39
- "gitHead": "6015850e7c20c130d625fcb327b10d7513b35707"
37
+ "gitHead": "38917e6027299d6cd86008e2ccd005d90bbf89c0"
40
38
  }
@@ -1,60 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.Finalize = void 0;
7
-
8
- var _cliCommand = _interopRequireWildcard(require("@percy/cli-command"));
9
-
10
- var _client = _interopRequireDefault(require("@percy/client"));
11
-
12
- var _logger = _interopRequireDefault(require("@percy/logger"));
13
-
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
- function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
17
-
18
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
-
20
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
21
-
22
- class Finalize extends _cliCommand.default {
23
- async run() {
24
- if (!this.isPercyEnabled()) {
25
- _logger.default.info('Percy is disabled');
26
-
27
- return;
28
- }
29
-
30
- let client = new _client.default();
31
-
32
- if (client.env.parallel.total !== -1) {
33
- _logger.default.error('This command should only be used with PERCY_PARALLEL_TOTAL=-1');
34
-
35
- _logger.default.error(`Current value is "${client.env.parallel.total}"`);
36
-
37
- return this.exit(1);
38
- }
39
-
40
- _logger.default.info('Finalizing parallel build...');
41
-
42
- await client.createBuild();
43
- let build = client.build;
44
- await client.finalizeBuild({
45
- all: true
46
- });
47
-
48
- _logger.default.info(`Finalized build #${build.number}: ${build.url}`);
49
- }
50
-
51
- }
52
-
53
- exports.Finalize = Finalize;
54
-
55
- _defineProperty(Finalize, "description", 'Finalize parallel Percy builds where PERCY_PARALLEL_TOTAL=-1');
56
-
57
- _defineProperty(Finalize, "flags", { ..._cliCommand.flags.logging
58
- });
59
-
60
- _defineProperty(Finalize, "examples", ['$ percy build:finalize']);
@@ -1,155 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.Wait = void 0;
7
-
8
- var _readline = _interopRequireDefault(require("readline"));
9
-
10
- var _cliCommand = _interopRequireWildcard(require("@percy/cli-command"));
11
-
12
- var _client = _interopRequireDefault(require("@percy/client"));
13
-
14
- var _logger = _interopRequireDefault(require("@percy/logger"));
15
-
16
- function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
17
-
18
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
-
20
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
-
22
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
23
-
24
- class Wait extends _cliCommand.default {
25
- async run() {
26
- if (!this.isPercyEnabled()) {
27
- _logger.default.info('Percy is disabled');
28
-
29
- return;
30
- }
31
-
32
- let client = new _client.default();
33
- let result = await client.waitForBuild({
34
- progress: this.progress,
35
- ...this.flags
36
- });
37
- return this.finish(result);
38
- } // Log build progress
39
-
40
-
41
- progress({
42
- attributes: {
43
- state,
44
- 'total-snapshots': count,
45
- 'total-comparisons': total,
46
- 'total-comparisons-finished': finished
47
- }
48
- }) {
49
- // update the same line each time
50
- _readline.default.cursorTo(process.stdout, 0); // still recieving snapshots
51
-
52
-
53
- if (state === 'pending') {
54
- process.stdout.write(_logger.default.formatter('Recieving snapshots...')); // need to clear the line before finishing
55
- } else if (finished === total || state === 'finished') {
56
- _readline.default.clearLine(process.stdout);
57
- } // processing snapshots
58
-
59
-
60
- if (state === 'processing') {
61
- process.stdout.write(_logger.default.formatter(`Processing ${count} snapshots - ` + (finished === total ? 'finishing up...' : `${finished} of ${total} comparisons finished...`)));
62
- }
63
- } // Log build status
64
-
65
-
66
- finish({
67
- attributes: {
68
- state,
69
- 'web-url': url,
70
- 'build-number': number,
71
- 'total-comparisons-diff': diffs,
72
- 'failure-reason': failReason,
73
- 'failure-details': failDetails
74
- }
75
- }) {
76
- if (state === 'finished') {
77
- _logger.default.info(`Build #${number} finished! ${url}`);
78
-
79
- _logger.default.info(`Found ${diffs} changes`);
80
-
81
- if (this.flags['fail-on-changes'] && diffs > 0) {
82
- return this.exit(1);
83
- }
84
- } else if (state === 'failed') {
85
- _logger.default.error(`Build #${number} failed! ${url}`);
86
-
87
- _logger.default.error(this.failure(failReason, failDetails));
88
-
89
- return this.exit(1);
90
- } else {
91
- _logger.default.error(`Build #${number} is ${state}. ${url}`);
92
-
93
- return this.exit(1);
94
- }
95
- } // Create failure messages
96
-
97
-
98
- failure(type, details) {
99
- switch (type) {
100
- case 'render_timeout':
101
- return 'Some snapshots in this build took too long to render even ' + 'after multiple retries.';
102
-
103
- case 'no_snapshots':
104
- return 'No snapshots were uploaded to this build.';
105
-
106
- case 'missing_finalize':
107
- return 'Failed to correctly finalize.';
108
-
109
- case 'missing_resources':
110
- // eslint-disable-next-line camelcase
111
- return (details === null || details === void 0 ? void 0 : details.missing_parallel_builds) ? `Only ${details.parallel_builds_received} of ` + `${details.parallel_builds_expected} parallelized build processes finished.` : 'Some build or snapshot resources failed to correctly upload.';
112
-
113
- default:
114
- return `Error: ${type}`;
115
- }
116
- }
117
-
118
- }
119
-
120
- exports.Wait = Wait;
121
-
122
- _defineProperty(Wait, "description", 'Wait for a build to be finished. Requires a full access PERCY_TOKEN');
123
-
124
- _defineProperty(Wait, "flags", { ..._cliCommand.flags.logging,
125
- build: _cliCommand.flags.string({
126
- char: 'b',
127
- description: 'build id',
128
- exclusive: ['project', 'commit']
129
- }),
130
- project: _cliCommand.flags.string({
131
- char: 'p',
132
- description: "build's project slug, required with --commit",
133
- inclusive: ['commit']
134
- }),
135
- commit: _cliCommand.flags.string({
136
- char: 'c',
137
- description: "build's commit sha for a project",
138
- inclusive: ['project']
139
- }),
140
- timeout: _cliCommand.flags.integer({
141
- char: 't',
142
- description: ['timeout, in milliseconds, to exit when there are no updates, ', 'defaults to 10 minutes'].join('')
143
- }),
144
- interval: _cliCommand.flags.integer({
145
- char: 'i',
146
- description: ['interval, in milliseconds, at which to poll for updates, ', 'defaults to 1000'].join('')
147
- }),
148
- 'fail-on-changes': _cliCommand.flags.boolean({
149
- char: 'f',
150
- default: false,
151
- description: 'exits with an error when diffs are found in snapshots'
152
- })
153
- });
154
-
155
- _defineProperty(Wait, "examples", ['$ percy build:wait --build 123', '$ percy build:wait --project test --commit HEAD']);
@@ -1 +0,0 @@
1
- {"version":"1.0.0-beta.8","commands":{"build:finalize":{"id":"build:finalize","description":"Finalize parallel Percy builds where PERCY_PARALLEL_TOTAL=-1","pluginName":"@percy/cli-build","pluginType":"core","aliases":[],"examples":["$ percy build:finalize"],"flags":{"verbose":{"name":"verbose","type":"boolean","char":"v","description":"log everything","allowNo":false},"quiet":{"name":"quiet","type":"boolean","char":"q","description":"log errors only","allowNo":false},"silent":{"name":"silent","type":"boolean","description":"log nothing","allowNo":false}},"args":[]},"build:wait":{"id":"build:wait","description":"Wait for a build to be finished. Requires a full access PERCY_TOKEN","pluginName":"@percy/cli-build","pluginType":"core","aliases":[],"examples":["$ percy build:wait --build 123","$ percy build:wait --project test --commit HEAD"],"flags":{"verbose":{"name":"verbose","type":"boolean","char":"v","description":"log everything","allowNo":false},"quiet":{"name":"quiet","type":"boolean","char":"q","description":"log errors only","allowNo":false},"silent":{"name":"silent","type":"boolean","description":"log nothing","allowNo":false},"build":{"name":"build","type":"option","char":"b","description":"build id"},"project":{"name":"project","type":"option","char":"p","description":"build's project slug, required with --commit"},"commit":{"name":"commit","type":"option","char":"c","description":"build's commit sha for a project"},"timeout":{"name":"timeout","type":"option","char":"t","description":"timeout, in milliseconds, to exit when there are no updates, defaults to 10 minutes"},"interval":{"name":"interval","type":"option","char":"i","description":"interval, in milliseconds, at which to poll for updates, defaults to 1000"},"fail-on-changes":{"name":"fail-on-changes","type":"boolean","char":"f","description":"exits with an error when diffs are found in snapshots","allowNo":false}},"args":[]}}}