Skip to content

Commit 7c58092

Browse files
committed
New CLI works with docker now -- commands will run on the local host unless specified to the dev container, like build-image
1 parent 6c6152a commit 7c58092

File tree

7 files changed

+196
-44
lines changed

7 files changed

+196
-44
lines changed

pnpm-lock.yaml

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

projects/js-packages/jetpack-cli/bin/jp.js

+149-13
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
#!/usr/bin/env node
22

33
import { spawnSync } from 'child_process';
4-
import fs from 'fs';
4+
import fs, { readFileSync } from 'fs';
55
import { dirname, resolve } from 'path';
66
import process from 'process';
7+
import { fileURLToPath } from 'url';
78
import chalk from 'chalk';
9+
import dotenv from 'dotenv';
810
import prompts from 'prompts';
911

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+
1016
/**
1117
* Check if a directory is the monorepo root.
1218
*
@@ -45,7 +51,6 @@ const findMonorepoRoot = startDir => {
4551
* @throws {Error} If clone fails
4652
*/
4753
const cloneMonorepo = async targetDir => {
48-
// eslint-disable-next-line no-console
4954
console.log( chalk.blue( 'Cloning Jetpack monorepo...' ) );
5055
const result = spawnSync(
5156
'git',
@@ -83,15 +88,15 @@ const initJetpack = async () => {
8388

8489
try {
8590
await cloneMonorepo( targetDir );
86-
// eslint-disable-next-line no-console
91+
8792
console.log( chalk.green( '\nJetpack monorepo has been cloned successfully!' ) );
88-
// eslint-disable-next-line no-console
93+
8994
console.log( '\nNext steps:' );
90-
// eslint-disable-next-line no-console
95+
9196
console.log( '1. cd', response.directory );
92-
// eslint-disable-next-line no-console
97+
9398
console.log( '2. jp docker up' );
94-
// eslint-disable-next-line no-console
99+
95100
console.log( '3. jp docker install' );
96101
} catch ( error ) {
97102
throw new Error( `Failed to initialize Jetpack: ${ error.message }` );
@@ -103,6 +108,12 @@ const main = async () => {
103108
try {
104109
const args = process.argv.slice( 2 );
105110

111+
// Handle version flag
112+
if ( args[ 0 ] === '--version' || args[ 0 ] === '-v' ) {
113+
console.log( chalk.green( packageJson.version ) );
114+
return;
115+
}
116+
106117
// Handle 'init' command specially
107118
if ( args[ 0 ] === 'init' ) {
108119
await initJetpack();
@@ -113,19 +124,145 @@ const main = async () => {
113124
const monorepoRoot = findMonorepoRoot( process.cwd() );
114125

115126
if ( ! monorepoRoot ) {
116-
// eslint-disable-next-line no-console
117127
console.error( chalk.red( 'Could not find Jetpack monorepo.' ) );
118-
// eslint-disable-next-line no-console
128+
119129
console.log( '\nTo get started:' );
120-
// eslint-disable-next-line no-console
130+
121131
console.log( '1. Run', chalk.blue( 'jp init' ), 'to clone the repository' );
122-
// eslint-disable-next-line no-console
132+
123133
console.log( ' OR' );
124-
// eslint-disable-next-line no-console
134+
125135
console.log( '2. Navigate to an existing Jetpack monorepo directory' );
126136
throw new Error( 'Monorepo not found' );
127137
}
128138

139+
// Handle docker commands on the host
140+
if ( args[ 0 ] === 'docker' ) {
141+
// Commands that should run in the container
142+
const containerCommands = [ 'build-image', 'install' ];
143+
if ( containerCommands.includes( args[ 1 ] ) ) {
144+
const result = spawnSync(
145+
resolve( monorepoRoot, 'tools/docker/bin/monorepo' ),
146+
[ 'pnpm', 'jetpack', ...args ],
147+
{
148+
stdio: 'inherit',
149+
shell: true,
150+
cwd: monorepoRoot,
151+
}
152+
);
153+
154+
if ( result.status !== 0 ) {
155+
throw new Error( `Command failed with status ${ result.status }` );
156+
}
157+
return;
158+
}
159+
160+
// Run config generation first if this is an 'up' command
161+
if ( args[ 1 ] === 'up' ) {
162+
// Create required directories
163+
fs.mkdirSync( resolve( monorepoRoot, 'tools/docker/data/jetpack_dev_mysql' ), {
164+
recursive: true,
165+
} );
166+
fs.mkdirSync( resolve( monorepoRoot, 'tools/docker/data/ssh.keys' ), { recursive: true } );
167+
fs.mkdirSync( resolve( monorepoRoot, 'tools/docker/wordpress' ), { recursive: true } );
168+
169+
const images = [
170+
{ name: 'mariadb:lts' },
171+
{ name: 'automattic/jetpack-wordpress-dev:latest' },
172+
{ name: 'phpmyadmin/phpmyadmin:latest', platform: 'linux/amd64' },
173+
{ name: 'maildev/maildev', platform: 'linux/amd64' },
174+
{ name: 'atmoz/sftp', platform: 'linux/amd64' },
175+
];
176+
177+
for ( const image of images ) {
178+
const inspect = spawnSync( 'docker', [ 'image', 'inspect', image.name ], {
179+
stdio: 'ignore',
180+
} );
181+
if ( inspect.status !== 0 ) {
182+
console.log( chalk.blue( `Pulling ${ image.name }...` ) );
183+
const pullArgs = [ 'pull', image.name ];
184+
if ( image.platform ) {
185+
pullArgs.splice( 1, 0, '--platform', image.platform );
186+
}
187+
const pull = spawnSync( 'docker', pullArgs, { stdio: 'inherit' } );
188+
if ( pull.status !== 0 ) {
189+
throw new Error( `Failed to pull ${ image.name }` );
190+
}
191+
}
192+
}
193+
194+
const configResult = spawnSync(
195+
resolve( monorepoRoot, 'tools/docker/bin/monorepo' ),
196+
[ 'pnpm', 'jetpack', 'docker', 'config' ],
197+
{
198+
stdio: 'inherit',
199+
shell: true,
200+
cwd: monorepoRoot,
201+
}
202+
);
203+
204+
if ( configResult.status !== 0 ) {
205+
throw new Error( 'Failed to generate Docker config' );
206+
}
207+
}
208+
209+
// Get project name (from docker.js)
210+
const projectName = args.includes( '--type=e2e' ) ? 'jetpack_e2e' : 'jetpack_dev';
211+
212+
// Load versions from .github/versions.sh
213+
const versionsPath = resolve( monorepoRoot, '.github/versions.sh' );
214+
const versions = fs.readFileSync( versionsPath, 'utf8' );
215+
const versionVars = {};
216+
versions.split( '\n' ).forEach( line => {
217+
const match = line.match( /^([A-Z_]+)=(.+)$/ );
218+
if ( match ) {
219+
versionVars[ match[ 1 ] ] = match[ 2 ].replace( /['"]/g, '' );
220+
}
221+
} );
222+
223+
// Build environment variables (from docker.js)
224+
const envVars = {
225+
...process.env,
226+
// Load from default.env
227+
...( fs.existsSync( resolve( monorepoRoot, 'tools/docker/default.env' ) )
228+
? dotenv.parse( fs.readFileSync( resolve( monorepoRoot, 'tools/docker/default.env' ) ) )
229+
: {} ),
230+
// Load from .env if it exists
231+
...( fs.existsSync( resolve( monorepoRoot, 'tools/docker/.env' ) )
232+
? dotenv.parse( fs.readFileSync( resolve( monorepoRoot, 'tools/docker/.env' ) ) )
233+
: {} ),
234+
HOST_CWD: monorepoRoot,
235+
PHP_VERSION: versionVars.PHP_VERSION,
236+
COMPOSER_VERSION: versionVars.COMPOSER_VERSION,
237+
NODE_VERSION: versionVars.NODE_VERSION,
238+
PNPM_VERSION: versionVars.PNPM_VERSION,
239+
COMPOSE_PROJECT_NAME: projectName,
240+
PORT_WORDPRESS: args.includes( '--type=e2e' ) ? '8889' : '80',
241+
};
242+
243+
// Build the list of compose files to use
244+
const composeFiles = [
245+
'-f',
246+
resolve( monorepoRoot, 'tools/docker/docker-compose.yml' ),
247+
'-f',
248+
resolve( monorepoRoot, 'tools/docker/compose-mappings.built.yml' ),
249+
'-f',
250+
resolve( monorepoRoot, 'tools/docker/compose-extras.built.yml' ),
251+
];
252+
253+
const result = spawnSync( 'docker', [ 'compose', ...composeFiles, ...args.slice( 1 ) ], {
254+
stdio: 'inherit',
255+
shell: true,
256+
cwd: resolve( monorepoRoot, 'tools/docker' ),
257+
env: envVars,
258+
} );
259+
260+
if ( result.status !== 0 ) {
261+
throw new Error( `Docker command failed with status ${ result.status }` );
262+
}
263+
return;
264+
}
265+
129266
// Run the monorepo script with the original arguments
130267
const result = spawnSync(
131268
resolve( monorepoRoot, 'tools/docker/bin/monorepo' ),
@@ -141,7 +278,6 @@ const main = async () => {
141278
throw new Error( `Command failed with status ${ result.status }` );
142279
}
143280
} catch ( error ) {
144-
// eslint-disable-next-line no-console
145281
console.error( chalk.red( error.message ) );
146282
process.exitCode = 1;
147283
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import makeBaseConfig from 'jetpack-js-tools/eslintrc/base.mjs';
2+
3+
export default [
4+
...makeBaseConfig( import.meta.url, { envs: [ 'node' ] } ),
5+
{
6+
rules: {
7+
'no-console': 'off',
8+
'n/no-process-exit': 'off',
9+
},
10+
},
11+
];

projects/js-packages/jetpack-cli/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@automattic/jetpack-cli",
3-
"version": "0.1.0-beta.1",
3+
"version": "0.1.0-beta.2",
44
"description": "Docker-based CLI for Jetpack development",
55
"bin": {
66
"jp": "bin/jp.js"
@@ -11,6 +11,7 @@
1111
"type": "module",
1212
"dependencies": {
1313
"chalk": "^4.1.2",
14+
"dotenv": "^16.3.1",
1415
"prompts": "^2.4.2"
1516
},
1617
"publishConfig": {

tools/cli/commands/docker.js

+18-3
Original file line numberDiff line numberDiff line change
@@ -554,14 +554,23 @@ const execJtCmdHandler = argv => {
554554
}
555555
};
556556

557+
/**
558+
* Generate Docker configuration files.
559+
*
560+
* @param {object} argv - The command line arguments
561+
*/
562+
async function generateConfig( argv ) {
563+
await setConfig( argv );
564+
}
565+
557566
/**
558567
* Definition for the Docker commands.
559568
*
560569
* @param {object} yargs - The Yargs dependency.
561570
* @return {object} Yargs with the Docker commands defined.
562571
*/
563572
export function dockerDefine( yargs ) {
564-
yargs.command( {
573+
return yargs.command( {
565574
command: 'docker <cmd>',
566575
description: 'Docker stuff',
567576
builder: yarg => {
@@ -832,9 +841,15 @@ export function dockerDefine( yargs ) {
832841
const envOpts = buildEnv( argv );
833842
composeExecutor( argv, opts, envOpts );
834843
},
844+
} )
845+
.command( {
846+
command: 'config',
847+
description: 'Generate Docker configuration files',
848+
builder: yargCmd => defaultOpts( yargCmd ),
849+
handler: async argv => {
850+
await generateConfig( argv );
851+
},
835852
} );
836853
},
837854
} );
838-
839-
return yargs;
840855
}

tools/docker/bin/monorepo

+4-24
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,8 @@ echo "Running command in monorepo container: $*"
1414
# Source the versions file
1515
source "$MONOREPO_ROOT/.github/versions.sh"
1616

17-
# Pre-pull Docker images if this is a docker command
18-
if [ "$1" = "pnpm" ] && [ "$2" = "jetpack" ] && [ "$3" = "docker" ] && [ "$4" = "up" ]; then
19-
echo "Pre-pulling required Docker images..."
20-
# Ensure MySQL data directory exists
21-
mkdir -p "$MONOREPO_ROOT/tools/docker/data/jetpack_dev_mysql"
22-
# Ensure SSH keys directory exists
23-
mkdir -p "$MONOREPO_ROOT/tools/docker/data/ssh.keys"
24-
# Only pull images that aren't present
25-
if ! docker image inspect mariadb:lts >/dev/null 2>&1; then
26-
docker pull mariadb:lts
27-
fi
28-
if ! docker image inspect automattic/jetpack-wordpress-dev:latest >/dev/null 2>&1; then
29-
docker pull automattic/jetpack-wordpress-dev:latest
30-
fi
31-
if ! docker image inspect phpmyadmin/phpmyadmin:latest >/dev/null 2>&1; then
32-
docker pull --platform linux/arm64 phpmyadmin/phpmyadmin:latest
33-
fi
34-
if ! docker image inspect maildev/maildev >/dev/null 2>&1; then
35-
docker pull --platform linux/arm64 maildev/maildev
36-
fi
37-
if ! docker image inspect atmoz/sftp >/dev/null 2>&1; then
38-
docker pull --platform linux/arm64 atmoz/sftp
39-
fi
40-
fi
17+
# Export variables needed by docker-compose
18+
export HOST_CWD="$MONOREPO_ROOT"
4119

4220
# Build the image if it doesn't exist
4321
if ! docker image inspect jetpack-monorepo:latest >/dev/null 2>&1; then
@@ -67,6 +45,8 @@ docker run --rm -it \
6745
-e TERM=$TERM \
6846
-e COLORTERM=$COLORTERM \
6947
-e DOCKER_ROOT="$MONOREPO_ROOT/tools/docker" \
48+
-e HOST_CWD="$MONOREPO_ROOT" \
49+
-e WORKSPACE_PATH="$MONOREPO_ROOT" \
7050
-e NPM_CONFIG_USERCONFIG=/root/.npmrc \
7151
-e NPM_CONFIG_CACHE=/root/.npm \
7252
-e PNPM_HOME=/root/.local/share/pnpm \

tools/docker/docker-compose.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ services:
5252

5353
monorepo:
5454
build:
55-
context: .
55+
context: ${HOST_CWD}/tools/docker
5656
dockerfile: Dockerfile.monorepo
5757
args:
5858
PHP_VERSION: ${PHP_VERSION}
5959
COMPOSER_VERSION: ${COMPOSER_VERSION}
6060
NODE_VERSION: ${NODE_VERSION}
6161
PNPM_VERSION: ${PNPM_VERSION}
6262
volumes:
63-
- ../..:${WORKSPACE_PATH:-/workspace}
64-
working_dir: ${WORKSPACE_PATH:-/workspace}
63+
- ${HOST_CWD}:/usr/local/src/jetpack-monorepo
64+
working_dir: /usr/local/src/jetpack-monorepo

0 commit comments

Comments
 (0)