@automattic/vip 2.32.4 → 2.33.0-dev1
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 +54 -28
- package/dist/bin/vip-backup-db.js +58 -0
- package/dist/bin/vip-backup.js +19 -0
- package/dist/bin/vip-import-media-abort.js +1 -0
- package/dist/bin/vip-import-media-status.js +1 -0
- package/dist/bin/vip-import-sql-status.js +1 -0
- package/dist/bin/vip.js +1 -1
- package/dist/commands/backup-db.js +2 -5
- package/dist/commands/export-sql.js +5 -0
- package/dist/lib/cli/format.js +31 -1
- package/dist/lib/dev-environment/dev-environment-lando.js +1 -1
- package/npm-shrinkwrap.json +643 -586
- package/package.json +5 -3
- package/export.sql +0 -627
package/CONTRIBUTING.md
CHANGED
|
@@ -72,19 +72,39 @@ For help, see: https://nodejs.org/en/docs/inspector
|
|
|
72
72
|
|
|
73
73
|
New libraries should generally support both CLI and web contexts, though some cases that won't make sense (e.g. formatting for CLI output). Ensuring the libraries are useful everywhere will allow us to offer consistent experiences regardless of the interface.
|
|
74
74
|
|
|
75
|
+
### go-search-replace binaries
|
|
76
|
+
|
|
77
|
+
Some unit tests require some go-search-replace executable binary files to run. Binaries files for
|
|
78
|
+
several OS architectures can be downloaded
|
|
79
|
+
from https://github.com/Automattic/go-search-replace/releases/
|
|
80
|
+
|
|
81
|
+
If, for some reason, you need to compile these binaries yourself, please follow instructions
|
|
82
|
+
at https://github.com/Automattic/go-search-replace
|
|
83
|
+
|
|
84
|
+
### Generating the types
|
|
85
|
+
|
|
86
|
+
If you're an employee of Automattic, you can follow these steps to regenerate the GraphQL types
|
|
87
|
+
used.
|
|
88
|
+
|
|
89
|
+
1. Get a hold of `schema.gql` and paste it in project root - this is the schema of the endpoint that
|
|
90
|
+
we communicate with.
|
|
91
|
+
2. Run `npm run typescript:codegen:install-dependencies` - this will install the codegen
|
|
92
|
+
dependencies without updating `package.json`
|
|
93
|
+
3. Run `npm run typescript:codegen:generate` - this will regenerate the types
|
|
94
|
+
|
|
75
95
|
## Release & Deployment Process
|
|
76
96
|
|
|
77
97
|
Our release flow for VIP CLI follows this pattern:
|
|
78
98
|
|
|
79
|
-
**_feature branch ->
|
|
99
|
+
**_feature branch -> trunk branch -> NPM release_**
|
|
80
100
|
|
|
81
101
|
- For feature branches, please follow A8C branch naming conventions (e.g.- `add/data-sync-command`, `fix/subsite-launch-command`, etc.)
|
|
82
102
|
- Include a Changelog for all npm version releases, including any minor or major versions
|
|
83
103
|
- This is a public repository. Please do not include any internal links in PRs, changelogs, testing instructions, etc.
|
|
84
|
-
- Merge changes from your feature branch to the `
|
|
85
|
-
- If you are ready to release your changes publicly, merge your changes from the `develop` branch to the `trunk` branch. All changes that are not ready to be public should be feature flagged or stay in the `develop` branch to avoid conflicts when releasing urgent fixes (not recommended).
|
|
104
|
+
- Merge changes from your feature branch to the `trunk` branch when they are ready to be published publicly.
|
|
86
105
|
- Finally, release your changes as a new minor or major NPM version. Ping in the #vip-platform channel to notify folks of a new release, but please feel free to release your changes without any blockers from the team. Any team member that is part of the Automattic NPM organization can release a new version; if you aren't a member, generic credentials are available in the Secret Store.
|
|
87
106
|
|
|
107
|
+
If you need to publish a security release, see [details below](#patching-old-releases).
|
|
88
108
|
### Changelogs
|
|
89
109
|
|
|
90
110
|
Changelogs allow customers to keep up with all the changes happening across our VIP Platform. Changelogs for VIP CLI are posted to the [VIP Cloud Changelog P2](https://wpvipchangelog.wordpress.com/), along with the repository’s `README.md`.
|
|
@@ -97,6 +117,12 @@ We use a custom pre-publish [script](https://github.com/Automattic/vip/blob/trun
|
|
|
97
117
|
|
|
98
118
|
Further checks can be added to this flow as needed.
|
|
99
119
|
|
|
120
|
+
### Versioning Guidelines
|
|
121
|
+
|
|
122
|
+
- `patch`: for non-breaking changes/bugfixes and small updates.
|
|
123
|
+
- `minor`: for some new features, bug fixes, and other non-breaking changes.
|
|
124
|
+
- `major`: for breaking changes.
|
|
125
|
+
|
|
100
126
|
### New Releases
|
|
101
127
|
|
|
102
128
|
Prepare the release by making sure that:
|
|
@@ -108,6 +134,8 @@ Prepare the release by making sure that:
|
|
|
108
134
|
1. Make sure not to merge anymore changes into `develop` while all the release steps below are in
|
|
109
135
|
progress.
|
|
110
136
|
|
|
137
|
+
You can release either using GitHub Actions or locally.
|
|
138
|
+
|
|
111
139
|
#### Changelog Generator Hint:
|
|
112
140
|
|
|
113
141
|
In the first step, you'll need to generate a changelog.
|
|
@@ -119,14 +147,32 @@ export LAST_RELEASE_DATE=2021-08-25T13:40:00+02
|
|
|
119
147
|
gh pr list --search "is:merged sort:updated-desc closed:>$LAST_RELEASE_DATE" | sed -e 's/\s\+\S\+\tMERGED.*$//' -e 's/^/- #/'
|
|
120
148
|
```
|
|
121
149
|
|
|
122
|
-
Then, let's publish:
|
|
123
150
|
|
|
124
|
-
|
|
151
|
+
#### Publishing via GitHub Actions (preferred)
|
|
152
|
+
|
|
153
|
+
This is the preferred method for pushing out the latest release. The workflow runs a bunch of validations, generates a build, bump versions + tags, pushes out to npm, and bumps to the next dev version.
|
|
154
|
+
|
|
155
|
+
1. Initiate the [release process here](https://github.com/Automattic/vip-cli/actions/workflows/npm-prepare-release.yml).
|
|
156
|
+
1. On the right-hand side, select "Run Workflow".
|
|
157
|
+
1. Pick your preferred version bump.
|
|
158
|
+
1. Click `Run Workflow`.
|
|
159
|
+
1. Wait for a pull request to appear. The pull request will update the version number and shall be assigned to you.
|
|
160
|
+
1. When ready, merge the pull request. This will lead to a new version to be [published on npmjs.com](https://www.npmjs.com/package/@automattic/vip).
|
|
161
|
+
1. Another pull request will be created to bump to a development version, also assigned to you. Merge it to finish the process.
|
|
162
|
+
|
|
163
|
+
#### Note on NPM token
|
|
164
|
+
|
|
165
|
+
Publishing via the GitHub Action requires that the `NPM_TOKEN` be set correctly in GitHub Actions secrets. This should be an npm token generated for a bot user on [the npm @automattic org](https://www.npmjs.com/settings/automattic) that has publish access to this repo.
|
|
166
|
+
|
|
167
|
+
#### Publishing locally
|
|
168
|
+
|
|
169
|
+
To publish locally, follow these steps:
|
|
170
|
+
|
|
171
|
+
1. Create a pull request that adds the next version's changelog into `trunk`. Use the Changelog
|
|
125
172
|
Generate Hint above to generate the changelog, and refer to previous releases to ensure that your
|
|
126
|
-
format matches.
|
|
127
|
-
1. Create a pull request that merges `develop` to `trunk`.
|
|
173
|
+
format matches.
|
|
128
174
|
1. Merge it after approval.
|
|
129
|
-
1. Make sure trunk branch is up-to-date `git pull`.
|
|
175
|
+
1. Make sure `trunk` branch is up-to-date `git pull`.
|
|
130
176
|
1. Make sure to clean all of your repositories of extra files. Run a dangerous, destructive
|
|
131
177
|
command `git clean -xfd` to do so.
|
|
132
178
|
1. Run `npm install`.
|
|
@@ -168,23 +214,3 @@ For these cases:
|
|
|
168
214
|
1. Follow the release steps outlined above (as a `patch` release).
|
|
169
215
|
|
|
170
216
|
Then, repeat for any additional versions that we need to patch.
|
|
171
|
-
|
|
172
|
-
### go-search-replace binaries
|
|
173
|
-
|
|
174
|
-
Some unit tests require some go-search-replace executable binary files to run. Binaries files for
|
|
175
|
-
several OS architectures can be downloaded
|
|
176
|
-
from https://github.com/Automattic/go-search-replace/releases/
|
|
177
|
-
|
|
178
|
-
If, for some reason, you need to compile these binaries yourself, please follow instructions
|
|
179
|
-
at https://github.com/Automattic/go-search-replace
|
|
180
|
-
|
|
181
|
-
### Generating the types
|
|
182
|
-
|
|
183
|
-
If you're an employee of Automattic, you can follow these steps to regenerate the GraphQL types
|
|
184
|
-
used.
|
|
185
|
-
|
|
186
|
-
1. Get a hold of `schema.gql` and paste it in project root - this is the schema of the endpoint that
|
|
187
|
-
we communicate with.
|
|
188
|
-
2. Run `npm run typescript:codegen:install-dependencies` - this will install the codegen
|
|
189
|
-
dependencies without updating `package.json`
|
|
190
|
-
3. Run `npm run typescript:codegen:generate` - this will regenerate the types
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @format
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* External dependencies
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Internal dependencies
|
|
14
|
+
*/
|
|
15
|
+
"use strict";
|
|
16
|
+
|
|
17
|
+
var _command = _interopRequireDefault(require("../lib/cli/command"));
|
|
18
|
+
var _tracker = require("../lib/tracker");
|
|
19
|
+
var _backupDb = require("../commands/backup-db");
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
|
+
const examples = [{
|
|
22
|
+
usage: 'vip backup db @mysite.develop',
|
|
23
|
+
description: 'Trigger a new backup for your database of the @mysite.develop environment'
|
|
24
|
+
}];
|
|
25
|
+
const appQuery = `
|
|
26
|
+
id,
|
|
27
|
+
name,
|
|
28
|
+
type,
|
|
29
|
+
organization { id, name },
|
|
30
|
+
environments{
|
|
31
|
+
id
|
|
32
|
+
appId
|
|
33
|
+
type
|
|
34
|
+
name
|
|
35
|
+
primaryDomain { name }
|
|
36
|
+
uniqueLabel
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
void (0, _command.default)({
|
|
40
|
+
appContext: true,
|
|
41
|
+
appQuery,
|
|
42
|
+
envContext: true,
|
|
43
|
+
module: 'backup-db',
|
|
44
|
+
requiredArgs: 0,
|
|
45
|
+
usage: 'vip backup db'
|
|
46
|
+
}).examples(examples).argv(process.argv, async (arg, {
|
|
47
|
+
app,
|
|
48
|
+
env
|
|
49
|
+
}) => {
|
|
50
|
+
const trackerFn = (0, _tracker.makeCommandTracker)('backup_db', {
|
|
51
|
+
app: app.id,
|
|
52
|
+
env: env.uniqueLabel
|
|
53
|
+
});
|
|
54
|
+
await trackerFn('execute');
|
|
55
|
+
const cmd = new _backupDb.BackupDBCommand(app, env, trackerFn);
|
|
56
|
+
await cmd.run();
|
|
57
|
+
await trackerFn('success');
|
|
58
|
+
});
|
|
@@ -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
|
+
void (0, _command.default)({
|
|
16
|
+
usage: 'vip backup'
|
|
17
|
+
}).command('db', 'Trigger a new backup for your database').example('vip backup sql @mysite.develop', 'Trigger a new backup for your database of the @mysite.develop environment').argv(process.argv, async () => {
|
|
18
|
+
await (0, _tracker.trackEvent)('vip_backup_command_execute');
|
|
19
|
+
});
|
package/dist/bin/vip.js
CHANGED
|
@@ -28,7 +28,7 @@ if (_config.default && _config.default.environment !== 'production') {
|
|
|
28
28
|
const tokenURL = 'https://dashboard.wpvip.com/me/cli/token';
|
|
29
29
|
const runCmd = async function () {
|
|
30
30
|
const cmd = (0, _command.default)();
|
|
31
|
-
cmd.command('logout', 'Logout from your current session').command('app', 'List and modify your VIP applications').command('cache', 'Manage page cache for your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-environment').command('export', 'Export data from your VIP application').command('import', 'Import media or SQL files into your VIP applications').command('logs', 'Get logs from your VIP applications').command('search-replace', 'Perform search and replace tasks on files').command('slowlogs', 'Get slowlogs from your VIP applications').command('sync', 'Sync production to a development environment').command('whoami', 'Display details about the currently logged-in user').command('validate', 'Validate your VIP application and environment').command('wp', 'Run WP CLI commands against an environment');
|
|
31
|
+
cmd.command('logout', 'Logout from your current session').command('app', 'List and modify your VIP applications').command('backup', 'Generate a backup for VIP applications').command('cache', 'Manage page cache for your VIP applications').command('config', 'Set configuration for your VIP applications').command('dev-env', 'Use local dev-environment').command('export', 'Export data from your VIP application').command('import', 'Import media or SQL files into your VIP applications').command('logs', 'Get logs from your VIP applications').command('search-replace', 'Perform search and replace tasks on files').command('slowlogs', 'Get slowlogs from your VIP applications').command('sync', 'Sync production to a development environment').command('whoami', 'Display details about the currently logged-in user').command('validate', 'Validate your VIP application and environment').command('wp', 'Run WP CLI commands against an environment');
|
|
32
32
|
cmd.argv(process.argv);
|
|
33
33
|
};
|
|
34
34
|
function doesArgvHaveAtLeastOneParam(argv, params) {
|
|
@@ -10,6 +10,7 @@ var _api = _interopRequireWildcard(require("../lib/api"));
|
|
|
10
10
|
var exit = _interopRequireWildcard(require("../lib/cli/exit"));
|
|
11
11
|
var _utils = require("../lib/utils");
|
|
12
12
|
var _progress = require("../lib/cli/progress");
|
|
13
|
+
var _format = require("../lib/cli/format");
|
|
13
14
|
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); }
|
|
14
15
|
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; }
|
|
15
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -148,10 +149,6 @@ class BackupDBCommand {
|
|
|
148
149
|
async run(silent = false) {
|
|
149
150
|
var _this$job4;
|
|
150
151
|
this.silent = silent;
|
|
151
|
-
let noticeMessage = `\n${_chalk.default.yellow('NOTICE: ')}`;
|
|
152
|
-
noticeMessage += 'If a recent database backup does not exist, a new one will be generated for this environment. ';
|
|
153
|
-
noticeMessage += 'Learn more about this: https://docs.wpvip.com/technical-references/vip-dashboard/backups/#2-download-a-full-database-backup \n';
|
|
154
|
-
this.log(noticeMessage);
|
|
155
152
|
await this.loadBackupJob();
|
|
156
153
|
if ((_this$job4 = this.job) !== null && _this$job4 !== void 0 && _this$job4.inProgressLock) {
|
|
157
154
|
this.log('Database backup already in progress...');
|
|
@@ -175,7 +172,7 @@ class BackupDBCommand {
|
|
|
175
172
|
stack: error.stack
|
|
176
173
|
});
|
|
177
174
|
const errMessage = `A new database backup was not generated because a recently generated backup already exists.
|
|
178
|
-
If you would like to run the same command, you can retry on or after
|
|
175
|
+
If you would like to run the same command, you can retry on or after ${(0, _format.formatDuration)(new Date(), new Date(retryAfter))}
|
|
179
176
|
Alternatively, you can export the latest existing database backup by running: ${_chalk.default.green('vip @app.env export sql')}, right away.
|
|
180
177
|
Learn more about limitations around generating database backups: https://docs.wpvip.com/technical-references/vip-dashboard/backups/#0-limitations
|
|
181
178
|
`;
|
|
@@ -8,6 +8,7 @@ var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
|
8
8
|
var _fs = _interopRequireDefault(require("fs"));
|
|
9
9
|
var _https = _interopRequireDefault(require("https"));
|
|
10
10
|
var _path = _interopRequireDefault(require("path"));
|
|
11
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
11
12
|
var _api = _interopRequireWildcard(require("../lib/api"));
|
|
12
13
|
var _format = require("../lib/cli/format");
|
|
13
14
|
var _progress = require("../lib/cli/progress");
|
|
@@ -313,6 +314,10 @@ class ExportSQLCommand {
|
|
|
313
314
|
}
|
|
314
315
|
async runBackupJob() {
|
|
315
316
|
const cmd = new _backupDb.BackupDBCommand(this.app, this.env);
|
|
317
|
+
let noticeMessage = `\n${_chalk.default.yellow('NOTICE: ')}`;
|
|
318
|
+
noticeMessage += 'If a recent database backup does not exist, a new one will be generated for this environment. ';
|
|
319
|
+
noticeMessage += 'Learn more about this: https://docs.wpvip.com/technical-references/vip-dashboard/backups/#2-download-a-full-database-backup \n';
|
|
320
|
+
this.log(noticeMessage);
|
|
316
321
|
await cmd.run(false);
|
|
317
322
|
}
|
|
318
323
|
|
package/dist/lib/cli/format.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.RunningSprite = exports.RUNNING_SPRITE_GLYPHS = void 0;
|
|
|
7
7
|
exports.capitalize = capitalize;
|
|
8
8
|
exports.formatBytes = void 0;
|
|
9
9
|
exports.formatData = formatData;
|
|
10
|
+
exports.formatDuration = formatDuration;
|
|
10
11
|
exports.formatEnvironment = formatEnvironment;
|
|
11
12
|
exports.formatSearchReplaceValues = formatSearchReplaceValues;
|
|
12
13
|
exports.getGlyphForStatus = getGlyphForStatus;
|
|
@@ -195,4 +196,33 @@ const formatBytes = (bytes, decimals = 2) => {
|
|
|
195
196
|
const idx = Math.floor(Math.log(bytes) / Math.log(bytesMultiplier));
|
|
196
197
|
return `${parseFloat((bytes / Math.pow(bytesMultiplier, idx)).toFixed(dm))} ${sizes[idx]}`;
|
|
197
198
|
};
|
|
198
|
-
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Get the duration between two dates
|
|
202
|
+
*
|
|
203
|
+
* @param {Date} from The start date
|
|
204
|
+
* @param {Date} to The end date
|
|
205
|
+
* @returns {string} The duration between the two dates
|
|
206
|
+
*/
|
|
207
|
+
exports.formatBytes = formatBytes;
|
|
208
|
+
function formatDuration(from, to) {
|
|
209
|
+
const millisecondsPerSecond = 1000;
|
|
210
|
+
const millisecondsPerMinute = 60 * millisecondsPerSecond;
|
|
211
|
+
const millisecondsPerHour = 60 * millisecondsPerMinute;
|
|
212
|
+
const millisecondsPerDay = 24 * millisecondsPerHour;
|
|
213
|
+
const duration = Math.abs(from.getTime() - to.getTime());
|
|
214
|
+
const days = Math.floor(duration / millisecondsPerDay);
|
|
215
|
+
const hours = Math.floor(duration % millisecondsPerDay / millisecondsPerHour);
|
|
216
|
+
const minutes = Math.floor(duration % millisecondsPerHour / millisecondsPerMinute);
|
|
217
|
+
let durationString = '';
|
|
218
|
+
if (days > 0) {
|
|
219
|
+
durationString += `${days} day${days > 1 ? 's' : ''} `;
|
|
220
|
+
}
|
|
221
|
+
if (hours > 0) {
|
|
222
|
+
durationString += `${hours} hour${hours > 1 ? 's' : ''} `;
|
|
223
|
+
}
|
|
224
|
+
if (minutes > 0) {
|
|
225
|
+
durationString += `${minutes} minute${minutes > 1 ? 's' : ''} `;
|
|
226
|
+
}
|
|
227
|
+
return durationString.trim();
|
|
228
|
+
}
|
|
@@ -398,7 +398,7 @@ async function checkEnvHealth(lando, instancePath) {
|
|
|
398
398
|
urls[url] = service.service;
|
|
399
399
|
});
|
|
400
400
|
});
|
|
401
|
-
const urlsToScan = Object.keys(urls);
|
|
401
|
+
const urlsToScan = Object.keys(urls).filter(url => !url.includes('*'));
|
|
402
402
|
let scanResults = [];
|
|
403
403
|
if (Array.isArray(app.urls)) {
|
|
404
404
|
scanResults = app.urls;
|