Skip to content

Commit

Permalink
cli: Build in dependency order, optionally with dependencies (#22580)
Browse files Browse the repository at this point in the history
When multiple projects are being built, build them in dependency order
(i.e. each project's dependencies are build before the project is).

If the new `--deps` option is specified, include all dependencies of the
specified projects in the build.
  • Loading branch information
anomiex authored Feb 1, 2022
1 parent 4e69791 commit fb2c7da
Showing 1 changed file with 46 additions and 10 deletions.
56 changes: 46 additions & 10 deletions tools/cli/commands/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import chalk from 'chalk';
import execa from 'execa';
import fs from 'fs/promises';
import inquirer from 'inquirer';
import Listr from 'listr';
import SilentRenderer from 'listr-silent-renderer';
import UpdateRenderer from 'listr-update-renderer';
Expand All @@ -13,6 +13,7 @@ import UpdateRenderer from 'listr-update-renderer';
*/
import { chalkJetpackGreen } from '../helpers/styling.js';
import formatDuration from '../helpers/format-duration.js';
import { getDependencies, filterDeps, getBuildOrder } from '../helpers/dependencyAnalysis.js';
import promptForProject from '../helpers/promptForProject.js';
import { readComposerJson } from '../helpers/json.js';
import { getInstallArgs, projectDir } from '../helpers/install.js';
Expand All @@ -38,6 +39,10 @@ export function builder( yargs ) {
type: 'boolean',
description: 'Build all projects.',
} )
.option( 'deps', {
type: 'boolean',
description: 'Build dependencies of the specified projects too.',
} )
.option( 'production', {
alias: 'p',
type: 'boolean',
Expand All @@ -59,6 +64,8 @@ export function builder( yargs ) {
* @param {object} argv - the arguments passed.
*/
export async function handler( argv ) {
let dependencies = await getDependencies( process.cwd(), 'build' );

if ( argv.project.length === 1 ) {
if ( argv.project[ 0 ] === 'packages' ) {
argv.project = allProjectsByType( 'packages' );
Expand All @@ -75,9 +82,22 @@ export async function handler( argv ) {
if ( argv.project.length === 0 ) {
argv.project = '';
argv = await promptForProject( argv );
argv = await promptForDeps( argv );
argv.project = [ argv.project ];
}

// Check for unknown projects.
argv.project = [ ...new Set( argv.project ) ];
const missing = new Set( argv.project.filter( p => ! dependencies.has( p ) ) );
if ( missing.size ) {
for ( const project of missing ) {
console.error( chalk.red( `Project ${ project } does not exist!` ) );
}
argv.project = argv.project.filter( p => dependencies.has( p ) );
}

dependencies = filterDeps( dependencies, argv.project, { dependencies: argv.deps } );

const listr = new Listr( [], {
renderer: argv.v ? SilentRenderer : UpdateRenderer,
} );
Expand All @@ -95,15 +115,7 @@ export async function handler( argv ) {
}

// Add build tasks.
for ( const project of new Set( argv.project ) ) {
// Does the project even exist?
if (
( await fs.access( `projects/${ project }/composer.json` ).catch( () => false ) ) === false
) {
console.error( chalk.red( `Project ${ project } does not exist!` ) );
continue;
}

for ( const project of getBuildOrder( dependencies ).flat() ) {
const cwd = projectDir( project );
listr.add(
createBuildTask( argv, `Build ${ project }`, async t => {
Expand Down Expand Up @@ -195,3 +207,27 @@ function createBuildTask( argv, title, build ) {
},
};
}

/**
* Prompt for whether dependencies should be built too.
*
* @param {object} options - Passthrough of the argv object.
* @returns {object} argv object with the project property.
*/
async function promptForDeps( options ) {
if ( typeof options.deps !== 'undefined' ) {
return options;
}

const answers = await inquirer.prompt( [
{
type: 'confirm',
name: 'deps',
message: `Build dependencies of ${ options.project } too?`,
},
] );
return {
...options,
deps: answers.deps,
};
}

0 comments on commit fb2c7da

Please sign in to comment.