@automattic/vip 2.26.0 → 2.26.2

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.
@@ -93,7 +93,7 @@ async function stopEnvironment(lando, slug) {
93
93
  }
94
94
  async function createEnvironment(instanceData) {
95
95
  const slug = instanceData.siteSlug;
96
- debug('Will create an environment', slug, 'with instanceData: ', instanceData);
96
+ debug('Will process an environment', slug, 'with instanceData for creation: ', instanceData);
97
97
  const instancePath = getEnvironmentPath(slug);
98
98
  debug('Instance path for', slug, 'is:', instancePath);
99
99
  const alreadyExists = _fs.default.existsSync(instancePath);
@@ -101,11 +101,12 @@ async function createEnvironment(instanceData) {
101
101
  throw new Error('Environment already exists.');
102
102
  }
103
103
  const preProcessedInstanceData = preProcessInstanceData(instanceData);
104
+ debug('Will create an environment', slug, 'with instanceData: ', preProcessedInstanceData);
104
105
  await prepareLandoEnv(preProcessedInstanceData, instancePath);
105
106
  }
106
107
  async function updateEnvironment(instanceData) {
107
108
  const slug = instanceData.siteSlug;
108
- debug('Will update an environment', slug, 'with instanceData: ', instanceData);
109
+ debug('Will process an environment', slug, 'with instanceData for updating: ', instanceData);
109
110
  const instancePath = getEnvironmentPath(slug);
110
111
  debug('Instance path for', slug, 'is:', instancePath);
111
112
  const alreadyExists = _fs.default.existsSync(instancePath);
@@ -113,6 +114,7 @@ async function updateEnvironment(instanceData) {
113
114
  throw new Error('Environment doesn\'t exist.');
114
115
  }
115
116
  const preProcessedInstanceData = preProcessInstanceData(instanceData);
117
+ debug('Will create an environment', slug, 'with instanceData: ', preProcessedInstanceData);
116
118
  await prepareLandoEnv(preProcessedInstanceData, instancePath);
117
119
  }
