@automattic/vip 3.1.1-dev.1 → 3.3.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.
@@ -3,14 +3,14 @@ env_file:
3
3
  - .env
4
4
  proxy:
5
5
  nginx:
6
- - <%= siteSlug %>.vipdev.lndo.site
6
+ - <%= siteSlug %>.<%= domain %>
7
7
  <% if ( multisite ) { %>
8
- - '*.<%= siteSlug %>.vipdev.lndo.site'
8
+ - '*.<%= siteSlug %>.<%= domain %>'
9
9
  <% } %>
10
10
  phpmyadmin:
11
- - <%= siteSlug %>-pma.vipdev.lndo.site
11
+ - <%= siteSlug %>-pma.<%= domain %>
12
12
  mailpit:
13
- - <%= siteSlug %>-mailpit.vipdev.lndo.site:8025
13
+ - <%= siteSlug %>-mailpit.<%= domain %>:8025
14
14
 
15
15
  services:
16
16
  devtools:
@@ -38,7 +38,6 @@ services:
38
38
  image: ghcr.io/automattic/vip-container-images/nginx:latest
39
39
  command: nginx -g "daemon off;"
40
40
  environment:
41
- LANDO_NO_SCRIPTS: 1
42
41
  LANDO_NEEDS_EXEC: 1
43
42
  volumes:
44
43
  - ./nginx/extra.conf:/etc/nginx/conf.extra/extra.conf
@@ -79,9 +78,9 @@ services:
79
78
  sh /dev-tools/setup.sh
80
79
  --host database
81
80
  --user root
82
- --domain "http://<%= siteSlug %>.vipdev.lndo.site/"
81
+ --domain "http://<%= siteSlug %>.<%= domain %>/"
83
82
  --title "<%= wpTitle %>"
84
- <% if ( multisite ) { %>--ms-domain "<%= siteSlug %>.vipdev.lndo.site" <% if ( multisite === true || multisite === 'subdomain' ) { %>--subdomain <% } %> <% } %>
83
+ <% if ( multisite ) { %>--ms-domain "<%= siteSlug %>.<%= domain %>" <% if ( multisite === true || multisite === 'subdomain' ) { %>--subdomain <% } %> <% } %>
85
84
  database:
86
85
  type: compose
87
86
  services:
@@ -226,7 +225,6 @@ services:
226
225
  - ":8025"
227
226
  environment:
228
227
  LANDO_NO_USER_PERMS: 1
229
- LANDO_NO_SCRIPTS: 1
230
228
  LANDO_NEEDS_EXEC: 1
231
229
  <% } %>
232
230
 
