@automattic/vip 2.6.0 → 2.7.1
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.
- package/README.md +7 -0
- package/dist/bin/vip-logs.js +151 -0
- package/dist/bin/vip.js +1 -1
- package/dist/lib/app-logs/app-logs.js +62 -0
- package/dist/lib/site-import/status.js +16 -9
- package/npm-shrinkwrap.json +14441 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -27,6 +27,13 @@ By default, we record information about the usage of this tool using an in-house
|
|
|
27
27
|
|
|
28
28
|
## Changelog
|
|
29
29
|
|
|
30
|
+
### 2.7.0 (07 December 2021)
|
|
31
|
+
- #941 [dev-env] Bump lando CLI dependency
|
|
32
|
+
- #938 Hide roll back message after SQL Import failure for launched sites
|
|
33
|
+
- #936 Sets jest maxWorkers to 4
|
|
34
|
+
|
|
35
|
+
https://github.com/Automattic/vip/releases/tag/v2.7.0
|
|
36
|
+
|
|
30
37
|
### 2.6.0 (23 November 2021)
|
|
31
38
|
- #921 [dev-env] Introuces update to change existing environment
|
|
32
39
|
- #928 [dev-env] Switch lando to use our fork
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Internal dependencies
|
|
5
|
+
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "__esModule", {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
exports.getLogs = getLogs;
|
|
12
|
+
exports.validateInputs = validateInputs;
|
|
13
|
+
exports.appQuery = void 0;
|
|
14
|
+
|
|
15
|
+
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
16
|
+
|
|
17
|
+
var _rollbar = require("../lib/rollbar");
|
|
18
|
+
|
|
19
|
+
var _tracker = require("../lib/tracker");
|
|
20
|
+
|
|
21
|
+
var logsLib = _interopRequireWildcard(require("../lib/app-logs/app-logs"));
|
|
22
|
+
|
|
23
|
+
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
24
|
+
|
|
25
|
+
var _format = require("../lib/cli/format");
|
|
26
|
+
|
|
27
|
+
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); }
|
|
28
|
+
|
|
29
|
+
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; }
|
|
30
|
+
|
|
31
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
32
|
+
|
|
33
|
+
const LIMIT_MAX = 5000;
|
|
34
|
+
const LIMIT_MIN = 1;
|
|
35
|
+
const ALLOWED_TYPES = ['app', 'batch'];
|
|
36
|
+
const ALLOWED_FORMATS = ['csv', 'json', 'text'];
|
|
37
|
+
|
|
38
|
+
async function getLogs(arg, opt) {
|
|
39
|
+
validateInputs(opt.type, opt.limit, opt.format);
|
|
40
|
+
const trackingParams = {
|
|
41
|
+
command: 'vip logs',
|
|
42
|
+
org_id: opt.app.organization.id,
|
|
43
|
+
app_id: opt.app.id,
|
|
44
|
+
env_id: opt.env.id,
|
|
45
|
+
type: opt.type,
|
|
46
|
+
limit: opt.limit,
|
|
47
|
+
format: opt.format
|
|
48
|
+
};
|
|
49
|
+
await (0, _tracker.trackEvent)('logs_command_execute', trackingParams);
|
|
50
|
+
let logs = [];
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
logs = await logsLib.getRecentLogs(opt.app.id, opt.env.id, opt.type, opt.limit);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
_rollbar.rollbar.error(error);
|
|
56
|
+
|
|
57
|
+
await (0, _tracker.trackEvent)('logs_command_error', { ...trackingParams,
|
|
58
|
+
error: error.message
|
|
59
|
+
});
|
|
60
|
+
return exit.withError(error.message);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await (0, _tracker.trackEvent)('logs_command_success', { ...trackingParams,
|
|
64
|
+
logs_output: logs.length
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (!logs.length) {
|
|
68
|
+
console.error('No logs found');
|
|
69
|
+
return;
|
|
70
|
+
} // Strip out __typename
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
logs = logs.map(log => {
|
|
74
|
+
const {
|
|
75
|
+
timestamp,
|
|
76
|
+
message
|
|
77
|
+
} = log;
|
|
78
|
+
return {
|
|
79
|
+
timestamp,
|
|
80
|
+
message
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
let output = '';
|
|
84
|
+
|
|
85
|
+
if (opt.format && 'text' === opt.format) {
|
|
86
|
+
const rows = [];
|
|
87
|
+
|
|
88
|
+
for (const {
|
|
89
|
+
timestamp,
|
|
90
|
+
message
|
|
91
|
+
} of logs) {
|
|
92
|
+
rows.push(`${timestamp} ${message}`);
|
|
93
|
+
output = rows.join('\n');
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
output = (0, _format.formatData)(logs, opt.format);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log(output);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function validateInputs(type, limit, format) {
|
|
103
|
+
if (!ALLOWED_TYPES.includes(type)) {
|
|
104
|
+
exit.withError(`Invalid type: ${type}. The supported types are: ${ALLOWED_TYPES.join(', ')}.`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!ALLOWED_FORMATS.includes(format)) {
|
|
108
|
+
exit.withError(`Invalid format: ${format}. The supported formats are: ${ALLOWED_FORMATS.join(', ')}.`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!Number.isInteger(limit) || limit < LIMIT_MIN || limit > LIMIT_MAX) {
|
|
112
|
+
exit.withError(`Invalid limit: ${limit}. It should be a number between ${LIMIT_MIN} and ${LIMIT_MAX}.`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const appQuery = `
|
|
117
|
+
id
|
|
118
|
+
name
|
|
119
|
+
environments {
|
|
120
|
+
id
|
|
121
|
+
appId
|
|
122
|
+
name
|
|
123
|
+
type
|
|
124
|
+
}
|
|
125
|
+
organization {
|
|
126
|
+
id
|
|
127
|
+
name
|
|
128
|
+
}
|
|
129
|
+
`;
|
|
130
|
+
exports.appQuery = appQuery;
|
|
131
|
+
(0, _command.default)({
|
|
132
|
+
appContext: true,
|
|
133
|
+
appQuery,
|
|
134
|
+
envContext: true,
|
|
135
|
+
module: 'logs'
|
|
136
|
+
}).option('type', 'The type of logs to be returned: "app" or "batch"', 'app').option('limit', 'The maximum number of log lines', 500).option('format', 'Output the log lines in CSV or JSON format', 'text').examples([{
|
|
137
|
+
usage: 'vip @mysite.production logs',
|
|
138
|
+
description: 'Get the most recent app logs'
|
|
139
|
+
}, {
|
|
140
|
+
usage: 'vip @mysite.production logs --type batch',
|
|
141
|
+
description: 'Get the most recent batch logs'
|
|
142
|
+
}, {
|
|
143
|
+
usage: 'vip @mysite.production logs --limit 100',
|
|
144
|
+
description: 'Get the most recent 100 log entries'
|
|
145
|
+
}, {
|
|
146
|
+
usage: 'vip @mysite.production logs --limit 100 --format csv',
|
|
147
|
+
description: 'Get the most recent 100 log entries formatted as comma-separated values (CSV)'
|
|
148
|
+
}, {
|
|
149
|
+
usage: 'vip @mysite.production logs --limit 100 --format json',
|
|
150
|
+
description: 'Get the most recent 100 log entries formatted as JSON'
|
|
151
|
+
}]).argv(process.argv, getLogs);
|
package/dist/bin/vip.js
CHANGED
|
@@ -48,7 +48,7 @@ const runCmd = async function () {
|
|
|
48
48
|
await _token.default.purge();
|
|
49
49
|
await (0, _tracker.trackEvent)('logout_command_execute');
|
|
50
50
|
console.log('You are successfully logged out.');
|
|
51
|
-
}).command('app', 'List and modify your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-environment').command('import', 'Import media or SQL files into your VIP applications').command('search-replace', 'Perform search and replace tasks on files').command('sync', 'Sync production to a development environment').command('wp', 'Run WP CLI commands against an environment');
|
|
51
|
+
}).command('app', 'List and modify your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-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('sync', 'Sync production to a development environment').command('wp', 'Run WP CLI commands against an environment');
|
|
52
52
|
cmd.argv(process.argv);
|
|
53
53
|
};
|
|
54
54
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getRecentLogs = getRecentLogs;
|
|
7
|
+
|
|
8
|
+
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
9
|
+
|
|
10
|
+
var _api = _interopRequireDefault(require("../api"));
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @format
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* External dependencies
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Internal dependencies
|
|
25
|
+
*/
|
|
26
|
+
const QUERY_ENVIRONMENT_LOGS = (0, _graphqlTag.default)`
|
|
27
|
+
query GetAppLogs( $appId: Int, $envId: Int, $type: AppEnvironmentLogType, $limit: Int ) {
|
|
28
|
+
app( id: $appId ) {
|
|
29
|
+
environments( id: $envId ) {
|
|
30
|
+
id
|
|
31
|
+
logs( type: $type, limit: $limit ) {
|
|
32
|
+
nodes {
|
|
33
|
+
timestamp
|
|
34
|
+
message
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
async function getRecentLogs(appId, envId, type, limit) {
|
|
43
|
+
var _response$data, _response$data$app, _response$data$app$en, _response$data$app$en2;
|
|
44
|
+
|
|
45
|
+
const api = await (0, _api.default)();
|
|
46
|
+
const response = await api.query({
|
|
47
|
+
query: QUERY_ENVIRONMENT_LOGS,
|
|
48
|
+
variables: {
|
|
49
|
+
appId,
|
|
50
|
+
envId,
|
|
51
|
+
type,
|
|
52
|
+
limit
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const logs = response === null || response === void 0 ? void 0 : (_response$data = response.data) === null || _response$data === void 0 ? void 0 : (_response$data$app = _response$data.app) === null || _response$data$app === void 0 ? void 0 : (_response$data$app$en = _response$data$app.environments[0]) === null || _response$data$app$en === void 0 ? void 0 : (_response$data$app$en2 = _response$data$app$en.logs) === null || _response$data$app$en2 === void 0 ? void 0 : _response$data$app$en2.nodes;
|
|
56
|
+
|
|
57
|
+
if (!logs) {
|
|
58
|
+
throw new Error('Unable to query logs');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return logs;
|
|
62
|
+
}
|
|
@@ -48,6 +48,7 @@ const IMPORT_SQL_PROGRESS_QUERY = (0, _graphqlTag.default)`
|
|
|
48
48
|
environments(id: $envId) {
|
|
49
49
|
id
|
|
50
50
|
isK8sResident
|
|
51
|
+
launched
|
|
51
52
|
jobs(types: "sql_import") {
|
|
52
53
|
id
|
|
53
54
|
type
|
|
@@ -106,7 +107,8 @@ async function getStatus(api, appId, envId) {
|
|
|
106
107
|
const [environment] = environments;
|
|
107
108
|
const {
|
|
108
109
|
importStatus,
|
|
109
|
-
jobs
|
|
110
|
+
jobs,
|
|
111
|
+
launched
|
|
110
112
|
} = environment;
|
|
111
113
|
|
|
112
114
|
if (!environment.isK8sResident && !(jobs !== null && jobs !== void 0 && jobs.length)) {
|
|
@@ -116,15 +118,16 @@ async function getStatus(api, appId, envId) {
|
|
|
116
118
|
const [importJob] = jobs;
|
|
117
119
|
return {
|
|
118
120
|
importStatus,
|
|
119
|
-
importJob
|
|
121
|
+
importJob,
|
|
122
|
+
launched
|
|
120
123
|
};
|
|
121
124
|
}
|
|
122
125
|
|
|
123
|
-
function getErrorMessage(importFailed) {
|
|
126
|
+
function getErrorMessage(importFailed, launched = false) {
|
|
124
127
|
debug({
|
|
125
128
|
importFailed
|
|
126
129
|
});
|
|
127
|
-
const rollbackMessage = `Your site is ${_chalk.default.blue('automatically being rolled back')} to the last backup prior to your import job.
|
|
130
|
+
const rollbackMessage = launched ? '' : `Your site is ${_chalk.default.blue('automatically being rolled back')} to the last backup prior to your import job.
|
|
128
131
|
`;
|
|
129
132
|
let message = importFailed.error;
|
|
130
133
|
|
|
@@ -262,7 +265,8 @@ ${maybeExitPrompt}
|
|
|
262
265
|
}
|
|
263
266
|
|
|
264
267
|
const {
|
|
265
|
-
importStatus
|
|
268
|
+
importStatus,
|
|
269
|
+
launched
|
|
266
270
|
} = status;
|
|
267
271
|
let {
|
|
268
272
|
importJob
|
|
@@ -352,7 +356,8 @@ ${maybeExitPrompt}
|
|
|
352
356
|
|
|
353
357
|
if (!jobSteps.length) {
|
|
354
358
|
return reject({
|
|
355
|
-
error: 'Could not enumerate the import job steps'
|
|
359
|
+
error: 'Could not enumerate the import job steps',
|
|
360
|
+
launched
|
|
356
361
|
});
|
|
357
362
|
}
|
|
358
363
|
|
|
@@ -375,7 +380,8 @@ ${maybeExitPrompt}
|
|
|
375
380
|
commandOutput: failedImportStep.output,
|
|
376
381
|
error: 'Import step failed',
|
|
377
382
|
stepName: failedImportStep.name,
|
|
378
|
-
errorText: failedImportStep.error
|
|
383
|
+
errorText: failedImportStep.error,
|
|
384
|
+
launched
|
|
379
385
|
});
|
|
380
386
|
}
|
|
381
387
|
|
|
@@ -385,7 +391,8 @@ ${maybeExitPrompt}
|
|
|
385
391
|
if (jobStatus === 'error') {
|
|
386
392
|
return reject({
|
|
387
393
|
error: 'Import job failed',
|
|
388
|
-
steps: jobSteps
|
|
394
|
+
steps: jobSteps,
|
|
395
|
+
launched
|
|
389
396
|
});
|
|
390
397
|
}
|
|
391
398
|
|
|
@@ -425,7 +432,7 @@ ${maybeExitPrompt}
|
|
|
425
432
|
progressTracker.print({
|
|
426
433
|
clearAfter: true
|
|
427
434
|
});
|
|
428
|
-
exit.withError(getErrorMessage(importFailed));
|
|
435
|
+
exit.withError(getErrorMessage(importFailed, importFailed.launched));
|
|
429
436
|
}
|
|
430
437
|
}
|
|
431
438
|
|