@automattic/vip 3.18.0 → 3.19.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/dist/bin/vip-app.js +6 -2
- package/dist/bin/vip-import-media.js +1 -1
- package/dist/bin/vip-import-sql.js +4 -4
- package/dist/bin/vip-import-validate-files.js +1 -4
- package/dist/bin/vip-wp.js +18 -7
- package/dist/bin/vip.js +1 -1
- package/dist/commands/backup-db.js +2 -5
- package/dist/commands/dev-env-sync-sql.js +13 -4
- package/dist/commands/phpmyadmin.js +4 -7
- package/dist/commands/wp-ssh.js +3 -5
- package/dist/lib/analytics/clients/tracks.js +0 -1
- package/dist/lib/analytics/index.js +0 -1
- package/dist/lib/backup-storage-availability/backup-storage-availability.js +0 -1
- package/dist/lib/cli/command.js +9 -11
- package/dist/lib/cli/config.js +30 -11
- package/dist/lib/cli/format.js +4 -8
- package/dist/lib/config/software.js +2 -1
- package/dist/lib/custom-deploy/custom-deploy.js +2 -2
- package/dist/lib/database.js +6 -6
- package/dist/lib/dev-environment/dev-environment-cli.js +5 -3
- package/dist/lib/dev-environment/dev-environment-core.js +2 -4
- package/dist/lib/dev-environment/dev-environment-database.js +4 -0
- package/dist/lib/dev-environment/dev-environment-lando.js +3 -2
- package/dist/lib/keychain/insecure.js +0 -1
- package/dist/lib/keychain.js +5 -4
- package/dist/lib/media-import/config.js +1 -1
- package/dist/lib/site-import/status.js +2 -7
- package/dist/lib/validations/is-multisite-domain-mapped.js +3 -2
- package/dist/lib/validations/line-by-line.js +2 -2
- package/docs/CHANGELOG.md +55 -0
- package/npm-shrinkwrap.json +3650 -4015
- package/package.json +12 -15
- package/dist/bin/vip-validate-preflight.js +0 -481
- package/dist/bin/vip-validate.js +0 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/vip",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.19.1",
|
|
4
4
|
"description": "The VIP Javascript library & CLI",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -62,8 +62,6 @@
|
|
|
62
62
|
"vip-search-replace": "dist/bin/vip-search-replace.js",
|
|
63
63
|
"vip-slowlogs": "dist/bin/vip-slowlogs.js",
|
|
64
64
|
"vip-sync": "dist/bin/vip-sync.js",
|
|
65
|
-
"vip-validate": "dist/bin/vip-validate.js",
|
|
66
|
-
"vip-validate-preflight": "dist/bin/vip-validate-preflight.js",
|
|
67
65
|
"vip-whoami": "dist/bin/vip-whoami.js",
|
|
68
66
|
"vip-wp": "dist/bin/vip-wp.js",
|
|
69
67
|
"vip-logout": "dist/bin/vip-logout.js"
|
|
@@ -114,19 +112,19 @@
|
|
|
114
112
|
"homepage": "https://github.com/Automattic/vip#readme",
|
|
115
113
|
"devDependencies": {
|
|
116
114
|
"@automattic/eslint-plugin-wpvip": "0.13.1",
|
|
117
|
-
"@babel/cli": "7.
|
|
118
|
-
"@babel/core": "7.
|
|
119
|
-
"@babel/preset-env": "7.
|
|
115
|
+
"@babel/cli": "7.28.0",
|
|
116
|
+
"@babel/core": "7.28.0",
|
|
117
|
+
"@babel/preset-env": "7.28.0",
|
|
120
118
|
"@babel/preset-typescript": "7.27.1",
|
|
121
|
-
"@jest/globals": "^
|
|
122
|
-
"@jest/test-sequencer": "^
|
|
119
|
+
"@jest/globals": "^30.0.0",
|
|
120
|
+
"@jest/test-sequencer": "^30.0.0",
|
|
123
121
|
"@types/args": "^5.0.3",
|
|
124
122
|
"@types/cli-table": "^0.3.4",
|
|
125
123
|
"@types/configstore": "5.0.1",
|
|
126
124
|
"@types/debug": "^4.1.12",
|
|
127
125
|
"@types/dockerode": "^3.3.23",
|
|
128
126
|
"@types/ejs": "^3.1.5",
|
|
129
|
-
"@types/jest": "^
|
|
127
|
+
"@types/jest": "^30.0.0",
|
|
130
128
|
"@types/js-yaml": "^4.0.9",
|
|
131
129
|
"@types/node": "^24.0.0",
|
|
132
130
|
"@types/node-fetch": "^2.6.9",
|
|
@@ -139,7 +137,7 @@
|
|
|
139
137
|
"@types/xml2js": "^0.4.14",
|
|
140
138
|
"dockerode": "^4.0.0",
|
|
141
139
|
"eslint": "^8.35.0",
|
|
142
|
-
"jest": "^
|
|
140
|
+
"jest": "^30.0.0",
|
|
143
141
|
"nock": "13.5.6",
|
|
144
142
|
"prettier": "npm:wp-prettier@2.8.5",
|
|
145
143
|
"rimraf": "6.0.1",
|
|
@@ -147,7 +145,6 @@
|
|
|
147
145
|
},
|
|
148
146
|
"dependencies": {
|
|
149
147
|
"@apollo/client": "3.3.6",
|
|
150
|
-
"@automattic/vip-go-preflight-checks": "^2.0.16",
|
|
151
148
|
"@automattic/vip-search-replace": "^1.1.1",
|
|
152
149
|
"@json2csv/plainjs": "^7.0.3",
|
|
153
150
|
"@wwa/single-line-log": "^1.1.4",
|
|
@@ -163,11 +160,11 @@
|
|
|
163
160
|
"fetch-retry": "^6.0.0",
|
|
164
161
|
"graphql": "15.5.1",
|
|
165
162
|
"graphql-tag": "2.12.6",
|
|
166
|
-
"https-proxy-agent": "^
|
|
163
|
+
"https-proxy-agent": "^7.0.6",
|
|
167
164
|
"ini": "5.0.0",
|
|
168
165
|
"js-yaml": "^4.1.0",
|
|
169
166
|
"jwt-decode": "4.0.0",
|
|
170
|
-
"lando": "github:automattic/lando-cli#
|
|
167
|
+
"lando": "github:automattic/lando-cli#4cbdcf85ddd8b7ff53e912b9d9f1fced57ce39b7",
|
|
171
168
|
"node-fetch": "^2.6.1",
|
|
172
169
|
"node-stream-zip": "1.15.0",
|
|
173
170
|
"open": "^10.0.0",
|
|
@@ -175,8 +172,8 @@
|
|
|
175
172
|
"semver": "7.7.2",
|
|
176
173
|
"shelljs": "^0.10.0",
|
|
177
174
|
"socket.io-client": "^4.5.3",
|
|
178
|
-
"socket.io-stream": "npm:@
|
|
179
|
-
"socks-proxy-agent": "^
|
|
175
|
+
"socket.io-stream": "npm:@wwa/socket.io-stream@^0.10.0",
|
|
176
|
+
"socks-proxy-agent": "^8.0.5",
|
|
180
177
|
"ssh2": "1.16.0",
|
|
181
178
|
"tar": "^7.4.0",
|
|
182
179
|
"update-notifier": "7.3.1",
|
|
@@ -1,481 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
exports.__esModule = true;
|
|
5
|
-
exports.appQuery = void 0;
|
|
6
|
-
exports.vipValidatePreflightCommand = vipValidatePreflightCommand;
|
|
7
|
-
var _vipGoPreflightChecks = require("@automattic/vip-go-preflight-checks");
|
|
8
|
-
var _chalk = _interopRequireDefault(require("chalk"));
|
|
9
|
-
var _enquirer = require("enquirer");
|
|
10
|
-
var _fs = require("fs");
|
|
11
|
-
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
12
|
-
var _ini = _interopRequireDefault(require("ini"));
|
|
13
|
-
var _path = _interopRequireDefault(require("path"));
|
|
14
|
-
var _api = _interopRequireWildcard(require("../lib/api"));
|
|
15
|
-
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
16
|
-
var _envAlias = require("../lib/cli/envAlias");
|
|
17
|
-
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
18
|
-
var _tracker = require("../lib/tracker");
|
|
19
|
-
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
20
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
21
|
-
const ALLOWED_NODEJS_VERSIONS = ['18', '20', '22'];
|
|
22
|
-
const appQuery = exports.appQuery = `
|
|
23
|
-
id
|
|
24
|
-
name
|
|
25
|
-
repo
|
|
26
|
-
environments {
|
|
27
|
-
id
|
|
28
|
-
appId
|
|
29
|
-
name
|
|
30
|
-
type
|
|
31
|
-
environmentVariables {
|
|
32
|
-
nodes {
|
|
33
|
-
name,
|
|
34
|
-
value
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
organization {
|
|
39
|
-
id
|
|
40
|
-
name
|
|
41
|
-
}
|
|
42
|
-
`;
|
|
43
|
-
let suppressOutput = false;
|
|
44
|
-
let outputFormat = 'table';
|
|
45
|
-
let harmoniaArgs = [];
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @param {string[]} messages
|
|
49
|
-
*/
|
|
50
|
-
function logToConsole(...messages) {
|
|
51
|
-
if (suppressOutput) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
if (messages.length === 0) {
|
|
55
|
-
messages = [''];
|
|
56
|
-
}
|
|
57
|
-
messages.forEach(message => console.log(message));
|
|
58
|
-
}
|
|
59
|
-
async function getBuildConfiguration(application, environment) {
|
|
60
|
-
const api = (0, _api.default)();
|
|
61
|
-
|
|
62
|
-
// Disable the global GraphQL error handling, so we can catch Unauthorized errors and recommend next steps.
|
|
63
|
-
(0, _api.disableGlobalGraphQLErrorHandling)();
|
|
64
|
-
const buildConfigQuery = (0, _graphqlTag.default)`
|
|
65
|
-
query BuildConfig($appId: Int, $envId: Int) {
|
|
66
|
-
app(id: $appId) {
|
|
67
|
-
environments(id: $envId) {
|
|
68
|
-
id
|
|
69
|
-
buildConfiguration {
|
|
70
|
-
buildType
|
|
71
|
-
nodeBuildDockerEnv
|
|
72
|
-
nodeJSVersion
|
|
73
|
-
npmToken
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
`;
|
|
79
|
-
try {
|
|
80
|
-
const result = await api.query({
|
|
81
|
-
query: buildConfigQuery,
|
|
82
|
-
fetchPolicy: 'network-only',
|
|
83
|
-
variables: {
|
|
84
|
-
appId: environment.appId,
|
|
85
|
-
envId: environment.id
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Reenable GraphQL error handling
|
|
90
|
-
(0, _api.enableGlobalGraphQLErrorHandling)();
|
|
91
|
-
return result.data.app.environments[0].buildConfiguration;
|
|
92
|
-
} catch (error) {
|
|
93
|
-
if (error.graphQLErrors && error.graphQLErrors.find(gqlError => gqlError.message === 'Unauthorized')) {
|
|
94
|
-
console.log(`${_chalk.default.red('Error:')} You do not have sufficient 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` + 'Read more about organization and application roles in our documentation:\n' + _chalk.default.underline('https://docs.wpvip.com/manage-user-access/vip-dashboard/'));
|
|
95
|
-
await (0, _tracker.trackEvent)('validate_preflight_command_error', {
|
|
96
|
-
env_id: environment.id,
|
|
97
|
-
app_id: environment.appId,
|
|
98
|
-
error: 'unauthorized'
|
|
99
|
-
});
|
|
100
|
-
process.exit(1);
|
|
101
|
-
} else {
|
|
102
|
-
// Handle it elsewhere
|
|
103
|
-
throw error;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* @param {string} argv
|
|
110
|
-
*/
|
|
111
|
-
async function vipValidatePreflightCommand(arg, opt) {
|
|
112
|
-
harmoniaArgs = await validateArgs(opt);
|
|
113
|
-
const appId = opt.env?.appId ?? 0;
|
|
114
|
-
const envId = opt.env?.id ?? 0;
|
|
115
|
-
const baseTrackingParams = {
|
|
116
|
-
env_id: envId,
|
|
117
|
-
app_id: appId,
|
|
118
|
-
command: 'vip validate preflight',
|
|
119
|
-
...sanitizeArgsForTracking(harmoniaArgs)
|
|
120
|
-
};
|
|
121
|
-
await (0, _tracker.trackEvent)('validate_preflight_command_execute', baseTrackingParams);
|
|
122
|
-
logToConsole(' /\\ /\\__ _ _ __ _ __ ___ ___ _ __ (_) __ _ ');
|
|
123
|
-
logToConsole(" / /_/ / _` | '__| '_ ` _ \\ / _ \\| '_ \\| |/ _` |");
|
|
124
|
-
logToConsole('/ __ / (_| | | | | | | | | (_) | | | | | (_| |');
|
|
125
|
-
logToConsole('\\/ /_/ \\__,_|_| |_| |_| |_|\\___/|_| |_|_|\\__,_|');
|
|
126
|
-
logToConsole('VIP Harmonia - Application testing made easy\n');
|
|
127
|
-
const harmonia = new _vipGoPreflightChecks.Harmonia();
|
|
128
|
-
harmonia.setSource('vip-cli');
|
|
129
|
-
if (harmoniaArgs.buildType !== 'nodejs') {
|
|
130
|
-
await (0, _tracker.trackEvent)('validate_preflight_command_error', {
|
|
131
|
-
...baseTrackingParams,
|
|
132
|
-
error: 'not-nodejs'
|
|
133
|
-
});
|
|
134
|
-
exit.withError('Currently, only Node.js applications are supported.');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Register the default tests.
|
|
138
|
-
harmonia.registerDefaultTests();
|
|
139
|
-
|
|
140
|
-
// Create the Site Config objects
|
|
141
|
-
const siteOptions = new _vipGoPreflightChecks.SiteConfig({
|
|
142
|
-
siteID: envId,
|
|
143
|
-
nodejsVersion: harmoniaArgs.nodejsVersion,
|
|
144
|
-
repository: opt.app?.repo ?? 'no-repo',
|
|
145
|
-
baseURL: 'http://localhost:' + harmoniaArgs.port,
|
|
146
|
-
dockerBuildEnvs: harmoniaArgs.nodeBuildDockerEnv,
|
|
147
|
-
topRequests: [],
|
|
148
|
-
// TODO: get top 10 of most requested URLs
|
|
149
|
-
wait: harmoniaArgs.wait
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// Get package.json
|
|
153
|
-
const packageJSONfile = _path.default.resolve(opt.path, 'package.json');
|
|
154
|
-
let packageJSON;
|
|
155
|
-
try {
|
|
156
|
-
// eslint-disable-next-line security/detect-non-literal-require
|
|
157
|
-
packageJSON = require(packageJSONfile);
|
|
158
|
-
siteOptions.setPackageJSON(packageJSON);
|
|
159
|
-
} catch (error) {
|
|
160
|
-
await (0, _tracker.trackEvent)('validate_preflight_command_error', {
|
|
161
|
-
...baseTrackingParams,
|
|
162
|
-
error: 'missing-package-json'
|
|
163
|
-
});
|
|
164
|
-
return exit.withError(`Could not find a 'package.json' in the current directory (${opt.path}).`);
|
|
165
|
-
}
|
|
166
|
-
const customEnvVars = {};
|
|
167
|
-
if (opt.env?.environmentVariables?.nodes.length > 0) {
|
|
168
|
-
opt.env.environmentVariables.nodes.forEach(envVar => {
|
|
169
|
-
customEnvVars[envVar.name] = envVar.value;
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Create the EnviornmentVariables object
|
|
174
|
-
const envVars = new _vipGoPreflightChecks.EnvironmentVariables({
|
|
175
|
-
PORT: harmoniaArgs.port,
|
|
176
|
-
...customEnvVars
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Add NPM_TOKEN environment variable, if present
|
|
180
|
-
if (harmoniaArgs.npmToken) {
|
|
181
|
-
envVars.set('NPM_TOKEN', harmoniaArgs.npmToken);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Get from .env, if exists
|
|
185
|
-
let dotenvOptions = {};
|
|
186
|
-
try {
|
|
187
|
-
const dotenvPath = _path.default.resolve(opt.path, '.env');
|
|
188
|
-
const dotenvContent = (0, _fs.readFileSync)(dotenvPath);
|
|
189
|
-
dotenvOptions = _ini.default.parse(dotenvContent);
|
|
190
|
-
} catch (error) {
|
|
191
|
-
// nothing
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Save dotenv in the site config
|
|
195
|
-
siteOptions.set('dotenv', dotenvOptions);
|
|
196
|
-
|
|
197
|
-
// Bootstrap
|
|
198
|
-
try {
|
|
199
|
-
harmonia.bootstrap(siteOptions, envVars);
|
|
200
|
-
} catch (error) {
|
|
201
|
-
await (0, _tracker.trackEvent)('validate_preflight_command_error', {
|
|
202
|
-
...baseTrackingParams,
|
|
203
|
-
error: error.message
|
|
204
|
-
});
|
|
205
|
-
return exit.withError(error.message);
|
|
206
|
-
}
|
|
207
|
-
setupEvents(harmonia);
|
|
208
|
-
runHarmonia(harmonia);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* @param {Harmonia} harmonia
|
|
213
|
-
*/
|
|
214
|
-
function setupEvents(harmonia) {
|
|
215
|
-
// Register some events handlers
|
|
216
|
-
harmonia.on('ready', () => {
|
|
217
|
-
logToConsole('Harmonia is ready! ');
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
// Register the event handlers to output some information during the execution
|
|
221
|
-
harmonia.on('beforeTestSuite', suite => {
|
|
222
|
-
const description = suite.description ? `- ${_chalk.default.italic(suite.description)}` : '';
|
|
223
|
-
logToConsole(` >> Running test suite ${_chalk.default.bold(suite.name)} ${description} `);
|
|
224
|
-
logToConsole();
|
|
225
|
-
});
|
|
226
|
-
harmonia.on('beforeTest', test => {
|
|
227
|
-
logToConsole(` [ ${_chalk.default.bold(test.name)} ] - ${test.description}`);
|
|
228
|
-
});
|
|
229
|
-
harmonia.on('afterTest', (test, result) => {
|
|
230
|
-
switch (result.getType()) {
|
|
231
|
-
case _vipGoPreflightChecks.TestResultType.Success:
|
|
232
|
-
logToConsole(` ✅ ${_chalk.default.bgGreen(' Test passed with no errors. ')}`);
|
|
233
|
-
break;
|
|
234
|
-
case _vipGoPreflightChecks.TestResultType.Failed:
|
|
235
|
-
logToConsole(` ❌ ${_chalk.default.bgRed(` Test failed with ${result.getErrors().length} errors. `)}`);
|
|
236
|
-
break;
|
|
237
|
-
case _vipGoPreflightChecks.TestResultType.PartialSuccess:
|
|
238
|
-
logToConsole(` ✅ ${_chalk.default.bgYellow(' Test partially succeeded. ')}`);
|
|
239
|
-
break;
|
|
240
|
-
case _vipGoPreflightChecks.TestResultType.Aborted:
|
|
241
|
-
logToConsole(` ❌ ${_chalk.default.bgRedBright.underline(' Test aborted! ')} - There was a critical error that makes`, 'the application incompatible with the VIP Platform.');
|
|
242
|
-
break;
|
|
243
|
-
case _vipGoPreflightChecks.TestResultType.Skipped:
|
|
244
|
-
logToConsole(` ${_chalk.default.bgGrey.bold(' Skipped ')}\t${result.getLastNotice().message}`);
|
|
245
|
-
}
|
|
246
|
-
logToConsole();
|
|
247
|
-
});
|
|
248
|
-
harmonia.on('afterTestSuite', (test, result) => {
|
|
249
|
-
// Create a badge
|
|
250
|
-
let badge;
|
|
251
|
-
switch (result.getType()) {
|
|
252
|
-
case _vipGoPreflightChecks.TestResultType.Failed:
|
|
253
|
-
badge = _chalk.default.bgRed.bold(' FAILED ');
|
|
254
|
-
break;
|
|
255
|
-
case _vipGoPreflightChecks.TestResultType.Aborted:
|
|
256
|
-
badge = _chalk.default.bgRedBright.underline.bold(' ABORTED ');
|
|
257
|
-
break;
|
|
258
|
-
case _vipGoPreflightChecks.TestResultType.PartialSuccess:
|
|
259
|
-
badge = _chalk.default.bgYellow.bold(' PASS ');
|
|
260
|
-
break;
|
|
261
|
-
default:
|
|
262
|
-
badge = _chalk.default.bgGreen.bold(' PASS ');
|
|
263
|
-
break;
|
|
264
|
-
}
|
|
265
|
-
logToConsole(` >> ${badge} Finished running ${_chalk.default.bold(test.name)} suite`);
|
|
266
|
-
logToConsole();
|
|
267
|
-
});
|
|
268
|
-
harmonia.on('issue', issue => {
|
|
269
|
-
let issueTypeString = issue.getTypeString();
|
|
270
|
-
switch (issue.type) {
|
|
271
|
-
case _vipGoPreflightChecks.IssueType.Blocker:
|
|
272
|
-
issueTypeString = _chalk.default.bgRedBright.underline.bold(issueTypeString);
|
|
273
|
-
break;
|
|
274
|
-
case _vipGoPreflightChecks.IssueType.Error:
|
|
275
|
-
issueTypeString = _chalk.default.bgRed.bold(issueTypeString);
|
|
276
|
-
break;
|
|
277
|
-
case _vipGoPreflightChecks.IssueType.Warning:
|
|
278
|
-
issueTypeString = _chalk.default.bgYellow.bold(issueTypeString);
|
|
279
|
-
break;
|
|
280
|
-
case _vipGoPreflightChecks.IssueType.Notice:
|
|
281
|
-
issueTypeString = _chalk.default.bgGray.bold(issueTypeString);
|
|
282
|
-
break;
|
|
283
|
-
}
|
|
284
|
-
const documentation = issue.documentation ? `(${issue.documentation})` : '';
|
|
285
|
-
|
|
286
|
-
// Replace \n with \n\t\t to keep new lines aligned
|
|
287
|
-
const message = issue.message.replace(/\n/g, '\n\t\t');
|
|
288
|
-
logToConsole(` ${issueTypeString} \t${message} ${documentation}`);
|
|
289
|
-
|
|
290
|
-
// If it's a Blocker or Error, and the issue includes a stdout, print it out.
|
|
291
|
-
const issueData = issue.getData();
|
|
292
|
-
if (issueData && [_vipGoPreflightChecks.IssueType.Blocker, _vipGoPreflightChecks.IssueType.Error].includes(issue.type)) {
|
|
293
|
-
if (issueData.all) {
|
|
294
|
-
logToConsole(issueData.all);
|
|
295
|
-
logToConsole();
|
|
296
|
-
} else if (typeof issueData === 'string') {
|
|
297
|
-
logToConsole(issueData);
|
|
298
|
-
logToConsole();
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
function runHarmonia(harmonia) {
|
|
304
|
-
harmonia.run().then(async results => await handleResults(harmonia, results));
|
|
305
|
-
}
|
|
306
|
-
async function handleResults(harmonia, results) {
|
|
307
|
-
// Calculate the results
|
|
308
|
-
const resultCounter = harmonia.countResults(false);
|
|
309
|
-
const testSuiteResults = results.filter(result => result instanceof _vipGoPreflightChecks.TestSuiteResult);
|
|
310
|
-
|
|
311
|
-
// Send success event
|
|
312
|
-
await (0, _tracker.trackEvent)('validate_preflight_command_success', {
|
|
313
|
-
command: 'vip validate preflight',
|
|
314
|
-
...sanitizeArgsForTracking(harmoniaArgs),
|
|
315
|
-
skipped: resultCounter[_vipGoPreflightChecks.TestResultType.Skipped],
|
|
316
|
-
success: resultCounter[_vipGoPreflightChecks.TestResultType.Success],
|
|
317
|
-
partial_success: resultCounter[_vipGoPreflightChecks.TestResultType.PartialSuccess],
|
|
318
|
-
failed: resultCounter[_vipGoPreflightChecks.TestResultType.Failed],
|
|
319
|
-
aborted: resultCounter[_vipGoPreflightChecks.TestResultType.Aborted]
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
// If the output is JSON, reenable the logToConsole output and print-out the json format.
|
|
323
|
-
if (outputFormat === 'json') {
|
|
324
|
-
suppressOutput = false;
|
|
325
|
-
logToConsole(harmonia.resultsJSON());
|
|
326
|
-
process.exit(0);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Print the results
|
|
330
|
-
logToConsole('\n' + _chalk.default.bgGray(' HARMONIA RESULTS \n'));
|
|
331
|
-
if (resultCounter[_vipGoPreflightChecks.TestResultType.Skipped]) {
|
|
332
|
-
logToConsole(` ${_chalk.default.bold.bgGrey(' SKIPPED ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.Skipped])} tests`);
|
|
333
|
-
}
|
|
334
|
-
if (resultCounter[_vipGoPreflightChecks.TestResultType.Success]) {
|
|
335
|
-
logToConsole(` ${_chalk.default.bold.bgGreen(' PASSED ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.Success])} tests`);
|
|
336
|
-
}
|
|
337
|
-
if (resultCounter[_vipGoPreflightChecks.TestResultType.PartialSuccess]) {
|
|
338
|
-
logToConsole(` ${_chalk.default.bold.bgYellow(' PARTIAL SUCCESS ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.PartialSuccess])} tests`);
|
|
339
|
-
}
|
|
340
|
-
if (resultCounter[_vipGoPreflightChecks.TestResultType.Failed]) {
|
|
341
|
-
logToConsole(` ${_chalk.default.bold.bgRed(' FAILED ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.Failed])} tests`);
|
|
342
|
-
}
|
|
343
|
-
if (resultCounter[_vipGoPreflightChecks.TestResultType.Aborted]) {
|
|
344
|
-
logToConsole(` ${_chalk.default.bold.bgRedBright(' ABORTED ')} - ${_chalk.default.bold(resultCounter[_vipGoPreflightChecks.TestResultType.Aborted])} tests`);
|
|
345
|
-
}
|
|
346
|
-
logToConsole();
|
|
347
|
-
logToConsole(` > Total of ${_chalk.default.bold(results.length - testSuiteResults.length)} tests have been executed.`);
|
|
348
|
-
logToConsole();
|
|
349
|
-
|
|
350
|
-
// If there is a Aborted test result
|
|
351
|
-
if (resultCounter[_vipGoPreflightChecks.TestResultType.Aborted]) {
|
|
352
|
-
logToConsole(`${_chalk.default.bold.bgRedBright(' NOT PASS ')} There was a critical failure that makes the application ` + 'incompatible with the VIP Platform. Please review the results and re-run the tests.');
|
|
353
|
-
process.exit(1);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
// If there is only a partial success, but no failures
|
|
357
|
-
if (resultCounter[_vipGoPreflightChecks.TestResultType.PartialSuccess] && !resultCounter[_vipGoPreflightChecks.TestResultType.Failed]) {
|
|
358
|
-
logToConsole(`${_chalk.default.bold.bgYellow(' PASS ')} The application has passed the required tests, but it does not follow all of the recommendations.`);
|
|
359
|
-
logToConsole('Please review the results.');
|
|
360
|
-
process.exit(0);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// If there is a failure
|
|
364
|
-
if (resultCounter[_vipGoPreflightChecks.TestResultType.Failed]) {
|
|
365
|
-
logToConsole(`${_chalk.default.bold.bgRed(' NOT PASS ')} The application has failed some tests, and will very likely have problems on a production ` + 'environment. Please review all of the errors found in the results.');
|
|
366
|
-
process.exit(1);
|
|
367
|
-
}
|
|
368
|
-
logToConsole(`${_chalk.default.bold.bgGreen(' PASS ')} Congratulations! The application passes all of the tests.`);
|
|
369
|
-
process.exit(0);
|
|
370
|
-
}
|
|
371
|
-
async function validateArgs(opt) {
|
|
372
|
-
const args = {};
|
|
373
|
-
|
|
374
|
-
// Verbose
|
|
375
|
-
if (opt.verbose) {
|
|
376
|
-
_vipGoPreflightChecks.Harmonia.setVerbosity(true);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Set path
|
|
380
|
-
if (opt.path) {
|
|
381
|
-
_vipGoPreflightChecks.Harmonia.setCwd(opt.path);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// If the JSON option is enabled, all the stdout should be suppressed to prevent polluting the output.
|
|
385
|
-
if (opt.format === 'json') {
|
|
386
|
-
suppressOutput = true;
|
|
387
|
-
outputFormat = 'json';
|
|
388
|
-
}
|
|
389
|
-
if (opt.app) {
|
|
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 ?? 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 ?? 3000;
|
|
422
|
-
args.port = 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
|
-
* @return {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
|
-
format: true
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
// The @app.env selector is optional, so we need to check if it was passed
|
|
451
|
-
const parsedAlias = (0, _envAlias.parseEnvAliasFromArgv)(process.argv);
|
|
452
|
-
if (parsedAlias.app) {
|
|
453
|
-
commandOpts = {
|
|
454
|
-
...commandOpts,
|
|
455
|
-
appQuery,
|
|
456
|
-
envContext: true,
|
|
457
|
-
appContext: true
|
|
458
|
-
};
|
|
459
|
-
} else {
|
|
460
|
-
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 be defined.');
|
|
461
|
-
}
|
|
462
|
-
const usage = 'vip validate preflight';
|
|
463
|
-
(0, _command.default)({
|
|
464
|
-
commandOpts,
|
|
465
|
-
usage
|
|
466
|
-
}).option('verbose', 'Increase logging level to include app build and server boot up messages.', false).option('node-version', `Set a version of Node.js for the tests. Accepts semver format (MAJOR.MINOR.PATCH) or a MAJOR (${ALLOWED_NODEJS_VERSIONS.join(', ')}).`).option('wait', 'Set the number of milliseconds to delay the start of the tests. Only necessary if an application requires a greater amount of time to start.', 3000).option(['p', 'port'], 'Set a port for the application. (Defaults to a random value between 3001 and 3999)').option(['P', 'path'], 'Path to the app to be tested', process.cwd()).examples([{
|
|
467
|
-
usage: 'vip validate preflight',
|
|
468
|
-
description: 'Run the validate command from within the root of the local Node.js codebase directory.'
|
|
469
|
-
}, {
|
|
470
|
-
usage: 'vip validate preflight --path=/Users/example/Desktop/example-node-repo',
|
|
471
|
-
description: 'Run the validate command against a Node.js application directory at a specific local path.'
|
|
472
|
-
}, {
|
|
473
|
-
usage: 'vip @example-node-app.production validate preflight --node-version=20',
|
|
474
|
-
description: 'Run the validation tests with a specific version of Node.js.'
|
|
475
|
-
}, {
|
|
476
|
-
usage: 'vip validate preflight --format=json > results.json',
|
|
477
|
-
description: 'Output the results of the validation tests to a local file in JSON format.'
|
|
478
|
-
}, {
|
|
479
|
-
usage: 'vip @example-node-app.production validate preflight',
|
|
480
|
-
description: 'Run the validation tests with settings based on a targeted VIP Platform environment.'
|
|
481
|
-
}]).argv(process.argv, vipValidatePreflightCommand);
|
package/dist/bin/vip-validate.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
5
|
-
var _tracker = require("../lib/tracker");
|
|
6
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
-
(0, _command.default)({
|
|
8
|
-
requiredArgs: 0
|
|
9
|
-
}).command('preflight', 'Run a full suite of validation tests against a local Node.js codebase to identify potential issues that could prevent successful building or deploying.').argv(process.argv, async () => {
|
|
10
|
-
await (0, _tracker.trackEvent)('vip_validate_command_execute');
|
|
11
|
-
});
|