@automattic/vip 2.22.0 → 2.24.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.
- package/CHANGELOG.md +38 -13
- package/assets/dev-env.lando.template.yml.ejs +6 -1
- package/dist/bin/vip-app-list.js +0 -12
- package/dist/bin/vip-app.js +6 -13
- package/dist/bin/vip-cache-purge-url.js +4 -19
- package/dist/bin/vip-cache.js +0 -2
- package/dist/bin/vip-config-envvar-delete.js +4 -19
- package/dist/bin/vip-config-envvar-get-all.js +6 -19
- package/dist/bin/vip-config-envvar-get.js +4 -15
- package/dist/bin/vip-config-envvar-list.js +8 -20
- package/dist/bin/vip-config-envvar-set.js +4 -23
- package/dist/bin/vip-config-envvar.js +0 -2
- package/dist/bin/vip-config-software-get.js +0 -17
- package/dist/bin/vip-config-software-update.js +6 -22
- package/dist/bin/vip-config-software.js +0 -2
- package/dist/bin/vip-config.js +0 -2
- package/dist/bin/vip-dev-env-create.js +8 -21
- package/dist/bin/vip-dev-env-destroy.js +4 -11
- package/dist/bin/vip-dev-env-exec.js +4 -14
- package/dist/bin/vip-dev-env-import-media.js +3 -8
- package/dist/bin/vip-dev-env-import-sql.js +10 -23
- package/dist/bin/vip-dev-env-import.js +0 -3
- package/dist/bin/vip-dev-env-info.js +5 -13
- package/dist/bin/vip-dev-env-list.js +4 -9
- package/dist/bin/vip-dev-env-start.js +9 -17
- package/dist/bin/vip-dev-env-stop.js +4 -11
- package/dist/bin/vip-dev-env-update.js +4 -12
- package/dist/bin/vip-dev-env.js +0 -2
- package/dist/bin/vip-import-media-abort.js +0 -18
- package/dist/bin/vip-import-media-status.js +0 -12
- package/dist/bin/vip-import-media.js +6 -23
- package/dist/bin/vip-import-sql-status.js +0 -12
- package/dist/bin/vip-import-sql.js +33 -99
- package/dist/bin/vip-import-validate-files.js +21 -42
- package/dist/bin/vip-import-validate-sql.js +0 -8
- package/dist/bin/vip-import.js +0 -3
- package/dist/bin/vip-logs.js +20 -50
- package/dist/bin/vip-search-replace.js +8 -14
- package/dist/bin/vip-sync.js +2 -25
- package/dist/bin/vip-validate-preflight.js +467 -0
- package/dist/bin/vip-validate.js +19 -0
- package/dist/bin/vip-whoami.js +2 -14
- package/dist/bin/vip-wp.js +39 -89
- package/dist/bin/vip.js +14 -40
- package/dist/lib/analytics/clients/pendo.js +9 -18
- package/dist/lib/analytics/clients/stub.js +1 -3
- package/dist/lib/analytics/clients/tracks.js +11 -20
- package/dist/lib/analytics/index.js +4 -11
- package/dist/lib/api/app.js +1 -11
- package/dist/lib/api/cache-purge.js +4 -7
- package/dist/lib/api/feature-flags.js +1 -4
- package/dist/lib/api/http.js +9 -15
- package/dist/lib/api/user.js +1 -7
- package/dist/lib/api.js +7 -18
- package/dist/lib/app-logs/app-logs.js +2 -9
- package/dist/lib/app.js +2 -5
- package/dist/lib/cli/apiConfig.js +4 -19
- package/dist/lib/cli/command.js +43 -133
- package/dist/lib/cli/config.js +1 -5
- package/dist/lib/cli/envAlias.js +14 -15
- package/dist/lib/cli/exit.js +4 -6
- package/dist/lib/cli/format.js +8 -50
- package/dist/lib/cli/progress.js +13 -42
- package/dist/lib/cli/prompt.js +1 -5
- package/dist/lib/cli/repo.js +7 -20
- package/dist/lib/client-file-uploader.js +44 -97
- package/dist/lib/config/software.js +2 -52
- package/dist/lib/constants/dev-environment.js +1 -2
- package/dist/lib/constants/file-size.js +1 -1
- package/dist/lib/constants/vipgo.js +1 -1
- package/dist/lib/dev-environment/dev-environment-cli.js +140 -195
- package/dist/lib/dev-environment/dev-environment-core.js +91 -186
- package/dist/lib/dev-environment/dev-environment-lando.js +32 -96
- package/dist/lib/env.js +1 -4
- package/dist/lib/envvar/api-delete.js +1 -4
- package/dist/lib/envvar/api-get-all.js +1 -4
- package/dist/lib/envvar/api-get.js +1 -2
- package/dist/lib/envvar/api-list.js +3 -4
- package/dist/lib/envvar/api-set.js +1 -4
- package/dist/lib/envvar/api.js +5 -16
- package/dist/lib/envvar/input.js +1 -8
- package/dist/lib/envvar/logging.js +2 -6
- package/dist/lib/envvar/read-file.js +1 -3
- package/dist/lib/http/proxy-agent.js +17 -22
- package/dist/lib/keychain/browser.js +1 -4
- package/dist/lib/keychain/insecure.js +1 -10
- package/dist/lib/keychain/secure.js +1 -8
- package/dist/lib/keychain.js +4 -8
- package/dist/lib/logout.js +0 -6
- package/dist/lib/media-import/media-file-import.js +3 -7
- package/dist/lib/media-import/progress.js +6 -17
- package/dist/lib/media-import/status.js +14 -65
- package/dist/lib/read-file.js +1 -6
- package/dist/lib/rollbar.js +1 -7
- package/dist/lib/search-and-replace.js +9 -41
- package/dist/lib/site-import/db-file-import.js +3 -9
- package/dist/lib/site-import/status.js +17 -74
- package/dist/lib/token.js +1 -33
- package/dist/lib/tracker.js +4 -20
- package/dist/lib/user-error.js +0 -2
- package/dist/lib/validations/is-multi-site-sql-dump.js +4 -12
- package/dist/lib/validations/is-multi-site.js +5 -21
- package/dist/lib/validations/is-multisite-domain-mapped.js +5 -31
- package/dist/lib/validations/line-by-line.js +4 -16
- package/dist/lib/validations/site-type.js +10 -19
- package/dist/lib/validations/sql.js +11 -76
- package/dist/lib/validations/utils.js +1 -6
- package/dist/lib/vip-import-validate-files.js +82 -109
- package/npm-shrinkwrap.json +894 -357
- package/package.json +5 -2
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "__esModule", {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
exports.appQuery = void 0;
|
|
12
|
+
exports.vipValidatePreflightCommand = vipValidatePreflightCommand;
|
|
13
|
+
var _vipGoPreflightChecks = require("@automattic/vip-go-preflight-checks");
|
|
14
|
+
var _path = _interopRequireDefault(require("path"));
|
|
15
|
+
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
16
|
+
var _fs = require("fs");
|
|
17
|
+
var _ini = _interopRequireDefault(require("ini"));
|
|
18
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
19
|
+
var _enquirer = require("enquirer");
|
|
20
|
+
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
21
|
+
var _envAlias = require("../lib/cli/envAlias");
|
|
22
|
+
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
23
|
+
var _api = _interopRequireWildcard(require("../lib/api"));
|
|
24
|
+
var _tracker = require("../lib/tracker");
|
|
25
|
+
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); }
|
|
26
|
+
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; }
|
|
27
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
28
|
+
/**
|
|
29
|
+
* Internal dependencies
|
|
30
|
+
*/
|
|
31
|
+
const ALLOWED_NODEJS_VERSIONS = ['14', '16', '18'];
|
|
32
|
+
const appQuery = `
|
|
33
|
+
id
|
|
34
|
+
name
|
|
35
|
+
repo
|
|
36
|
+
environments {
|
|
37
|
+
id
|
|
38
|
+
appId
|
|
39
|
+
name
|
|
40
|
+
type
|
|
41
|
+
environmentVariables {
|
|
42
|
+
nodes {
|
|
43
|
+
name,
|
|
44
|
+
value
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
organization {
|
|
49
|
+
id
|
|
50
|
+
name
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
exports.appQuery = appQuery;
|
|
54
|
+
let suppressOutput = false;
|
|
55
|
+
let outputJson = false;
|
|
56
|
+
let harmoniaArgs = [];
|
|
57
|
+
function logToConsole(...messages) {
|
|
58
|
+
if (suppressOutput) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (messages.length === 0) {
|
|
62
|
+
messages = [''];
|
|
63
|
+
}
|
|
64
|
+
messages.forEach(message => console.log(message));
|
|
65
|
+
}
|
|
66
|
+
async function getBuildConfiguration(application, environment) {
|
|
67
|
+
const api = await (0, _api.default)();
|
|
68
|
+
|
|
69
|
+
// Disable the global GraphQL error handling, so we can catch Unauthorized errors and recommend next steps.
|
|
70
|
+
(0, _api.disableGlobalGraphQLErrorHandling)();
|
|
71
|
+
const buildConfigQuery = (0, _graphqlTag.default)`
|
|
72
|
+
query BuildConfig( $appId: Int, $envId: Int ) {
|
|
73
|
+
app(id: $appId) {
|
|
74
|
+
environments(id: $envId) {
|
|
75
|
+
id,
|
|
76
|
+
buildConfiguration {
|
|
77
|
+
buildType
|
|
78
|
+
nodeBuildDockerEnv,
|
|
79
|
+
nodeJSVersion,
|
|
80
|
+
npmToken,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}`;
|
|
85
|
+
try {
|
|
86
|
+
const result = await api.query({
|
|
87
|
+
query: buildConfigQuery,
|
|
88
|
+
fetchPolicy: 'network-only',
|
|
89
|
+
variables: {
|
|
90
|
+
appId: environment.appId,
|
|
91
|
+
envId: environment.id
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Reenable GraphQL error handling
|
|
96
|
+
(0, _api.enableGlobalGraphQLErrorHandling)();
|
|
97
|
+
return result.data.app.environments[0].buildConfiguration;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (error.graphQLErrors && error.graphQLErrors.find(gqlError => gqlError.message === 'Unauthorized')) {
|
|
100
|
+
console.log(`${_chalk.default.red('Error:')} You don't have the required permissions to run validations for this environment.\n` + `You must be either be an admin of the ${_chalk.default.bold.underline(application.organization.name)} organization, or, alternatively,\n` + `a guest of that organization and an admin of the ${_chalk.default.bold.underline(application.name)} application.\n\n` + 'You can read more about organization and application roles on our documentation:\n' + _chalk.default.underline('https://docs.wpvip.com/technical-references/enterprise-authentication/'));
|
|
101
|
+
await (0, _tracker.trackEvent)('validate_preflight_command_error', {
|
|
102
|
+
env_id: environment.id,
|
|
103
|
+
app_id: environment.appId,
|
|
104
|
+
error: 'unauthorized'
|
|
105
|
+
});
|
|
106
|
+
process.exit(1);
|
|
107
|
+
} else {
|
|
108
|
+
// Handle it elsewhere
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function vipValidatePreflightCommand(arg, opt) {
|
|
114
|
+
var _opt$env$appId, _opt$env, _opt$env$id, _opt$env2, _opt$app$repo, _opt$app, _opt$env3, _opt$env3$environment;
|
|
115
|
+
harmoniaArgs = await validateArgs(opt);
|
|
116
|
+
const appId = (_opt$env$appId = (_opt$env = opt.env) === null || _opt$env === void 0 ? void 0 : _opt$env.appId) !== null && _opt$env$appId !== void 0 ? _opt$env$appId : 0;
|
|
117
|
+
const envId = (_opt$env$id = (_opt$env2 = opt.env) === null || _opt$env2 === void 0 ? void 0 : _opt$env2.id) !== null && _opt$env$id !== void 0 ? _opt$env$id : 0;
|
|
118
|
+
const baseTrackingParams = {
|
|
119
|
+
env_id: envId,
|
|
120
|
+
app_id: appId,
|
|
121
|
+
command: 'vip validate preflight',
|
|
122
|
+
...sanitizeArgsForTracking(harmoniaArgs)
|
|
123
|
+
};
|
|
124
|
+
await (0, _tracker.trackEvent)('validate_preflight_command_execute', baseTrackingParams);
|
|
125
|
+
logToConsole(' /\\ /\\__ _ _ __ _ __ ___ ___ _ __ (_) __ _ ');
|
|
126
|
+
logToConsole(' / /_/ / _` | \'__| \'_ ` _ \\ / _ \\| \'_ \\| |/ _` |');
|
|
127
|
+
logToConsole('/ __ / (_| | | | | | | | | (_) | | | | | (_| |');
|
|
128
|
+
logToConsole('\\/ /_/ \\__,_|_| |_| |_| |_|\\___/|_| |_|_|\\__,_|');
|
|
129
|
+
logToConsole('VIP Harmonia - Application testing made easy\n');
|
|
130
|
+
const harmonia = new _vipGoPreflightChecks.Harmonia();
|
|
131
|
+
harmonia.setSource('vip-cli');
|
|
132
|
+
if (harmoniaArgs.buildType !== 'nodejs') {
|
|
133
|
+
await (0, _tracker.trackEvent)('validate_preflight_command_error', {
|
|
134
|
+
...baseTrackingParams,
|
|
135
|
+
error: 'not-nodejs'
|
|
136
|
+
});
|
|
137
|
+
exit.withError('Currently, only Node.js applications are supported.');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Register the default tests.
|
|
141
|
+
harmonia.registerDefaultTests();
|
|
142
|
+
|
|
143
|
+
// Create the Site Config objects
|
|
144
|
+
const siteOptions = new _vipGoPreflightChecks.SiteConfig({
|
|
145
|
+
siteID: envId,
|
|
146
|
+
nodejsVersion: harmoniaArgs.nodejsVersion,
|
|
147
|
+
repository: (_opt$app$repo = (_opt$app = opt.app) === null || _opt$app === void 0 ? void 0 : _opt$app.repo) !== null && _opt$app$repo !== void 0 ? _opt$app$repo : 'no-repo',
|
|
148
|
+
baseURL: 'http://localhost:' + harmoniaArgs.port,
|
|
149
|
+
dockerBuildEnvs: harmoniaArgs.nodeBuildDockerEnv,
|
|
150
|
+
topRequests: [],
|
|
151
|
+
// TODO: get top 10 of most requested URLs
|
|
152
|
+
wait: harmoniaArgs.wait
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Get package.json
|
|
156
|
+
const packageJSONfile = _path.default.resolve(opt.path, 'package.json');
|
|
157
|
+
let packageJSON;
|
|
158
|
+
try {
|
|
159
|
+
packageJSON = require(packageJSONfile);
|
|
160
|
+
siteOptions.setPackageJSON(packageJSON);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
await (0, _tracker.trackEvent)('validate_preflight_command_error', {
|
|
163
|
+
...baseTrackingParams,
|
|
164
|
+
error: 'missing-package-json'
|
|
165
|
+
});
|
|
166
|
+
return exit.withError(`Could not find a 'package.json' in the current folder (${opt.path}).`);
|
|
167
|
+
}
|
|
168
|
+
const customEnvVars = {};
|
|
169
|
+
if (((_opt$env3 = opt.env) === null || _opt$env3 === void 0 ? void 0 : (_opt$env3$environment = _opt$env3.environmentVariables) === null || _opt$env3$environment === void 0 ? void 0 : _opt$env3$environment.nodes.length) > 0) {
|
|
170
|
+
opt.env.environmentVariables.nodes.forEach(envVar => {
|
|
171
|
+
customEnvVars[envVar.name] = envVar.value;
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Create the EnviornmentVariables object
|
|
176
|
+
const envVars = new _vipGoPreflightChecks.EnvironmentVariables({
|
|
177
|
+
PORT: harmoniaArgs.port,
|
|
178
|
+
...customEnvVars
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Add NPM_TOKEN environment variable, if present
|
|
182
|
+
if (harmoniaArgs.npmToken) {
|
|
183
|
+
envVars.set('NPM_TOKEN', harmoniaArgs.npmToken);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Get from .env, if exists
|
|
187
|
+
let dotenvOptions = {};
|
|
188
|
+
try {
|
|
189
|
+
const dotenvPath = _path.default.resolve(opt.path, '.env');
|
|
190
|
+
const dotenvContent = (0, _fs.readFileSync)(dotenvPath);
|
|
191
|
+
dotenvOptions = _ini.default.parse(dotenvContent);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
// nothing
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Save dotenv in the site config
|
|
197
|
+
siteOptions.set('dotenv', dotenvOptions);
|
|
198
|
+
|
|
199
|
+
// Bootstrap
|
|
200
|
+
try {
|
|
201
|
+
harmonia.bootstrap(siteOptions, envVars);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
await (0, _tracker.trackEvent)('validate_preflight_command_error', {
|
|
204
|
+
...baseTrackingParams,
|
|
205
|
+
error: error.message
|
|
206
|
+
});
|
|
207
|
+
return exit.withError(error.message);
|
|
208
|
+
}
|
|
209
|
+
setupEvents(harmonia);
|
|
210
|
+
runHarmonia(harmonia);
|
|
211
|
+
}
|
|
212
|
+
function setupEvents(harmonia) {
|
|
213
|
+
// Register some events handlers
|
|
214
|
+
harmonia.on('ready', () => {
|
|
215
|
+
logToConsole('Harmonia is ready! ');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Register the event handlers to output some information during the execution
|
|
219
|
+
harmonia.on('beforeTestSuite', suite => {
|
|
220
|
+
const description = suite.description ? `- ${_chalk.default.italic(suite.description)}` : '';
|
|
221
|
+
logToConsole(` >> Running test suite ${_chalk.default.bold(suite.name)} ${description} `);
|
|
222
|
+
logToConsole();
|
|
223
|
+
});
|
|
224
|
+
harmonia.on('beforeTest', test => {
|
|
225
|
+
logToConsole(` [ ${_chalk.default.bold(test.name)} ] - ${test.description}`);
|
|
226
|
+
});
|
|
227
|
+
harmonia.on('afterTest', (test, result) => {
|
|
228
|
+
switch (result.getType()) {
|
|
229
|
+
case _vipGoPreflightChecks.TestResultType.Success:
|
|
230
|
+
logToConsole(` ✅ ${_chalk.default.bgGreen(' Test passed with no errors. ')}`);
|
|
231
|
+
break;
|
|
232
|
+
case _vipGoPreflightChecks.TestResultType.Failed:
|
|
233
|
+
logToConsole(` ❌ ${_chalk.default.bgRed(` Test failed with ${result.getErrors().length} errors. `)}`);
|
|
234
|
+
break;
|
|
235
|
+
case _vipGoPreflightChecks.TestResultType.PartialSuccess:
|
|
236
|
+
logToConsole(` ✅ ${_chalk.default.bgYellow(' Test partially succeeded. ')}`);
|
|
237
|
+
break;
|
|
238
|
+
case _vipGoPreflightChecks.TestResultType.Aborted:
|
|
239
|
+
logToConsole(` ❌ ${_chalk.default.bgRedBright.underline(' Test aborted! ')} - There was a critical error that makes`, 'the application incompatible with the VIP Platform.');
|
|
240
|
+
break;
|
|
241
|
+
case _vipGoPreflightChecks.TestResultType.Skipped:
|
|
242
|
+
logToConsole(` ${_chalk.default.bgGrey.bold(' Skipped ')}\t${result.getLastNotice().message}`);
|
|
243
|
+
}
|
|
244
|
+
logToConsole();
|
|
245
|
+
});
|
|
246
|
+
harmonia.on('afterTestSuite', (test, result) => {
|
|
247
|
+
// Create a badge
|
|
248
|
+
let badge;
|
|
249
|
+
switch (result.getType()) {
|
|
250
|
+
case _vipGoPreflightChecks.TestResultType.Failed:
|
|
251
|
+
badge = _chalk.default.bgRed.bold(' FAILED ');
|
|
252
|
+
break;
|
|
253
|
+
case _vipGoPreflightChecks.TestResultType.Aborted:
|
|
254
|
+
badge = _chalk.default.bgRedBright.underline.bold(' ABORTED ');
|
|
255
|
+
break;
|
|
256
|
+
case _vipGoPreflightChecks.TestResultType.PartialSuccess:
|
|
257
|
+
badge = _chalk.default.bgYellow.bold(' PASS ');
|
|
258
|
+
break;
|
|
259
|
+
default:
|
|
260
|
+
badge = _chalk.default.bgGreen.bold(' PASS ');
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
logToConsole(` >> ${badge} Finished running ${_chalk.default.bold(test.name)} suite`);
|
|
264
|
+
logToConsole();
|
|
265
|
+
});
|
|
266
|
+
harmonia.on('issue', issue => {
|
|
267
|
+
let issueTypeString = issue.getTypeString();
|
|
268
|
+
switch (issue.type) {
|
|
269
|
+
case _vipGoPreflightChecks.IssueType.Blocker:
|
|
270
|
+
issueTypeString = _chalk.default.bgRedBright.underline.bold(issueTypeString);
|
|
271
|
+
break;
|
|
272
|
+
case _vipGoPreflightChecks.IssueType.Error:
|
|
273
|
+
issueTypeString = _chalk.default.bgRed.bold(issueTypeString);
|
|
274
|
+
break;
|
|
275
|
+
case _vipGoPreflightChecks.IssueType.Warning:
|
|
276
|
+
issueTypeString = _chalk.default.bgYellow.bold(issueTypeString);
|
|
277
|
+
break;
|
|
278
|
+
case _vipGoPreflightChecks.IssueType.Notice:
|
|
279
|
+
issueTypeString = _chalk.default.bgGray.bold(issueTypeString);
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
const documentation = issue.documentation ? `(${issue.documentation})` : '';
|
|
283
|
+
|
|
284
|
+
// Replace \n with \n\t\t to keep new lines aligned
|
|
285
|
+
const message = issue.message.replace(/\n/g, '\n\t\t');
|
|
286
|
+
logToConsole(` ${issueTypeString} \t${message} ${documentation}`);
|
|
287
|
+
|
|
288
|
+
// If it's a Blocker or Error, and the issue includes a stdout, print it out.
|
|
289
|
+
const issueData = issue.getData();
|
|
290
|
+
if (issueData && [_vipGoPreflightChecks.IssueType.Blocker, _vipGoPreflightChecks.IssueType.Error].includes(issue.type)) {
|
|
291
|
+
if (issueData.all) {
|
|
292
|
+
logToConsole(issueData.all);
|
|
293
|
+
logToConsole();
|
|
294
|
+
} else if (typeof issueData === 'string') {
|
|
295
|
+
logToConsole(issueData);
|
|
296
|
+
logToConsole();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
function runHarmonia(harmonia) {
|
|
302
|
+
harmonia.run().then(async results => await handleResults(harmonia, results));
|
|
303
|
+
}
|
|
304
|
+
async function handleResults(harmonia, results) {
|
|
305
|
+
// Calculate the results
|
|
306
|
+
const resultCounter = harmonia.countResults(false);
|
|
307
|
+
const testSuiteResults = results.filter(result => result instanceof _vipGoPreflightChecks.TestSuiteResult);
|
|
308
|
+
|
|
309
|
+
// Send success event
|
|
310
|
+
await (0, _tracker.trackEvent)('validate_preflight_command_success', {
|
|
311
|
+
command: 'vip validate preflight',
|
|
312
|
+
...sanitizeArgsForTracking(harmoniaArgs),
|
|
313
|
+
skipped: resultCounter[_vipGoPreflightChecks.TestResultType.Skipped],
|
|
314
|
+
success: resultCounter[_vipGoPreflightChecks.TestResultType.Success],
|
|
315
|
+
partial_success: resultCounter[_vipGoPreflightChecks.TestResultType.PartialSuccess],
|
|
316
|
+
failed: resultCounter[_vipGoPreflightChecks.TestResultType.Failed],
|
|
317
|
+
aborted: resultCounter[_vipGoPreflightChecks.TestResultType.Aborted]
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// If the output is JSON, reenable the logToConsole output and print-out the json format.
|
|
321
|
+
if (outputJson) {
|
|
322
|
+
suppressOutput = false;
|
|
323
|
+
logToConsole(harmonia.resultsJSON());
|
|
324
|
+
process.exit(0);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Print the results
|
|
328
|
+
logToConsole('\n' + _chalk.default.bgGray(' HARMONIA RESULTS \n'));
|
|
329
|
+
if (resultCounter[_vipGoPreflightChecks.TestResultType.Skipped]) {
|
|
330
|
+
logToConsole(` ${_chalk.default.bold.bgGrey(' SKIPPED ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.Skipped])} tests`);
|
|
331
|
+
}
|
|
332
|
+
if (resultCounter[_vipGoPreflightChecks.TestResultType.Success]) {
|
|
333
|
+
logToConsole(` ${_chalk.default.bold.bgGreen(' PASSED ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.Success])} tests`);
|
|
334
|
+
}
|
|
335
|
+
if (resultCounter[_vipGoPreflightChecks.TestResultType.PartialSuccess]) {
|
|
336
|
+
logToConsole(` ${_chalk.default.bold.bgYellow(' PARTIAL SUCCESS ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.PartialSuccess])} tests`);
|
|
337
|
+
}
|
|
338
|
+
if (resultCounter[_vipGoPreflightChecks.TestResultType.Failed]) {
|
|
339
|
+
logToConsole(` ${_chalk.default.bold.bgRed(' FAILED ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.Failed])} tests`);
|
|
340
|
+
}
|
|
341
|
+
if (resultCounter[_vipGoPreflightChecks.TestResultType.Aborted]) {
|
|
342
|
+
logToConsole(` ${_chalk.default.bold.bgRedBright(' ABORTED ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.Aborted])} tests`);
|
|
343
|
+
}
|
|
344
|
+
logToConsole();
|
|
345
|
+
logToConsole(` > Total of ${_chalk.default.bold(results.length - testSuiteResults.length)} tests have been executed.`);
|
|
346
|
+
logToConsole();
|
|
347
|
+
|
|
348
|
+
// If there is a Aborted test result
|
|
349
|
+
if (resultCounter[_vipGoPreflightChecks.TestResultType.Aborted]) {
|
|
350
|
+
logToConsole(`${_chalk.default.bold.bgRedBright(' NOT PASS ')} There was a critical failure that makes the application ` + 'incompatible with VIP Go. Please review the results and re-run the tests.');
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// If there is only a partial success, but no failures
|
|
355
|
+
if (resultCounter[_vipGoPreflightChecks.TestResultType.PartialSuccess] && !resultCounter[_vipGoPreflightChecks.TestResultType.Failed]) {
|
|
356
|
+
logToConsole(`${_chalk.default.bold.bgYellow(' PASS ')} The application has passed the required tests, but it does not follow all the recommendations.`);
|
|
357
|
+
logToConsole('Please review the results.');
|
|
358
|
+
process.exit(0);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// If there is a failure
|
|
362
|
+
if (resultCounter[_vipGoPreflightChecks.TestResultType.Failed]) {
|
|
363
|
+
logToConsole(`${_chalk.default.bold.bgRed(' NOT PASS ')} The application has failed some tests, and will very likely have problems in a production ` + 'environment. Please review all the errors found in the results.');
|
|
364
|
+
process.exit(1);
|
|
365
|
+
}
|
|
366
|
+
logToConsole(`${_chalk.default.bold.bgGreen(' PASS ')} Congratulations. The application passes all the tests.`);
|
|
367
|
+
process.exit(0);
|
|
368
|
+
}
|
|
369
|
+
async function validateArgs(opt) {
|
|
370
|
+
var _opt$wait, _opt$port;
|
|
371
|
+
const args = {};
|
|
372
|
+
|
|
373
|
+
// Verbose
|
|
374
|
+
if (opt.verbose) {
|
|
375
|
+
_vipGoPreflightChecks.Harmonia.setVerbosity(true);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Set path
|
|
379
|
+
if (opt.path) {
|
|
380
|
+
_vipGoPreflightChecks.Harmonia.setCwd(opt.path);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// If the JSON option is enabled, all the stdout should be suppressed to prevent polluting the output.
|
|
384
|
+
if (opt.json) {
|
|
385
|
+
suppressOutput = true;
|
|
386
|
+
outputJson = true;
|
|
387
|
+
}
|
|
388
|
+
if (opt.app) {
|
|
389
|
+
var _opt$nodeVersion;
|
|
390
|
+
// Get build information from API and store it in the env object
|
|
391
|
+
const buildConfig = await getBuildConfiguration(opt.app, opt.env);
|
|
392
|
+
args.app_id = opt.app.id;
|
|
393
|
+
args.env_id = opt.env.id;
|
|
394
|
+
args.nodejsVersion = (_opt$nodeVersion = opt.nodeVersion) !== null && _opt$nodeVersion !== void 0 ? _opt$nodeVersion : buildConfig.nodeJSVersion;
|
|
395
|
+
args.buildType = buildConfig.buildType;
|
|
396
|
+
args.npmToken = buildConfig.npmToken;
|
|
397
|
+
args.nodeBuildDockerEnv = buildConfig.nodeBuildDockerEnv;
|
|
398
|
+
} else {
|
|
399
|
+
args.app_id = 0;
|
|
400
|
+
args.env_id = 0;
|
|
401
|
+
args.buildType = 'nodejs';
|
|
402
|
+
|
|
403
|
+
// If no node.js version is specified, prompt the user to select one
|
|
404
|
+
if (!opt.nodeVersion) {
|
|
405
|
+
// Ask for a node.js version
|
|
406
|
+
try {
|
|
407
|
+
const selection = await (0, _enquirer.prompt)({
|
|
408
|
+
type: 'select',
|
|
409
|
+
name: 'nodejsVersion',
|
|
410
|
+
message: 'Which Node.js version do you want to use?',
|
|
411
|
+
choices: ALLOWED_NODEJS_VERSIONS
|
|
412
|
+
});
|
|
413
|
+
args.nodejsVersion = selection.nodejsVersion;
|
|
414
|
+
} catch (err) {
|
|
415
|
+
exit.withError('No Node.js version selected. Aborting.');
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
args.nodejsVersion = opt.nodeVersion;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
args.wait = (_opt$wait = opt.wait) !== null && _opt$wait !== void 0 ? _opt$wait : 3000;
|
|
422
|
+
args.port = (_opt$port = opt.port) !== null && _opt$port !== void 0 ? _opt$port : Math.floor(Math.random() * 1000) + 3001; // Get a PORT from 3001 and 3999
|
|
423
|
+
|
|
424
|
+
return args;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Remove sensitive information from the tracked events and snake_case the keys.
|
|
429
|
+
*
|
|
430
|
+
* @param {object} args The arguments passed to the command.
|
|
431
|
+
* @returns {object} Copy of the arguments without sensitive information.
|
|
432
|
+
*/
|
|
433
|
+
function sanitizeArgsForTracking(args) {
|
|
434
|
+
const protectedKeys = ['npmToken', 'nodeBuildDockerEnv'];
|
|
435
|
+
const sanitizedArgs = {};
|
|
436
|
+
Object.entries(args).forEach(([key, value]) => {
|
|
437
|
+
if (protectedKeys.includes(key)) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
// snake_case the key, as required by Tracks
|
|
441
|
+
sanitizedArgs[key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)] = value;
|
|
442
|
+
});
|
|
443
|
+
return sanitizedArgs;
|
|
444
|
+
}
|
|
445
|
+
let commandOpts = {
|
|
446
|
+
module: 'harmonia'
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// The @app.env selector is optional, so we need to check if it was passed
|
|
450
|
+
const parsedAlias = (0, _envAlias.parseEnvAliasFromArgv)(process.argv);
|
|
451
|
+
if (parsedAlias.app) {
|
|
452
|
+
commandOpts = {
|
|
453
|
+
...commandOpts,
|
|
454
|
+
appQuery,
|
|
455
|
+
envContext: true,
|
|
456
|
+
appContext: true
|
|
457
|
+
};
|
|
458
|
+
} else {
|
|
459
|
+
logToConsole(_chalk.default.bold.yellow('Warning: ') + 'The preflight tests are running without a provided application and/or environment.\n' + 'Some app-dependent configurations, such as environment variables, might not defined.');
|
|
460
|
+
}
|
|
461
|
+
(0, _command.default)(commandOpts).option('verbose', 'Increase logging level to include app build and server boot up messages', false).option('node-version', 'Select a specific target Node.JS version in semver format (MAJOR.MINOR.PATCH) or a MAJOR').option('wait', 'Configure the time to wait in ms for the app to boot up. Do not change unless you have issues', 3000).option(['p', 'port'], 'Configure the port to use for the app (defaults to a random port between 3001 and 3999)').option('json', 'Output the results as JSON', false).option(['P', 'path'], 'Path to the app to be tested', process.cwd()).examples([{
|
|
462
|
+
usage: 'vip @mysite.production validate preflight',
|
|
463
|
+
description: 'Runs the preflight tests to validate if your application is ready to be deployed to VIP Go'
|
|
464
|
+
}, {
|
|
465
|
+
usage: 'vip @mysite.production validate preflight --json > results.json',
|
|
466
|
+
description: 'Runs the preflight tests, but output the results in JSON format, and redirect the output to a file'
|
|
467
|
+
}]).argv(process.argv, vipValidatePreflightCommand);
|
|
@@ -0,0 +1,19 @@
|
|
|
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 _tracker = require("../lib/tracker");
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
(0, _command.default)({
|
|
16
|
+
requiredArgs: 1
|
|
17
|
+
}).command('preflight', 'Runs preflight tests to validate if your application is ready to be deployed').argv(process.argv, async () => {
|
|
18
|
+
await (0, _tracker.trackEvent)('vip_validate_command_execute');
|
|
19
|
+
});
|
package/dist/bin/vip-whoami.js
CHANGED
|
@@ -18,47 +18,35 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
18
18
|
value: true
|
|
19
19
|
});
|
|
20
20
|
exports.whoamiCommand = whoamiCommand;
|
|
21
|
-
|
|
22
21
|
var _user = require("../lib/api/user");
|
|
23
|
-
|
|
24
22
|
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
25
|
-
|
|
26
23
|
var _tracker = require("../lib/tracker");
|
|
27
|
-
|
|
28
24
|
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
29
|
-
|
|
30
25
|
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); }
|
|
31
|
-
|
|
32
26
|
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; }
|
|
33
|
-
|
|
34
27
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
35
|
-
|
|
36
28
|
async function whoamiCommand() {
|
|
37
29
|
const trackingParams = {
|
|
38
30
|
command: 'vip whoami'
|
|
39
31
|
};
|
|
40
32
|
await (0, _tracker.trackEvent)('whoami_command_execute', trackingParams);
|
|
41
33
|
let currentUser = {};
|
|
42
|
-
|
|
43
34
|
try {
|
|
44
35
|
currentUser = await (0, _user.getCurrentUserInfo)();
|
|
45
36
|
} catch (err) {
|
|
46
|
-
await (0, _tracker.trackEvent)('whoami_command_error', {
|
|
37
|
+
await (0, _tracker.trackEvent)('whoami_command_error', {
|
|
38
|
+
...trackingParams,
|
|
47
39
|
error: err.message
|
|
48
40
|
});
|
|
49
41
|
exit.withError(`Failed to fetch information about the currently logged-in user error: ${err.message}`);
|
|
50
42
|
}
|
|
51
|
-
|
|
52
43
|
await (0, _tracker.trackEvent)('whoami_command_success', trackingParams);
|
|
53
44
|
const output = [`- Howdy ${currentUser.displayName}!`, `- Your user ID is ${currentUser.id}`];
|
|
54
|
-
|
|
55
45
|
if (currentUser.isVIP) {
|
|
56
46
|
output.push('- Your account has VIP Staff permissions');
|
|
57
47
|
}
|
|
58
|
-
|
|
59
48
|
console.log(output.join('\n'));
|
|
60
49
|
}
|
|
61
|
-
|
|
62
50
|
(0, _command.default)({
|
|
63
51
|
usage: 'vip whoami'
|
|
64
52
|
}).examples([{
|