Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Env: Add debug mode. #20348

Merged
merged 4 commits into from
Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/env/lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ const withSpinner = ( command ) => ( ...args ) => {

module.exports = function cli() {
yargs.usage( wpPrimary( '$0 <command>' ) );
yargs.option( 'debug', {
type: 'boolean',
describe: 'Enable debug output.',
default: false,
} );

yargs.command(
'start',
Expand Down
19 changes: 10 additions & 9 deletions packages/env/lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ const HOME_PATH_PREFIX = `~${ path.sep }`;
* A wp-env config object.
*
* @typedef Config
* @property {string} name Name of the environment.
* @property {string} configDirectoryPath Path to the .wp-env.json file.
* @property {string} workDirectoryPath Path to the work directory located in ~/.wp-env.
* @property {string} dockerComposeConfigPath Path to the docker-compose.yml file.
* @property {Source|null} coreSource The WordPress installation to load in the environment.
* @property {Source[]} pluginSources Plugins to load in the environment.
* @property {Source[]} themeSources Themes to load in the environment.
* @property {number} port The port on which to start the development WordPress environment.
* @property {number} testsPort The port on which to start the testing WordPress environment.
* @property {string} name Name of the environment.
* @property {string} configDirectoryPath Path to the .wp-env.json file.
* @property {string} workDirectoryPath Path to the work directory located in ~/.wp-env.
* @property {string} dockerComposeConfigPath Path to the docker-compose.yml file.
* @property {Source|null} coreSource The WordPress installation to load in the environment.
* @property {Source[]} pluginSources Plugins to load in the environment.
* @property {Source[]} themeSources Themes to load in the environment.
* @property {number} port The port on which to start the development WordPress environment.
* @property {number} testsPort The port on which to start the testing WordPress environment.
* @property {boolean} debug True if debug mode is enabled.
*/

/**
Expand Down
35 changes: 24 additions & 11 deletions packages/env/lib/download-source.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ const NodeGit = require( 'nodegit' );
* Downloads the given source if necessary. The specific action taken depends
* on the source type.
*
* @param {Source} source The source to download.
* @param {Object} options
* @param {Source} source The source to download.
* @param {Object} options
* @param {Function} options.onProgress A function called with download progress. Will be invoked with one argument: a number that ranges from 0 to 1 which indicates current download progress for this source.
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {boolean} options.debug True if debug mode is enabled.
*/
module.exports = async function downloadSource( source, options ) {
if ( source.type === 'git' ) {
Expand All @@ -26,11 +28,20 @@ module.exports = async function downloadSource( source, options ) {
* Clones the git repository at `source.url` into `source.path`. If the
* repository already exists, it is updated instead.
*
* @param {Source} source The source to download.
* @param {Object} options
* @param {Source} source The source to download.
* @param {Object} options
* @param {Function} options.onProgress A function called with download progress. Will be invoked with one argument: a number that ranges from 0 to 1 which indicates current download progress for this source.
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {boolean} options.debug True if debug mode is enabled.
*/
async function downloadGitSource( source, { onProgress } ) {
async function downloadGitSource( source, { onProgress, spinner, debug } ) {
const log = debug
? // eslint-disable-next-line no-console
( message ) => {
spinner.info( `NodeGit: ${ message }` );
spinner.start();
}
: () => {};
onProgress( 0 );

const gitFetchOptions = {
Expand All @@ -50,20 +61,22 @@ async function downloadGitSource( source, { onProgress } ) {
},
};

// Clone or get the repo.
log( 'Cloning or getting the repo.' );
const repository = await NodeGit.Clone(
source.url,
source.path,
gitFetchOptions
)
// Repo already exists, get it.
.catch( () => NodeGit.Repository.open( source.path ) );
).catch( () => {
log( 'Repo already exists, get it.' );
return NodeGit.Repository.open( source.path );
} );

// Checkout the specified ref.
log( 'Fetching the specified ref.' );
const remote = await repository.getRemote( 'origin' );
await remote.fetch( source.ref, gitFetchOptions.fetchOpts );
await remote.disconnect();
try {
log( 'Checking out the specified ref.' );
await repository.checkoutRef(
await repository
.getReference( 'FETCH_HEAD' )
Expand All @@ -77,7 +90,7 @@ async function downloadGitSource( source, { onProgress } ) {
}
);
} catch ( error ) {
// Some commit refs need to be set as detached.
log( 'Ref needs to be set as detached.' );
await repository.setHeadDetached( source.ref );
}

Expand Down
94 changes: 70 additions & 24 deletions packages/env/lib/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ module.exports = {
/**
* Starts the development server.
*
* @param {Object} options
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {Object} options
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {boolean} options.debug True if debug mode is enabled.
*/
async start( { spinner } ) {
async start( { spinner, debug } ) {
/**
* If the Docker image is already running and the `wp-env` files have been
* deleted, the start command will not complete successfully. Stopping
Expand All @@ -46,7 +47,7 @@ module.exports = {
*/
await module.exports.stop( { spinner } );

const config = await initConfig();
const config = await initConfig( { spinner, debug } );

spinner.text = 'Downloading WordPress.';

Expand All @@ -69,12 +70,15 @@ module.exports = {
// Preemptively start the database while we wait for sources to download.
dockerCompose.upOne( 'mysql', {
config: config.dockerComposeConfigPath,
log: config.debug,
epiqueras marked this conversation as resolved.
Show resolved Hide resolved
} ),

( async () => {
if ( config.coreSource ) {
await downloadSource( config.coreSource, {
onProgress: getProgressSetter( 'core' ),
spinner,
debug: config.debug,
} );
await copyCoreFiles(
config.coreSource.path,
Expand All @@ -86,12 +90,16 @@ module.exports = {
...config.pluginSources.map( ( source ) =>
downloadSource( source, {
onProgress: getProgressSetter( source.basename ),
spinner,
debug: config.debug,
} )
),

...config.themeSources.map( ( source ) =>
downloadSource( source, {
onProgress: getProgressSetter( source.basename ),
spinner,
debug: config.debug,
} )
),
] );
Expand All @@ -100,6 +108,7 @@ module.exports = {

await dockerCompose.upMany( [ 'wordpress', 'tests-wordpress' ], {
config: config.dockerComposeConfigPath,
log: config.debug,
} );

try {
Expand Down Expand Up @@ -129,28 +138,36 @@ module.exports = {
/**
* Stops the development server.
*
* @param {Object} options
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {Object} options
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {boolean} options.debug True if debug mode is enabled.
*/
async stop( { spinner } ) {
const { dockerComposeConfigPath } = await initConfig();
async stop( { spinner, debug } ) {
const { dockerComposeConfigPath } = await initConfig( {
spinner,
debug,
} );

spinner.text = 'Stopping WordPress.';

await dockerCompose.down( { config: dockerComposeConfigPath } );
await dockerCompose.down( {
config: dockerComposeConfigPath,
log: debug,
} );

spinner.text = 'Stopped WordPress.';
},

/**
* Wipes the development server's database, the tests server's database, or both.
*
* @param {Object} options
* @param {string} options.environment The environment to clean. Either 'development', 'tests', or 'all'.
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {Object} options
* @param {string} options.environment The environment to clean. Either 'development', 'tests', or 'all'.
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {boolean} options.debug True if debug mode is enabled.
*/
async clean( { environment, spinner } ) {
const config = await initConfig();
async clean( { environment, spinner, debug } ) {
const config = await initConfig( { spinner, debug } );

const description = `${ environment } environment${
environment === 'all' ? 's' : ''
Expand Down Expand Up @@ -183,13 +200,14 @@ module.exports = {
/**
* Runs an arbitrary command on the given Docker container.
*
* @param {Object} options
* @param {Object} options.container The Docker container to run the command on.
* @param {Object} options.command The command to run.
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {Object} options
* @param {Object} options.container The Docker container to run the command on.
* @param {Object} options.command The command to run.
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {boolean} options.debug True if debug mode is enabled.
*/
async run( { container, command, spinner } ) {
const config = await initConfig();
async run( { container, command, spinner, debug } ) {
const config = await initConfig( { spinner, debug } );

command = command.join( ' ' );

Expand All @@ -198,6 +216,7 @@ module.exports = {
const result = await dockerCompose.run( container, command, {
config: config.dockerComposeConfigPath,
commandOptions: [ '--rm' ],
log: config.debug,
} );

if ( result.out ) {
Expand All @@ -223,19 +242,40 @@ module.exports = {
* Initializes the local environment so that Docker commands can be run. Reads
* ./.wp-env.json, creates ~/.wp-env, and creates ~/.wp-env/docker-compose.yml.
*
* @param {Object} options
* @param {Object} options.spinner A CLI spinner which indicates progress.
* @param {boolean} options.debug True if debug mode is enabled.
*
* @return {Config} The-env config object.
*/
async function initConfig() {
async function initConfig( { spinner, debug } ) {
const configPath = path.resolve( '.wp-env.json' );
const config = await readConfig( configPath );
config.debug = debug;
epiqueras marked this conversation as resolved.
Show resolved Hide resolved

await fs.mkdir( config.workDirectoryPath, { recursive: true } );

const dockerComposeConfig = buildDockerComposeConfig( config );
await fs.writeFile(
config.dockerComposeConfigPath,
yaml.dump( buildDockerComposeConfig( config ) )
yaml.dump( dockerComposeConfig )
);

if ( config.debug ) {
spinner.info(
`Config:\n${ JSON.stringify(
config,
null,
4
) }\n\nDocker Compose Config:\n${ JSON.stringify(
dockerComposeConfig,
null,
4
) }`
);
spinner.start();
}

return config;
}

Expand Down Expand Up @@ -294,10 +334,11 @@ async function retry( action, { times, delay = 5000 } ) {
*
* @param {Config} config The wp-env config object.
*/
async function checkDatabaseConnection( { dockerComposeConfigPath } ) {
async function checkDatabaseConnection( { dockerComposeConfigPath, debug } ) {
await dockerCompose.run( 'cli', 'wp db check', {
config: dockerComposeConfigPath,
commandOptions: [ '--rm' ],
log: debug,
} );
}

Expand All @@ -313,6 +354,7 @@ async function configureWordPress( environment, config ) {
const options = {
config: config.dockerComposeConfigPath,
commandOptions: [ '--rm' ],
log: config.debug,
};

const port = environment === 'development' ? config.port : config.testsPort;
Expand Down Expand Up @@ -356,10 +398,14 @@ async function configureWordPress( environment, config ) {
* @param {string} environment The environment to clean. Either 'development', 'tests', or 'all'.
* @param {Config} config The wp-env config object.
*/
async function resetDatabase( environment, { dockerComposeConfigPath } ) {
async function resetDatabase(
environment,
{ dockerComposeConfigPath, debug }
) {
const options = {
config: dockerComposeConfigPath,
commandOptions: [ '--rm' ],
log: debug,
};

const tasks = [];
Expand Down