@automattic/vip 2.9.5 → 2.11.2
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/CONTRIBUTING.md +2 -11
- package/README.md +26 -0
- package/dist/bin/vip-dev-env-create.js +9 -1
- package/dist/bin/vip-dev-env-destroy.js +7 -7
- package/dist/bin/vip-dev-env-exec.js +7 -1
- package/dist/bin/vip-dev-env-import-media.js +7 -1
- package/dist/bin/vip-dev-env-import-sql.js +7 -1
- package/dist/bin/vip-dev-env-info.js +10 -1
- package/dist/bin/vip-dev-env-list.js +10 -1
- package/dist/bin/vip-dev-env-start.js +14 -3
- package/dist/bin/vip-dev-env-stop.js +7 -1
- package/dist/bin/vip-dev-env-update.js +8 -2
- package/dist/bin/vip-import-sql.js +7 -1
- package/dist/lib/analytics/clients/pendo.js +92 -0
- package/dist/lib/analytics/index.js +8 -3
- package/dist/lib/dev-environment/dev-environment-cli.js +56 -1
- package/dist/lib/dev-environment/dev-environment-core.js +4 -2
- package/dist/lib/dev-environment/dev-environment-lando.js +35 -3
- package/dist/lib/tracker.js +15 -7
- package/npm-shrinkwrap.json +1 -1
- package/package/dist/bin/vip-app-list.js +73 -0
- package/package/dist/bin/vip-app.js +76 -0
- package/package/dist/bin/vip-config-envvar-delete.js +97 -0
- package/package/dist/bin/vip-config-envvar-get-all.js +94 -0
- package/package/dist/bin/vip-config-envvar-get.js +79 -0
- package/package/dist/bin/vip-config-envvar-list.js +91 -0
- package/package/dist/bin/vip-config-envvar-set.js +123 -0
- package/package/dist/bin/vip-config-envvar.js +23 -0
- package/package/dist/bin/vip-config.js +20 -0
- package/package/dist/bin/vip-dev-env-create.js +105 -0
- package/package/dist/bin/vip-dev-env-destroy.js +56 -0
- package/package/dist/bin/vip-dev-env-exec.js +67 -0
- package/package/dist/bin/vip-dev-env-import-media.js +51 -0
- package/package/dist/bin/vip-dev-env-import-sql.js +83 -0
- package/package/dist/bin/vip-dev-env-import.js +32 -0
- package/package/dist/bin/vip-dev-env-info.js +61 -0
- package/package/dist/bin/vip-dev-env-list.js +46 -0
- package/package/dist/bin/vip-dev-env-start.js +77 -0
- package/package/dist/bin/vip-dev-env-stop.js +52 -0
- package/package/dist/bin/vip-dev-env-update.js +89 -0
- package/package/dist/bin/vip-dev-env.js +23 -0
- package/package/dist/bin/vip-import-media-abort.js +132 -0
- package/package/dist/bin/vip-import-media-status.js +84 -0
- package/package/dist/bin/vip-import-media.js +168 -0
- package/package/dist/bin/vip-import-sql-status.js +83 -0
- package/package/dist/bin/vip-import-sql.js +580 -0
- package/package/dist/bin/vip-import-validate-files.js +191 -0
- package/package/dist/bin/vip-import-validate-sql.js +34 -0
- package/package/dist/bin/vip-import.js +20 -0
- package/package/dist/bin/vip-logs.js +232 -0
- package/package/dist/bin/vip-search-replace.js +71 -0
- package/package/dist/bin/vip-sync.js +191 -0
- package/package/dist/bin/vip-whoami.js +67 -0
- package/package/dist/bin/vip-wp.js +555 -0
- package/package/dist/bin/vip.js +149 -0
- package/package/dist/lib/analytics/clients/client.js +1 -0
- package/package/dist/lib/analytics/clients/pendo.js +92 -0
- package/package/dist/lib/analytics/clients/stub.js +19 -0
- package/package/dist/lib/analytics/clients/tracks.js +128 -0
- package/package/dist/lib/analytics/index.js +45 -0
- package/package/dist/lib/api/app.js +70 -0
- package/package/dist/lib/api/feature-flags.js +39 -0
- package/package/dist/lib/api/user.js +58 -0
- package/package/dist/lib/api.js +136 -0
- package/package/dist/lib/app-logs/app-logs.js +70 -0
- package/package/dist/lib/cli/apiConfig.js +90 -0
- package/package/dist/lib/cli/command.js +606 -0
- package/package/dist/lib/cli/envAlias.js +60 -0
- package/package/dist/lib/cli/exit.js +33 -0
- package/package/dist/lib/cli/format.js +213 -0
- package/package/dist/lib/cli/pager.js +52 -0
- package/package/dist/lib/cli/progress.js +208 -0
- package/package/dist/lib/cli/prompt.js +37 -0
- package/package/dist/lib/cli/repo.js +77 -0
- package/package/dist/lib/client-file-uploader.js +602 -0
- package/package/dist/lib/constants/dev-environment.js +42 -0
- package/package/dist/lib/constants/file-size.js +14 -0
- package/package/dist/lib/dev-environment/dev-environment-cli.js +508 -0
- package/package/dist/lib/dev-environment/dev-environment-core.js +620 -0
- package/package/dist/lib/dev-environment/dev-environment-lando.js +330 -0
- package/package/dist/lib/dev-environment/types.js +1 -0
- package/package/dist/lib/env.js +36 -0
- package/package/dist/lib/envvar/api-delete.js +56 -0
- package/package/dist/lib/envvar/api-get-all.js +59 -0
- package/package/dist/lib/envvar/api-get.js +24 -0
- package/package/dist/lib/envvar/api-list.js +60 -0
- package/package/dist/lib/envvar/api-set.js +58 -0
- package/package/dist/lib/envvar/api.js +104 -0
- package/package/dist/lib/envvar/input.js +55 -0
- package/package/dist/lib/envvar/logging.js +33 -0
- package/package/dist/lib/envvar/read-file.js +43 -0
- package/package/dist/lib/http/socks-proxy-agent.js +25 -0
- package/package/dist/lib/keychain/browser.js +35 -0
- package/package/dist/lib/keychain/insecure.js +63 -0
- package/package/dist/lib/keychain/keychain.js +1 -0
- package/package/dist/lib/keychain/secure.js +36 -0
- package/package/dist/lib/keychain.js +36 -0
- package/package/dist/lib/media-import/media-file-import.js +34 -0
- package/package/dist/lib/media-import/progress.js +86 -0
- package/package/dist/lib/media-import/status.js +335 -0
- package/package/dist/lib/rollbar.js +35 -0
- package/package/dist/lib/search-and-replace.js +203 -0
- package/package/dist/lib/site-import/db-file-import.js +46 -0
- package/package/dist/lib/site-import/status.js +444 -0
- package/package/dist/lib/token.js +132 -0
- package/package/dist/lib/tracker.js +96 -0
- package/package/dist/lib/validations/is-multi-site-sql-dump.js +59 -0
- package/package/dist/lib/validations/is-multi-site.js +99 -0
- package/package/dist/lib/validations/line-by-line.js +92 -0
- package/package/dist/lib/validations/site-type.js +66 -0
- package/package/dist/lib/validations/sql.js +371 -0
- package/package/dist/lib/vip-import-validate-files.js +548 -0
- package/package/vip.iml +11 -0
- package/package.json +1 -1
- package/vip.iml +11 -0
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.startEnvironment = startEnvironment;
|
|
7
|
+
exports.stopEnvironment = stopEnvironment;
|
|
8
|
+
exports.createEnvironment = createEnvironment;
|
|
9
|
+
exports.updateEnvironment = updateEnvironment;
|
|
10
|
+
exports.destroyEnvironment = destroyEnvironment;
|
|
11
|
+
exports.printAllEnvironmentsInfo = printAllEnvironmentsInfo;
|
|
12
|
+
exports.printEnvironmentInfo = printEnvironmentInfo;
|
|
13
|
+
exports.exec = exec;
|
|
14
|
+
exports.doesEnvironmentExist = doesEnvironmentExist;
|
|
15
|
+
exports.readEnvironmentData = readEnvironmentData;
|
|
16
|
+
exports.getEnvironmentPath = getEnvironmentPath;
|
|
17
|
+
exports.getApplicationInformation = getApplicationInformation;
|
|
18
|
+
exports.resolveImportPath = resolveImportPath;
|
|
19
|
+
exports.importMediaPath = importMediaPath;
|
|
20
|
+
exports.fetchVersionList = fetchVersionList;
|
|
21
|
+
exports.getVersionList = getVersionList;
|
|
22
|
+
|
|
23
|
+
var _debug = _interopRequireDefault(require("debug"));
|
|
24
|
+
|
|
25
|
+
var _xdgBasedir = _interopRequireDefault(require("xdg-basedir"));
|
|
26
|
+
|
|
27
|
+
var _nodeFetch = _interopRequireDefault(require("node-fetch"));
|
|
28
|
+
|
|
29
|
+
var _os = _interopRequireDefault(require("os"));
|
|
30
|
+
|
|
31
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
32
|
+
|
|
33
|
+
var _ejs = _interopRequireDefault(require("ejs"));
|
|
34
|
+
|
|
35
|
+
var _path = _interopRequireDefault(require("path"));
|
|
36
|
+
|
|
37
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
38
|
+
|
|
39
|
+
var _enquirer = require("enquirer");
|
|
40
|
+
|
|
41
|
+
var _copyDir = _interopRequireDefault(require("copy-dir"));
|
|
42
|
+
|
|
43
|
+
var _devEnvironmentLando = require("./dev-environment-lando");
|
|
44
|
+
|
|
45
|
+
var _searchAndReplace = require("../search-and-replace");
|
|
46
|
+
|
|
47
|
+
var _devEnvironmentCli = require("./dev-environment-cli");
|
|
48
|
+
|
|
49
|
+
var _app = _interopRequireDefault(require("../api/app"));
|
|
50
|
+
|
|
51
|
+
var _devEnvironment = require("../constants/dev-environment");
|
|
52
|
+
|
|
53
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
* @format
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* External dependencies
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Internal dependencies
|
|
66
|
+
*/
|
|
67
|
+
const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
|
|
68
|
+
|
|
69
|
+
const landoFileTemplatePath = _path.default.join(__dirname, '..', '..', '..', 'assets', 'dev-env.lando.template.yml.ejs');
|
|
70
|
+
|
|
71
|
+
const nginxFileTemplatePath = _path.default.join(__dirname, '..', '..', '..', 'assets', 'dev-env.nginx.template.conf.ejs');
|
|
72
|
+
|
|
73
|
+
const landoFileName = '.lando.yml';
|
|
74
|
+
const nginxFileName = 'extra.conf';
|
|
75
|
+
const instanceDataFileName = 'instance_data.json';
|
|
76
|
+
const homeDirPathInsideContainers = '/user';
|
|
77
|
+
const uploadPathString = 'uploads';
|
|
78
|
+
const nginxPathString = 'nginx';
|
|
79
|
+
|
|
80
|
+
async function startEnvironment(slug, options) {
|
|
81
|
+
debug('Will start an environment', slug);
|
|
82
|
+
const instancePath = getEnvironmentPath(slug);
|
|
83
|
+
debug('Instance path for', slug, 'is:', instancePath);
|
|
84
|
+
|
|
85
|
+
const environmentExists = _fs.default.existsSync(instancePath);
|
|
86
|
+
|
|
87
|
+
if (!environmentExists) {
|
|
88
|
+
throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const updated = await updateWordPressImage(slug);
|
|
92
|
+
|
|
93
|
+
if (options.skipRebuild && !updated) {
|
|
94
|
+
await (0, _devEnvironmentLando.landoStart)(instancePath);
|
|
95
|
+
} else {
|
|
96
|
+
await (0, _devEnvironmentLando.landoRebuild)(instancePath);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
await printEnvironmentInfo(slug);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function stopEnvironment(slug) {
|
|
103
|
+
debug('Will stop an environment', slug);
|
|
104
|
+
const instancePath = getEnvironmentPath(slug);
|
|
105
|
+
debug('Instance path for', slug, 'is:', instancePath);
|
|
106
|
+
|
|
107
|
+
const environmentExists = _fs.default.existsSync(instancePath);
|
|
108
|
+
|
|
109
|
+
if (!environmentExists) {
|
|
110
|
+
throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
await (0, _devEnvironmentLando.landoStop)(instancePath);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function createEnvironment(instanceData) {
|
|
117
|
+
const slug = instanceData.siteSlug;
|
|
118
|
+
debug('Will create an environment', slug, 'with instanceData: ', instanceData);
|
|
119
|
+
const instancePath = getEnvironmentPath(slug);
|
|
120
|
+
debug('Instance path for', slug, 'is:', instancePath);
|
|
121
|
+
|
|
122
|
+
const alreadyExists = _fs.default.existsSync(instancePath);
|
|
123
|
+
|
|
124
|
+
if (alreadyExists) {
|
|
125
|
+
throw new Error('Environment already exists.');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const preProcessedInstanceData = preProcessInstanceData(instanceData);
|
|
129
|
+
await prepareLandoEnv(preProcessedInstanceData, instancePath);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function updateEnvironment(instanceData) {
|
|
133
|
+
const slug = instanceData.siteSlug;
|
|
134
|
+
debug('Will update an environment', slug, 'with instanceData: ', instanceData);
|
|
135
|
+
const instancePath = getEnvironmentPath(slug);
|
|
136
|
+
debug('Instance path for', slug, 'is:', instancePath);
|
|
137
|
+
|
|
138
|
+
const alreadyExists = _fs.default.existsSync(instancePath);
|
|
139
|
+
|
|
140
|
+
if (!alreadyExists) {
|
|
141
|
+
throw new Error('Environment doesn\'t exist.');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const preProcessedInstanceData = preProcessInstanceData(instanceData);
|
|
145
|
+
await prepareLandoEnv(preProcessedInstanceData, instancePath);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function preProcessInstanceData(instanceData) {
|
|
149
|
+
const newInstanceData = { ...instanceData
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
if (instanceData.mediaRedirectDomain && !instanceData.mediaRedirectDomain.match(/^http/)) {
|
|
153
|
+
// We need to make sure the redirect is an absolute path
|
|
154
|
+
newInstanceData.mediaRedirectDomain = `https://${instanceData.mediaRedirectDomain}`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
newInstanceData.enterpriseSearchEnabled = instanceData.enterpriseSearchEnabled || false;
|
|
158
|
+
newInstanceData.php = instanceData.php || _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS.default;
|
|
159
|
+
return newInstanceData;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function destroyEnvironment(slug, removeFiles) {
|
|
163
|
+
debug('Will destroy an environment', slug);
|
|
164
|
+
const instancePath = getEnvironmentPath(slug);
|
|
165
|
+
debug('Instance path for', slug, 'is:', instancePath);
|
|
166
|
+
|
|
167
|
+
const environmentExists = _fs.default.existsSync(instancePath);
|
|
168
|
+
|
|
169
|
+
if (!environmentExists) {
|
|
170
|
+
throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const landoFilePath = _path.default.join(instancePath, landoFileName);
|
|
174
|
+
|
|
175
|
+
if (_fs.default.existsSync(landoFilePath)) {
|
|
176
|
+
debug('Lando file exists, will lando destroy.');
|
|
177
|
+
await (0, _devEnvironmentLando.landoDestroy)(instancePath);
|
|
178
|
+
} else {
|
|
179
|
+
debug("Lando file doesn't exist, skipping lando destroy.");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (removeFiles) {
|
|
183
|
+
await _fs.default.promises.rm(instancePath, {
|
|
184
|
+
recursive: true
|
|
185
|
+
});
|
|
186
|
+
console.log(`${_chalk.default.green('✓')} Environment files deleted successfully.`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function printAllEnvironmentsInfo() {
|
|
191
|
+
const allEnvNames = getAllEnvironmentNames();
|
|
192
|
+
debug('Will print info for all environments. Names found: ', allEnvNames);
|
|
193
|
+
console.log('Found ' + _chalk.default.bold(allEnvNames.length) + ' environments' + (allEnvNames.length ? ':' : '.'));
|
|
194
|
+
|
|
195
|
+
for (const envName of allEnvNames) {
|
|
196
|
+
console.log('\n');
|
|
197
|
+
await printEnvironmentInfo(envName);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function printEnvironmentInfo(slug) {
|
|
202
|
+
debug('Will get info for an environment', slug);
|
|
203
|
+
const instancePath = getEnvironmentPath(slug);
|
|
204
|
+
debug('Instance path for', slug, 'is:', instancePath);
|
|
205
|
+
|
|
206
|
+
const environmentExists = _fs.default.existsSync(instancePath);
|
|
207
|
+
|
|
208
|
+
if (!environmentExists) {
|
|
209
|
+
throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const appInfo = await (0, _devEnvironmentLando.landoInfo)(instancePath);
|
|
213
|
+
(0, _devEnvironmentCli.printTable)(appInfo);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async function exec(slug, args) {
|
|
217
|
+
debug('Will run a wp command on env', slug, 'with args', args);
|
|
218
|
+
const instancePath = getEnvironmentPath(slug);
|
|
219
|
+
debug('Instance path for', slug, 'is:', instancePath);
|
|
220
|
+
|
|
221
|
+
const environmentExists = _fs.default.existsSync(instancePath);
|
|
222
|
+
|
|
223
|
+
if (!environmentExists) {
|
|
224
|
+
throw new Error(_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const command = args.shift();
|
|
228
|
+
let commandArgs = [...args];
|
|
229
|
+
|
|
230
|
+
if ('add-site' === command) {
|
|
231
|
+
commandArgs = [...args.map(argument => argument.replace('--new-site-', '--'))];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
await (0, _devEnvironmentLando.landoExec)(instancePath, command, commandArgs);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function doesEnvironmentExist(slug) {
|
|
238
|
+
debug('Will check for environment', slug);
|
|
239
|
+
const instancePath = getEnvironmentPath(slug);
|
|
240
|
+
debug('Instance path for', slug, 'is:', instancePath);
|
|
241
|
+
return _fs.default.existsSync(instancePath);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function readEnvironmentData(slug) {
|
|
245
|
+
debug('Will try to get instance data for environment', slug);
|
|
246
|
+
const instancePath = getEnvironmentPath(slug);
|
|
247
|
+
|
|
248
|
+
const instanceDataTargetPath = _path.default.join(instancePath, instanceDataFileName);
|
|
249
|
+
|
|
250
|
+
const instanceDataString = _fs.default.readFileSync(instanceDataTargetPath, 'utf8');
|
|
251
|
+
|
|
252
|
+
return JSON.parse(instanceDataString);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function prepareLandoEnv(instanceData, instancePath) {
|
|
256
|
+
const landoFile = await _ejs.default.renderFile(landoFileTemplatePath, instanceData);
|
|
257
|
+
const nginxFile = await _ejs.default.renderFile(nginxFileTemplatePath, instanceData);
|
|
258
|
+
const instanceDataFile = JSON.stringify(instanceData);
|
|
259
|
+
|
|
260
|
+
const landoFileTargetPath = _path.default.join(instancePath, landoFileName);
|
|
261
|
+
|
|
262
|
+
const nginxFolderPath = _path.default.join(instancePath, nginxPathString);
|
|
263
|
+
|
|
264
|
+
const nginxFileTargetPath = _path.default.join(nginxFolderPath, nginxFileName);
|
|
265
|
+
|
|
266
|
+
const instanceDataTargetPath = _path.default.join(instancePath, instanceDataFileName);
|
|
267
|
+
|
|
268
|
+
_fs.default.mkdirSync(instancePath, {
|
|
269
|
+
recursive: true
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
_fs.default.mkdirSync(nginxFolderPath, {
|
|
273
|
+
recursive: true
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
_fs.default.writeFileSync(landoFileTargetPath, landoFile);
|
|
277
|
+
|
|
278
|
+
_fs.default.writeFileSync(nginxFileTargetPath, nginxFile);
|
|
279
|
+
|
|
280
|
+
_fs.default.writeFileSync(instanceDataTargetPath, instanceDataFile);
|
|
281
|
+
|
|
282
|
+
debug(`Lando file created in ${landoFileTargetPath}`);
|
|
283
|
+
debug(`Nginx file created in ${nginxFileTargetPath}`);
|
|
284
|
+
debug(`Instance data file created in ${instanceDataTargetPath}`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function getAllEnvironmentNames() {
|
|
288
|
+
const mainEnvironmentPath = _xdgBasedir.default.data || _os.default.tmpdir();
|
|
289
|
+
|
|
290
|
+
const baseDir = _path.default.join(mainEnvironmentPath, 'vip', 'dev-environment');
|
|
291
|
+
|
|
292
|
+
const doWeHaveAnyEnvironment = _fs.default.existsSync(baseDir);
|
|
293
|
+
|
|
294
|
+
let envNames = [];
|
|
295
|
+
|
|
296
|
+
if (doWeHaveAnyEnvironment) {
|
|
297
|
+
const files = _fs.default.readdirSync(baseDir);
|
|
298
|
+
|
|
299
|
+
envNames = files.filter(file => {
|
|
300
|
+
const fullPath = _path.default.join(baseDir, file);
|
|
301
|
+
|
|
302
|
+
return _fs.default.lstatSync(fullPath).isDirectory();
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return envNames;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function getEnvironmentPath(name) {
|
|
310
|
+
if (!name) {
|
|
311
|
+
throw new Error('Name was not provided');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const mainEnvironmentPath = _xdgBasedir.default.data || _os.default.tmpdir();
|
|
315
|
+
|
|
316
|
+
return _path.default.join(mainEnvironmentPath, 'vip', 'dev-environment', name + '');
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async function getApplicationInformation(appId, envType) {
|
|
320
|
+
// $FlowFixMe: gql template is not supported by flow
|
|
321
|
+
const fieldsQuery = `
|
|
322
|
+
id,
|
|
323
|
+
name,
|
|
324
|
+
repository {
|
|
325
|
+
htmlUrl,
|
|
326
|
+
fullName
|
|
327
|
+
},
|
|
328
|
+
environments {
|
|
329
|
+
id,
|
|
330
|
+
name,
|
|
331
|
+
type,
|
|
332
|
+
branch,
|
|
333
|
+
isMultisite,
|
|
334
|
+
primaryDomain {
|
|
335
|
+
name
|
|
336
|
+
}
|
|
337
|
+
}`;
|
|
338
|
+
const queryResult = await (0, _app.default)(appId, fieldsQuery);
|
|
339
|
+
const appData = {};
|
|
340
|
+
|
|
341
|
+
if (queryResult) {
|
|
342
|
+
var _queryResult$reposito;
|
|
343
|
+
|
|
344
|
+
appData.id = queryResult.id;
|
|
345
|
+
appData.name = queryResult.name;
|
|
346
|
+
appData.repository = (_queryResult$reposito = queryResult.repository) === null || _queryResult$reposito === void 0 ? void 0 : _queryResult$reposito.htmlUrl;
|
|
347
|
+
const environments = queryResult.environments || [];
|
|
348
|
+
let envData;
|
|
349
|
+
|
|
350
|
+
if (envType) {
|
|
351
|
+
envData = environments.find(candidateEnv => candidateEnv.type === envType);
|
|
352
|
+
} else if (1 === environments.length) {
|
|
353
|
+
envData = environments[0];
|
|
354
|
+
} else {
|
|
355
|
+
const choices = environments.map(candidateEnv => candidateEnv.type);
|
|
356
|
+
const {
|
|
357
|
+
env
|
|
358
|
+
} = await (0, _enquirer.prompt)({
|
|
359
|
+
type: 'select',
|
|
360
|
+
name: 'env',
|
|
361
|
+
message: 'Which environment?',
|
|
362
|
+
choices
|
|
363
|
+
});
|
|
364
|
+
envData = environments.find(candidateEnv => candidateEnv.type === env);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (envData) {
|
|
368
|
+
var _envData$primaryDomai;
|
|
369
|
+
|
|
370
|
+
appData.environment = {
|
|
371
|
+
name: envData.name,
|
|
372
|
+
branch: envData.branch,
|
|
373
|
+
type: envData.type,
|
|
374
|
+
isMultisite: envData.isMultisite,
|
|
375
|
+
primaryDomain: ((_envData$primaryDomai = envData.primaryDomain) === null || _envData$primaryDomai === void 0 ? void 0 : _envData$primaryDomai.name) || ''
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return appData;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async function resolveImportPath(slug, fileName, searchReplace, inPlace) {
|
|
384
|
+
let resolvedPath = (0, _devEnvironmentCli.resolvePath)(fileName);
|
|
385
|
+
|
|
386
|
+
if (!_fs.default.existsSync(resolvedPath)) {
|
|
387
|
+
throw new Error('The provided file does not exist or it is not valid (see "--help" for examples)');
|
|
388
|
+
} // Run Search and Replace if the --search-replace flag was provided
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
if (searchReplace && searchReplace.length) {
|
|
392
|
+
const {
|
|
393
|
+
outputFileName
|
|
394
|
+
} = await (0, _searchAndReplace.searchAndReplace)(resolvedPath, searchReplace, {
|
|
395
|
+
isImport: true,
|
|
396
|
+
output: true,
|
|
397
|
+
inPlace
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
if (typeof outputFileName !== 'string') {
|
|
401
|
+
throw new Error('Unable to determine location of the intermediate search & replace file.');
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const environmentPath = getEnvironmentPath(slug);
|
|
405
|
+
|
|
406
|
+
const baseName = _path.default.basename(outputFileName);
|
|
407
|
+
|
|
408
|
+
resolvedPath = _path.default.join(environmentPath, baseName);
|
|
409
|
+
|
|
410
|
+
_fs.default.renameSync(outputFileName, resolvedPath);
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Docker container does not have acces to the host filesystem.
|
|
414
|
+
* However lando maps os.homedir() to /user in the container. So if we replace the path in the same way
|
|
415
|
+
* in the Docker container will get the file from within the mapped volume under /user.
|
|
416
|
+
*/
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
let inContainerPath = resolvedPath.replace(_os.default.homedir(), homeDirPathInsideContainers);
|
|
420
|
+
|
|
421
|
+
if (_path.default.sep === '\\') {
|
|
422
|
+
// Because the file path generated for windows will have \ instead of / we need to replace that as well so that the path inside the container (unix) still works.
|
|
423
|
+
inContainerPath = inContainerPath.replace(/\\/g, '/');
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
debug(`Import file path ${resolvedPath} will be mapped to ${inContainerPath}`);
|
|
427
|
+
return {
|
|
428
|
+
resolvedPath,
|
|
429
|
+
inContainerPath
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
async function importMediaPath(slug, filePath) {
|
|
434
|
+
const resolvedPath = (0, _devEnvironmentCli.resolvePath)(filePath);
|
|
435
|
+
|
|
436
|
+
if (!_fs.default.existsSync(resolvedPath) || !_fs.default.lstatSync(resolvedPath).isDirectory()) {
|
|
437
|
+
throw new Error('The provided path does not exist or it is not valid (see "--help" for examples)');
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const files = _fs.default.readdirSync(resolvedPath);
|
|
441
|
+
|
|
442
|
+
if (files.indexOf(uploadPathString) > -1) {
|
|
443
|
+
const confirm = await (0, _enquirer.prompt)({
|
|
444
|
+
type: 'confirm',
|
|
445
|
+
name: 'continue',
|
|
446
|
+
message: 'The provided path contains an uploads folder inside. Do you want to continue?'
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
if (!confirm.continue) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const environmentPath = getEnvironmentPath(slug);
|
|
455
|
+
|
|
456
|
+
const uploadsPath = _path.default.join(environmentPath, uploadPathString);
|
|
457
|
+
|
|
458
|
+
console.log(`${_chalk.default.yellow('-')} Started copying files`);
|
|
459
|
+
|
|
460
|
+
_copyDir.default.sync(resolvedPath, uploadsPath);
|
|
461
|
+
|
|
462
|
+
console.log(`${_chalk.default.green('✓')} Files successfully copied to ${uploadsPath}.`);
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Uses the WordPress versions manifest on github.com
|
|
466
|
+
* Informs the user several things:
|
|
467
|
+
* - If the WordPress image their env uses is no longer available
|
|
468
|
+
* - If there is a newer version of the WordPress version currently used
|
|
469
|
+
* - A choice to use a different image
|
|
470
|
+
*
|
|
471
|
+
* @param {Object=} slug slug
|
|
472
|
+
* @return {boolean} boolean
|
|
473
|
+
*/
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
async function updateWordPressImage(slug) {
|
|
477
|
+
const versions = await getVersionList();
|
|
478
|
+
let message, envData, currentWordPressTag; // Get the current environment configuration
|
|
479
|
+
|
|
480
|
+
try {
|
|
481
|
+
envData = readEnvironmentData(slug);
|
|
482
|
+
currentWordPressTag = envData.wordpress.tag;
|
|
483
|
+
} catch (error) {
|
|
484
|
+
// This can throw an exception if the env is build with older vip version
|
|
485
|
+
if ('ENOENT' === error.code) {
|
|
486
|
+
message = 'Environment was created before update was supported.\n\n';
|
|
487
|
+
message += 'To update environment please destroy it and create a new one.';
|
|
488
|
+
} else {
|
|
489
|
+
message = `An error prevented reading the configuration of: ${slug}\n\n ${error}`;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
(0, _devEnvironmentCli.handleCLIException)(new Error(message));
|
|
493
|
+
return false;
|
|
494
|
+
} // sort
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
versions.sort((before, after) => before.tag < after.tag ? 1 : -1); // Newest WordPress Image but that is not trunk
|
|
498
|
+
|
|
499
|
+
const newestWordPressImage = versions.find(({
|
|
500
|
+
tag
|
|
501
|
+
}) => tag !== 'trunk');
|
|
502
|
+
console.log('The most recent WordPress version available is: ' + _chalk.default.green(newestWordPressImage.tag)); // If the currently used version is the most up to date: exit.
|
|
503
|
+
|
|
504
|
+
if (currentWordPressTag === newestWordPressImage.tag) {
|
|
505
|
+
console.log('Environment WordPress version is: ' + _chalk.default.green(currentWordPressTag) + ' ... 😎 nice! ');
|
|
506
|
+
return false;
|
|
507
|
+
} // Determine if there is an image available for the current WordPress version
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
const match = versions.find(({
|
|
511
|
+
tag
|
|
512
|
+
}) => tag === currentWordPressTag); // If there is no available image for the currently installed version, give user a path to change
|
|
513
|
+
|
|
514
|
+
if (typeof match === 'undefined') {
|
|
515
|
+
console.log(`Installed WordPress: ${currentWordPressTag} has no available container image in repository. `);
|
|
516
|
+
console.log('You must select a new WordPress image to continue... ');
|
|
517
|
+
} else {
|
|
518
|
+
console.log('Environment WordPress version is: ' + _chalk.default.yellow(`${match.tag} (${match.ref})`));
|
|
519
|
+
|
|
520
|
+
if (envData.wordpress.doNotUpgrade || false) {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
} // Prompt the user to select a new WordPress Version
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
const confirm = await (0, _enquirer.prompt)({
|
|
527
|
+
type: 'select',
|
|
528
|
+
name: 'upgrade',
|
|
529
|
+
message: 'Would You like to change the WordPress version? ',
|
|
530
|
+
choices: ['yes', 'no', "no (don't ask anymore)"]
|
|
531
|
+
}); // If the user takes the new WP version path
|
|
532
|
+
|
|
533
|
+
if (confirm.upgrade === 'yes') {
|
|
534
|
+
console.log('Upgrading from: ' + _chalk.default.yellow(currentWordPressTag) + ' to:'); // Select a new image
|
|
535
|
+
|
|
536
|
+
const choice = await (0, _devEnvironmentCli.promptForComponent)('wordpress');
|
|
537
|
+
const version = versions.find(({
|
|
538
|
+
tag
|
|
539
|
+
}) => tag.trim() === choice.tag.trim()); // Write new data and stage for rebuild
|
|
540
|
+
|
|
541
|
+
envData.wordpress.tag = version.tag;
|
|
542
|
+
envData.wordpress.ref = version.ref;
|
|
543
|
+
await updateEnvironment(envData);
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (confirm.upgrade === "no (don't ask anymore)") {
|
|
548
|
+
envData.wordpress.doNotUpgrade = true;
|
|
549
|
+
console.log("We won't ask about upgrading this environment anymore.");
|
|
550
|
+
console.log('To manually upgrade please run:' + `${_chalk.default.yellow(`vip dev-env update --slug=${slug}`)}`);
|
|
551
|
+
await updateEnvironment(envData);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Makes a web call to raw.githubusercontent.com
|
|
558
|
+
*/
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
async function fetchVersionList() {
|
|
562
|
+
const url = `https://${_devEnvironment.DEV_ENVIRONMENT_RAW_GITHUB_HOST}${_devEnvironment.DEV_ENVIRONMENT_WORDPRESS_VERSIONS_URI}`;
|
|
563
|
+
return (0, _nodeFetch.default)(url).then(res => res.text());
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Encapsulates the logic for determining if a file is expired by an arbitrary TTL
|
|
567
|
+
* @param {string} cacheFile uri of cache file
|
|
568
|
+
* @param {number} ttl time to live in seconds
|
|
569
|
+
* @returns {boolean} version list expired true/false
|
|
570
|
+
*/
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
function isVersionListExpired(cacheFile, ttl) {
|
|
574
|
+
const stats = _fs.default.statSync(cacheFile);
|
|
575
|
+
|
|
576
|
+
const expire = new Date(stats.mtime);
|
|
577
|
+
expire.setSeconds(expire.getSeconds() + ttl);
|
|
578
|
+
return +new Date() > expire;
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Uses a cache file to keep the version list in tow until it is ultimately outdated
|
|
582
|
+
*/
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
async function getVersionList() {
|
|
586
|
+
let res;
|
|
587
|
+
|
|
588
|
+
const mainEnvironmentPath = _xdgBasedir.default.data || _os.default.tmpdir();
|
|
589
|
+
|
|
590
|
+
const cacheFile = _path.default.join(mainEnvironmentPath, 'vip', _devEnvironment.DEV_ENVIRONMENT_WORDPRESS_CACHE_KEY); // Handle from cache
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
try {
|
|
594
|
+
// If the cache doesn't exist, create it
|
|
595
|
+
if (!_fs.default.existsSync(cacheFile)) {
|
|
596
|
+
res = await fetchVersionList();
|
|
597
|
+
|
|
598
|
+
_fs.default.writeFileSync(cacheFile, res);
|
|
599
|
+
} // If the cache is expired, refresh it
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
if (isVersionListExpired(cacheFile, _devEnvironment.DEV_ENVIRONMENT_WORDPRESS_VERSION_TTL)) {
|
|
603
|
+
res = await fetchVersionList();
|
|
604
|
+
|
|
605
|
+
_fs.default.writeFileSync(cacheFile, res);
|
|
606
|
+
}
|
|
607
|
+
} catch (err) {
|
|
608
|
+
// Soft error handling here, since it's still possible to use a previously cached file.
|
|
609
|
+
console.log(_chalk.default.yellow('fetchWordPressVersionList failed to retrieve an updated version list'));
|
|
610
|
+
debug(err);
|
|
611
|
+
} // Try to parse the cached file if it exists.
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
try {
|
|
615
|
+
return JSON.parse(_fs.default.readFileSync(cacheFile));
|
|
616
|
+
} catch (err) {
|
|
617
|
+
debug(err);
|
|
618
|
+
return [];
|
|
619
|
+
}
|
|
620
|
+
}
|