@automattic/vip 2.16.0 → 2.18.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,17 +3,43 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.appQueryFragments = exports.appQuery = void 0;
6
+ exports.getUpdateResult = exports.triggerUpdate = exports.promptForUpdate = exports.appQueryFragments = exports.appQuery = void 0;
7
+
8
+ var _enquirer = require("enquirer");
9
+
10
+ var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
11
+
12
+ var _debug = _interopRequireDefault(require("debug"));
13
+
14
+ var _app = require("../app");
15
+
16
+ var _api = _interopRequireDefault(require("../api"));
17
+
18
+ var _userError = _interopRequireDefault(require("../user-error"));
19
+
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+
22
+ /**
23
+ * External dependencies
24
+ */
25
+
26
+ /**
27
+ * Internal dependencies
28
+ */
29
+ const UPDATE_PROGRESS_POLL_INTERVAL = 5;
30
+ const debug = (0, _debug.default)('@automattic/vip:bin:config-software');
7
31
  const appQuery = `
8
32
  id,
9
33
  name,
10
34
  type,
35
+ typeId,
11
36
  organization { id, name },
12
37
  environments{
13
38
  appId
14
39
  id
15
40
  name
16
41
  type
42
+ uniqueLabel
17
43
  softwareSettings {
18
44
  php {
19
45
  ...Software
@@ -54,4 +80,266 @@ const appQueryFragments = `fragment Software on AppEnvironmentSoftwareSettingsSo
54
80
  }
55
81
  }
