@automattic/vip 2.24.1 → 2.25.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/CONTRIBUTING.md +38 -8
  3. package/README.md +6 -0
  4. package/assets/dev-env.lando.template.yml.ejs +3 -11
  5. package/dist/bin/vip-app-list.js +0 -1
  6. package/dist/bin/vip-app.js +0 -1
  7. package/dist/bin/vip-config.js +0 -2
  8. package/dist/bin/vip-dev-env-create.js +2 -1
  9. package/dist/bin/vip-dev-env-destroy.js +2 -1
  10. package/dist/bin/vip-dev-env-exec.js +25 -10
  11. package/dist/bin/vip-dev-env-import-media.js +2 -4
  12. package/dist/bin/vip-dev-env-import-sql.js +30 -8
  13. package/dist/bin/vip-dev-env-info.js +2 -1
  14. package/dist/bin/vip-dev-env-list.js +3 -1
  15. package/dist/bin/vip-dev-env-start.js +1 -0
  16. package/dist/bin/vip-dev-env-stop.js +2 -1
  17. package/dist/bin/vip-dev-env-update.js +5 -5
  18. package/dist/bin/vip-import-sql.js +11 -0
  19. package/dist/bin/vip-import-validate-files.js +0 -1
  20. package/dist/bin/vip-import-validate-sql.js +0 -2
  21. package/dist/bin/vip-logs.js +0 -1
  22. package/dist/bin/vip-sync.js +0 -1
  23. package/dist/bin/vip-validate-preflight.js +0 -1
  24. package/dist/bin/vip-wp.js +0 -1
  25. package/dist/bin/vip.js +0 -1
  26. package/dist/lib/analytics/clients/pendo.js +0 -1
  27. package/dist/lib/analytics/clients/tracks.js +0 -2
  28. package/dist/lib/api/app.js +0 -3
  29. package/dist/lib/api/feature-flags.js +0 -3
  30. package/dist/lib/cli/command.js +9 -3
  31. package/dist/lib/cli/envAlias.js +0 -1
  32. package/dist/lib/cli/exit.js +1 -1
  33. package/dist/lib/cli/format.js +0 -1
  34. package/dist/lib/cli/progress.js +0 -3
  35. package/dist/lib/cli/prompt.js +0 -4
  36. package/dist/lib/cli/repo.js +0 -2
  37. package/dist/lib/dev-environment/dev-environment-cli.js +36 -29
  38. package/dist/lib/dev-environment/dev-environment-core.js +39 -42
  39. package/dist/lib/dev-environment/dev-environment-lando.js +101 -70
  40. package/dist/lib/envvar/api-delete.js +0 -3
  41. package/dist/lib/envvar/api-get-all.js +0 -3
  42. package/dist/lib/envvar/api-get.js +0 -3
  43. package/dist/lib/envvar/api-list.js +0 -3
  44. package/dist/lib/envvar/api-set.js +0 -3
  45. package/dist/lib/keychain/browser.js +0 -2
  46. package/dist/lib/keychain/insecure.js +0 -1
  47. package/dist/lib/media-import/progress.js +0 -3
  48. package/dist/lib/token.js +0 -3
  49. package/dist/lib/vip-import-validate-files.js +0 -2
  50. package/npm-shrinkwrap.json +2638 -2894
  51. package/package.json +21 -14
  52. package/.prettierrc +0 -9
  53. package/jest.setupMocks.js +0 -7
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.bootstrapLando = bootstrapLando;
7
+ exports.isEnvUp = isEnvUp;
7
8
  exports.landoDestroy = landoDestroy;
8
9
  exports.landoExec = landoExec;
9
10
  exports.landoInfo = landoInfo;