@@ -84,10 +84,10 @@ cmd.argv(process.argv, async (arg, opt) => {
84
84
  preselectedOptions = (0, _devEnvironmentConfigurationFile.mergeConfigurationFileOptions)(opt, configurationFileOptions);
85
85
  suppressPrompts = true;
86
86
  }
87
- const instanceData = await (0, _devEnvironmentCli.promptForArguments)(preselectedOptions, defaultOptions, suppressPrompts);
87
+ const instanceData = await (0, _devEnvironmentCli.promptForArguments)(preselectedOptions, defaultOptions, suppressPrompts, true);
88
88
  instanceData.siteSlug = slug;
89
89
  try {
90
- await (0, _devEnvironmentCore.createEnvironment)(instanceData);
90
+ await (0, _devEnvironmentCore.createEnvironment)(lando, instanceData);
91
91
  await (0, _devEnvironmentCore.printEnvironmentInfo)(lando, slug, {
92
92
  extended: false,
93
93
  suppressWarnings: true
@@ -15,23 +15,59 @@ const usage = 'vip dev-env stop';
15
15
  const examples = [{
16
16
  usage: `${exampleUsage} --slug=example-site`,
17
17
  description: 'Stop a local environment named "example-site".'
18
+ }, {
19
+ usage: `${exampleUsage} --all`,
20
+ description: 'Stops all local environments.'
18
21
  }];
19
22
  (0, _command.default)({
20
23
  usage
21
- }).option('slug', 'A unique name for a local environment. Default is "vip-local".', undefined, _devEnvironmentCli.processSlug).examples(examples).argv(process.argv, async (arg, opt) => {
22
- const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
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) => {
23
25
  const lando = await (0, _devEnvironmentLando.bootstrapLando)();
24
- await (0, _devEnvironmentCli.validateDependencies)(lando, slug);
26
+ await (0, _devEnvironmentCli.validateDependencies)(lando, '');
25
27
  debug('Args: ', arg, 'Options: ', opt);
26
- const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
28
+
29
+ /** @type {Record< string, unknown >} */
30
+ let trackingInfo;
31
+ /** @type {string[]} */
32
+ let environments;
33
+ if (opt.all) {
34
+ trackingInfo = {
35
+ all: true
36
+ };
37
+ environments = (0, _devEnvironmentCore.getAllEnvironmentNames)();
38
+ } else {
39
+ const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
40
+ trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
41
+ environments = [slug];
42
+ }
27
43
  await (0, _tracker.trackEvent)('dev_env_stop_command_execute', trackingInfo);
28
- try {
29
- await (0, _devEnvironmentCore.stopEnvironment)(lando, slug);
30
- const message = _chalk.default.green('✓') + ' environment stopped.\n';
31
- console.log(message);
44
+ for (const slug of environments) {
45
+ try {
46
+ // eslint-disable-next-line no-await-in-loop
47
+ await (0, _devEnvironmentCore.stopEnvironment)(lando, slug);
48
+ const message = _chalk.default.green('✓') + ` environment "${slug}" stopped.\n`;
49
+ console.log(message);
50
+ } catch (error) {
51
+ let err;
52
+ if (!(error instanceof Error)) {
53
+ err = new Error(error?.toString());
54
+ } else {
55
+ err = error;
56
+ }
57
+ process.exitCode = 1;
58
+ const errorTrackingInfo = {
59
+ ...trackingInfo,
60
+ failure: err.message,
61
+ stack: err.stack
62
+ };
63
+
64
+ // trackEvent does not throw
65
+ // eslint-disable-next-line no-await-in-loop
66
+ await (0, _tracker.trackEvent)('dev_env_stop_command_error', errorTrackingInfo);
67
+ console.error(_chalk.default.red('Error:'), err.message.replace('ERROR: ', ''));
68
+ }
69
+ }
70
+ if (process.exitCode === 0) {
32
71
  await (0, _tracker.trackEvent)('dev_env_stop_command_success', trackingInfo);
33
- } catch (error) {
34
- await (0, _devEnvironmentCli.handleCLIException)(error, 'dev_env_stop_command_error', trackingInfo);
35
- process.exitCode = 1;
36
72
  }
37
73
  });
@@ -55,8 +55,8 @@ cmd.argv(process.argv, async (arg, opt) => {
55
55
 
56
56
  /** @type {InstanceOptions} */
57
57
  const defaultOptions = {
58
- appCode: currentInstanceData.appCode.dir || currentInstanceData.appCode.tag || 'latest',
59
- muPlugins: currentInstanceData.muPlugins.dir || currentInstanceData.muPlugins.tag || 'latest',
58
+ appCode: currentInstanceData.appCode.dir || currentInstanceData.appCode.tag || 'demo',
59
+ muPlugins: currentInstanceData.muPlugins.dir || currentInstanceData.muPlugins.tag || 'demo',
60
60
  wordpress: currentInstanceData.wordpress.tag || 'trunk',
61
61
  elasticsearch: currentInstanceData.elasticsearch,
62
62
  php: currentInstanceData.php || _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS[Object.keys(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS)[0]].image,
@@ -73,9 +73,9 @@ cmd.argv(process.argv, async (arg, opt) => {
73
73
  .filter(option => !['debug', 'help', 'slug'].includes(option)); // Filter out options that are not related to instance configuration
74
74
 
75
75
  const suppressPrompts = providedOptions.length > 0 || thereAreOptionsFromConfigFile;
76
- const instanceData = await (0, _devEnvironmentCli.promptForArguments)(finalPreselectedOptions, defaultOptions, suppressPrompts);
76
+ const instanceData = await (0, _devEnvironmentCli.promptForArguments)(finalPreselectedOptions, defaultOptions, suppressPrompts, false);
77
77
  instanceData.siteSlug = slug;
78
- await (0, _devEnvironmentCore.updateEnvironment)(instanceData);
78
+ await (0, _devEnvironmentCore.updateEnvironment)(lando, instanceData);
79
79
  const message = '\n' + _chalk.default.green('✓') + ' environment updated. Please start environment again for changes to take effect: ' + _chalk.default.bold(`vip dev-env --slug ${slug} start`);
80
80
  console.log(message);
81
81
  await (0, _tracker.trackEvent)('dev_env_update_command_success', trackingInfo);
@@ -22,6 +22,8 @@ const ALLOWED_FORMATS = ['csv', 'json', 'table'];
22
22
  const DEFAULT_POLLING_DELAY_IN_SECONDS = 30;
23
23
  const MIN_POLLING_DELAY_IN_SECONDS = 5;
24
24
  const MAX_POLLING_DELAY_IN_SECONDS = 300;
25
+ const exampleUsage = 'vip @example-app.develop slowlogs';
26
+ const baseUsage = 'vip slowlogs';
25
27
  async function getSlowlogs(arg, opt) {
26
28
  validateInputs(opt.limit, opt.format);
27
29
  const trackingParams = getBaseTrackingParams(opt);
@@ -167,17 +169,18 @@ void (0, _command.default)({
167
169
  appQuery,
168
170
  envContext: true,
169
171
  format: false,
170
- module: 'slowlogs'
171
- }).option('limit', 'The maximum number of log lines', 500).option('format', 'Output the log lines in CSV or JSON format', 'table').examples([{
172
- description: 'Get the most recent app slowlogs',
173
- usage: 'vip @mysite.production slowlogs'
172
+ module: 'slowlogs',
173
+ usage: baseUsage
174
+ }).option('limit', 'The maximum number of log entries', 500).option('format', 'Output the log entries in CSV or JSON format', 'table').examples([{
175
+ description: 'Retrieve up to 500 of the most recent entries from the MySQL slow query logs in the default format.',
176
+ usage: exampleUsage
174
177
  }, {
175
- usage: 'vip @mysite.production slowlogs --limit 100',
176
- description: 'Get the most recent 100 slowlog entries'
178
+ description: 'Retrieve up to 50 of the most recent entries from the MySQL slow query logs in the default format.',
179
+ usage: `${exampleUsage} --limit=50`
177
180
  }, {
178
- usage: 'vip @mysite.production slowlogs --limit 100 --format csv',
179
- description: 'Get the most recent 100 slowlog entries formatted as comma-separated values (CSV)'
181
+ description: 'Retrieve up to 100 of the most recent entries from the MySQL slow query logs in CSV format.',
182
+ usage: `${exampleUsage} --limit=100 --format=csv`
180
183
  }, {
181
- usage: 'vip @mysite.production slowlogs --limit 100 --format json',
182
- description: 'Get the most recent 100 slowlog entries formatted as JSON'
184
+ description: 'Retrieve up to 100 of the most recent entries from the MySQL slow query logs in JSON format.',
185
+ usage: `${exampleUsage} --limit=100 --format=json`
183
186
  }]).argv(process.argv, getSlowlogs);
package/dist/bin/vip.js CHANGED
@@ -22,7 +22,7 @@ const tokenURL = 'https://dashboard.wpvip.com/me/cli/token';
22
22
  const customDeployToken = process.env.WPVIP_DEPLOY_TOKEN;
23
23
  const runCmd = async function () {
24
24
  const cmd = (0, _command.default)();
25
- cmd.command('logout', 'Log out the current authenticated VIP-CLI user.').command('app', 'List and modify your VIP applications').command('backup', 'Generate a backup of an environment.').command('cache', 'Manage page cache for your VIP applications').command('config', 'Manage environment configurations.').command('dev-env', 'Create and manage VIP Local Development Environments.').command('export', 'Export a copy of data associated with an environment.').command('import', 'Import media or SQL files into your VIP applications').command('logs', 'Get logs from your VIP applications').command('search-replace', 'Perform search and replace tasks on files').command('slowlogs', 'Get slowlogs from your VIP applications').command('db', "Access an environment's database.").command('sync', 'Sync production to a development environment').command('whoami', 'Retrieve details about the current authenticated VIP-CLI user.').command('validate', 'Validate your VIP application and environment').command('wp', 'Run WP CLI commands against an environment');
25
+ cmd.command('logout', 'Log out the current authenticated VIP-CLI user.').command('app', 'List and modify your VIP applications').command('backup', 'Generate a backup of an environment.').command('cache', 'Manage page cache for your VIP applications').command('config', 'Manage environment configurations.').command('dev-env', 'Create and manage VIP Local Development Environments.').command('export', 'Export a copy of data associated with an environment.').command('import', 'Import media or SQL files into your VIP applications').command('logs', 'Get logs from your VIP applications').command('search-replace', 'Perform search and replace tasks on files').command('slowlogs', 'Retrieve MySQL slow query logs from an environment.').command('db', "Access an environment's database.").command('sync', 'Sync production to a development environment').command('whoami', 'Retrieve details about the current authenticated VIP-CLI user.').command('validate', 'Validate your VIP application and environment').command('wp', 'Run WP CLI commands against an environment');
26
26
  cmd.argv(process.argv);
27
27
  };
28
28
 
@@ -4,11 +4,6 @@ exports.__esModule = true;
4
4
  exports.DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL = exports.DEV_ENVIRONMENT_WORDPRESS_VERSIONS_URI = exports.DEV_ENVIRONMENT_WORDPRESS_CACHE_KEY = exports.DEV_ENVIRONMENT_VERSION = exports.DEV_ENVIRONMENT_SUBCOMMAND = exports.DEV_ENVIRONMENT_RAW_GITHUB_HOST = exports.DEV_ENVIRONMENT_PROMPT_INTRO = exports.DEV_ENVIRONMENT_PHP_VERSIONS = exports.DEV_ENVIRONMENT_NOT_FOUND = exports.DEV_ENVIRONMENT_FULL_COMMAND = exports.DEV_ENVIRONMENT_DEFAULTS = exports.DEV_ENVIRONMENT_COMPONENTS_WITH_WP = exports.DEV_ENVIRONMENT_COMPONENTS = void 0;
5
5
  const DEV_ENVIRONMENT_SUBCOMMAND = exports.DEV_ENVIRONMENT_SUBCOMMAND = 'dev-env';
6
6
  const DEV_ENVIRONMENT_FULL_COMMAND = exports.DEV_ENVIRONMENT_FULL_COMMAND = `vip ${DEV_ENVIRONMENT_SUBCOMMAND}`;
7
- const DEV_ENVIRONMENT_DEFAULTS = exports.DEV_ENVIRONMENT_DEFAULTS = {
8
- title: 'VIP Dev',
9
- multisite: false,
10
- phpVersion: '8.0'
11
- };
12
7
  const DEV_ENVIRONMENT_PROMPT_INTRO = exports.DEV_ENVIRONMENT_PROMPT_INTRO = 'This is a wizard to help you set up your local dev environment.\n\n' + 'Sensible default values were pre-selected for convenience. ' + 'You may also choose to create multiple environments with different settings using the --slug option.\n\n';
13
8
  const DEV_ENVIRONMENT_NOT_FOUND = exports.DEV_ENVIRONMENT_NOT_FOUND = 'Environment not found.';
14
9
  const DEV_ENVIRONMENT_COMPONENTS = exports.DEV_ENVIRONMENT_COMPONENTS = ['muPlugins', 'appCode'];
@@ -32,4 +27,9 @@ const DEV_ENVIRONMENT_PHP_VERSIONS = exports.DEV_ENVIRONMENT_PHP_VERSIONS = {
32
27
  label: '8.3'
33
28
  }
34
29
  };
30
+ const DEV_ENVIRONMENT_DEFAULTS = exports.DEV_ENVIRONMENT_DEFAULTS = {
31
+ title: 'VIP Dev',
32
+ multisite: false,
33
+ phpVersion: Object.keys(DEV_ENVIRONMENT_PHP_VERSIONS)[0]
34
+ };
35
35
  const DEV_ENVIRONMENT_VERSION = exports.DEV_ENVIRONMENT_VERSION = '2.0.3';
@@ -13,6 +13,7 @@ exports.postStart = postStart;
13
13
  exports.printTable = printTable;
14
14
  exports.processBooleanOption = processBooleanOption;
15
15
  exports.processComponentOptionInput = processComponentOptionInput;
16
+ exports.processMediaRedirectDomainOption = processMediaRedirectDomainOption;
16
17
  exports.processSlug = processSlug;
17
18
  exports.processStringOrBooleanOption = processStringOrBooleanOption;
18
19
  exports.processVersionOption = processVersionOption;
@@ -213,7 +214,7 @@ function getOptionsFromAppInfo(appInfo) {
213
214
  * @return {any} instance data
214
215
  */
215
216
  // eslint-disable-next-line complexity
216
- async function promptForArguments(preselectedOptions, defaultOptions, suppressPrompts = false) {
217
+ async function promptForArguments(preselectedOptions, defaultOptions, suppressPrompts, create) {
217
218
  debug('Provided preselected', preselectedOptions, 'and default', defaultOptions);
218
219
  if (suppressPrompts) {
219
220
  preselectedOptions = {
@@ -257,7 +258,7 @@ async function promptForArguments(preselectedOptions, defaultOptions, suppressPr
257
258
  mailpit: 'Mailpit',
258
259
  photon: 'Photon'
259
260
  };
260
- if (!instanceData.mediaRedirectDomain && defaultOptions.mediaRedirectDomain) {
261
+ if (create && !instanceData.mediaRedirectDomain && defaultOptions.mediaRedirectDomain) {
261
262
  const mediaRedirectPromptText = `Would you like to redirect to ${defaultOptions.mediaRedirectDomain} for missing media files?`;
262
263
  const setMediaRedirectDomain = await promptForBoolean(mediaRedirectPromptText, true);
263
264
  if (setMediaRedirectDomain) {
@@ -304,6 +305,16 @@ async function processWordPress(preselectedValue, defaultValue) {
304
305
  } else {
305
306
  result = await promptForWordPress(defaultObject);
306
307
  }
308
+ const versions = await (0, _devEnvironmentCore.getVersionList)();
309
+ if (versions.length) {
310
+ versions.sort((before, after) => before.tag < after.tag ? 1 : -1);
311
+ const match = versions.find(({
312
+ tag
313
+ }) => tag === result.tag);
314
+ if (typeof match === 'undefined') {
315
+ throw new _userError.default(`Unknown or unsupported WordPress version: ${result.tag}.`);
316
+ }
317
+ }
307
318
  debug(result);
308
319
  return result;
309
320
  }
@@ -444,24 +455,19 @@ function resolveMultisite(value) {
444
455
  return isMultisiteOption(value) ? value : _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.multisite;
445
456
  }
446
457
  function resolvePhpVersion(version) {
447
- debug(`Resolving PHP version %j`, version);
448
- if (version.startsWith('image:')) {
449
- return version;
458
+ // It is painful to rewrite tests :-(
459
+ if (version === '') {
460
+ return '';
450
461
  }
462
+ debug(`Resolving PHP version %j`, version);
451
463
  let result;
452
464
  if (!(version in _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS)) {
453
465
  const images = Object.values(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS);
454
466
  const image = images.find(value => value.image === version);
455
467
  if (image) {
456
468
  result = image.image;
457
- } else if (version.includes('/')) {
458
- // Assuming this is a Docker image
459
- // This can happen when we first called `vip dev-env update -P image:ghcr.io/...`
460
- // and then called `vip dev-env update` again. The custom image won't match our images
461
- // but we still want to use it.
462
- result = version;
463
469
  } else {
464
- result = images[0].image;
470
+ throw new _userError.default(`Unknown or unsupported PHP version: ${version}.`);
465
471
  }
466
472
  } else {
467
473
  result = _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS[version].image;
@@ -579,6 +585,17 @@ function processBooleanOption(value) {
579
585
  // eslint-disable-next-line @typescript-eslint/no-base-to-string
580
586
  return !FALSE_OPTIONS.includes(value.toString().toLowerCase()); // NOSONAR
581
587
  }
588
+ function processMediaRedirectDomainOption(value) {
589
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
590
+ const val = (value ?? '').toString();
591
+ if (FALSE_OPTIONS.includes(val.toLowerCase())) {
592
+ return '';
593
+ }
594
+ if (TRUE_OPTIONS.includes(val.toLowerCase())) {
595
+ throw new _userError.default('Media redirect domain must be a domain name or an URL');
596
+ }
597
+ return val;
598
+ }
582
599
  function processStringOrBooleanOption(value) {
583
600
  if (typeof value === 'boolean') {
584
601
  return value;
@@ -605,7 +622,7 @@ function processVersionOption(value) {
605
622
  }
606
623
  function addDevEnvConfigurationOptions(command) {
607
624
  // We leave the third parameter to undefined on some because the defaults are handled in preProcessInstanceData()
608
- return command.option('wordpress', 'Use a specific WordPress version', undefined, processVersionOption).option(['u', 'mu-plugins'], 'Use a specific mu-plugins changeset or local directory').option('app-code', 'Use the application code from a local directory or use "demo" for VIP skeleton code').option('phpmyadmin', 'Enable PHPMyAdmin component. By default it is disabled', undefined, processBooleanOption).option('xdebug', 'Enable XDebug. By default it is disabled', undefined, processBooleanOption).option('xdebug_config', 'Extra configuration to pass to xdebug via XDEBUG_CONFIG environment variable').option('elasticsearch', 'Enable Elasticsearch (needed by Enterprise Search)', undefined, processBooleanOption).option(['r', 'media-redirect-domain'], 'Domain to redirect for missing media files. This can be used to still have images without the need to import them locally.').option('php', 'Explicitly choose PHP version to use', undefined, processVersionOption).option(['A', 'mailpit'], 'Enable Mailpit. By default it is disabled', undefined, processBooleanOption).option(['H', 'photon'], 'Enable Photon. By default it is disabled', undefined, processBooleanOption);
625
+ return command.option('wordpress', 'Use a specific WordPress version', undefined, processVersionOption).option(['u', 'mu-plugins'], 'Use a specific mu-plugins changeset or local directory').option('app-code', 'Use the application code from a local directory or use "demo" for VIP skeleton code').option('phpmyadmin', 'Enable PHPMyAdmin component. By default it is disabled', undefined, processBooleanOption).option('xdebug', 'Enable XDebug. By default it is disabled', undefined, processBooleanOption).option('xdebug_config', 'Extra configuration to pass to xdebug via XDEBUG_CONFIG environment variable').option('elasticsearch', 'Enable Elasticsearch (needed by Enterprise Search)', undefined, processBooleanOption).option(['r', 'media-redirect-domain'], 'Domain to redirect for missing media files. This can be used to still have images without the need to import them locally.', undefined, processMediaRedirectDomainOption).option('php', 'Explicitly choose PHP version to use', undefined, processVersionOption).option(['A', 'mailpit'], 'Enable Mailpit. By default it is disabled', undefined, processBooleanOption).option(['H', 'photon'], 'Enable Photon. By default it is disabled', undefined, processBooleanOption);
609
626
  }
610
627
 
611
628
  /**
@@ -169,7 +169,7 @@ function getConfigurationFileExample() {
169
169
  return `configuration-version: ${getLatestConfigurationFileVersion()}
170
170
  slug: dev-site
171
171
  title: Dev Site
172
- php: 8.0
172
+ php: 8.2
173
173
  wordpress: 6.2
174
174
  app-code: ../
175
175
  mu-plugins: image
@@ -70,9 +70,9 @@ async function startEnvironment(lando, slug, options) {
70
70
  }
71
71
  let updated = false;
72
72
  if (!options.skipWpVersionsCheck) {
73
- updated = await maybeUpdateWordPressImage(slug);
73
+ updated = await maybeUpdateWordPressImage(lando, slug);
74
74
  }
75
- updated = updated || (await maybeUpdateVersion(slug));
75
+ updated = updated || (await maybeUpdateVersion(lando, slug));
76
76
  if (options.skipRebuild && !updated) {
77
77
  await (0, _devEnvironmentLando.landoStart)(lando, instancePath);
78
78
  } else {
@@ -92,7 +92,7 @@ async function stopEnvironment(lando, slug) {
92
92
  }
93
93
  await (0, _devEnvironmentLando.landoStop)(lando, instancePath);
94
94
  }
95
- async function createEnvironment(instanceData) {
95
+ async function createEnvironment(lando, instanceData) {
96
96
  const slug = instanceData.siteSlug;
97
97
  debug('Will process an environment', slug, 'with instanceData for creation: ', instanceData);
98
98
  const instancePath = getEnvironmentPath(slug);
@@ -103,9 +103,9 @@ async function createEnvironment(instanceData) {
103
103
  }
104
104
  const preProcessedInstanceData = preProcessInstanceData(instanceData);
105
105
  debug('Will create an environment', slug, 'with instanceData: ', preProcessedInstanceData);
106
- await prepareLandoEnv(preProcessedInstanceData, instancePath);
106
+ await prepareLandoEnv(lando, preProcessedInstanceData, instancePath);
107
107
  }
108
- async function updateEnvironment(instanceData) {
108
+ async function updateEnvironment(lando, instanceData) {
109
109
  const slug = instanceData.siteSlug;
110
110
  debug('Will process an environment', slug, 'with instanceData for updating: ', instanceData);
111
111
  const instancePath = getEnvironmentPath(slug);
@@ -116,7 +116,7 @@ async function updateEnvironment(instanceData) {
116
116
  }
117
117
  const preProcessedInstanceData = preProcessInstanceData(instanceData);
118
118
  debug('Will create an environment', slug, 'with instanceData: ', preProcessedInstanceData);
119
- await prepareLandoEnv(preProcessedInstanceData, instancePath);
119
+ await prepareLandoEnv(lando, preProcessedInstanceData, instancePath);
120
120
  }
121
121
  function preProcessInstanceData(instanceData) {
122
122
  const newInstanceData = {
@@ -131,9 +131,6 @@ function preProcessInstanceData(instanceData) {
131
131
  newInstanceData.elasticsearch = instanceData.elasticsearch || false; // NOSONAR
132
132
 
133
133
  newInstanceData.php = instanceData.php || _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS[Object.keys(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS)[0]].image;
134
- if (newInstanceData.php.startsWith('image:')) {
135
- newInstanceData.php = newInstanceData.php.slice('image:'.length);
136
- }
137
134
 
138
135
  // FIXME: isNaN supports only number in TypeScript, actually, because isNaN('123') returns false despite being a string
139
136
  if (isNaN(instanceData.wordpress.tag)) {
@@ -211,7 +208,7 @@ function parseComponentForInfo(component) {
211
208
  }
212
209
 
213
210
  // Environments created by the old code will have `component.tag` set to `demo` instead of `undefined`.
214
- if (component.tag === 'demo') {
211
+ if (component.tag === 'demo' || component.tag === 'latest') {
215
212
  component.tag = undefined;
216
213
  }
217
214
  return component.tag ?? '[demo-image]';
@@ -245,6 +242,11 @@ async function printEnvironmentInfo(lando, slug, options) {
245
242
  appInfo.title = environmentData.wpTitle;
246
243
  appInfo.multisite = Boolean(environmentData.multisite);
247
244
  appInfo.php = environmentData.php.split(':')[1];
245
+ let xdebug = environmentData.xdebug ? 'enabled' : 'disabled';
246
+ if (environmentData.xdebug && environmentData.xdebugConfig) {
247
+ xdebug += ' (with additional configuration)';
248
+ }
249
+ appInfo.xdebug = xdebug;
248
250
  appInfo.wordpress = parseComponentForInfo(environmentData.wordpress);
249
251
  appInfo['Mu plugins'] = parseComponentForInfo(environmentData.muPlugins);
250
252
  appInfo['App Code'] = parseComponentForInfo(environmentData.appCode);
@@ -327,9 +329,13 @@ function writeEnvironmentData(slug, data) {
327
329
  const instanceDataTargetPath = _nodePath.default.join(instancePath, instanceDataFileName);
328
330
  return _nodeFs.default.promises.writeFile(instanceDataTargetPath, JSON.stringify(data, null, 2));
329
331
  }
330
- async function prepareLandoEnv(instanceData, instancePath) {
331
- const landoFile = await _ejs.default.renderFile(landoFileTemplatePath, instanceData);
332
- const nginxFile = await _ejs.default.renderFile(nginxFileTemplatePath, instanceData);
332
+ async function prepareLandoEnv(lando, instanceData, instancePath) {
333
+ const templateData = {
334
+ ...instanceData,
335
+ domain: lando.config.domain
336
+ };
337
+ const landoFile = await _ejs.default.renderFile(landoFileTemplatePath, templateData);
338
+ const nginxFile = await _ejs.default.renderFile(nginxFileTemplatePath, templateData);
333
339
  const instanceDataFile = JSON.stringify(instanceData);
334
340
  const landoFileTargetPath = _nodePath.default.join(instancePath, landoFileName);
335
341
  const landoBackupFileTargetPath = _nodePath.default.join(instancePath, landoBackupFileName);
@@ -507,7 +513,7 @@ async function importMediaPath(slug, filePath) {
507
513
  * @param {string} slug slug
508
514
  * @return {boolean} boolean
509
515
  */
510
- async function maybeUpdateWordPressImage(slug) {
516
+ async function maybeUpdateWordPressImage(lando, slug) {
511
517
  const versions = await getVersionList();
512
518
  if (!versions.length) {
513
519
  return false;
@@ -588,7 +594,7 @@ async function maybeUpdateWordPressImage(slug) {
588
594
  // FIXME: version?.tag is possibly null. Should we throw if we can't find a version somehow?
589
595
  envData.wordpress.tag = version?.tag ?? '';
590
596
  envData.wordpress.ref = version?.ref;
591
- await updateEnvironment(envData);
597
+ await updateEnvironment(lando, envData);
592
598
  return true;
593
599
  }
594
600
  if (confirm.upgrade === "no (don't ask anymore)") {
@@ -596,16 +602,16 @@ async function maybeUpdateWordPressImage(slug) {
596
602
  envData.wordpress.doNotUpgrade = true;
597
603
  console.log("We won't ask about upgrading this environment anymore.");
598
604
  console.log(`To manually upgrade please run: ${_chalk.default.yellow(updateCommand)}`);
599
- await updateEnvironment(envData);
605
+ await updateEnvironment(lando, envData);
600
606
  }
601
607
  return false;
602
608
  }
603
- async function maybeUpdateVersion(slug) {
609
+ async function maybeUpdateVersion(lando, slug) {
604
610
  const envData = readEnvironmentData(slug);
605
611
  const currentVersion = envData.version;
606
612
  console.log('Current local environment version is: ' + _chalk.default.yellow(currentVersion));
607
613
  if (!currentVersion || _semver.default.lt(currentVersion, _devEnvironment.DEV_ENVIRONMENT_VERSION)) {
608
- await updateEnvironment(envData);
614
+ await updateEnvironment(lando, envData);
609
615
  console.log('Local environment version updated to: ' + _chalk.default.green(_devEnvironment.DEV_ENVIRONMENT_VERSION));
610
616
  return true;
611
617
  }
@@ -106,7 +106,7 @@ async function initLandoApplication(lando, instancePath) {
106
106
  await app.init();
107
107
  return app;
108
108
  }
109
- async function regenerateLandofile(instancePath) {
109
+ async function regenerateLandofile(lando, instancePath) {
110
110
  const landoFile = _nodePath.default.join(instancePath, '.lando.yml');
111
111
  try {
112
112
  const now = new Date().toISOString().replace(/[^\d]/g, '').slice(0, -3);
@@ -119,13 +119,13 @@ async function regenerateLandofile(instancePath) {
119
119
  const slug = _nodePath.default.basename(instancePath);
120
120
  const currentInstanceData = (0, _devEnvironmentCore.readEnvironmentData)(slug);
121
121
  currentInstanceData.pullAfter = 0;
122
- await (0, _devEnvironmentCore.updateEnvironment)(currentInstanceData);
122
+ await (0, _devEnvironmentCore.updateEnvironment)(lando, currentInstanceData);
123
123
  }
124
124
  async function landoRecovery(lando, instancePath, error) {
125
125
  debug('Error initializing Lando app', error);
126
126
  console.warn(_chalk.default.yellow('There was an error initializing Lando, trying to recover...'));
127
127
  try {
128
- await regenerateLandofile(instancePath);
128
+ await regenerateLandofile(lando, instancePath);
129
129
  } catch (err) {
130
130
  console.error(`${_chalk.default.bold.red('Recovery failed, aborting.')} Please recreate the environment or contact support.`);
131
131
  throw err;
package/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  ## Changelog
2
2
 
3
+ ### 3.3.0
4
+
5
+ * fix(dev-env): make sure wildcard subdomains work with SSL/TLS
6
+ * feat(dev-env): add XDebug information to `vip dev-env info --extended`
7
+
8
+ **Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.2.0...3.3.0
9
+
10
+ ### 3.2.0
11
+
12
+ * feat(dev-env): make `domain` configurable
13
+ * build(deps): bump actions/dependency-review-action from 4.3.2 to 4.3.3
14
+ * build(deps-dev): bump the babel group with 4 updates
15
+ * Update the slowlogs command to follow the VIP-CLI styleguide
16
+ * feat(dev-env): add `--all` to `vip dev-env stop`
17
+ * chore: update lando to 77dad3a
18
+ * fix: CVE-2024-29415 in `socks`
19
+ * fix(dev-env): allow for unsetting media redirect domain
20
+ * fix(dev-env): validate version values
21
+
22
+ **Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.1.0...3.2.0
23
+
3
24
  ### 3.1.0
4
25
 
5
26
  * Integrate Media Import v2 flow and expand on media import error report messaging