@percy/cli-exec 1.0.0 → 1.0.3

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/common.js ADDED
@@ -0,0 +1,10 @@
1
+ export const flags = [{
2
+ name: 'port',
3
+ description: 'Local CLI server port',
4
+ env: 'PERCY_SERVER_PORT',
5
+ percyrc: 'port',
6
+ type: 'number',
7
+ parse: Number,
8
+ default: 5338,
9
+ short: 'P'
10
+ }];
package/dist/exec.js ADDED
@@ -0,0 +1,114 @@
1
+ import command from '@percy/cli-command';
2
+ import * as common from './common.js';
3
+ import start from './start.js';
4
+ import stop from './stop.js';
5
+ import ping from './ping.js';
6
+ export const exec = command('exec', {
7
+ description: 'Start and stop Percy around a supplied command',
8
+ usage: '[options] -- <command>',
9
+ commands: [start, stop, ping],
10
+ flags: [...common.flags, {
11
+ name: 'parallel',
12
+ description: 'Marks the build as one of many parallel builds',
13
+ parse: () => {
14
+ var _process$env;
15
+
16
+ return !!((_process$env = process.env).PERCY_PARALLEL_TOTAL || (_process$env.PERCY_PARALLEL_TOTAL = '-1'));
17
+ }
18
+ }, {
19
+ name: 'partial',
20
+ description: 'Marks the build as a partial build',
21
+ parse: () => {
22
+ var _process$env2;
23
+
24
+ return !!((_process$env2 = process.env).PERCY_PARTIAL_BUILD || (_process$env2.PERCY_PARTIAL_BUILD = '1'));
25
+ }
26
+ }],
27
+ examples: ['$0 -- echo "percy is running around this echo command"', '$0 -- yarn test'],
28
+ loose: ['Warning: Missing command separator (--),', 'some command options may not work as expected'].join(' '),
29
+ percy: {
30
+ server: true
31
+ }
32
+ }, async function* ({
33
+ flags,
34
+ argv,
35
+ env,
36
+ percy,
37
+ log,
38
+ exit
39
+ }) {
40
+ let [command, ...args] = argv; // command is required
41
+
42
+ if (!command) {
43
+ log.error("You must supply a command to run after '--'");
44
+ log.info('Example:');
45
+ log.info(' $ percy exec -- npm test');
46
+ exit(1);
47
+ } // verify the provided command exists
48
+
49
+
50
+ let {
51
+ default: which
52
+ } = await import('which');
53
+
54
+ if (!which.sync(command, {
55
+ nothrow: true
56
+ })) {
57
+ exit(127, `Command not found "${command}"`);
58
+ } // attempt to start percy if enabled
59
+
60
+
61
+ if (!percy) {
62
+ log.warn('Percy is disabled');
63
+ } else {
64
+ try {
65
+ yield* percy.yield.start();
66
+ } catch (error) {
67
+ if (error.canceled) throw error;
68
+ log.warn('Skipping visual tests');
69
+ log.error(error);
70
+ }
71
+ } // provide SDKs with useful env vars
72
+
73
+
74
+ env.PERCY_SERVER_ADDRESS = percy === null || percy === void 0 ? void 0 : percy.address();
75
+ env.PERCY_LOGLEVEL = log.loglevel(); // run the provided command
76
+
77
+ log.info(`Running "${[command, ...args].join(' ')}"`);
78
+ let [status, error] = yield* spawn(command, args); // stop percy if running (force stop if there is an error);
79
+
80
+ await (percy === null || percy === void 0 ? void 0 : percy.stop(!!error)); // forward any returned status code
81
+
82
+ if (status) exit(status, error);
83
+ }); // Spawn a command with cross-spawn and return an array containing the resulting status code along
84
+ // with any error encountered while running. Uses a generator pattern to handle interupt signals.
85
+
86
+ async function* spawn(cmd, args) {
87
+ let {
88
+ default: crossSpawn
89
+ } = await import('cross-spawn');
90
+ let proc, closed, error;
91
+
92
+ try {
93
+ proc = crossSpawn(cmd, args, {
94
+ stdio: 'inherit'
95
+ });
96
+ proc.on('close', code => closed = code);
97
+ proc.on('error', err => error = err); // run until an event is triggered
98
+
99
+ /* eslint-disable-next-line no-unmodified-loop-condition */
100
+
101
+ while (closed == null && error == null) {
102
+ yield new Promise(r => setImmediate(r));
103
+ }
104
+
105
+ if (error) throw error;
106
+ return [closed];
107
+ } catch (err) {
108
+ if (!err.signal) return [1, err];
109
+ proc.kill(err.signal);
110
+ return [0, err];
111
+ }
112
+ }
113
+
114
+ export default exec;
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { default, exec } from './exec.js';
2
+ export { start } from './start.js';
3
+ export { stop } from './stop.js';
4
+ export { ping } from './ping.js';
package/dist/ping.js ADDED
@@ -0,0 +1,32 @@
1
+ import command from '@percy/cli-command';
2
+ import * as common from './common.js';
3
+ export const ping = command('ping', {
4
+ description: 'Pings a local running Percy snapshot server',
5
+ flags: common.flags,
6
+ percy: true
7
+ }, async ({
8
+ flags,
9
+ percy,
10
+ log,
11
+ exit
12
+ }) => {
13
+ if (!percy) exit(0, 'Percy is disabled');
14
+ let {
15
+ request
16
+ } = await import('@percy/cli-command/utils');
17
+ let ping = `http://localhost:${flags.port}/percy/healthcheck`;
18
+
19
+ try {
20
+ await request(ping, {
21
+ retryNotFound: true,
22
+ noProxy: true
23
+ });
24
+ } catch (err) {
25
+ log.error('Percy is not running');
26
+ log.debug(err);
27
+ exit(1);
28
+ }
29
+
30
+ log.info('Percy is running');
31
+ });
32
+ export default ping;
package/dist/start.js ADDED
@@ -0,0 +1,28 @@
1
+ import command from '@percy/cli-command';
2
+ import * as common from './common.js';
3
+ export const start = command('start', {
4
+ description: 'Starts a local Percy snapshot server',
5
+ flags: common.flags,
6
+ examples: ['$0 &> percy.log'],
7
+ percy: {
8
+ server: true
9
+ }
10
+ }, async function* ({
11
+ percy,
12
+ exit
13
+ }) {
14
+ if (!percy) exit(0, 'Percy is disabled'); // start percy
15
+
16
+ yield* percy.yield.start();
17
+
18
+ try {
19
+ // run until stopped or terminated
20
+ while (percy.readyState < 3) {
21
+ yield new Promise(r => setImmediate(r));
22
+ }
23
+ } catch (error) {
24
+ await percy.stop(true);
25
+ throw error;
26
+ }
27
+ });
28
+ export default start;
package/dist/stop.js ADDED
@@ -0,0 +1,39 @@
1
+ import command from '@percy/cli-command';
2
+ import * as common from './common.js';
3
+ export const stop = command('stop', {
4
+ description: 'Stops a local running Percy snapshot server',
5
+ flags: common.flags,
6
+ percy: true
7
+ }, async ({
8
+ flags,
9
+ percy,
10
+ log,
11
+ exit
12
+ }) => {
13
+ if (!percy) exit(0, 'Percy is disabled');
14
+ let {
15
+ request
16
+ } = await import('@percy/cli-command/utils');
17
+ let stop = `http://localhost:${flags.port}/percy/stop`;
18
+ let ping = `http://localhost:${flags.port}/percy/healthcheck`;
19
+
20
+ try {
21
+ await request(stop, {
22
+ method: 'POST',
23
+ noProxy: true
24
+ });
25
+ } catch (err) {
26
+ log.error('Percy is not running');
27
+ log.debug(err);
28
+ exit(1);
29
+ } // retry heathcheck until it fails
30
+
31
+
32
+ await new Promise(function check(resolve) {
33
+ return request(ping, {
34
+ noProxy: true
35
+ }).then(() => setTimeout(check, 100, resolve)).catch(resolve);
36
+ });
37
+ log.info('Percy has stopped');
38
+ });
39
+ export default stop;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/cli-exec",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,7 @@
14
14
  "node": ">=14"
15
15
  },
16
16
  "files": [
17
- "./dist"
17
+ "dist"
18
18
  ],
19
19
  "main": "./dist/index.js",
20
20
  "type": "module",
@@ -32,9 +32,9 @@
32
32
  ]
33
33
  },
34
34
  "dependencies": {
35
- "@percy/cli-command": "1.0.0",
35
+ "@percy/cli-command": "1.0.3",
36
36
  "cross-spawn": "^7.0.3",
37
37
  "which": "^2.0.2"
38
38
  },
39
- "gitHead": "6df509421a60144e4f9f5d59dc57a5675372a0b2"
39
+ "gitHead": "a259d5cff0933711bced21a979c577e70765d318"
40
40
  }