@@ -20,9 +21,10 @@ var _utils = _interopRequireDefault(require("lando/plugins/lando-core/lib/utils"
20
21
  var _build = _interopRequireDefault(require("lando/plugins/lando-tooling/lib/build"));
21
22
  var _chalk = _interopRequireDefault(require("chalk"));
22
23
  var _app = _interopRequireDefault(require("lando/lib/app"));
23
- var _userError = _interopRequireDefault(require("../user-error"));
24
24
  var _dns = _interopRequireDefault(require("dns"));
25
25
  var _devEnvironmentCore = require("./dev-environment-core");
26
+ var _devEnvironment = require("../constants/dev-environment");
27
+ var _userError = _interopRequireDefault(require("../user-error"));
26
28
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
29
  /**
28
30
  *
@@ -58,8 +60,10 @@ function getLandoUserConfigurationRoot() {
58
60
  * @returns {object} Lando configuration
59
61
  */
60
62
  function getLandoConfig() {
61
- const landoPath = _path.default.join(__dirname, '..', '..', '..', 'node_modules', 'lando');
62
- debug(`Getting lando config, using path '${landoPath}' for plugins`);
63
+ const nodeModulesPath = _path.default.join(__dirname, '..', '..', '..', 'node_modules');
64
+ const landoPath = _path.default.join(nodeModulesPath, 'lando');
65
+ const atLandoPath = _path.default.join(nodeModulesPath, '@lando');
66
+ debug(`Getting lando config, using paths '${landoPath}' and '${atLandoPath}' for plugins`);
63
67
  const isLandoDebugSelected = (process.env.DEBUG || '').includes(DEBUG_KEY);
64
68
  const isAllDebugSelected = process.env.DEBUG === '*';
65
69
  const logLevelConsole = isAllDebugSelected || isLandoDebugSelected ? 'debug' : 'warn';
@@ -69,14 +73,39 @@ function getLandoConfig() {
69
73
  preLandoFiles: ['.lando.base.yml', '.lando.dist.yml', '.lando.upstream.yml'],
70
74
  postLandoFiles: ['.lando.local.yml'],
71
75
  pluginDirs: [landoPath, {
72
- path: _path.default.join(landoPath, 'integrations'),
73
- subdir: '.'
76
+ path: atLandoPath,
77
+ subdir: '.',
78
+ namespace: '@lando'
74
79
  }],
80
+ disablePlugins: [
81
+ // Plugins we need:
82
+ // '@lando/compose',
83
+ // '@lando/mailhog',
84
+ // '@lando/memcached',
85
+ // '@lando/phpmyadmin',
86
+ // The rest we don't need
87
+ '@lando/acquia', '@lando/apache', '@lando/argv', '@lando/backdrop', '@lando/dotnet', '@lando/drupal', '@lando/elasticsearch', '@lando/go', '@lando/joomla', '@lando/lagoon', '@lando/lamp', '@lando/laravel', '@lando/lemp', '@lando/mariadb', '@lando/mean', '@lando/mongo', '@lando/mssql', '@lando/mysql', '@lando/nginx', '@lando/node', '@lando/pantheon', '@lando/php', '@lando/platformsh', '@lando/postgres', '@lando/python', '@lando/redis', '@lando/ruby', '@lando/solr', '@lando/symfony', '@lando/tomcat', '@lando/varnish', '@lando/wordpress'],
75
88
  proxyName: 'vip-dev-env-proxy',
76
89
  userConfRoot: getLandoUserConfigurationRoot(),
77
90
  home: ''
78
91
  };
79
92
  }
93
+ const appMap = new Map();
94
+ async function getLandoApplication(lando, instancePath) {
95
+ if (appMap.has(instancePath)) {
96
+ return Promise.resolve(appMap.get(instancePath));
97
+ }
98
+ if (!(await (0, _devEnvironmentCore.doesEnvironmentExist)(instancePath))) {
99
+ throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
100
+ }
101
+ const app = lando.getApp(instancePath);
102
+ addHooks(app, lando);
103
+ appMap.set(instancePath, app);
104
+ if (!app.initialized) {
105
+ await app.init();
106
+ }
107
+ return app;
108
+ }
80
109
  async function bootstrapLando() {
81
110
  const lando = new _lando.default(getLandoConfig());
82
111
  await lando.bootstrap();
@@ -84,22 +113,18 @@ async function bootstrapLando() {
84
113
  }
85
114
  async function landoStart(lando, instancePath) {
86
115
  debug('Will start lando app on path:', instancePath);
87
- const app = lando.getApp(instancePath);
88
- await app.init();
89
- addHooks(app, lando);
116
+ const app = await getLandoApplication(lando, instancePath);
90
117
  await app.start();
91
118
  }
92
119
  async function landoRebuild(lando, instancePath) {
93
120
  debug('Will rebuild lando app on path:', instancePath);
94
- const app = lando.getApp(instancePath);
95
- await app.init();
121
+ const app = await getLandoApplication(lando, instancePath);
96
122
  await ensureNoOrphantProxyContainer(lando);
97
- addHooks(app, lando);
98
123
  await app.rebuild();
99
124
  }
100
125
  function addHooks(app, lando) {
101
126
  app.events.on('post-start', 1, () => healthcheckHook(app, lando));
102
- lando.events.on('pre-engine-build', 5, async data => {
127
+ lando.events.once('pre-engine-build', async data => {
103
128
  const instanceData = (0, _devEnvironmentCore.readEnvironmentData)(app._name);
104
129
  let registryResolvable = false;
105
130
  try {
@@ -122,42 +147,46 @@ function addHooks(app, lando) {
122
147
  }
123
148
  const healthChecks = {
124
149
  database: 'mysql -uroot --silent --execute "SHOW DATABASES;"',
125
- 'vip-search': "curl -s --noproxy '*' -XGET localhost:9200",
150
+ elasticsearch: "curl -s --noproxy '*' -XGET localhost:9200",
126
151
  php: '[[ -f /wp/wp-includes/pomo/mo.php ]]'
127
152
  };
128
153
  async function healthcheckHook(app, lando) {
154
+ const now = new Date();
129
155
  try {
130
156
  await lando.Promise.retry(async () => {
131
157
  const list = await lando.engine.list({
132
158
  project: app.project
133
159
  });
134
160
  const notHealthyContainers = [];
161
+ const checkPromises = [];
162
+ const containerOrder = [];
135
163
  for (const container of list) {
136
164
  if (healthChecks[container.service]) {
137
- try {
138
- debug(`Testing ${container.service}: ${healthChecks[container.service]}`);
139
- await app.engine.run({
140
- id: container.id,
141
- cmd: healthChecks[container.service],
142
- compose: app.compose,
143
- project: app.project,
144
- opts: {
145
- silent: true,
146
- noTTY: true,
147
- cstdio: 'pipe',
148
- services: [container.service]
149
- }
150
- });
151
- } catch (exception) {
152
- debug(`${container.service} Health check failed`);
153
- notHealthyContainers.push(container);
154
- }
165
+ debug(`Testing ${container.service}: ${healthChecks[container.service]}`);
166
+ containerOrder.push(container);
167
+ checkPromises.push(app.engine.run({
168
+ id: container.id,
169
+ cmd: healthChecks[container.service],
170
+ compose: app.compose,
171
+ project: app.project,
172
+ opts: {
173
+ silent: true,
174
+ noTTY: true,
175
+ cstdio: 'pipe',
176
+ services: [container.service]
177
+ }
178
+ }));
155
179
  }
156
180
  }
157
- if (notHealthyContainers.length) {
158
- for (const container of notHealthyContainers) {
159
- console.log(`Waiting for service ${container.service} ...`);
181
+ const results = await Promise.allSettled(checkPromises);
182
+ results.forEach((result, index) => {
183
+ if (result.status === 'rejected') {
184
+ debug(`${containerOrder[index].service} Health check failed`);
185
+ notHealthyContainers.push(containerOrder[index]);
160
186
  }
187
+ });
188
+ if (notHealthyContainers.length) {
189
+ notHealthyContainers.forEach(container => console.log(`Waiting for service ${container.service} ...`));
161
190
  return Promise.reject(notHealthyContainers);
162
191
  }
163
192
  }, {
@@ -165,31 +194,28 @@ async function healthcheckHook(app, lando) {
165
194
  backoff: 1000
166
195
  });
167
196
  } catch (containersWithFailingHealthCheck) {
168
- for (const container of containersWithFailingHealthCheck) {
169
- console.log(_chalk.default.yellow('WARNING:') + ` Service ${container.service} failed healthcheck`);
170
- }
197
+ containersWithFailingHealthCheck.forEach(container => console.log(_chalk.default.yellow('WARNING:') + ` Service ${container.service} failed healthcheck`));
171
198
  }
199
+ const duration = new Date().getTime() - now.getTime();
200
+ debug(`Healthcheck completed in ${duration}ms`);
172
201
  }
173
202
  async function landoStop(lando, instancePath) {
174
203
  debug('Will stop lando app on path:', instancePath);
175
- const app = lando.getApp(instancePath);
176
- await app.init();
204
+ const app = await getLandoApplication(lando, instancePath);
177
205
  await app.stop();
178
206
  }
179
207
  async function landoDestroy(lando, instancePath) {
180
208
  debug('Will destroy lando app on path:', instancePath);
181
- const app = lando.getApp(instancePath);
182
- await app.init();
209
+ const app = await getLandoApplication(lando, instancePath);
183
210
  await app.destroy();
184
211
  }
185
212
  async function landoInfo(lando, instancePath) {
186
213
  var _app$info$find;
187
- const app = lando.getApp(instancePath);
188
- await app.init();
214
+ const app = await getLandoApplication(lando, instancePath);
189
215
  let appInfo = _utils.default.startTable(app);
190
216
  const reachableServices = app.info.filter(service => service.urls.length);
191
217
  reachableServices.forEach(service => appInfo[`${service.service} urls`] = service.urls);
192
- const isUp = await isEnvUp(app);
218
+ const isUp = await isEnvUp(lando, instancePath);
193
219
  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];
194
220
  const extraService = await getExtraServicesConnections(lando, app);
195
221
  appInfo = {
@@ -213,7 +239,7 @@ async function landoInfo(lando, instancePath) {
213
239
  return appInfo;
214
240
  }
215
241
  const extraServiceDisplayConfiguration = [{
216
- name: 'vip-search',
242
+ name: 'elasticsearch',
217
243
  label: 'enterprise search',
218
244
  protocol: 'http'
219
245
  }, {
@@ -248,43 +274,48 @@ async function getExtraServicesConnections(lando, app) {
248
274
  }
249
275
  return extraServices;
250
276
  }
251
- async function isEnvUp(app) {
277
+ async function isEnvUp(lando, instancePath) {
278
+ const now = new Date();
279
+ const app = await getLandoApplication(lando, instancePath);
252
280
  const reachableServices = app.info.filter(service => service.urls.length);
253
281
  const urls = reachableServices.map(service => service.urls).flat();
254
282
  const scanResult = await app.scanUrls(urls, {
255
283
  max: 1
256
284
  });
285
+ const duration = new Date().getTime() - now.getTime();
286
+ debug('isEnvUp took %d ms', duration);
287
+
257
288
  // If all the URLs are reachable then the app is considered 'up'
258
289
  return (scanResult === null || scanResult === void 0 ? void 0 : scanResult.length) && scanResult.filter(result => result.status).length === scanResult.length;
259
290
  }
260
291
  async function landoExec(lando, instancePath, toolName, args, options) {
261
- const app = lando.getApp(instancePath);
262
- await app.init();
263
- if (!options.force) {
264
- const isUp = await isEnvUp(app);
265
- if (!isUp) {
266
- throw new _userError.default('Environment needs to be started before running wp command');
267
- }
268
- }
292
+ const app = await getLandoApplication(lando, instancePath);
269
293
  const tool = app.config.tooling[toolName];
270
294
  if (!tool) {
271
- throw new Error(`${toolName} is not a known lando task`);
295
+ throw new _userError.default(`${toolName} is not a known lando task`);
296
+ }
297
+ const savedArgv = process.argv;
298
+ try {
299
+ /*
300
+ lando is looking in both passed args and process.argv so we need to do a bit of hack to fake process.argv
301
+ so that lando doesn't try to interpret args not meant for wp.
302
+ Lando drops first 3 args (<node> <lando> <command>) from process.argv and process rest, so we will fake 3 args + the real args
303
+ */
304
+ process.argv = ['0', '1', '3'].concat(args);
305
+ tool.app = app;
306
+ tool.name = toolName;
307
+ if (options.stdio) {
308
+ tool.stdio = options.stdio;
309
+ }
310
+ const task = (0, _build.default)(tool, lando);
311
+ const argv = {
312
+ // eslint-disable-next-line id-length
313
+ _: args
314
+ };
315
+ await task.run(argv);
316
+ } finally {
317
+ process.argv = savedArgv;
272
318
  }
273
-
274
- /*
275
- lando is looking in both passed args and process.argv so we need to do a bit of hack to fake process.argv
276
- so that lando doesn't try to interpret args not meant for wp.
277
- Lando drops first 3 args (<node> <lando> <command>) from process.argv and process rest, so we will fake 3 args + the real args
278
- */
279
- process.argv = ['0', '1', '3'].concat(args);
280
- tool.app = app;
281
- tool.name = toolName;
282
- const task = (0, _build.default)(tool, lando);
283
- const argv = {
284
- _: args // eslint-disable-line
285
- };
286
-
287
- await task.run(argv);
288
319
  }
289
320
 
290
321
  /**
@@ -7,15 +7,12 @@ exports.default = deleteEnvVar;
7
7
  var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
8
8
  var _api = _interopRequireDefault(require("../api"));
9
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
-
11
10
  /**
12
11
  * External dependencies
13
12
  */
14
-
15
13
  /**
16
14
  * Internal dependencies
17
15
  */
18
-
19
16
  const mutation = (0, _graphqlTag.default)`
20
17
  mutation DeleteEnvironmentVariable(
21
18
  $appId: Int!
@@ -7,15 +7,12 @@ exports.default = getEnvVars;
7
7
  var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
8
8
  var _api = _interopRequireDefault(require("../api"));
9
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
-
11
10
  /**
12
11
  * External dependencies
13
12
  */
14
-
15
13
  /**
16
14
  * Internal dependencies
17
15
  */
18
-
19
16
  const query = (0, _graphqlTag.default)`
20
17
  query GetEnvironmentVariablesWithValues(
21
18
  $appId: Int!
@@ -6,15 +6,12 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = getEnvVar;
7
7
  var _apiGetAll = _interopRequireDefault(require("./api-get-all"));
8
8
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
-
10
9
  /**
11
10
  * External dependencies
12
11
  */
13
-
14
12
  /**
15
13
  * Internal dependencies
16
14
  */
17
-
18
15
  async function getEnvVar(appId, envId, name) {
19
16
  const envvars = await (0, _apiGetAll.default)(appId, envId);
20
17
  return envvars.find(({
@@ -7,15 +7,12 @@ exports.default = listEnvVars;
7
7
  var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
8
8
  var _api = _interopRequireDefault(require("../api"));
9
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
-
11
10
  /**
12
11
  * External dependencies
13
12
  */
14
-
15
13
  /**
16
14
  * Internal dependencies
17
15
  */
18
-
19
16
  const query = (0, _graphqlTag.default)`
20
17
  query GetEnvironmentVariables(
21
18
  $appId: Int!
@@ -7,15 +7,12 @@ exports.default = setEnvVar;
7
7
  var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
8
8
  var _api = _interopRequireDefault(require("../api"));
9
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
-
11
10
  /**
12
11
  * External dependencies
13
12
  */
14
-
15
13
  /**
16
14
  * Internal dependencies
17
15
  */
18
-
19
16
  const mutation = (0, _graphqlTag.default)`
20
17
  mutation AddEnvironmentVariable(
21
18
  $appId: Int!
@@ -4,11 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  /**
9
8
  * Internal dependencies
10
9
  */
11
-
12
10
  class Secure {
13
11
  getPassword(service) {
14
12
  return new Promise(resolve => {
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  /**
9
8
  * External dependencies
10
9
  */
@@ -8,15 +8,12 @@ var _singleLineLog = require("single-line-log");
8
8
  var _status = require("./status");
9
9
  var _format = require("../cli/format");
10
10
  /** @format */
11
-
12
11
  /**
13
12
  * External dependencies
14
13
  */
15
-
16
14
  /**
17
15
  * Internal dependencies
18
16
  */
19
-
20
17
  const PRINT_INTERVAL = process.env.DEBUG ? 5000 : 200; // How often the report is printed. Mainly affects the "spinner" animation.
21
18
 
22
19
  class MediaImportProgressTracker {
package/dist/lib/token.js CHANGED
@@ -9,15 +9,12 @@ var _uuid2 = require("uuid");
9
9
  var _keychain = _interopRequireDefault(require("./keychain"));
10
10
  var _api = require("./api");
11
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
-
13
12
  /**
14
13
  * External dependencies
15
14
  */
16
-
17
15
  /**
18
16
  * Internal dependencies
19
17
  */
20
-
21
18
  // Config
22
19
  const SERVICE = 'vip-go-cli';
23
20
  exports.SERVICE = SERVICE;
@@ -8,11 +8,9 @@ var _chalk = _interopRequireDefault(require("chalk"));
8
8
  var _fs = _interopRequireDefault(require("fs"));
9
9
  var _path = _interopRequireDefault(require("path"));
10
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
12
11
  /**
13
12
  * External dependencies
14
13
  */
15
-
16
14
  // Accepted media file extensions
17
15
  const acceptedExtensions = ['jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'svg', 'tiff', 'tif', 'ico', 'asf', 'asx', 'wmv', 'wmx', 'wm', 'avi', 'divx', 'mov', 'qt', 'mpeg', 'mpg', 'mpe', 'mp4', 'm4v', 'ogv', 'webm', 'mkv', '3gp', '3gpp', '3g2', '3gp2', 'txt', 'asc', 'c', 'cc', 'h', 'srt', 'csv', 'tsv', 'ics', 'rtx', 'css', 'vtt', 'dfxp', 'mp3', 'm4a', 'm4b', 'ra', 'ram', 'wav', 'ogg', 'oga', 'mid', 'midi', 'wma', 'wax', 'mka', 'rtf', 'js', 'pdf', 'class', 'psd', 'xcf', 'doc', 'pot', 'pps', 'ppt', 'wri', 'xla', 'xls', 'xlt', 'xlw', 'mdb', 'mpp', 'docx', 'docm', 'dotx', 'dotm', 'xlsx', 'xlsm', 'xlsb', 'xltx', 'xltm', 'xlam', 'pptx', 'pptm', 'ppsx', 'ppsm', 'potx', 'potm', 'ppam', 'sldx', 'sldm', 'onetoc', ' onetoc2', 'onetmp', 'onepkg', 'oxps', 'xps', 'odt', 'odp', 'ods', 'odg', 'odc', 'odb', 'odf', 'webp', 'wp', 'wpd', 'key', 'numbers', 'pages'];
18
16