56
82
  `;
57
- exports.appQueryFragments = appQueryFragments;
83
+ exports.appQueryFragments = appQueryFragments;
84
+ const updateSoftwareMutation = (0, _graphqlTag.default)`
85
+ mutation UpdateSoftwareSettings(
86
+ $appId: Int!
87
+ $envId: Int!
88
+ $component: String!
89
+ $version: String!
90
+ ) {
91
+ updateSoftwareSettings(
92
+ input: {
93
+ appId: $appId
94
+ environmentId: $envId
95
+ softwareName: $component
96
+ softwareVersion: $version
97
+ }
98
+ ) {
99
+ php {
100
+ ...Software
101
+ }
102
+ wordpress {
103
+ ...Software
104
+ }
105
+ muplugins {
106
+ ...Software
107
+ }
108
+ nodejs {
109
+ ...Software
110
+ }
111
+ }
112
+ }
113
+ ${appQueryFragments}
114
+ `;
115
+ const updateJobQuery = (0, _graphqlTag.default)`
116
+ query UpdateJob($appId: Int!, $envId: Int!) {
117
+ app(id: $appId ) {
118
+ environments(id: $envId) {
119
+ jobs (types:["upgrade_php", "upgrade_wordpress", "upgrade_muplugins", "upgrade_nodejs"]) {
120
+ type
121
+ completedAt
122
+ createdAt
123
+ inProgressLock
124
+ progress {
125
+ status
126
+ steps {
127
+ step
128
+ name
129
+ status
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }`;
136
+ const COMPONENT_NAMES = {
137
+ wordpress: 'WordPress',
138
+ php: 'PHP',
139
+ muplugins: 'MU Plugins',
140
+ nodejs: 'Node.js'
141
+ };
142
+ const MANAGED_OPTION_KEY = 'managed_latest';
143
+
144
+ const _optionsForVersion = softwareSettings => {
145
+ const {
146
+ options,
147
+ current,
148
+ pinned,
149
+ slug
150
+ } = softwareSettings;
151
+ const versionChoices = {
152
+ managed: [],
153
+ supported: [],
154
+ test: [],
155
+ deprecated: []
156
+ };
157
+
158
+ for (const option of options) {
159
+ if (option.deprecated) {
160
+ versionChoices.deprecated.push({
161
+ message: `${option.version} (deprecated)`,
162
+ value: option.version
163
+ });
164
+ } else if (option.unstable) {
165
+ versionChoices.test.push({
166
+ message: `${option.version} (test)`,
167
+ value: option.version
168
+ });
169
+ } else {
170
+ versionChoices.supported.push({
171
+ message: option.version,
172
+ value: option.version
173
+ });
174
+ }
175
+ }
176
+
177
+ if (slug === 'wordpress') {
178
+ versionChoices.managed.push({
179
+ message: 'Managed updates',
180
+ value: MANAGED_OPTION_KEY
181
+ });
182
+ }
183
+
184
+ const allOptions = [...versionChoices.managed, ...versionChoices.supported, ...versionChoices.test, ...versionChoices.deprecated];
185
+ return allOptions.map(option => {
186
+ const isActivePinned = option.value === MANAGED_OPTION_KEY && !pinned;
187
+ const isActiveVersion = option.value === current.version && pinned;
188
+
189
+ if (isActivePinned || isActiveVersion) {
190
+ return {
191
+ message: `Active: ${option.message}`,
192
+ value: option.value,
193
+ disabled: true
194
+ };
195
+ }
196
+
197
+ return option;
198
+ });
199
+ };
200
+
201
+ const _processComponent = async (appTypeId, userProvidedComponent) => {
202
+ const validComponents = [];
203
+
204
+ if ((0, _app.isAppWordPress)(appTypeId)) {
205
+ validComponents.push('wordpress', 'php', 'muplugins');
206
+ } else if ((0, _app.isAppNodejs)(appTypeId)) {
207
+ validComponents.push('nodejs');
208
+ }
209
+
210
+ if (userProvidedComponent) {
211
+ if (!validComponents.includes(userProvidedComponent)) {
212
+ throw new _userError.default(`Component ${userProvidedComponent} is not supported. Use one of: ${validComponents.join(',')}`);
213
+ }
214
+
215
+ return userProvidedComponent;
216
+ }
217
+
218
+ if (validComponents.length === 0) {
219
+ throw new _userError.default('No components are supported for this application');
220
+ }
221
+
222
+ if (validComponents.length === 1) {
223
+ return validComponents[0];
224
+ }
225
+
226
+ const choices = validComponents.map(item => ({
227
+ message: COMPONENT_NAMES[item],
228
+ value: item
229
+ }));
230
+ const select = new _enquirer.Select({
231
+ message: 'Component to update',
232
+ choices
233
+ });
234
+ return await select.run();
235
+ };
236
+
237
+ const _processComponentVersion = async (softwareSettings, component, userProvidedVersion) => {
238
+ const versionChoices = _optionsForVersion(softwareSettings[component]);
239
+
240
+ if (userProvidedVersion) {
241
+ const validValues = versionChoices.map(item => item.value);
242
+
243
+ if (!validValues.includes(userProvidedVersion)) {
244
+ throw new _userError.default(`Version ${userProvidedVersion} is not supported for ${COMPONENT_NAMES[component]}. Use one of: ${validValues.join(',')}`);
245
+ }
246
+
247
+ return userProvidedVersion;
248
+ }
249
+
250
+ const versionSelect = new _enquirer.Select({
251
+ message: `Version for ${COMPONENT_NAMES[component]} to upgrade to`,
252
+ choices: versionChoices
253
+ });
254
+ return await versionSelect.run();
255
+ };
256
+
257
+ const promptForUpdate = async (appTypeId, opts, softwareSettings) => {
258
+ const component = await _processComponent(appTypeId, opts.component);
259
+ const version = await _processComponentVersion(softwareSettings, component, opts.version);
260
+ const confirm = opts.force || (await new _enquirer.Confirm({
261
+ message: `Are you sure you want to upgrade ${COMPONENT_NAMES[component]} to ${version}?`
262
+ }).run());
263
+
264
+ if (confirm) {
265
+ return {
266
+ component,
267
+ version
268
+ };
269
+ }
270
+
271
+ throw new _userError.default('Update canceled');
272
+ };
273
+
274
+ exports.promptForUpdate = promptForUpdate;
275
+
276
+ const triggerUpdate = async variables => {
277
+ debug('Triggering update', variables);
278
+ const api = await (0, _api.default)();
279
+ return await api.mutate({
280
+ mutation: updateSoftwareMutation,
281
+ variables
282
+ });
283
+ };
284
+
285
+ exports.triggerUpdate = triggerUpdate;
286
+
287
+ const _getLatestJob = async (appId, envId) => {
288
+ var _result$data, _result$data$app;
289
+
290
+ const api = await (0, _api.default)();
291
+ const result = await api.query({
292
+ query: updateJobQuery,
293
+ variables: {
294
+ appId,
295
+ envId
296
+ },
297
+ fetchPolicy: 'network-only'
298
+ });
299
+ const jobs = (result === null || result === void 0 ? void 0 : (_result$data = result.data) === null || _result$data === void 0 ? void 0 : (_result$data$app = _result$data.app) === null || _result$data$app === void 0 ? void 0 : _result$data$app.environments[0].jobs) || [];
300
+
301
+ if (jobs.length) {
302
+ return jobs.reduce((prev, current) => prev.createdAt > current.createdAt ? prev : current);
303
+ }
304
+
305
+ return null;
306
+ };
307
+
308
+ const _getCompletedJob = async (appId, envId) => {
309
+ const latestJob = await _getLatestJob(appId, envId);
310
+ debug('Latest job result:', latestJob);
311
+
312
+ if (!latestJob || !latestJob.inProgressLock) {
313
+ return latestJob;
314
+ }
315
+
316
+ debug(`Sleep for ${UPDATE_PROGRESS_POLL_INTERVAL} seconds`);
317
+ await new Promise(resolve => setTimeout(resolve, UPDATE_PROGRESS_POLL_INTERVAL * 1000));
318
+ return _getCompletedJob(appId, envId);
319
+ };
320
+
321
+ const getUpdateResult = async (appId, envId) => {
322
+ var _completedJob$progres, _completedJob$progres2, _completedJob$progres3;
323
+
324
+ debug('Getting update result', {
325
+ appId,
326
+ envId
327
+ });
328
+ const completedJob = await _getCompletedJob(appId, envId);
329
+ const success = !completedJob || (completedJob === null || completedJob === void 0 ? void 0 : (_completedJob$progres = completedJob.progress) === null || _completedJob$progres === void 0 ? void 0 : _completedJob$progres.status) === 'success';
330
+
331
+ if (success) {
332
+ return {
333
+ ok: true
334
+ };
335
+ }
336
+
337
+ const failedStep = completedJob === null || completedJob === void 0 ? void 0 : (_completedJob$progres2 = completedJob.progress) === null || _completedJob$progres2 === void 0 ? void 0 : (_completedJob$progres3 = _completedJob$progres2.steps) === null || _completedJob$progres3 === void 0 ? void 0 : _completedJob$progres3.find(step => step.status === 'failed');
338
+ const error = failedStep ? `Failed during step: ${failedStep.name}` : 'Software update failed';
339
+ return {
340
+ ok: false,
341
+ errorMessage: error
342
+ };
343
+ };
344
+
345
+ exports.getUpdateResult = getUpdateResult;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.NODEJS_SITE_TYPE_IDS = exports.NODEJS_MYSQL_REDIS_APPLICATION_TYPE_ID = exports.NODEJS_REDIS_APPLICATION_TYPE_ID = exports.NODEJS_MYSQL_APPLICATION_TYPE_ID = exports.NODEJS_APPLICATION_TYPE_ID = exports.WORDPRESS_SITE_TYPE_IDS = exports.WORDPRESS_NON_PROD_APPLICATION_TYPE_ID = exports.WORDPRESS_APPLICATION_TYPE_ID = void 0;
7
+ const WORDPRESS_APPLICATION_TYPE_ID = 2;
8
+ exports.WORDPRESS_APPLICATION_TYPE_ID = WORDPRESS_APPLICATION_TYPE_ID;
9
+ const WORDPRESS_NON_PROD_APPLICATION_TYPE_ID = 6;
10
+ exports.WORDPRESS_NON_PROD_APPLICATION_TYPE_ID = WORDPRESS_NON_PROD_APPLICATION_TYPE_ID;
11
+ const WORDPRESS_SITE_TYPE_IDS = [WORDPRESS_APPLICATION_TYPE_ID, WORDPRESS_NON_PROD_APPLICATION_TYPE_ID];
12
+ exports.WORDPRESS_SITE_TYPE_IDS = WORDPRESS_SITE_TYPE_IDS;
13
+ const NODEJS_APPLICATION_TYPE_ID = 3;
14
+ exports.NODEJS_APPLICATION_TYPE_ID = NODEJS_APPLICATION_TYPE_ID;
15
+ const NODEJS_MYSQL_APPLICATION_TYPE_ID = 5;
16
+ exports.NODEJS_MYSQL_APPLICATION_TYPE_ID = NODEJS_MYSQL_APPLICATION_TYPE_ID;
17
+ const NODEJS_REDIS_APPLICATION_TYPE_ID = 7;
18
+ exports.NODEJS_REDIS_APPLICATION_TYPE_ID = NODEJS_REDIS_APPLICATION_TYPE_ID;
19
+ const NODEJS_MYSQL_REDIS_APPLICATION_TYPE_ID = 8;
20
+ exports.NODEJS_MYSQL_REDIS_APPLICATION_TYPE_ID = NODEJS_MYSQL_REDIS_APPLICATION_TYPE_ID;
21
+ const NODEJS_SITE_TYPE_IDS = [NODEJS_APPLICATION_TYPE_ID, NODEJS_MYSQL_APPLICATION_TYPE_ID, NODEJS_REDIS_APPLICATION_TYPE_ID, NODEJS_MYSQL_REDIS_APPLICATION_TYPE_ID];
22
+ exports.NODEJS_SITE_TYPE_IDS = NODEJS_SITE_TYPE_IDS;
@@ -45,7 +45,7 @@ var _devEnvironmentCore = require("./dev-environment-core");
45
45
 
46
46
  var _devEnvironmentLando = require("./dev-environment-lando");
47
47
 
48
- var _userError = _interopRequireDefault(require("../cli/userError"));
48
+ var _userError = _interopRequireDefault(require("../user-error"));
49
49
 
50
50
  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); }
51
51
 
@@ -421,21 +421,26 @@ const componentDisplayNames = {
421
421
  muPlugins: 'vip-go-mu-plugins',
422
422
  appCode: 'application code'
423
423
  };
424
+ const componentDemoyNames = {
425
+ muPlugins: 'vip-go-mu-plugins',
426
+ appCode: 'vip-go-skeleton'
427
+ };
424
428
 
425
429
  async function promptForComponent(component, allowLocal, defaultObject) {
426
430
  debug(`Prompting for ${component} with default:`, defaultObject);
427
431
  const componentDisplayName = componentDisplayNames[component] || component;
432
+ const componentDemoName = componentDemoyNames[component] || component;
428
433
  const modChoices = [];
429
434
 
430
435
  if (allowLocal) {
431
436
  modChoices.push({
432
- message: `local folder - where you already have ${componentDisplayName} code`,
437
+ message: `Custom - Path to a locally cloned ${componentDisplayName} directory`,
433
438
  value: 'local'
434
439
  });
435
440
  }
436
441
 
437
442
  modChoices.push({
438
- message: 'demo image - that gets automatically fetched',
443
+ message: `Demo - Automatically fetched ${componentDemoName}`,
439
444
  value: 'image'
440
445
  });
441
446
  let initialMode = 'image';
@@ -100,7 +100,9 @@ async function startEnvironment(slug, options) {
100
100
  await (0, _devEnvironmentLando.landoRebuild)(instancePath);
101
101
  }
102
102
 
103
- await printEnvironmentInfo(slug);
103
+ await printEnvironmentInfo(slug, {
104
+ extended: false
105
+ });
104
106
  }
105
107
 
106
108
  async function stopEnvironment(slug) {
@@ -191,18 +193,26 @@ async function destroyEnvironment(slug, removeFiles) {
191
193
  }
192
194
  }
193
195
 
194
- async function printAllEnvironmentsInfo() {
196
+ async function printAllEnvironmentsInfo(options) {
195
197
  const allEnvNames = getAllEnvironmentNames();
196
198
  debug('Will print info for all environments. Names found: ', allEnvNames);
197
199
  console.log('Found ' + _chalk.default.bold(allEnvNames.length) + ' environments' + (allEnvNames.length ? ':' : '.'));
198
200
 
199
201
  for (const envName of allEnvNames) {
200
202
  console.log('\n');
201
- await printEnvironmentInfo(envName);
203
+ await printEnvironmentInfo(envName, options);
202
204
  }
203
205
  }
204
206
 
205
- async function printEnvironmentInfo(slug) {
207
+ function parseComponentForInfo(component) {
208
+ if (component.mode === 'local') {
209
+ return component.dir || '';
210
+ }
211
+
212
+ return component.tag || '[demo-image]';
213
+ }
214
+
215
+ async function printEnvironmentInfo(slug, options) {
206
216
  debug('Will get info for an environment', slug);
207
217
  const instancePath = getEnvironmentPath(slug);
208
218
  debug('Instance path for', slug, 'is:', instancePath);
@@ -214,6 +224,21 @@ async function printEnvironmentInfo(slug) {
214
224
  }
215
225
 
216
226
  const appInfo = await (0, _devEnvironmentLando.landoInfo)(instancePath);
227
+
228
+ if (options.extended) {
229
+ const environmentData = readEnvironmentData(slug);
230
+ appInfo.title = environmentData.wpTitle;
231
+ appInfo.multisite = !!environmentData.multisite;
232
+ appInfo.php = environmentData.php.split(':')[1];
233
+ appInfo.wordpress = parseComponentForInfo(environmentData.wordpress);
234
+ appInfo['Mu plugins'] = parseComponentForInfo(environmentData.muPlugins);
235
+ appInfo['App Code'] = parseComponentForInfo(environmentData.appCode);
236
+
237
+ if (environmentData.mediaRedirectDomain) {
238
+ appInfo['Media Redirect'] = environmentData.mediaRedirectDomain;
239
+ }
240
+ }
241
+
217
242
  (0, _devEnvironmentCli.printTable)(appInfo);
218
243
  }
219
244
 
@@ -4,8 +4,6 @@ var _socksProxyAgent = require("socks-proxy-agent");
4
4
 
5
5
  var _httpsProxyAgent = require("https-proxy-agent");
6
6
 
7
- var _httpProxyAgent = require("http-proxy-agent");
8
-
9
7
  var _proxyFromEnv = require("proxy-from-env");
10
8
 
11
9
  var _debug = _interopRequireDefault(require("debug"));
@@ -27,15 +25,13 @@ const debug = (0, _debug.default)('vip:proxy-agent');
27
25
  // 2. No applicable variables are set: null is returned (thus, no proxy agent is returned)
28
26
  // 3. VIP_USE_SYSTEM_PROXY and SOCKS_PROXY are set: a SOCKS_PROXY is returned
29
27
  // 4. VIP_USE_SYSTEM_PROXY and HTTPS_PROXY are set: an HTTPS_PROXY is returned
30
- // 5. VIP_USE_SYSTEM_PROXY and HTTP_PROXY are set: an HTTP_PROXY is returned
31
- // 6. NO_PROXY is set along with VIP_USE_SYSTEM_PROXY and any system proxy: null is returned if the no proxy applies, otherwise the first active proxy is used
28
+ // 5. NO_PROXY is set along with VIP_USE_SYSTEM_PROXY and any system proxy: null is returned if the no proxy applies, otherwise the first active proxy is used
32
29
  // This allows near full customization by the client of what proxy should be used, instead of making assumptions based on the URL string
33
30
 
34
31
  function createProxyAgent(url) {
35
32
  const VIP_PROXY = process.env.VIP_PROXY || process.env.vip_proxy || null;
36
33
  const SOCKS_PROXY = process.env.SOCKS_PROXY || process.env.socks_proxy || null;
37
34
  const HTTPS_PROXY = process.env.HTTPS_PROXY || process.env.https_proxy || null;
38
- const HTTP_PROXY = process.env.HTTP_PROXY || process.env.http_proxy || null;
39
35
  const NO_PROXY = process.env.NO_PROXY || process.env.no_proxy || null; // VIP Socks Proxy should take precedence and should be fully backward compatible
40
36
 
41
37
  if (VIP_PROXY) {
@@ -54,11 +50,6 @@ function createProxyAgent(url) {
54
50
  debug(`Enabling HTTPS proxy support using config: ${HTTPS_PROXY}`);
55
51
  return new _httpsProxyAgent.HttpsProxyAgent(HTTPS_PROXY);
56
52
  }
57
-
58
- if (HTTP_PROXY) {
59
- debug(`Enabling HTTP proxy support using config: ${HTTP_PROXY}`);
60
- return new _httpProxyAgent.HttpProxyAgent(HTTP_PROXY);
61
- }
62
53
  } // If no environment variables are set, the no proxy is in effect, or if the proxy enable is not set return null (equivilant of no Proxy agent)
63
54
 
64
55
 
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _token = _interopRequireDefault(require("./token"));
9
+
10
+ var _tracker = require("./tracker");
11
+
12
+ var _http = _interopRequireDefault(require("./api/http"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ var _default = async () => {
20
+ await (0, _http.default)('/logout', {
21
+ method: 'post'
22
+ });
23
+ await _token.default.purge();
24
+ await (0, _tracker.trackEvent)('logout_command_execute');
25
+ };
26
+
27
+ exports.default = _default;
File without changes