118
120
  function preProcessInstanceData(instanceData) {
@@ -128,6 +130,9 @@ function preProcessInstanceData(instanceData) {
128
130
  if (newInstanceData.php.startsWith('image:')) {
129
131
  newInstanceData.php = newInstanceData.php.slice('image:'.length);
130
132
  }
133
+ if (isNaN(instanceData.wordpress.tag)) {
134
+ newInstanceData.wordpress.tag = 'trunk';
135
+ }
131
136
  if (!newInstanceData.xdebugConfig) {
132
137
  newInstanceData.xdebugConfig = '';
133
138
  }
@@ -142,6 +147,11 @@ function preProcessInstanceData(instanceData) {
142
147
  if (!newInstanceData.mailhog) {
143
148
  newInstanceData.mailhog = false;
144
149
  }
150
+
151
+ // MariaDB migration
152
+ if (!newInstanceData.mariadb) {
153
+ newInstanceData.mariadb = undefined;
154
+ }
145
155
  return newInstanceData;
146
156
  }
147
157
  async function destroyEnvironment(lando, slug, removeFiles) {
@@ -198,7 +208,7 @@ async function printEnvironmentInfo(lando, slug, options) {
198
208
  if (!environmentExists) {
199
209
  throw new _userError.default(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
200
210
  }
201
- const appInfo = await (0, _devEnvironmentLando.landoInfo)(lando, instancePath);
211
+ const appInfo = await (0, _devEnvironmentLando.landoInfo)(lando, instancePath, !!options.suppressWarnings);
202
212
  if (options.extended) {
203
213
  const environmentData = readEnvironmentData(slug);
204
214
  appInfo.title = environmentData.wpTitle;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.bootstrapLando = bootstrapLando;
7
+ exports.checkEnvHealth = checkEnvHealth;
7
8
  exports.isEnvUp = isEnvUp;
8
9
  exports.landoDestroy = landoDestroy;
9
10
  exports.landoExec = landoExec;
@@ -18,6 +19,7 @@ var _os = _interopRequireDefault(require("os"));
18
19
  var _fs = _interopRequireDefault(require("fs"));
19
20
  var _path = _interopRequireDefault(require("path"));
20
21
  var _lando = _interopRequireDefault(require("lando/lib/lando"));
22
+ var _bootstrap = require("lando/lib/bootstrap");
21
23
  var _utils = _interopRequireDefault(require("lando/plugins/lando-core/lib/utils"));
22
24
  var _build = _interopRequireDefault(require("lando/plugins/lando-tooling/lib/build"));
23
25
  var _chalk = _interopRequireDefault(require("chalk"));
@@ -48,7 +50,7 @@ async function getLandoConfig() {
48
50
  const nodeModulesPath = _path.default.join(__dirname, '..', '..', '..', 'node_modules');
49
51
  const landoPath = _path.default.join(nodeModulesPath, 'lando');
50
52
  const atLandoPath = _path.default.join(nodeModulesPath, '@lando');
51
- debug(`Getting lando config, using paths '${landoPath}' and '${atLandoPath}' for plugins`);
53
+ debug(`Getting Lando config, using paths '${landoPath}' and '${atLandoPath}' for plugins`);
52
54
  const isLandoDebugSelected = _debug.default.enabled(DEBUG_KEY);
53
55
  const isAllDebugSelected = _debug.default.enabled('"*"');
54
56
  let logLevelConsole;
@@ -69,8 +71,9 @@ async function getLandoConfig() {
69
71
  } catch (err) {
70
72
  // Ignore
71
73
  }
72
- return {
74
+ const config = {
73
75
  logLevelConsole,
76
+ configSources: [_path.default.join(landoDir, 'config.yml')],
74
77
  landoFile: '.lando.yml',
75
78
  preLandoFiles: ['.lando.base.yml', '.lando.dist.yml', '.lando.upstream.yml'],
76
79
  postLandoFiles: ['.lando.local.yml'],
@@ -92,6 +95,7 @@ async function getLandoConfig() {
92
95
  domain: 'lndo.site',
93
96
  version: 'unknown'
94
97
  };
98
+ return (0, _bootstrap.buildConfig)(config);
95
99
  }
96
100
  const appMap = new Map();
97
101
  async function regenerateLandofile(instancePath) {
@@ -102,7 +106,7 @@ async function regenerateLandofile(instancePath) {
102
106
  await _fs.default.promises.rename(landoFile, backup);
103
107
  console.warn(_chalk.default.yellow('Backed up %s to %s'), landoFile, backup);
104
108
  } catch (err) {
105
- // Rename failed - possible the file does not exist. Silently ignoring.
109
+ // Rename failed - possibly the file does not exist. Silently ignoring.
106
110
  }
107
111
  const slug = _path.default.basename(instancePath);
108
112
  const currentInstanceData = (0, _devEnvironmentCore.readEnvironmentData)(slug);
@@ -138,7 +142,7 @@ async function getLandoApplication(lando, instancePath) {
138
142
  let app;
139
143
  try {
140
144
  app = lando.getApp(instancePath);
141
- addHooks(app, lando);
145
+ await addHooks(app, lando);
142
146
  await app.init();
143
147
  } catch (error) {
144
148
  app = await landoRecovery(lando, instancePath, error);
@@ -162,7 +166,7 @@ async function landoRebuild(lando, instancePath) {
162
166
  await ensureNoOrphantProxyContainer(lando);
163
167
  await app.rebuild();
164
168
  }
165
- function addHooks(app, lando) {
169
+ async function addHooks(app, lando) {
166
170
  app.events.on('post-start', 1, () => healthcheckHook(app, lando));
167
171
  lando.events.once('pre-engine-build', async data => {
168
172
  const instanceData = (0, _devEnvironmentCore.readEnvironmentData)(app._name);
@@ -249,13 +253,13 @@ async function landoDestroy(lando, instancePath) {
249
253
  const app = await getLandoApplication(lando, instancePath);
250
254
  await app.destroy();
251
255
  }
252
- async function landoInfo(lando, instancePath) {
256
+ async function landoInfo(lando, instancePath, suppressWarnings) {
253
257
  var _app$info$find;
254
258
  const app = await getLandoApplication(lando, instancePath);
255
259
  let appInfo = _utils.default.startTable(app);
256
260
  const reachableServices = app.info.filter(service => service.urls.length);
257
261
  reachableServices.forEach(service => appInfo[`${service.service} urls`] = service.urls);
258
- const isUp = await isEnvUp(lando, instancePath);
262
+ const health = await checkEnvHealth(lando, instancePath);
259
263
  const frontEndUrl = (_app$info$find = app.info.find(service => 'nginx' === service.service)) === null || _app$info$find === void 0 ? void 0 : _app$info$find.urls[0];
260
264
  const extraService = await getExtraServicesConnections(lando, app);
261
265
  appInfo = {
@@ -264,7 +268,15 @@ async function landoInfo(lando, instancePath) {
264
268
  ...extraService
265
269
  };
266
270
  delete appInfo.name;
267
- appInfo.status = isUp ? _chalk.default.green('UP') : _chalk.default.yellow('DOWN');
271
+ const hasResults = Object.values(health).length > 0;
272
+ const hasWarnings = Object.values(health).some(status => !status);
273
+ if (hasResults && !hasWarnings) {
274
+ appInfo.status = _chalk.default.green('UP');
275
+ } else if (health.nginx) {
276
+ appInfo.status = _chalk.default.yellow('PARTIALLY UP');
277
+ } else {
278
+ appInfo.status = _chalk.default.red('DOWN');
279
+ }
268
280
 
269
281
  // Add login information
270
282
  if (frontEndUrl) {
@@ -273,6 +285,15 @@ async function landoInfo(lando, instancePath) {
273
285
  appInfo['Default username'] = 'vipgo';
274
286
  appInfo['Default password'] = 'password';
275
287
  }
288
+ if (!suppressWarnings && hasWarnings) {
289
+ let message = _chalk.default.bold.yellow('The following services have failed health checks:\n');
290
+ Object.keys(health).forEach(service => {
291
+ if (!health[service]) {
292
+ message += `${_chalk.default.red(service)}\n`;
293
+ }
294
+ });
295
+ appInfo['Health warnings'] = message;
296
+ }
276
297
 
277
298
  // Add documentation link
278
299
  appInfo.Documentation = 'https://docs.wpvip.com/technical-references/vip-local-development-environment/';
@@ -286,6 +307,9 @@ const extraServiceDisplayConfiguration = [{
286
307
  name: 'phpmyadmin',
287
308
  // Skipping, as the phpmyadmin was already printed by the regular services
288
309
  skip: true
310
+ }, {
311
+ name: 'mailhog',
312
+ skip: true
289
313
  }];
290
314
  async function getExtraServicesConnections(lando, app) {
291
315
  const extraServices = {};
@@ -316,19 +340,39 @@ async function getExtraServicesConnections(lando, app) {
316
340
  }
317
341
  return extraServices;
318
342
  }
343
+ async function checkEnvHealth(lando, instancePath) {
344
+ const urls = {};
345
+ const now = new Date();
346
+ const app = await getLandoApplication(lando, instancePath);
347
+ app.info.filter(service => service.urls.length).forEach(service => {
348
+ service.urls.forEach(url => {
349
+ urls[url] = service.service;
350
+ });
351
+ });
352
+ const scanResults = await app.scanUrls(Object.keys(urls), {
353
+ max: 1
354
+ });
355
+ const result = {};
356
+ scanResults.forEach(scanResult => {
357
+ result[urls[scanResult.url]] = scanResult.status;
358
+ });
359
+ const duration = new Date().getTime() - now.getTime();
360
+ debug('checkEnvHealth took %d ms', duration);
361
+ return result;
362
+ }
319
363
  async function isEnvUp(lando, instancePath) {
320
364
  const now = new Date();
321
365
  const app = await getLandoApplication(lando, instancePath);
322
366
  const reachableServices = app.info.filter(service => service.urls.length);
323
- const urls = reachableServices.map(service => service.urls).flat();
324
- const scanResult = await app.scanUrls(urls, {
367
+ const webUrls = reachableServices.map(service => service.urls).flat().filter(url => !url.match(/^https?:\/\/(localhost|127\.0\.0\.1):/));
368
+ const scanResult = await app.scanUrls(webUrls, {
325
369
  max: 1
326
370
  });
327
371
  const duration = new Date().getTime() - now.getTime();
328
372
  debug('isEnvUp took %d ms', duration);
329
373
 
330
374
  // If all the URLs are reachable then the app is considered 'up'
331
- return (scanResult === null || scanResult === void 0 ? void 0 : scanResult.length) && scanResult.filter(result => result.status).length === scanResult.length;
375
+ return scanResult.length && scanResult.filter(result => result.status).length === scanResult.length;
332
376
  }
333
377
  async function landoExec(lando, instancePath, toolName, args, options) {
334
378
  const app = await getLandoApplication(lando, instancePath);
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.getReadAndWriteStreams = getReadAndWriteStreams;
7
7
  exports.searchAndReplace = void 0;
8
8
  var _fs = _interopRequireDefault(require("fs"));
9
- var _os = _interopRequireDefault(require("os"));
10
9
  var _path = _interopRequireDefault(require("path"));
11
10
  var _chalk = _interopRequireDefault(require("chalk"));
12
11
  var _debug = _interopRequireDefault(require("debug"));
@@ -15,6 +14,7 @@ var _tracker = require("../lib/tracker");
15
14
  var _prompt = require("../lib/cli/prompt");
16
15
  var _clientFileUploader = require("../lib/client-file-uploader");
17
16
  var exit = _interopRequireWildcard(require("../lib/cli/exit"));
17
+ var _utils = require("./utils");
18
18
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
19
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
20
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -37,11 +37,6 @@ const flatten = arr => {
37
37
  return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
38
38
  }, []);
39
39
  };
40
- function makeTempDir() {
41
- const tmpDir = _fs.default.mkdtempSync(_path.default.join(_os.default.tmpdir(), 'vip-search-replace-'));
42
- debug(`Created a directory to hold temporary files: ${tmpDir}`);
43
- return tmpDir;
44
- }
45
40
  function getReadAndWriteStreams({
46
41
  fileName,
47
42
  inPlace,
@@ -51,7 +46,7 @@ function getReadAndWriteStreams({
51
46
  let usingStdOut = false;
52
47
  let outputFileName;
53
48
  if (inPlace) {
54
- const midputFileName = _path.default.join(makeTempDir(), _path.default.basename(fileName));
49
+ const midputFileName = _path.default.join((0, _utils.makeTempDir)('vip-search-replace'), _path.default.basename(fileName));
55
50
  _fs.default.copyFileSync(fileName, midputFileName);
56
51
  debug(`Copied input file to ${midputFileName}`);
57
52
  debug(`Set output to the original file path ${fileName}`);
@@ -81,7 +76,7 @@ function getReadAndWriteStreams({
81
76
  break;
82
77
  default:
83
78
  {
84
- const tmpOutFile = _path.default.join(makeTempDir(), _path.default.basename(fileName));
79
+ const tmpOutFile = _path.default.join((0, _utils.makeTempDir)('vip-search-replace'), _path.default.basename(fileName));
85
80
  writeStream = _fs.default.createWriteStream(tmpOutFile);
86
81
  outputFileName = tmpOutFile;
87
82
  debug(`Outputting to file: ${outputFileName}`);
package/dist/lib/utils.js CHANGED
@@ -3,7 +3,28 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.makeTempDir = makeTempDir;
6
7
  exports.pollUntil = pollUntil;
8
+ var _fs = _interopRequireDefault(require("fs"));
9
+ var _path = _interopRequireDefault(require("path"));
10
+ var _os = _interopRequireDefault(require("os"));
11
+ var _debug = _interopRequireDefault(require("debug"));
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+ /**
14
+ *
15
+ * @format
16
+ */
17
+
18
+ /**
19
+ * External dependencies
20
+ */
21
+
22
+ /**
23
+ * Internal dependencies
24
+ */
25
+
26
+ const debug = (0, _debug.default)('@automattic/vip:lib:utils');
27
+
7
28
  /**
8
29
  * Polls a function until its return value satisfies a condition
9
30
  *
@@ -25,4 +46,24 @@ async function pollUntil(fn, interval, isDone) {
25
46
  // eslint-disable-next-line no-await-in-loop
26
47
  await new Promise(res => setTimeout(res, interval));
27
48
  }
49
+ }
50
+
51
+ /**
52
+ * Create a temporary directory in the system's temp directory
53
+ *
54
+ * @param {string} prefix Prefix for the directory name
55
+ * @return {string} Path to the temporary directory
56
+ * @throws {Error} If the directory cannot be created
57
+ */
58
+ function makeTempDir(prefix = 'vip-cli') {
59
+ const tempDir = _fs.default.mkdtempSync(_path.default.join(_os.default.tmpdir(), `${prefix}-`));
60
+ debug(`Created a directory to hold temporary files: ${tempDir}`);
61
+ process.on('exit', () => {
62
+ _fs.default.rmSync(tempDir, {
63
+ recursive: true,
64
+ force: true
65
+ });
66
+ debug(`Removed temporary directory: ${tempDir}`);
67
+ });
68
+ return tempDir;
28
69
  }