Skip to content

Commit

Permalink
Env: Add debug mode. (#20348)
Browse files Browse the repository at this point in the history
* Env: Add debug flag.

* Env: Log Docker commands in debug mode.

* Env: Log Git commands in debug mode.

* Env: Log config and Docker Compose file in debug mode and log using the spinner.
  • Loading branch information
epiqueras authored Feb 21, 2020
1 parent 320f460 commit dfbdc69
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 44 deletions.
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,
} ),

( 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;

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

0 comments on commit dfbdc69

Please sign in to comment.