Skip to content

Commit 4391224

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 67296ba commit 4391224

18 files changed

+299
-23
lines changed

pnpm-lock.yaml

+11-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Files not needed to be distributed in the package.
2+
.gitattributes export-ignore
3+
node_modules export-ignore
4+
5+
# Files to exclude from the mirror repo
6+
/changelog/** production-exclude
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
vendor/
2+
node_modules/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
+18
Original file line numberDiff line numberDiff line change
@@ -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+

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
}

projects/js-packages/jetpack-cli/changelog/.gitkeep

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: added
3+
4+
Initial version.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "automattic/jetpack-cli",
3+
"description": "Development tools for the Jetpack monorepo",
4+
"type": "library",
5+
"license": "GPL-2.0-or-later",
6+
"require": {},
7+
"require-dev": {
8+
"automattic/jetpack-changelogger": "@dev"
9+
},
10+
"autoload": {
11+
"classmap": [
12+
"src/"
13+
]
14+
},
15+
"scripts": {
16+
"phpunit": [
17+
"./vendor/phpunit/phpunit/phpunit --colors=always"
18+
],
19+
"test-coverage": [
20+
"php -dpcov.directory=. ./vendor/bin/phpunit --coverage-php \"$COVERAGE_DIR/php.cov\""
21+
],
22+
"test-php": [
23+
"@composer phpunit"
24+
]
25+
},
26+
"repositories": [
27+
{
28+
"type": "path",
29+
"url": "../../packages/*",
30+
"options": {
31+
"monorepo": true
32+
}
33+
}
34+
],
35+
"minimum-stability": "dev",
36+
"prefer-stable": true
37+
}
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

+3-2
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-alpha",
44
"description": "Docker-based CLI for Jetpack development",
55
"bin": {
66
"jp": "bin/jp.js"
@@ -10,7 +10,8 @@
1010
],
1111
"type": "module",
1212
"dependencies": {
13-
"chalk": "^4.1.2",
13+
"chalk": "^5.4.1",
14+
"dotenv": "^16.3.1",
1415
"prompts": "^2.4.2"
1516
},
1617
"publishConfig": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Put your code in this `src/` folder!
2+
// Feel free to delete or rename this file.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// We recommend using `jest` for testing. If you're testing React code, we recommend `@testing-library/react` and related packages.
2+
// Please match the versions used elsewhere in the monorepo.
3+
//
4+
// Please don't add new uses of `mocha`, `chai`, `sinon`, `enzyme`, and so on. We're trying to standardize on one testing framework.
5+
//
6+
// The default setup is to have files named like "name.test.js" (or .jsx, .ts, or .tsx) in this `tests/` directory.
7+
// But you could instead put them in `src/`, or put files like "name.js" (or .jsx, .ts, or .tsx) in `test` or `__tests__` directories somewhere.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const path = require( 'path' );
2+
const baseConfig = require( 'jetpack-js-tools/jest/config.base.js' );
3+
4+
module.exports = {
5+
...baseConfig,
6+
rootDir: path.join( __dirname, '..' ),
7+
};

0 commit comments

Comments
 (0)