@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.
Files changed (3) hide show
  1. package/README.md +18 -0
  2. package/bin/jp.js +166 -13
  3. 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
- // eslint-disable-next-line no-console
91
+
87
92
  console.log( chalk.green( '\nJetpack monorepo has been cloned successfully!' ) );
88
- // eslint-disable-next-line no-console
93
+
89
94
  console.log( '\nNext steps:' );
90
- // eslint-disable-next-line no-console
95
+
91
96
  console.log( '1. cd', response.directory );
92
- // eslint-disable-next-line no-console
97
+
93
98
  console.log( '2. jp docker up' );
94
- // eslint-disable-next-line no-console
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
- // eslint-disable-next-line no-console
128
+
119
129
  console.log( '\nTo get started:' );
120
- // eslint-disable-next-line no-console
130
+
121
131
  console.log( '1. Run', chalk.blue( 'jp init' ), 'to clone the repository' );
122
- // eslint-disable-next-line no-console
132
+
123
133
  console.log( ' OR' );
124
- // eslint-disable-next-line no-console
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-beta.1",
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.2",
13
+ "chalk": "^5.4.1",
14
+ "dotenv": "^16.3.1",
14
15
  "prompts": "^2.4.2"
15
16
  },
16
17
  "publishConfig": {