@automattic/vip 3.5.0 → 3.6.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.
@@ -50,7 +50,7 @@ cmd.argv(process.argv, async (arg, opt) => {
50
50
  slug = await (0, _devEnvironmentCli.getEnvironmentName)(environmentNameOptions);
51
51
  }
52
52
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
53
- await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
53
+ (0, _devEnvironmentCli.validateDependencies)(lando);
54
54
  debug('Args: ', arg, 'Options: ', opt);
55
55
  const trackingInfo = {
56
56
  slug,
@@ -24,7 +24,7 @@ const examples = [{
24
24
  }).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option('soft', 'Preserve an environment’s configuration files; allows an environment to be regenerated with the start command.').examples(examples).argv(process.argv, async (arg, opt) => {
25
25
  const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
26
26
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
27
- await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
27
+ (0, _devEnvironmentCli.validateDependencies)(lando);
28
28
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
29
29
  await (0, _tracker.trackEvent)('dev_env_destroy_command_execute', trackingInfo);
30
30
  debug('Args: ', arg, 'Options: ', opt);
@@ -26,7 +26,7 @@ const examples = [{
26
26
  }).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option('force', 'Skip validation for a local environment to be in a running state.', undefined, _devEnvironmentCli.processBooleanOption).option('quiet', 'Suppress informational messages.', undefined, _devEnvironmentCli.processBooleanOption).examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
27
27
  const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
28
28
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
29
- await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
29
+ (0, _devEnvironmentCli.validateDependencies)(lando);
30
30
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
31
31
  await (0, _tracker.trackEvent)('dev_env_exec_command_execute', trackingInfo);
32
32
  try {
@@ -36,7 +36,7 @@ const examples = [{
36
36
  slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
37
37
  trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
38
38
  }
39
- await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
39
+ (0, _devEnvironmentCli.validateDependencies)(lando);
40
40
  await (0, _tracker.trackEvent)('dev_env_info_command_execute', trackingInfo);
41
41
  debug('Args: ', arg, 'Options: ', opt);
42
42
  try {
@@ -18,7 +18,7 @@ const examples = [{
18
18
  }).examples(examples).argv(process.argv, async () => {
19
19
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
20
20
  lando.events.constructor.prototype.setMaxListeners(1024);
21
- await (0, _devEnvironmentCli.validateDependencies)(lando, '');
21
+ (0, _devEnvironmentCli.validateDependencies)(lando);
22
22
  const trackingInfo = {
23
23
  all: true
24
24
  };
@@ -26,7 +26,7 @@ const examples = [{
26
26
  }).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option(['f', 'follow'], 'Continually output logs as they are generated.').option('service', 'Restrict to a single service.').examples(examples).argv(process.argv, async (arg, opt) => {
27
27
  const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
28
28
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
29
- await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
29
+ (0, _devEnvironmentCli.validateDependencies)(lando);
30
30
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
31
31
  await (0, _tracker.trackEvent)('dev_env_logs_command_execute', trackingInfo);
32
32
  debug('Args: ', arg, 'Options: ', opt);
@@ -49,7 +49,7 @@ const examples = [{
49
49
  all: true
50
50
  };
51
51
  await (0, _tracker.trackEvent)('dev_env_purge_command_execute', trackingInfo);
52
- await (0, _devEnvironmentCli.validateDependencies)(lando, '');
52
+ (0, _devEnvironmentCli.validateDependencies)(lando);
53
53
  const removeFiles = !(opt.soft || false);
54
54
  try {
55
55
  for (const slug of allEnvNames) {
@@ -58,7 +58,7 @@ function getCommand(args) {
58
58
  }).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option('root', 'Create with root privileges.').option('service', 'Restrict to a single service.').examples(examples).argv(process.argv, async (args, opt) => {
59
59
  const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
60
60
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
61
- await (0, _devEnvironmentCli.validateDependencies)(lando, '');
61
+ (0, _devEnvironmentCli.validateDependencies)(lando);
62
62
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
63
63
  await (0, _tracker.trackEvent)('dev_env_shell_command_execute', trackingInfo);
64
64
  debug('Args: ', args, 'Options: ', opt);
@@ -29,7 +29,7 @@ const examples = [{
29
29
  }).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option('skip-rebuild', 'Only start services that are not in a running state.').option(['w', 'skip-wp-versions-check'], 'Skip the prompt to update WordPress; occurs if the last major release version is not configured.').option('vscode', 'Generate a Visual Studio Code Workspace file.').examples(examples).argv(process.argv, async (arg, opt) => {
30
30
  const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
31
31
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
32
- await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
32
+ (0, _devEnvironmentCli.validateDependencies)(lando);
33
33
  const startProcessing = new Date();
34
34
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
35
35
  trackingInfo.vscode = Boolean(opt.vscode);
@@ -23,7 +23,7 @@ const examples = [{
23
23
  usage
24
24
  }).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).option('all', 'Stop all local environments.').examples(examples).argv(process.argv, async (arg, opt) => {
25
25
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
26
- await (0, _devEnvironmentCli.validateDependencies)(lando, '');
26
+ (0, _devEnvironmentCli.validateDependencies)(lando);
27
27
  debug('Args: ', arg, 'Options: ', opt);
28
28
 
29
29
  /** @type {Record< string, unknown >} */
@@ -32,7 +32,7 @@ cmd.examples(examples);
32
32
  cmd.argv(process.argv, async (arg, opt) => {
33
33
  const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
34
34
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
35
- await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
35
+ (0, _devEnvironmentCli.validateDependencies)(lando);
36
36
  const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
37
37
  await (0, _tracker.trackEvent)('dev_env_update_command_execute', trackingInfo);
38
38
  try {
@@ -26,7 +26,7 @@ class DevEnvImportSQLCommand {
26
26
  }
27
27
  async run() {
28
28
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
29
- await (0, _devEnvironmentCli.validateDependencies)(lando, this.slug);
29
+ (0, _devEnvironmentCli.validateDependencies)(lando);
30
30
  (0, _sql.validateImportFileExtension)(this.fileName);
31
31
 
32
32
  // Check if file is compressed and if so, extract the
@@ -250,7 +250,7 @@ _args.default.argv = async function (argv, cb) {
250
250
  });
251
251
  exit.withError('Environment production is not allowed for this command');
252
252
  }
253
- const env = options.app.environments.find(cur => getEnvIdentifier(cur) === options.env);
253
+ const env = options.app.environments.find(cur => getEnvIdentifier(cur).toLowerCase() === options.env.toLowerCase());
254
254
  if (!env) {
255
255
  await (0, _tracker.trackEvent)('command_childcontext_param_error', {
256
256
  error: `Invalid child environment (${options.env}) specified`
@@ -33,7 +33,6 @@ var _child_process = require("child_process");
33
33
  var _debug = _interopRequireDefault(require("debug"));
34
34
  var _enquirer = require("enquirer");
35
35
  var _formatters = _interopRequireDefault(require("lando/lib/formatters"));
36
- var _promises = require("node:dns/promises");
37
36
  var _nodeFs = require("node:fs");
38
37
  var _nodeOs = require("node:os");
39
38
  var _path = _interopRequireDefault(require("path"));
@@ -98,38 +97,9 @@ async function handleCLIException(exception, trackKey, trackBaseInfo = {}) {
98
97
  debug(exception);
99
98
  }
100
99
  }
101
- const verifyDNSResolution = async (slug, domain) => {
102
- const expectedIP = '127.0.0.1';
103
- const testDomain = `${slug}.${domain}`;
104
- const advice = `Please add following line to hosts file on your system:\n\n${expectedIP} ${testDomain}\n\nLearn more: https://docs.wpvip.com/vip-local-development-environment/troubleshooting-dev-env/#h-resolve-networking-configuration-issues\n`;
105
- debug(`Verifying DNS resolution for ${testDomain}`);
106
- try {
107
- let address;
108
- try {
109
- address = await (0, _promises.lookup)(testDomain, 4);
110
- debug(`Got DNS response ${address.address}`);
111
- } catch (error) {
112
- throw new _userError.default(`DNS resolution for ${testDomain} failed.`, {
113
- cause: error
114
- });
115
- }
116
- if (address.address !== expectedIP) {
117
- throw new _userError.default(`DNS resolution for ${testDomain} returned unexpected IP ${address.address}. Expected value is ${expectedIP}.`);
118
- }
119
- } catch (error) {
120
- if (error instanceof _userError.default) {
121
- console.warn(_chalk.default.yellow.bold('Warning:'), `${error.message}\n\n${advice}`);
122
- } else {
123
- throw error;
124
- }
125
- }
126
- };
127
- const validateDependencies = async (lando, slug) => {
100
+ const validateDependencies = lando => {
128
101
  const now = new Date();
129
102
  (0, _devEnvironmentLando.validateDockerInstalled)(lando);
130
- if (slug) {
131
- await verifyDNSResolution(slug, lando.config.domain ?? 'vipdev.lndo.site');
132
- }
133
103
  const duration = new Date().getTime() - now.getTime();
134
104
  debug('Validation checks completed in %d ms', duration);
135
105
  };
@@ -250,6 +250,7 @@ async function printEnvironmentInfo(lando, slug, options) {
250
250
  xdebug += ' (with additional configuration)';
251
251
  }
252
252
  appInfo.xdebug = xdebug;
253
+ appInfo.cron = environmentData.cron ? 'enabled' : 'disabled';
253
254
  appInfo.wordpress = parseComponentForInfo(environmentData.wordpress);
254
255
  appInfo['Mu plugins'] = parseComponentForInfo(environmentData.muPlugins);
255
256
  appInfo['App Code'] = parseComponentForInfo(environmentData.appCode);
@@ -390,6 +390,36 @@ async function getExtraServicesConnections(lando, app) {
390
390
  }
391
391
  return extraServices;
392
392
  }
393
+ async function tryResolveDomains(urls) {
394
+ const domains = [...new Set(urls.filter(url => url.toLowerCase().startsWith('http')).map(url => {
395
+ try {
396
+ return new URL(url).hostname;
397
+ } catch (err) {
398
+ return undefined;
399
+ }
400
+ }).filter(domain => domain !== undefined))];
401
+ const domainsToFix = [];
402
+ for (const domain of domains) {
403
+ try {
404
+ // eslint-disable-next-line no-await-in-loop
405
+ const address = await (0, _promises.lookup)(domain, 4);
406
+ debug('%s resolves to %s', domain, address.address);
407
+ if (address.address !== '127.0.0.1') {
408
+ domainsToFix.push(domain);
409
+ console.warn(_chalk.default.yellow.bold('WARNING:'), `${domain} resolves to ${address.address} instead of 127.0.0.1. Things may not work as expected.`);
410
+ }
411
+ } catch (err) {
412
+ const msg = err instanceof Error ? err.message : 'Unknown error';
413
+ domainsToFix.push(domain);
414
+ console.warn(_chalk.default.yellow.bold('WARNING:'), `Failed to resolve ${domain}: ${msg}`);
415
+ }
416
+ }
417
+ if (domainsToFix.length) {
418
+ console.warn(_chalk.default.yellow('Please add the following lines to the hosts file on your system:\n'));
419
+ console.warn(domainsToFix.map(domain => `127.0.0.1 ${domain}`).join('\n'));
420
+ console.warn(_chalk.default.yellow('\nLearn more: https://docs.wpvip.com/vip-local-development-environment/troubleshooting-dev-env/#h-resolve-networking-configuration-issues\n'));
421
+ }
422
+ }
393
423
  async function checkEnvHealth(lando, instancePath) {
394
424
  const urls = {};
395
425
  const now = new Date();
@@ -400,10 +430,17 @@ async function checkEnvHealth(lando, instancePath) {
400
430
  });
401
431
  });
402
432
  const urlsToScan = Object.keys(urls).filter(url => !url.includes('*'));
433
+ await tryResolveDomains(urlsToScan);
403
434
  let scanResults = [];
404
435
  if (Array.isArray(app.urls)) {
405
436
  scanResults = app.urls;
406
- app.urls.forEach(entry => urlsToScan.splice(urlsToScan.indexOf(entry.url), 1));
437
+ app.urls.forEach(entry => {
438
+ // We use different status codes to see if the service is up.
439
+ // We may consider the service is up when Lando considers it is down.
440
+ if (entry.color !== 'red') {
441
+ urlsToScan.splice(urlsToScan.indexOf(entry.url), 1);
442
+ }
443
+ });
407
444
  }
408
445
  if (urlsToScan.length) {
409
446
  scanResults = scanResults.concat(await app.scanUrls(urlsToScan, {
@@ -424,8 +461,10 @@ async function isEnvUp(lando, instancePath) {
424
461
  const app = await getLandoApplication(lando, instancePath);
425
462
  const reachableServices = app.info.filter(service => service.urls.length);
426
463
  const webUrls = reachableServices.map(service => service.urls).flat().filter(url => !/^https?:\/\/(localhost|127\.0\.0\.1):/.exec(url));
464
+ await tryResolveDomains(webUrls);
427
465
  const scanResult = await app.scanUrls(webUrls, {
428
- max: 1
466
+ max: 1,
467
+ waitCodes: [502, 504]
429
468
  });
430
469
  const duration = new Date().getTime() - now.getTime();
431
470
  debug('isEnvUp took %d ms', duration);
package/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  ## Changelog
2
2
 
3
+ ## 3.6.0
4
+
5
+ * build(deps-dev): bump rimraf from 5.0.7 to 5.0.8
6
+ * feat(dev-env): add DNS check to health check to ensure domains resolve correctly
7
+
8
+ **Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.5.1...3.6.0
9
+
10
+ ## 3.5.1
11
+
12
+ * fix(dev-env): display cron status in `vip dev-env info --extended`
13
+ * build(deps-dev): bump typescript from 5.5.2 to 5.5.3
14
+ * fix: case mismatch in environment identifier matcher
15
+
16
+ **Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.5.0...3.5.1
17
+
3
18
  ### 3.5.0
4
19
 
5
20
  * feat(dev-env): add support for cron
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "3.5.0",
3
+ "version": "3.6.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@automattic/vip",
9
- "version": "3.5.0",
9
+ "version": "3.6.0",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
@@ -139,7 +139,7 @@
139
139
  "jest": "^29.7.0",
140
140
  "nock": "13.5.4",
141
141
  "prettier": "npm:wp-prettier@2.8.5",
142
- "rimraf": "5.0.7",
142
+ "rimraf": "5.0.8",
143
143
  "typescript": "^5.2.2"
144
144
  },
145
145
  "engines": {
@@ -11518,9 +11518,9 @@
11518
11518
  }
11519
11519
  },
11520
11520
  "node_modules/rimraf": {
11521
- "version": "5.0.7",
11522
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz",
11523
- "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==",
11521
+ "version": "5.0.8",
11522
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.8.tgz",
11523
+ "integrity": "sha512-XSh0V2/yNhDEi8HwdIefD8MLgs4LQXPag/nEJWs3YUc3Upn+UHa1GyIkEg9xSSNt7HnkO5FjTvmcRzgf+8UZuw==",
11524
11524
  "dependencies": {
11525
11525
  "glob": "^10.3.7"
11526
11526
  },
@@ -11528,7 +11528,7 @@
11528
11528
  "rimraf": "dist/esm/bin.mjs"
11529
11529
  },
11530
11530
  "engines": {
11531
- "node": ">=14.18"
11531
+ "node": ">=18"
11532
11532
  },
11533
11533
  "funding": {
11534
11534
  "url": "https://github.com/sponsors/isaacs"
@@ -12643,9 +12643,9 @@
12643
12643
  }
12644
12644
  },
12645
12645
  "node_modules/typescript": {
12646
- "version": "5.5.2",
12647
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz",
12648
- "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==",
12646
+ "version": "5.5.3",
12647
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
12648
+ "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
12649
12649
  "dev": true,
12650
12650
  "bin": {
12651
12651
  "tsc": "bin/tsc",
@@ -21846,9 +21846,9 @@
21846
21846
  "dev": true
21847
21847
  },
21848
21848
  "rimraf": {
21849
- "version": "5.0.7",
21850
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz",
21851
- "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==",
21849
+ "version": "5.0.8",
21850
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.8.tgz",
21851
+ "integrity": "sha512-XSh0V2/yNhDEi8HwdIefD8MLgs4LQXPag/nEJWs3YUc3Upn+UHa1GyIkEg9xSSNt7HnkO5FjTvmcRzgf+8UZuw==",
21852
21852
  "requires": {
21853
21853
  "glob": "^10.3.7"
21854
21854
  },
@@ -22653,9 +22653,9 @@
22653
22653
  }
22654
22654
  },
22655
22655
  "typescript": {
22656
- "version": "5.5.2",
22657
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz",
22658
- "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==",
22656
+ "version": "5.5.3",
22657
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
22658
+ "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
22659
22659
  "dev": true
22660
22660
  },
22661
22661
  "typical": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "3.5.0",
3
+ "version": "3.6.0",
4
4
  "description": "The VIP Javascript library & CLI",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -138,7 +138,7 @@
138
138
  "jest": "^29.7.0",
139
139
  "nock": "13.5.4",
140
140
  "prettier": "npm:wp-prettier@2.8.5",
141
- "rimraf": "5.0.7",
141
+ "rimraf": "5.0.8",
142
142
  "typescript": "^5.2.2"
143
143
  },
144
144
  "dependencies": {