@automattic/jetpack-cli 0.1.0-beta.1 → 0.1.0-beta3
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/README.md +18 -0
- package/bin/jp.js +166 -13
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Jetpack
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## How to install Jetpack plugin on your site
|
|
5
|
+
### Installation From Git Repo
|
|
6
|
+
|
|
7
|
+
## Contribute
|
|
8
|
+
|
|
9
|
+
## Get Help
|
|
10
|
+
|
|
11
|
+
## Security
|
|
12
|
+
|
|
13
|
+
Need to report a security vulnerability? Go to [https://automattic.com/security/](https://automattic.com/security/) or directly to our security bug bounty site [https://hackerone.com/automattic](https://hackerone.com/automattic).
|
|
14
|
+
|
|
15
|
+
## License
|
|
16
|
+
|
|
17
|
+
Licensed under [GNU General Public License v2 (or later)](./LICENSE.txt).
|
|
18
|
+
|
package/bin/jp.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from 'child_process';
|
|
4
|
-
import fs from 'fs';
|
|
4
|
+
import fs, { readFileSync } from 'fs';
|
|
5
5
|
import { dirname, resolve } from 'path';
|
|
6
6
|
import process from 'process';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
7
8
|
import chalk from 'chalk';
|
|
9
|
+
import dotenv from 'dotenv';
|
|
8
10
|
import prompts from 'prompts';
|
|
9
11
|
|
|
12
|
+
// Get package.json path relative to this file
|
|
13
|
+
const __dirname = dirname( fileURLToPath( import.meta.url ) );
|
|
14
|
+
const packageJson = JSON.parse( readFileSync( resolve( __dirname, '../package.json' ), 'utf8' ) );
|
|
15
|
+
|
|
10
16
|
/**
|
|
11
17
|
* Check if a directory is the monorepo root.
|
|
12
18
|
*
|
|
@@ -45,7 +51,6 @@ const findMonorepoRoot = startDir => {
|
|
|
45
51
|
* @throws {Error} If clone fails
|
|
46
52
|
*/
|
|
47
53
|
const cloneMonorepo = async targetDir => {
|
|
48
|
-
// eslint-disable-next-line no-console
|
|
49
54
|
console.log( chalk.blue( 'Cloning Jetpack monorepo...' ) );
|
|
50
55
|
const result = spawnSync(
|
|
51
56
|
'git',
|
|
@@ -83,15 +88,15 @@ const initJetpack = async () => {
|
|
|
83
88
|
|
|
84
89
|
try {
|
|
85
90
|
await cloneMonorepo( targetDir );
|
|
86
|
-
|
|
91
|
+
|
|
87
92
|
console.log( chalk.green( '\nJetpack monorepo has been cloned successfully!' ) );
|
|
88
|
-
|
|
93
|
+
|
|
89
94
|
console.log( '\nNext steps:' );
|
|
90
|
-
|
|
95
|
+
|
|
91
96
|
console.log( '1. cd', response.directory );
|
|
92
|
-
|
|
97
|
+
|
|
93
98
|
console.log( '2. jp docker up' );
|
|
94
|
-
|
|
99
|
+
|
|
95
100
|
console.log( '3. jp docker install' );
|
|
96
101
|
} catch ( error ) {
|
|
97
102
|
throw new Error( `Failed to initialize Jetpack: ${ error.message }` );
|
|
@@ -103,6 +108,12 @@ const main = async () => {
|
|
|
103
108
|
try {
|
|
104
109
|
const args = process.argv.slice( 2 );
|
|
105
110
|
|
|
111
|
+
// Handle version flag
|
|
112
|
+
if ( args[ 0 ] === '--version' || args[ 0 ] === '-v' ) {
|
|
113
|
+
console.log( chalk.green( packageJson.version ) );
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
106
117
|
// Handle 'init' command specially
|
|
107
118
|
if ( args[ 0 ] === 'init' ) {
|
|
108
119
|
await initJetpack();
|
|
@@ -113,19 +124,162 @@ const main = async () => {
|
|
|
113
124
|
const monorepoRoot = findMonorepoRoot( process.cwd() );
|
|
114
125
|
|
|
115
126
|
if ( ! monorepoRoot ) {
|
|
116
|
-
// eslint-disable-next-line no-console
|
|
117
127
|
console.error( chalk.red( 'Could not find Jetpack monorepo.' ) );
|
|
118
|
-
|
|
128
|
+
|
|
119
129
|
console.log( '\nTo get started:' );
|
|
120
|
-
|
|
130
|
+
|
|
121
131
|
console.log( '1. Run', chalk.blue( 'jp init' ), 'to clone the repository' );
|
|
122
|
-
|
|
132
|
+
|
|
123
133
|
console.log( ' OR' );
|
|
124
|
-
|
|
134
|
+
|
|
125
135
|
console.log( '2. Navigate to an existing Jetpack monorepo directory' );
|
|
126
136
|
throw new Error( 'Monorepo not found' );
|
|
127
137
|
}
|
|
128
138
|
|
|
139
|
+
// Handle docker commands that must run on the host machine
|
|
140
|
+
if ( args[ 0 ] === 'docker' ) {
|
|
141
|
+
const hostCommands = [ 'up', 'down', 'stop', 'clean' ];
|
|
142
|
+
if ( hostCommands.includes( args[ 1 ] ) ) {
|
|
143
|
+
// Handle command-specific setup/cleanup
|
|
144
|
+
if ( args[ 1 ] === 'up' ) {
|
|
145
|
+
// Create required directories
|
|
146
|
+
fs.mkdirSync( resolve( monorepoRoot, 'tools/docker/data/jetpack_dev_mysql' ), {
|
|
147
|
+
recursive: true,
|
|
148
|
+
} );
|
|
149
|
+
fs.mkdirSync( resolve( monorepoRoot, 'tools/docker/data/ssh.keys' ), {
|
|
150
|
+
recursive: true,
|
|
151
|
+
} );
|
|
152
|
+
fs.mkdirSync( resolve( monorepoRoot, 'tools/docker/wordpress' ), { recursive: true } );
|
|
153
|
+
|
|
154
|
+
// Create empty .env file
|
|
155
|
+
fs.writeFileSync( resolve( monorepoRoot, 'tools/docker/.env' ), '' );
|
|
156
|
+
|
|
157
|
+
const images = [
|
|
158
|
+
{ name: 'mariadb:lts' },
|
|
159
|
+
{ name: 'automattic/jetpack-wordpress-dev:latest' },
|
|
160
|
+
{ name: 'phpmyadmin/phpmyadmin:latest', platform: 'linux/amd64' },
|
|
161
|
+
{ name: 'maildev/maildev', platform: 'linux/amd64' },
|
|
162
|
+
{ name: 'atmoz/sftp', platform: 'linux/amd64' },
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
for ( const image of images ) {
|
|
166
|
+
const inspect = spawnSync( 'docker', [ 'image', 'inspect', image.name ], {
|
|
167
|
+
stdio: 'ignore',
|
|
168
|
+
} );
|
|
169
|
+
if ( inspect.status !== 0 ) {
|
|
170
|
+
console.log( chalk.blue( `Pulling ${ image.name }...` ) );
|
|
171
|
+
const pullArgs = [ 'pull', image.name ];
|
|
172
|
+
if ( image.platform ) {
|
|
173
|
+
pullArgs.splice( 1, 0, '--platform', image.platform );
|
|
174
|
+
}
|
|
175
|
+
const pull = spawnSync( 'docker', pullArgs, { stdio: 'inherit' } );
|
|
176
|
+
if ( pull.status !== 0 ) {
|
|
177
|
+
throw new Error( `Failed to pull ${ image.name }` );
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const configResult = spawnSync(
|
|
183
|
+
resolve( monorepoRoot, 'tools/docker/bin/monorepo' ),
|
|
184
|
+
[ 'pnpm', 'jetpack', 'docker', 'config' ],
|
|
185
|
+
{
|
|
186
|
+
stdio: 'inherit',
|
|
187
|
+
shell: true,
|
|
188
|
+
cwd: monorepoRoot,
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
if ( configResult.status !== 0 ) {
|
|
193
|
+
throw new Error( 'Failed to generate Docker config' );
|
|
194
|
+
}
|
|
195
|
+
} else if ( args[ 1 ] === 'clean' ) {
|
|
196
|
+
// After docker-compose down -v, also remove local files
|
|
197
|
+
const projectName = args.includes( '--type=e2e' ) ? 'jetpack_e2e' : 'jetpack_dev';
|
|
198
|
+
const cleanupPaths = [
|
|
199
|
+
resolve( monorepoRoot, 'tools/docker/wordpress/' ),
|
|
200
|
+
resolve( monorepoRoot, 'tools/docker/wordpress-develop/*' ),
|
|
201
|
+
resolve( monorepoRoot, 'tools/docker/logs/', projectName ),
|
|
202
|
+
resolve( monorepoRoot, 'tools/docker/data/', `${ projectName }_mysql` ),
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
// Function to clean up after docker-compose down
|
|
206
|
+
const cleanupFiles = () => {
|
|
207
|
+
for ( const path of cleanupPaths ) {
|
|
208
|
+
try {
|
|
209
|
+
fs.rmSync( path, { recursive: true, force: true } );
|
|
210
|
+
} catch ( error ) {
|
|
211
|
+
console.warn(
|
|
212
|
+
chalk.yellow( `Warning: Could not remove ${ path }: ${ error.message }` )
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Add cleanup to process events to ensure it runs after docker-compose
|
|
219
|
+
process.once( 'beforeExit', cleanupFiles );
|
|
220
|
+
|
|
221
|
+
// Replace 'clean' with 'down -v' in the arguments
|
|
222
|
+
args.splice( 1, 1, 'down', '-v' );
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Get project name (from docker.js)
|
|
226
|
+
const projectName = args.includes( '--type=e2e' ) ? 'jetpack_e2e' : 'jetpack_dev';
|
|
227
|
+
|
|
228
|
+
// Load versions from .github/versions.sh
|
|
229
|
+
const versionsPath = resolve( monorepoRoot, '.github/versions.sh' );
|
|
230
|
+
const versions = fs.readFileSync( versionsPath, 'utf8' );
|
|
231
|
+
const versionVars = {};
|
|
232
|
+
versions.split( '\n' ).forEach( line => {
|
|
233
|
+
const match = line.match( /^([A-Z_]+)=(.+)$/ );
|
|
234
|
+
if ( match ) {
|
|
235
|
+
versionVars[ match[ 1 ] ] = match[ 2 ].replace( /['"]/g, '' );
|
|
236
|
+
}
|
|
237
|
+
} );
|
|
238
|
+
|
|
239
|
+
// Build environment variables (from docker.js)
|
|
240
|
+
const envVars = {
|
|
241
|
+
...process.env,
|
|
242
|
+
// Load from default.env
|
|
243
|
+
...( fs.existsSync( resolve( monorepoRoot, 'tools/docker/default.env' ) )
|
|
244
|
+
? dotenv.parse( fs.readFileSync( resolve( monorepoRoot, 'tools/docker/default.env' ) ) )
|
|
245
|
+
: {} ),
|
|
246
|
+
// Load from .env if it exists
|
|
247
|
+
...( fs.existsSync( resolve( monorepoRoot, 'tools/docker/.env' ) )
|
|
248
|
+
? dotenv.parse( fs.readFileSync( resolve( monorepoRoot, 'tools/docker/.env' ) ) )
|
|
249
|
+
: {} ),
|
|
250
|
+
HOST_CWD: monorepoRoot,
|
|
251
|
+
PHP_VERSION: versionVars.PHP_VERSION,
|
|
252
|
+
COMPOSER_VERSION: versionVars.COMPOSER_VERSION,
|
|
253
|
+
NODE_VERSION: versionVars.NODE_VERSION,
|
|
254
|
+
PNPM_VERSION: versionVars.PNPM_VERSION,
|
|
255
|
+
COMPOSE_PROJECT_NAME: projectName,
|
|
256
|
+
PORT_WORDPRESS: args.includes( '--type=e2e' ) ? '8889' : '80',
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// Build the list of compose files to use
|
|
260
|
+
const composeFiles = [
|
|
261
|
+
'-f',
|
|
262
|
+
resolve( monorepoRoot, 'tools/docker/docker-compose.yml' ),
|
|
263
|
+
'-f',
|
|
264
|
+
resolve( monorepoRoot, 'tools/docker/compose-mappings.built.yml' ),
|
|
265
|
+
'-f',
|
|
266
|
+
resolve( monorepoRoot, 'tools/docker/compose-extras.built.yml' ),
|
|
267
|
+
];
|
|
268
|
+
|
|
269
|
+
const result = spawnSync( 'docker', [ 'compose', ...composeFiles, ...args.slice( 1 ) ], {
|
|
270
|
+
stdio: 'inherit',
|
|
271
|
+
shell: true,
|
|
272
|
+
cwd: resolve( monorepoRoot, 'tools/docker' ),
|
|
273
|
+
env: envVars,
|
|
274
|
+
} );
|
|
275
|
+
|
|
276
|
+
if ( result.status !== 0 ) {
|
|
277
|
+
throw new Error( `Docker command failed with status ${ result.status }` );
|
|
278
|
+
}
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
129
283
|
// Run the monorepo script with the original arguments
|
|
130
284
|
const result = spawnSync(
|
|
131
285
|
resolve( monorepoRoot, 'tools/docker/bin/monorepo' ),
|
|
@@ -141,7 +295,6 @@ const main = async () => {
|
|
|
141
295
|
throw new Error( `Command failed with status ${ result.status }` );
|
|
142
296
|
}
|
|
143
297
|
} catch ( error ) {
|
|
144
|
-
// eslint-disable-next-line no-console
|
|
145
298
|
console.error( chalk.red( error.message ) );
|
|
146
299
|
process.exitCode = 1;
|
|
147
300
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/jetpack-cli",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-beta3",
|
|
4
4
|
"description": "Docker-based CLI for Jetpack development",
|
|
5
5
|
"bin": {
|
|
6
6
|
"jp": "bin/jp.js"
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
],
|
|
11
11
|
"type": "module",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"chalk": "^4.1
|
|
13
|
+
"chalk": "^5.4.1",
|
|
14
|
+
"dotenv": "^16.3.1",
|
|
14
15
|
"prompts": "^2.4.2"
|
|
15
16
|
},
|
|
16
17
|
"publishConfig": {
|