@automattic/vip 2.32.2 → 2.32.4
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/CHANGELOG.md +22 -0
- package/assets/dev-env.lando.template.yml.ejs +10 -2
- package/dist/bin/vip-dev-env-exec.js +1 -7
- package/dist/bin/vip-dev-env-shell.js +0 -4
- package/dist/bin/vip-dev-env-start.js +1 -1
- package/dist/bin/vip-dev-env-sync-sql.js +8 -6
- package/dist/bin/vip-dev-env-update.js +1 -2
- package/dist/bin/vip-import-sql.js +2 -2
- package/dist/bin/vip-logout.js +23 -0
- package/dist/bin/vip-slowlogs.js +192 -0
- package/dist/bin/vip-validate-preflight.js +8 -10
- package/dist/bin/vip-whoami.js +1 -2
- package/dist/bin/vip.js +1 -5
- package/dist/commands/backup-db.js +8 -9
- package/dist/lib/api/app.js +2 -2
- package/dist/lib/api/cache-purge.js +2 -2
- package/dist/lib/api/http.js +2 -3
- package/dist/lib/app-logs/app-logs.js +2 -2
- package/dist/lib/app-slowlogs/app-slowlogs.js +63 -0
- package/dist/lib/app-slowlogs/types.js +1 -0
- package/dist/lib/cli/apiConfig.js +1 -1
- package/dist/lib/client-file-uploader.js +19 -4
- package/dist/lib/config/software.js +4 -4
- package/dist/lib/constants/dev-environment.js +7 -3
- package/dist/lib/dev-environment/dev-environment-cli.js +110 -117
- package/dist/lib/dev-environment/dev-environment-configuration-file.js +35 -36
- package/dist/lib/dev-environment/dev-environment-core.js +36 -19
- package/dist/lib/dev-environment/dev-environment-lando.js +80 -72
- package/dist/lib/dev-environment/docker-utils.js +8 -9
- package/dist/lib/envvar/api-get-all.js +2 -2
- package/dist/lib/envvar/api-list.js +3 -6
- package/dist/lib/envvar/input.js +1 -2
- package/dist/lib/site-import/status.js +5 -5
- package/dist/lib/token.js +3 -6
- package/dist/lib/validations/is-multi-site-sql-dump.js +0 -1
- package/dist/lib/validations/is-multi-site.js +14 -12
- package/dist/lib/validations/is-multisite-domain-mapped.js +5 -10
- package/dist/lib/validations/line-by-line.js +9 -13
- package/dist/lib/validations/site-type.js +2 -7
- package/dist/lib/validations/sql.js +14 -19
- package/dist/lib/validations/utils.js +1 -1
- package/export.sql +627 -0
- package/npm-shrinkwrap.json +913 -926
- package/package.json +12 -9
- package/tsconfig.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
### 2.32.4
|
|
4
|
+
|
|
5
|
+
- #1470 Rename prepare-release.yml to npm-prepare-release.yml
|
|
6
|
+
- #1469 fix compatibility issue
|
|
7
|
+
|
|
8
|
+
### 2.32.3
|
|
9
|
+
|
|
10
|
+
- #1456 Fix DB engine validation regex
|
|
11
|
+
- #1455 Fix SQL import command
|
|
12
|
+
- #1454 chore(deps): update lando to 5efb9eb
|
|
13
|
+
- #1453 Refactor logout
|
|
14
|
+
- #1425 Add Slowlogs command
|
|
15
|
+
- #1341 feat(dev-env): Add a concept of init-only containers
|
|
16
|
+
- #1344 fix(dev-env): Do not run URL scan unless really need to
|
|
17
|
+
- #1414 [dev-env] Tweak error handling dev-env sync
|
|
18
|
+
- #1452 chore(dev-deps): update TypeScript-related packages
|
|
19
|
+
- #1420 feat(dev-env): Adds automigration logic to dev-env
|
|
20
|
+
- #1451 chore(dev-deps): update testing tools
|
|
21
|
+
- #1448 chore(dev-deps): update babel packages to 7.22.9
|
|
22
|
+
- #1421 refactor: Convert dev-environment to TypeScript
|
|
23
|
+
- #1450 refactor: convert `validations` to TS
|
|
24
|
+
|
|
3
25
|
### 2.32.2
|
|
4
26
|
|
|
5
27
|
- #1443 On-demand Database Backup: Use a less error-prone way of detecting if we're rate limited
|
|
@@ -17,7 +17,7 @@ services:
|
|
|
17
17
|
type: compose
|
|
18
18
|
services:
|
|
19
19
|
image: ghcr.io/automattic/vip-container-images/dev-tools:0.9
|
|
20
|
-
command:
|
|
20
|
+
command: exit 0
|
|
21
21
|
volumes:
|
|
22
22
|
- devtools:/dev-tools
|
|
23
23
|
- scripts:/scripts
|
|
@@ -28,6 +28,7 @@ services:
|
|
|
28
28
|
volumes:
|
|
29
29
|
devtools: {}
|
|
30
30
|
scripts:
|
|
31
|
+
initOnly: true
|
|
31
32
|
|
|
32
33
|
nginx:
|
|
33
34
|
type: compose
|
|
@@ -154,6 +155,7 @@ services:
|
|
|
154
155
|
type: compose
|
|
155
156
|
services:
|
|
156
157
|
image: ghcr.io/automattic/vip-container-images/wordpress:<%= wordpress.tag %>
|
|
158
|
+
# command: /usr/local/bin/entrypoint.sh
|
|
157
159
|
command: sh -c "rsync -a --chown=www-data:www-data /wp/ /shared/; sleep infinity"
|
|
158
160
|
volumes:
|
|
159
161
|
- ./wordpress:/shared
|
|
@@ -162,6 +164,10 @@ services:
|
|
|
162
164
|
target: /scripts
|
|
163
165
|
volume:
|
|
164
166
|
nocopy: true
|
|
167
|
+
# environment:
|
|
168
|
+
# LANDO_NO_SCRIPTS: 1
|
|
169
|
+
# LANDO_NEEDS_EXEC: 1
|
|
170
|
+
# initOnly: true
|
|
165
171
|
|
|
166
172
|
<% if ( muPlugins.mode == 'image' ) { %>
|
|
167
173
|
vip-mu-plugins:
|
|
@@ -181,6 +187,7 @@ services:
|
|
|
181
187
|
LANDO_NEEDS_EXEC: 1
|
|
182
188
|
volumes:
|
|
183
189
|
mu-plugins: {}
|
|
190
|
+
initOnly: true
|
|
184
191
|
<% } %>
|
|
185
192
|
|
|
186
193
|
<% if ( appCode.mode == 'image' ) { %>
|
|
@@ -188,7 +195,7 @@ services:
|
|
|
188
195
|
type: compose
|
|
189
196
|
services:
|
|
190
197
|
image: ghcr.io/automattic/vip-container-images/skeleton:latest
|
|
191
|
-
command:
|
|
198
|
+
command: exit 0
|
|
192
199
|
volumes:
|
|
193
200
|
- clientcode_clientmuPlugins:/clientcode/client-mu-plugins
|
|
194
201
|
- clientcode_images:/clientcode/images
|
|
@@ -205,6 +212,7 @@ services:
|
|
|
205
212
|
clientcode_private: {}
|
|
206
213
|
clientcode_themes: {}
|
|
207
214
|
clientcode_vipconfig: {}
|
|
215
|
+
initOnly: true
|
|
208
216
|
<% } %>
|
|
209
217
|
|
|
210
218
|
<% if ( mailpit ) { %>
|
|
@@ -30,13 +30,7 @@ const examples = [{
|
|
|
30
30
|
}];
|
|
31
31
|
(0, _command.default)({
|
|
32
32
|
wildcardCommand: true
|
|
33
|
-
}).option('slug', 'Custom name of the dev environment').option('force', '
|
|
34
|
-
var _value$toLowerCase;
|
|
35
|
-
return 'false' !== (value === null || value === void 0 ? void 0 : (_value$toLowerCase = value.toLowerCase) === null || _value$toLowerCase === void 0 ? void 0 : _value$toLowerCase.call(value));
|
|
36
|
-
}).option('quiet', 'Suppress output', undefined, value => {
|
|
37
|
-
var _value$toLowerCase2;
|
|
38
|
-
return 'false' !== (value === null || value === void 0 ? void 0 : (_value$toLowerCase2 = value.toLowerCase) === null || _value$toLowerCase2 === void 0 ? void 0 : _value$toLowerCase2.call(value));
|
|
39
|
-
}).examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
|
|
33
|
+
}).option('slug', 'Custom name of the dev environment').option('force', 'Disable validations before task execution', undefined, _devEnvironmentCli.processBooleanOption).option('quiet', 'Suppress output', undefined, _devEnvironmentCli.processBooleanOption).examples(examples).argv(process.argv, async (unmatchedArgs, opt) => {
|
|
40
34
|
const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
|
|
41
35
|
const lando = await (0, _devEnvironmentLando.bootstrapLando)();
|
|
42
36
|
await (0, _devEnvironmentCli.validateDependencies)(lando, slug, opt.quiet);
|
|
@@ -18,14 +18,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
18
18
|
*/
|
|
19
19
|
const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
|
|
20
20
|
const userMap = {
|
|
21
|
-
devtools: 'www-data',
|
|
22
21
|
nginx: 'www-data',
|
|
23
22
|
php: 'www-data',
|
|
24
23
|
database: 'mysql',
|
|
25
24
|
memcached: 'memcache',
|
|
26
|
-
wordpress: 'www-data',
|
|
27
|
-
'vip-mu-plugins': 'www-data',
|
|
28
|
-
'demo-app-code': 'www-data',
|
|
29
25
|
elasticsearch: 'elasticsearch',
|
|
30
26
|
phpmyadmin: 'www-data',
|
|
31
27
|
mailhog: 'mailhog',
|
|
@@ -73,7 +73,7 @@ const examples = [{
|
|
|
73
73
|
await (0, _devEnvironmentCli.handleCLIException)(error, 'dev_env_start_command_error', trackingInfo);
|
|
74
74
|
process.exitCode = 1;
|
|
75
75
|
}
|
|
76
|
-
|
|
76
|
+
(0, _devEnvironmentCli.postStart)(slug, {
|
|
77
77
|
openVSCode: !!opt.vscode
|
|
78
78
|
});
|
|
79
79
|
});
|
|
@@ -21,6 +21,7 @@ var _userError = _interopRequireDefault(require("../lib/user-error"));
|
|
|
21
21
|
var _devEnvSyncSql = require("../commands/dev-env-sync-sql");
|
|
22
22
|
var _devEnvironment = require("../lib/constants/dev-environment");
|
|
23
23
|
var _tracker = require("../lib/tracker");
|
|
24
|
+
var _devEnvironmentCli = require("../lib/dev-environment/dev-environment-cli");
|
|
24
25
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
26
|
const examples = [{
|
|
26
27
|
usage: `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} sync sql @my-test.develop --slug=my_site`,
|
|
@@ -54,11 +55,12 @@ const appQuery = `
|
|
|
54
55
|
envContext: true,
|
|
55
56
|
requiredArgs: 0,
|
|
56
57
|
module: 'dev-env-sync-sql'
|
|
57
|
-
}).option('slug', 'Custom name of the dev environment').examples(examples).argv(process.argv, async (arg, {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
58
|
+
}).option('slug', 'Custom name of the dev environment').option('force', 'Disable validations before running sync', undefined, _devEnvironmentCli.processBooleanOption).examples(examples).argv(process.argv, async (arg, opt) => {
|
|
59
|
+
const {
|
|
60
|
+
app,
|
|
61
|
+
env
|
|
62
|
+
} = opt;
|
|
63
|
+
const slug = await (0, _devEnvironmentCli.getEnvironmentName)(opt);
|
|
62
64
|
const trackerFn = (0, _tracker.makeCommandTracker)('dev_env_sync_sql', {
|
|
63
65
|
app: app.id,
|
|
64
66
|
env: env.uniqueLabel,
|
|
@@ -68,7 +70,7 @@ const appQuery = `
|
|
|
68
70
|
await trackerFn('execute');
|
|
69
71
|
const lando = await (0, _devEnvironmentLando.bootstrapLando)();
|
|
70
72
|
const envPath = (0, _devEnvironmentCore.getEnvironmentPath)(slug);
|
|
71
|
-
if (!(await (0, _devEnvironmentLando.isEnvUp)(lando, envPath))) {
|
|
73
|
+
if (!(await (0, _devEnvironmentLando.isEnvUp)(lando, envPath)) && !opt.force) {
|
|
72
74
|
await trackerFn('env_not_running_error', {
|
|
73
75
|
errorMessage: 'Environment was not running'
|
|
74
76
|
});
|
|
@@ -39,7 +39,6 @@ cmd.argv(process.argv, async (arg, opt) => {
|
|
|
39
39
|
const trackingInfo = (0, _devEnvironmentCli.getEnvTrackingInfo)(slug);
|
|
40
40
|
await (0, _tracker.trackEvent)('dev_env_update_command_execute', trackingInfo);
|
|
41
41
|
try {
|
|
42
|
-
var _currentInstanceData$;
|
|
43
42
|
const environmentAlreadyExists = await (0, _devEnvironmentCore.doesEnvironmentExist)((0, _devEnvironmentCore.getEnvironmentPath)(slug));
|
|
44
43
|
if (!environmentAlreadyExists) {
|
|
45
44
|
throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
|
|
@@ -63,7 +62,7 @@ cmd.argv(process.argv, async (arg, opt) => {
|
|
|
63
62
|
mariadb: currentInstanceData.mariadb,
|
|
64
63
|
phpmyadmin: currentInstanceData.phpmyadmin,
|
|
65
64
|
xdebug: currentInstanceData.xdebug,
|
|
66
|
-
mailpit:
|
|
65
|
+
mailpit: currentInstanceData.mailpit ?? currentInstanceData.mailhog,
|
|
67
66
|
photon: currentInstanceData.photon,
|
|
68
67
|
mediaRedirectDomain: currentInstanceData.mediaRedirectDomain,
|
|
69
68
|
multisite: false,
|
|
@@ -271,8 +271,8 @@ const displayPlaybook = ({
|
|
|
271
271
|
var _app$environments, _selectedEnvironmentO;
|
|
272
272
|
// eslint-disable-next-line no-multi-spaces
|
|
273
273
|
console.log(` multisite: ${isMultiSite.toString()}`);
|
|
274
|
-
const selectedEnvironmentObj = app === null || app === void 0
|
|
275
|
-
siteArray = selectedEnvironmentObj === null || selectedEnvironmentObj === void 0
|
|
274
|
+
const selectedEnvironmentObj = app === null || app === void 0 || (_app$environments = app.environments) === null || _app$environments === void 0 ? void 0 : _app$environments.find(env => unformattedEnvironment === env.type);
|
|
275
|
+
siteArray = selectedEnvironmentObj === null || selectedEnvironmentObj === void 0 || (_selectedEnvironmentO = selectedEnvironmentObj.wpSites) === null || _selectedEnvironmentO === void 0 ? void 0 : _selectedEnvironmentO.nodes;
|
|
276
276
|
}
|
|
277
277
|
if (!tableNames.length) {
|
|
278
278
|
debug('Validation was skipped, no playbook information will be displayed');
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
"use strict";
|
|
11
|
+
|
|
12
|
+
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
13
|
+
var _logout = _interopRequireDefault(require("../lib/logout"));
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
void (0, _command.default)({
|
|
16
|
+
usage: 'vip logout'
|
|
17
|
+
}).examples([{
|
|
18
|
+
usage: 'vip logout',
|
|
19
|
+
description: 'Logs out current user.'
|
|
20
|
+
}]).argv(process.argv, async () => {
|
|
21
|
+
await (0, _logout.default)();
|
|
22
|
+
console.log('You are successfully logged out.');
|
|
23
|
+
});
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "__esModule", {
|
|
8
|
+
value: true
|
|
9
|
+
});
|
|
10
|
+
exports.appQuery = void 0;
|
|
11
|
+
exports.followLogs = followLogs;
|
|
12
|
+
exports.getSlowlogs = getSlowlogs;
|
|
13
|
+
exports.validateInputs = validateInputs;
|
|
14
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
15
|
+
var _promises = require("timers/promises");
|
|
16
|
+
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
17
|
+
var _tracker = require("../lib/tracker");
|
|
18
|
+
var slowlogsLib = _interopRequireWildcard(require("../lib/app-slowlogs/app-slowlogs"));
|
|
19
|
+
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
20
|
+
var _format = require("../lib/cli/format");
|
|
21
|
+
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); }
|
|
22
|
+
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; }
|
|
23
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
24
|
+
/**
|
|
25
|
+
* Internal dependencies
|
|
26
|
+
*/
|
|
27
|
+
const LIMIT_MIN = 1;
|
|
28
|
+
const LIMIT_MAX = 500;
|
|
29
|
+
const ALLOWED_FORMATS = ['csv', 'json', 'text'];
|
|
30
|
+
const DEFAULT_POLLING_DELAY_IN_SECONDS = 30;
|
|
31
|
+
const MIN_POLLING_DELAY_IN_SECONDS = 5;
|
|
32
|
+
const MAX_POLLING_DELAY_IN_SECONDS = 300;
|
|
33
|
+
async function getSlowlogs(arg, opt) {
|
|
34
|
+
validateInputs(opt.limit, opt.format);
|
|
35
|
+
const trackingParams = getBaseTrackingParams(opt);
|
|
36
|
+
await (0, _tracker.trackEvent)('slowlogs_command_execute', trackingParams);
|
|
37
|
+
let slowlogs;
|
|
38
|
+
try {
|
|
39
|
+
slowlogs = await slowlogsLib.getRecentSlowlogs(opt.app.id, opt.env.id, opt.limit);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
const err = error;
|
|
42
|
+
await (0, _tracker.trackEvent)('slowlogs_command_error', {
|
|
43
|
+
...trackingParams,
|
|
44
|
+
error: err.message
|
|
45
|
+
});
|
|
46
|
+
return exit.withError(err.message);
|
|
47
|
+
}
|
|
48
|
+
await (0, _tracker.trackEvent)('slowlogs_command_success', {
|
|
49
|
+
...trackingParams,
|
|
50
|
+
total: slowlogs.nodes.length
|
|
51
|
+
});
|
|
52
|
+
if (!slowlogs.nodes.length) {
|
|
53
|
+
console.error('No logs found');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
printSlowlogs(slowlogs.nodes, opt.format);
|
|
57
|
+
}
|
|
58
|
+
async function followLogs(opt) {
|
|
59
|
+
let after = null;
|
|
60
|
+
let isFirstRequest = true;
|
|
61
|
+
// How many times have we polled?
|
|
62
|
+
let requestNumber = 0;
|
|
63
|
+
const trackingParams = getBaseTrackingParams(opt);
|
|
64
|
+
|
|
65
|
+
// Set an initial default delay
|
|
66
|
+
let delay = DEFAULT_POLLING_DELAY_IN_SECONDS;
|
|
67
|
+
|
|
68
|
+
// eslint-disable-next-line no-constant-condition, @typescript-eslint/no-unnecessary-condition
|
|
69
|
+
while (true) {
|
|
70
|
+
const limit = isFirstRequest ? opt.limit : LIMIT_MAX;
|
|
71
|
+
requestNumber++;
|
|
72
|
+
trackingParams.request_number = requestNumber;
|
|
73
|
+
trackingParams.request_delay = delay;
|
|
74
|
+
trackingParams.limit = limit;
|
|
75
|
+
let slowlogs;
|
|
76
|
+
try {
|
|
77
|
+
// eslint-disable-next-line no-await-in-loop
|
|
78
|
+
slowlogs = await slowlogsLib.getRecentSlowlogs(opt.app.id, opt.env.id, limit, after);
|
|
79
|
+
|
|
80
|
+
// eslint-disable-next-line no-await-in-loop
|
|
81
|
+
await (0, _tracker.trackEvent)('slowlogs_command_follow_success', {
|
|
82
|
+
...trackingParams,
|
|
83
|
+
total: slowlogs.nodes.length
|
|
84
|
+
});
|
|
85
|
+
} catch (error) {
|
|
86
|
+
const err = error;
|
|
87
|
+
// eslint-disable-next-line no-await-in-loop
|
|
88
|
+
await (0, _tracker.trackEvent)('slowlogs_command_follow_error', {
|
|
89
|
+
...trackingParams,
|
|
90
|
+
error: err.message
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// If the first request fails we don't want to retry (it's probably not recoverable)
|
|
94
|
+
if (isFirstRequest) {
|
|
95
|
+
console.error(`${_chalk.default.red('Error:')} Failed to fetch slowlogs.`);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
// Increase the delay on errors to avoid overloading the server, up to a max of 5 minutes
|
|
99
|
+
delay += DEFAULT_POLLING_DELAY_IN_SECONDS;
|
|
100
|
+
delay = Math.min(delay, MAX_POLLING_DELAY_IN_SECONDS);
|
|
101
|
+
console.error(`${_chalk.default.red('Error:')} Failed to fetch slowlogs. Trying again in ${delay} seconds.`);
|
|
102
|
+
}
|
|
103
|
+
if (slowlogs) {
|
|
104
|
+
if (slowlogs.nodes.length) {
|
|
105
|
+
printSlowlogs(slowlogs.nodes, opt.format);
|
|
106
|
+
}
|
|
107
|
+
after = slowlogs.nextCursor;
|
|
108
|
+
isFirstRequest = false;
|
|
109
|
+
|
|
110
|
+
// Keep a sane lower limit of MIN_POLLING_DELAY_IN_SECONDS just in case something goes wrong in the server-side
|
|
111
|
+
delay = Math.max(slowlogs.pollingDelaySeconds || DEFAULT_POLLING_DELAY_IN_SECONDS, MIN_POLLING_DELAY_IN_SECONDS);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// eslint-disable-next-line no-await-in-loop
|
|
115
|
+
await (0, _promises.setTimeout)(delay * 1000);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function getBaseTrackingParams(opt) {
|
|
119
|
+
return {
|
|
120
|
+
command: 'vip slowlogs',
|
|
121
|
+
org_id: opt.app.organization.id,
|
|
122
|
+
app_id: opt.app.id,
|
|
123
|
+
env_id: opt.env.id,
|
|
124
|
+
limit: opt.limit,
|
|
125
|
+
follow: opt.follow ?? false,
|
|
126
|
+
format: opt.format
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function printSlowlogs(slowlogs, format) {
|
|
130
|
+
// Strip out __typename
|
|
131
|
+
slowlogs = slowlogs.map(log => {
|
|
132
|
+
const {
|
|
133
|
+
timestamp,
|
|
134
|
+
rowsSent,
|
|
135
|
+
rowsExamined,
|
|
136
|
+
queryTime,
|
|
137
|
+
requestUri,
|
|
138
|
+
query
|
|
139
|
+
} = log;
|
|
140
|
+
return {
|
|
141
|
+
timestamp,
|
|
142
|
+
rowsSent,
|
|
143
|
+
rowsExamined,
|
|
144
|
+
queryTime,
|
|
145
|
+
requestUri,
|
|
146
|
+
query
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
console.log((0, _format.formatData)(slowlogs, format));
|
|
150
|
+
}
|
|
151
|
+
function validateInputs(limit, format) {
|
|
152
|
+
if (!ALLOWED_FORMATS.includes(format)) {
|
|
153
|
+
exit.withError(`Invalid format: ${format}. The supported formats are: ${ALLOWED_FORMATS.join(', ')}.`);
|
|
154
|
+
}
|
|
155
|
+
if (!Number.isInteger(limit) || limit < LIMIT_MIN || limit > slowlogsLib.LIMIT_MAX) {
|
|
156
|
+
exit.withError(`Invalid limit: ${limit}. It should be a number between ${LIMIT_MIN} and ${slowlogsLib.LIMIT_MAX}.`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const appQuery = `
|
|
160
|
+
id
|
|
161
|
+
name
|
|
162
|
+
environments {
|
|
163
|
+
id
|
|
164
|
+
appId
|
|
165
|
+
name
|
|
166
|
+
type
|
|
167
|
+
}
|
|
168
|
+
organization {
|
|
169
|
+
id
|
|
170
|
+
name
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
exports.appQuery = appQuery;
|
|
174
|
+
void (0, _command.default)({
|
|
175
|
+
appContext: true,
|
|
176
|
+
appQuery,
|
|
177
|
+
envContext: true,
|
|
178
|
+
format: true,
|
|
179
|
+
module: 'slowlogs'
|
|
180
|
+
}).option('limit', 'The maximum number of log lines', 500).option('format', 'Output the log lines in CSV or JSON format', 'text').examples([{
|
|
181
|
+
description: 'Get the most recent app slowlogs',
|
|
182
|
+
usage: 'vip @mysite.production slowlogs'
|
|
183
|
+
}, {
|
|
184
|
+
usage: 'vip @mysite.production slowlogs --limit 100',
|
|
185
|
+
description: 'Get the most recent 100 slowlog entries'
|
|
186
|
+
}, {
|
|
187
|
+
usage: 'vip @mysite.production slowlogs --limit 100 --format csv',
|
|
188
|
+
description: 'Get the most recent 100 slowlog entries formatted as comma-separated values (CSV)'
|
|
189
|
+
}, {
|
|
190
|
+
usage: 'vip @mysite.production slowlogs --limit 100 --format json',
|
|
191
|
+
description: 'Get the most recent 100 slowlog entries formatted as JSON'
|
|
192
|
+
}]).argv(process.argv, getSlowlogs);
|
|
@@ -111,10 +111,10 @@ async function getBuildConfiguration(application, environment) {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
async function vipValidatePreflightCommand(arg, opt) {
|
|
114
|
-
var _opt$env
|
|
114
|
+
var _opt$env, _opt$env2, _opt$app, _opt$env3;
|
|
115
115
|
harmoniaArgs = await validateArgs(opt);
|
|
116
|
-
const appId = (
|
|
117
|
-
const envId = (
|
|
116
|
+
const appId = ((_opt$env = opt.env) === null || _opt$env === void 0 ? void 0 : _opt$env.appId) ?? 0;
|
|
117
|
+
const envId = ((_opt$env2 = opt.env) === null || _opt$env2 === void 0 ? void 0 : _opt$env2.id) ?? 0;
|
|
118
118
|
const baseTrackingParams = {
|
|
119
119
|
env_id: envId,
|
|
120
120
|
app_id: appId,
|
|
@@ -144,7 +144,7 @@ async function vipValidatePreflightCommand(arg, opt) {
|
|
|
144
144
|
const siteOptions = new _vipGoPreflightChecks.SiteConfig({
|
|
145
145
|
siteID: envId,
|
|
146
146
|
nodejsVersion: harmoniaArgs.nodejsVersion,
|
|
147
|
-
repository: (
|
|
147
|
+
repository: ((_opt$app = opt.app) === null || _opt$app === void 0 ? void 0 : _opt$app.repo) ?? 'no-repo',
|
|
148
148
|
baseURL: 'http://localhost:' + harmoniaArgs.port,
|
|
149
149
|
dockerBuildEnvs: harmoniaArgs.nodeBuildDockerEnv,
|
|
150
150
|
topRequests: [],
|
|
@@ -167,7 +167,7 @@ async function vipValidatePreflightCommand(arg, opt) {
|
|
|
167
167
|
return exit.withError(`Could not find a 'package.json' in the current folder (${opt.path}).`);
|
|
168
168
|
}
|
|
169
169
|
const customEnvVars = {};
|
|
170
|
-
if (((_opt$env3 = opt.env) === null || _opt$env3 === void 0
|
|
170
|
+
if (((_opt$env3 = opt.env) === null || _opt$env3 === void 0 || (_opt$env3 = _opt$env3.environmentVariables) === null || _opt$env3 === void 0 ? void 0 : _opt$env3.nodes.length) > 0) {
|
|
171
171
|
opt.env.environmentVariables.nodes.forEach(envVar => {
|
|
172
172
|
customEnvVars[envVar.name] = envVar.value;
|
|
173
173
|
});
|
|
@@ -368,7 +368,6 @@ async function handleResults(harmonia, results) {
|
|
|
368
368
|
process.exit(0);
|
|
369
369
|
}
|
|
370
370
|
async function validateArgs(opt) {
|
|
371
|
-
var _opt$wait, _opt$port;
|
|
372
371
|
const args = {};
|
|
373
372
|
|
|
374
373
|
// Verbose
|
|
@@ -387,12 +386,11 @@ async function validateArgs(opt) {
|
|
|
387
386
|
outputJson = true;
|
|
388
387
|
}
|
|
389
388
|
if (opt.app) {
|
|
390
|
-
var _opt$nodeVersion;
|
|
391
389
|
// Get build information from API and store it in the env object
|
|
392
390
|
const buildConfig = await getBuildConfiguration(opt.app, opt.env);
|
|
393
391
|
args.app_id = opt.app.id;
|
|
394
392
|
args.env_id = opt.env.id;
|
|
395
|
-
args.nodejsVersion =
|
|
393
|
+
args.nodejsVersion = opt.nodeVersion ?? buildConfig.nodeJSVersion;
|
|
396
394
|
args.buildType = buildConfig.buildType;
|
|
397
395
|
args.npmToken = buildConfig.npmToken;
|
|
398
396
|
args.nodeBuildDockerEnv = buildConfig.nodeBuildDockerEnv;
|
|
@@ -419,8 +417,8 @@ async function validateArgs(opt) {
|
|
|
419
417
|
args.nodejsVersion = opt.nodeVersion;
|
|
420
418
|
}
|
|
421
419
|
}
|
|
422
|
-
args.wait =
|
|
423
|
-
args.port =
|
|
420
|
+
args.wait = opt.wait ?? 3000;
|
|
421
|
+
args.port = opt.port ?? Math.floor(Math.random() * 1000) + 3001; // Get a PORT from 3001 and 3999
|
|
424
422
|
|
|
425
423
|
return args;
|
|
426
424
|
}
|
package/dist/bin/vip-whoami.js
CHANGED
|
@@ -21,7 +21,6 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
|
|
|
21
21
|
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; }
|
|
22
22
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
23
|
async function whoamiCommand() {
|
|
24
|
-
var _currentUser$displayN, _currentUser$id;
|
|
25
24
|
const trackingParams = {
|
|
26
25
|
command: 'vip whoami'
|
|
27
26
|
};
|
|
@@ -38,7 +37,7 @@ async function whoamiCommand() {
|
|
|
38
37
|
exit.withError(`Failed to fetch information about the currently logged-in user error: ${error.message}`);
|
|
39
38
|
}
|
|
40
39
|
await (0, _tracker.trackEvent)('whoami_command_success', trackingParams);
|
|
41
|
-
const output = [`- Howdy ${
|
|
40
|
+
const output = [`- Howdy ${currentUser.displayName ?? 'user'}!`, `- Your user ID is ${currentUser.id ?? ' not found'}`];
|
|
42
41
|
if (currentUser.isVIP) {
|
|
43
42
|
output.push('- Your account has VIP Staff permissions');
|
|
44
43
|
}
|
package/dist/bin/vip.js
CHANGED
|
@@ -12,7 +12,6 @@ var _config = _interopRequireDefault(require("../lib/cli/config"));
|
|
|
12
12
|
var _command = _interopRequireWildcard(require("../lib/cli/command"));
|
|
13
13
|
var _token2 = _interopRequireDefault(require("../lib/token"));
|
|
14
14
|
var _tracker = require("../lib/tracker");
|
|
15
|
-
var _logout = _interopRequireDefault(require("../lib/logout"));
|
|
16
15
|
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); }
|
|
17
16
|
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; }
|
|
18
17
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -29,10 +28,7 @@ if (_config.default && _config.default.environment !== 'production') {
|
|
|
29
28
|
const tokenURL = 'https://dashboard.wpvip.com/me/cli/token';
|
|
30
29
|
const runCmd = async function () {
|
|
31
30
|
const cmd = (0, _command.default)();
|
|
32
|
-
cmd.command('logout', 'Logout from your current session',
|
|
33
|
-
await (0, _logout.default)();
|
|
34
|
-
console.log('You are successfully logged out.');
|
|
35
|
-
}).command('app', 'List and modify your VIP applications').command('cache', 'Manage page cache for your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-environment').command('export', 'Export data from your VIP application').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('whoami', 'Display details about the currently logged-in user').command('validate', 'Validate your VIP application and environment').command('wp', 'Run WP CLI commands against an environment');
|
|
31
|
+
cmd.command('logout', 'Logout from your current session').command('app', 'List and modify your VIP applications').command('cache', 'Manage page cache for your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-environment').command('export', 'Export data from your VIP application').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('sync', 'Sync production to a development environment').command('whoami', 'Display details about the currently logged-in user').command('validate', 'Validate your VIP application and environment').command('wp', 'Run WP CLI commands against an environment');
|
|
36
32
|
cmd.argv(process.argv);
|
|
37
33
|
};
|
|
38
34
|
function doesArgvHaveAtLeastOneParam(argv, params) {
|
|
@@ -61,7 +61,7 @@ const DB_BACKUP_JOB_STATUS_QUERY = (0, _graphqlTag.default)`
|
|
|
61
61
|
`;
|
|
62
62
|
exports.DB_BACKUP_JOB_STATUS_QUERY = DB_BACKUP_JOB_STATUS_QUERY;
|
|
63
63
|
async function getBackupJob(appId, envId) {
|
|
64
|
-
var _app$environments
|
|
64
|
+
var _app$environments;
|
|
65
65
|
const api = await (0, _api.default)();
|
|
66
66
|
const response = await api.query({
|
|
67
67
|
query: DB_BACKUP_JOB_STATUS_QUERY,
|
|
@@ -76,7 +76,7 @@ async function getBackupJob(appId, envId) {
|
|
|
76
76
|
app
|
|
77
77
|
}
|
|
78
78
|
} = response;
|
|
79
|
-
return app === null || app === void 0
|
|
79
|
+
return app === null || app === void 0 || (_app$environments = app.environments) === null || _app$environments === void 0 || (_app$environments = _app$environments[0]) === null || _app$environments === void 0 || (_app$environments = _app$environments.jobs) === null || _app$environments === void 0 ? void 0 : _app$environments[0];
|
|
80
80
|
}
|
|
81
81
|
async function createBackupJob(appId, envId) {
|
|
82
82
|
// Disable global error handling so that we can handle errors ourselves
|
|
@@ -134,10 +134,10 @@ class BackupDBCommand {
|
|
|
134
134
|
this.progressTracker.stopPrinting();
|
|
135
135
|
}
|
|
136
136
|
async loadBackupJob() {
|
|
137
|
-
var _this$
|
|
138
|
-
this.job = await getBackupJob(
|
|
139
|
-
this.backupName = (
|
|
140
|
-
this.jobStatus = (
|
|
137
|
+
var _this$job, _this$job2, _this$job3;
|
|
138
|
+
this.job = await getBackupJob(this.app.id ?? 0, this.env.id ?? 0);
|
|
139
|
+
this.backupName = ((_this$job = this.job) === null || _this$job === void 0 || (_this$job = _this$job.metadata) === null || _this$job === void 0 || (_this$job = _this$job.find(meta => (meta === null || meta === void 0 ? void 0 : meta.name) === 'backupName')) === null || _this$job === void 0 ? void 0 : _this$job.value) ?? 'Unknown';
|
|
140
|
+
this.jobStatus = ((_this$job2 = this.job) === null || _this$job2 === void 0 || (_this$job2 = _this$job2.progress) === null || _this$job2 === void 0 ? void 0 : _this$job2.status) ?? undefined;
|
|
141
141
|
if ((_this$job3 = this.job) !== null && _this$job3 !== void 0 && _this$job3.completedAt) {
|
|
142
142
|
this.jobAge = (new Date().getTime() - new Date(this.job.completedAt).getTime()) / 1000 / 60;
|
|
143
143
|
} else {
|
|
@@ -157,18 +157,17 @@ class BackupDBCommand {
|
|
|
157
157
|
this.log('Database backup already in progress...');
|
|
158
158
|
} else {
|
|
159
159
|
try {
|
|
160
|
-
var _this$app$id2, _this$env$id2;
|
|
161
160
|
this.log('Generating a new database backup...');
|
|
162
161
|
this.progressTracker.stepRunning(this.steps.PREPARE);
|
|
163
162
|
this.progressTracker.startPrinting();
|
|
164
|
-
await createBackupJob(
|
|
163
|
+
await createBackupJob(this.app.id ?? 0, this.env.id ?? 0);
|
|
165
164
|
} catch (err) {
|
|
166
165
|
var _error$graphQLErrors, _graphQLError$extensi;
|
|
167
166
|
const error = err;
|
|
168
167
|
const graphQLError = (_error$graphQLErrors = error.graphQLErrors) === null || _error$graphQLErrors === void 0 ? void 0 : _error$graphQLErrors[0];
|
|
169
168
|
this.progressTracker.stepFailed(this.steps.PREPARE);
|
|
170
169
|
this.stopProgressTracker();
|
|
171
|
-
if ((graphQLError === null || graphQLError === void 0
|
|
170
|
+
if ((graphQLError === null || graphQLError === void 0 || (_graphQLError$extensi = graphQLError.extensions) === null || _graphQLError$extensi === void 0 ? void 0 : _graphQLError$extensi.errorHttpCode) === 429) {
|
|
172
171
|
const retryAfter = graphQLError.extensions.retryAfter;
|
|
173
172
|
await this.track('error', {
|
|
174
173
|
error_type: 'rate_limit_exceeded',
|
package/dist/lib/api/app.js
CHANGED
|
@@ -18,7 +18,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
18
18
|
async function _default(app, fields = 'id,name', fragments = '') {
|
|
19
19
|
const api = await (0, _api.default)();
|
|
20
20
|
if (isNaN(+app)) {
|
|
21
|
-
var _res$data$apps
|
|
21
|
+
var _res$data$apps;
|
|
22
22
|
const res = await api.query({
|
|
23
23
|
query: (0, _graphqlTag.default)`query App( $name: String ) {
|
|
24
24
|
apps( first: 1, name: $name ) {
|
|
@@ -34,7 +34,7 @@ async function _default(app, fields = 'id,name', fragments = '') {
|
|
|
34
34
|
name: app
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
|
-
if (!((_res$data$apps = res.data.apps) !== null && _res$data$apps !== void 0 && (_res$data$apps
|
|
37
|
+
if (!((_res$data$apps = res.data.apps) !== null && _res$data$apps !== void 0 && (_res$data$apps = _res$data$apps.edges) !== null && _res$data$apps !== void 0 && _res$data$apps.length)) {
|
|
38
38
|
return {};
|
|
39
39
|
}
|
|
40
40
|
return res.data.apps.edges[0];
|
|
@@ -43,7 +43,7 @@ const appQuery = `
|
|
|
43
43
|
`;
|
|
44
44
|
exports.appQuery = appQuery;
|
|
45
45
|
async function purgeCache(appId, envId, urls) {
|
|
46
|
-
var _response$data
|
|
46
|
+
var _response$data;
|
|
47
47
|
const api = await (0, _api.default)();
|
|
48
48
|
const variables = {
|
|
49
49
|
appId,
|
|
@@ -54,5 +54,5 @@ async function purgeCache(appId, envId, urls) {
|
|
|
54
54
|
mutation,
|
|
55
55
|
variables
|
|
56
56
|
});
|
|
57
|
-
return (
|
|
57
|
+
return ((_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.purgePageCache) ?? null;
|
|
58
58
|
}
|
package/dist/lib/api/http.js
CHANGED
|
@@ -31,7 +31,6 @@ const debug = (0, _debug.default)('@automattic/vip:http');
|
|
|
31
31
|
* @return {Promise} Return value of the `fetch` call
|
|
32
32
|
*/
|
|
33
33
|
var _default = async (path, options = {}) => {
|
|
34
|
-
var _options$headers;
|
|
35
34
|
let url = path;
|
|
36
35
|
|
|
37
36
|
// For convenience, we support just passing in the path to this function...
|
|
@@ -44,12 +43,12 @@ var _default = async (path, options = {}) => {
|
|
|
44
43
|
debug('running fetch', url);
|
|
45
44
|
return (0, _nodeFetch.default)(url, {
|
|
46
45
|
...options,
|
|
47
|
-
agent: proxyAgent
|
|
46
|
+
agent: proxyAgent ?? undefined,
|
|
48
47
|
headers: {
|
|
49
48
|
Authorization: `Bearer ${authToken.raw}`,
|
|
50
49
|
'User-Agent': _env.default.userAgent,
|
|
51
50
|
'Content-Type': 'application/json',
|
|
52
|
-
...(
|
|
51
|
+
...(options.headers ?? {})
|
|
53
52
|
},
|
|
54
53
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
55
54
|
body: typeof options.body === 'object' ? JSON.stringify(options.body) : options.body
|