diff --git a/tools/__tasks__/compile/conf/clean.js b/tools/__tasks__/compile/conf/clean.js index f34d9ecdd10..c8d87a17693 100644 --- a/tools/__tasks__/compile/conf/clean.js +++ b/tools/__tasks__/compile/conf/clean.js @@ -3,8 +3,9 @@ const rimraf = require('rimraf'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clear template rendering artefacts', + title: 'Clear template rendering artefacts', task: () => rimraf.sync(path.resolve(paths.root, 'common', 'conf', 'assets')), }; diff --git a/tools/__tasks__/compile/conf/copy.js b/tools/__tasks__/compile/conf/copy.js index 5760625f396..6768ac648e6 100644 --- a/tools/__tasks__/compile/conf/copy.js +++ b/tools/__tasks__/compile/conf/copy.js @@ -3,8 +3,9 @@ const cpy = require('cpy'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Copy assets', + title: 'Copy assets', task: () => Promise.all([ cpy('curl.js', paths.conf, { diff --git a/tools/__tasks__/compile/conf/index.js b/tools/__tasks__/compile/conf/index.js index 24a4597c400..27359dbf4c5 100644 --- a/tools/__tasks__/compile/conf/index.js +++ b/tools/__tasks__/compile/conf/index.js @@ -1,13 +1,18 @@ const copy = require('./copy.js'); const inlineSVGs = require('../inline-svgs/index.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile assets for template rendering in Play', - task: [ - // prettier: multi-line - copy, - inlineSVGs, - ], + title: 'Compile assets for template rendering in Play', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + copy, + inlineSVGs, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/css/clean.js b/tools/__tasks__/compile/css/clean.js index c69783a553c..edd145cf723 100644 --- a/tools/__tasks__/compile/css/clean.js +++ b/tools/__tasks__/compile/css/clean.js @@ -3,8 +3,9 @@ const rimraf = require('rimraf'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clear CSS build artefacts', + title: 'Clear CSS build artefacts', task: () => { rimraf.sync(path.resolve(paths.target, 'stylesheets')); rimraf.sync(path.resolve(paths.hash, 'stylesheets')); diff --git a/tools/__tasks__/compile/css/index.dev.js b/tools/__tasks__/compile/css/index.dev.js index 6ca6e39d66c..d85cf112218 100644 --- a/tools/__tasks__/compile/css/index.dev.js +++ b/tools/__tasks__/compile/css/index.dev.js @@ -3,15 +3,20 @@ const mkdir = require('./mkdir.js'); const images = require('../images/index.js'); const sass = require('./sass.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile CSS', - task: [ - // prettier: multi-line - clean, - mkdir, - images, - sass, - ], + title: 'Compile CSS (dev)', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + mkdir, + images, + sass, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/css/index.js b/tools/__tasks__/compile/css/index.js index 6ca6e39d66c..4251c629464 100644 --- a/tools/__tasks__/compile/css/index.js +++ b/tools/__tasks__/compile/css/index.js @@ -3,15 +3,20 @@ const mkdir = require('./mkdir.js'); const images = require('../images/index.js'); const sass = require('./sass.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile CSS', - task: [ - // prettier: multi-line - clean, - mkdir, - images, - sass, - ], + title: 'Compile CSS', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + mkdir, + images, + sass, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/css/mkdir.js b/tools/__tasks__/compile/css/mkdir.js index 06d26a0b3e2..7cf87d362f6 100644 --- a/tools/__tasks__/compile/css/mkdir.js +++ b/tools/__tasks__/compile/css/mkdir.js @@ -1,8 +1,9 @@ const mkdirp = require('mkdirp'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Create CSS target directory', + title: 'Create CSS target directory', task: () => mkdirp.sync(`${paths.target}/stylesheets`), }; diff --git a/tools/__tasks__/compile/css/sass.js b/tools/__tasks__/compile/css/sass.js index 6eca5b1d1a2..34bf9bb78c0 100644 --- a/tools/__tasks__/compile/css/sass.js +++ b/tools/__tasks__/compile/css/sass.js @@ -1,45 +1,51 @@ const compile = require('../../../compile-css'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile Sass', - task: [ - { - description: 'Old IE', - task: () => - compile('old-ie.*.scss', { - browsers: 'Explorer 8', - remify: false, - }), - }, - { - description: 'IE9', - task: () => - compile('ie9.*.scss', { - browsers: 'Explorer 9', - }), - }, - { - description: 'Email', - task: () => - compile('head.email-{article,front}.scss', { - remify: false, - }), - }, - { - description: 'Modern', - task: () => - compile('!(_|ie9|old-ie|*email-article|*email-front)*.scss'), - }, - { - description: 'Inline', - task: () => compile('inline/*.scss'), - }, - { - description: 'Atoms', - task: () => compile('atoms/*.scss'), - }, - ], - concurrent: true, + title: 'Compile Sass', + task: (ctx, task) => + task.newListr( + [ + { + title: 'Old IE', + task: () => + compile('old-ie.*.scss', { + browsers: 'Explorer 8', + remify: false, + }), + }, + { + title: 'IE9', + task: () => + compile('ie9.*.scss', { + browsers: 'Explorer 9', + }), + }, + { + title: 'Email', + task: () => + compile('head.email-{article,front}.scss', { + remify: false, + }), + }, + { + title: 'Modern', + task: () => + compile( + '!(_|ie9|old-ie|*email-article|*email-front)*.scss', + ), + }, + { + title: 'Inline', + task: () => compile('inline/*.scss'), + }, + { + title: 'Atoms', + task: () => compile('atoms/*.scss'), + }, + ], + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/data/amp.js b/tools/__tasks__/compile/data/amp.js index cf1fd9ed14a..86c0c4036d8 100644 --- a/tools/__tasks__/compile/data/amp.js +++ b/tools/__tasks__/compile/data/amp.js @@ -10,8 +10,9 @@ const ampIframeHtml = path.join(paths.vendor, 'data/amp-iframe.html'); // The static assets const staticDir = path.resolve(paths.target, 'data', 'vendor'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Copy AMP iframe HTML', + title: 'Copy AMP iframe HTML', task: () => cpy(ampIframeHtml, staticDir, { parents: false, diff --git a/tools/__tasks__/compile/data/clean.js b/tools/__tasks__/compile/data/clean.js index 442111a26a2..06e597e5938 100644 --- a/tools/__tasks__/compile/data/clean.js +++ b/tools/__tasks__/compile/data/clean.js @@ -3,8 +3,9 @@ const rimraf = require('rimraf'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clear Data build artefacts', + title: 'Clear Data build artefacts', task: () => { rimraf.sync(path.resolve(paths.target, 'data')); rimraf.sync(path.resolve(paths.hash, 'data')); diff --git a/tools/__tasks__/compile/data/download.js b/tools/__tasks__/compile/data/download.js index a6cc7a9590d..b5eff952b10 100644 --- a/tools/__tasks__/compile/data/download.js +++ b/tools/__tasks__/compile/data/download.js @@ -20,8 +20,9 @@ const currentVendorListJSON = path.join( 'data/cmp_vendorlist.json', ); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Downloading data files', + title: 'Downloading data files', task: () => new Promise((resolve, reject) => { request(vendorListOfficialUrl, (error, response, body) => { diff --git a/tools/__tasks__/compile/data/index.dev.js b/tools/__tasks__/compile/data/index.dev.js index 6e4e1b950c5..e2f8e21f2a3 100644 --- a/tools/__tasks__/compile/data/index.dev.js +++ b/tools/__tasks__/compile/data/index.dev.js @@ -2,14 +2,19 @@ const clean = require('./clean.js'); const download = require('./download.js'); const amp = require('./amp.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clean download and build data assets (dev)', - task: [ - // prettier: multi-line - clean, - download, - amp, - ], + title: 'Clean download and build data assets (dev)', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + download, + amp, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/data/index.js b/tools/__tasks__/compile/data/index.js index ee7ab43f258..d6984398c82 100644 --- a/tools/__tasks__/compile/data/index.js +++ b/tools/__tasks__/compile/data/index.js @@ -2,14 +2,19 @@ const clean = require('./clean.js'); const download = require('./download.js'); const amp = require('./amp.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clean download and build data assets', - task: [ - // prettier: multi-line - clean, - download, - amp, - ], + title: 'Clean download and build data assets', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + download, + amp, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/data/index.watch.js b/tools/__tasks__/compile/data/index.watch.js index ea88e83551b..aee47c28d4f 100644 --- a/tools/__tasks__/compile/data/index.watch.js +++ b/tools/__tasks__/compile/data/index.watch.js @@ -2,14 +2,19 @@ const clean = require('./clean.js'); const download = require('./download.js'); const amp = require('./amp.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clean, download and build data assets (watch)', - task: [ - // prettier: multi-line - clean, - download, - amp, - ], + title: 'Clean, download and build data assets (watch)', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + download, + amp, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/hash/clean.js b/tools/__tasks__/compile/hash/clean.js index 618c7fb6f4f..47c557b4bea 100644 --- a/tools/__tasks__/compile/hash/clean.js +++ b/tools/__tasks__/compile/hash/clean.js @@ -3,8 +3,9 @@ const rimraf = require('rimraf'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clear asset hash artefacts', + title: 'Clear asset hash artefacts', task: () => rimraf.sync(path.resolve(paths.hash, 'assets')), }; diff --git a/tools/__tasks__/compile/hash/index.js b/tools/__tasks__/compile/hash/index.js index c347ee8229d..73a5c60dec0 100644 --- a/tools/__tasks__/compile/hash/index.js +++ b/tools/__tasks__/compile/hash/index.js @@ -12,136 +12,156 @@ const writeFile = pify(fs.writeFile); const clean = require('./clean.js'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Version assets', - task: [ - clean, - { - description: 'Hash assets', - task: () => { - const webpackRegex = /graun\./; - const webpackChunkRegex = /chunk/; - const sourcemapRegex = /\.map$/; + title: 'Version assets', + task: (ctx, task) => + task.newListr( + [ + clean, + { + title: 'Hash assets', + task: () => { + const webpackRegex = /graun\./; + const webpackChunkRegex = /chunk/; + const sourcemapRegex = /\.map$/; - // create the hashed asset map for all files in target - const assetMap = glob - .sync('**/!(*.map)', { nodir: true, cwd: paths.target }) - .reduce((map, assetPath) => { - const assetLocation = path.resolve( - paths.target, - assetPath, - ); - const hasSourceMap = fs.existsSync( - `${assetLocation}.map`, - ); + // create the hashed asset map for all files in target + const assetMap = glob + .sync('**/!(*.map)', { + nodir: true, + cwd: paths.target, + }) + .reduce((map, assetPath) => { + const assetLocation = path.resolve( + paths.target, + assetPath, + ); + const hasSourceMap = fs.existsSync( + `${assetLocation}.map`, + ); - // webpack bundles come pre-hashed, so we won't hash them, just add them - if (webpackRegex.test(assetPath)) { - const sourcemap = hasSourceMap - ? { - [`${assetPath}.map`]: `${assetPath}.map`, - } - : {}; + // webpack bundles come pre-hashed, so we won't hash them, just add them + if (webpackRegex.test(assetPath)) { + const sourcemap = hasSourceMap + ? { + [`${assetPath}.map`]: `${assetPath}.map`, + } + : {}; - return Object.assign( - map, - { [assetPath]: assetPath }, - sourcemap, - ); - } + return Object.assign( + map, + { [assetPath]: assetPath }, + sourcemap, + ); + } - // hash everything else as normal - const assetHash = hasha.fromFileSync(assetLocation, { - algorithm: 'md5', - }); - const hashedPath = path.join( - path.dirname(assetPath), - assetHash, - path.basename(assetPath), - ); - const sourcemap = hasSourceMap - ? { [`${assetPath}.map`]: `${hashedPath}.map` } - : {}; + // hash everything else as normal + const assetHash = hasha.fromFileSync( + assetLocation, + { + algorithm: 'md5', + }, + ); + const hashedPath = path.join( + path.dirname(assetPath), + assetHash, + path.basename(assetPath), + ); + const sourcemap = hasSourceMap + ? { + [`${assetPath}.map`]: `${hashedPath}.map`, + } + : {}; - return Object.assign( - map, - { [assetPath]: hashedPath }, - sourcemap, - ); - }, {}); + return Object.assign( + map, + { [assetPath]: hashedPath }, + sourcemap, + ); + }, {}); - return Promise.all( - // copy all the built files to their hash locations - Object.keys(assetMap).map((asset) => - cpFile( - path.resolve(paths.target, asset), - path.resolve(paths.hash, assetMap[asset]), - ), - ), - ) - .then(() => { - // we need unhashed keys for webpack entry bundles so we can refer to them in play templates. - // since they arrived ready-hashed, we need to add some new ones from the hashed ones... + return Promise.all( + // copy all the built files to their hash locations + Object.keys(assetMap).map((asset) => + cpFile( + path.resolve(paths.target, asset), + path.resolve(paths.hash, assetMap[asset]), + ), + ), + ) + .then(() => { + // we need unhashed keys for webpack entry bundles so we can refer to them in play templates. + // since they arrived ready-hashed, we need to add some new ones from the hashed ones... - // get the webpack entry bundles - const webpackEntryBundles = Object.keys( - assetMap, - ).filter( - (key) => - webpackRegex.test(key) && - !webpackChunkRegex.test(key) && - !sourcemapRegex.test(key), - ); + // get the webpack entry bundles + const webpackEntryBundles = Object.keys( + assetMap, + ).filter( + (key) => + webpackRegex.test(key) && + !webpackChunkRegex.test(key) && + !sourcemapRegex.test(key), + ); - // create a new key for each one and add them them to asset map - return Object.assign( - {}, - assetMap, - webpackEntryBundles.reduce( - (map, webpackEntryBundle) => - Object.assign(map, { - [webpackEntryBundle.replace( - /(javascripts\/)(.+\/)/, - '$1', - )]: assetMap[webpackEntryBundle], - }), - {}, - ), - webpackEntryBundles.reduce( - (map, webpackEntryBundle) => - Object.assign(map, { - [webpackEntryBundle.replace( - /(javascripts\/commercial\/)(.+\/)/, - '$1', - )]: assetMap[webpackEntryBundle], - }), - {}, - ), - ); - }) - .then( - ( - normalisedAssetMap, // save the asset map - ) => - mkdirp(path.resolve(paths.hash, 'assets')).then( - () => - writeFile( - path.resolve( - paths.hash, - 'assets', - 'assets.map', - ), - JSON.stringify( - normalisedAssetMap, - null, - 4, + // create a new key for each one and add them them to asset map + return Object.assign( + {}, + assetMap, + webpackEntryBundles.reduce( + (map, webpackEntryBundle) => + Object.assign(map, { + [webpackEntryBundle.replace( + /(javascripts\/)(.+\/)/, + '$1', + )]: + assetMap[ + webpackEntryBundle + ], + }), + {}, + ), + webpackEntryBundles.reduce( + (map, webpackEntryBundle) => + Object.assign(map, { + [webpackEntryBundle.replace( + /(javascripts\/commercial\/)(.+\/)/, + '$1', + )]: + assetMap[ + webpackEntryBundle + ], + }), + {}, + ), + ); + }) + .then( + ( + normalisedAssetMap, // save the asset map + ) => + mkdirp( + path.resolve(paths.hash, 'assets'), + ).then(() => + writeFile( + path.resolve( + paths.hash, + 'assets', + 'assets.map', + ), + JSON.stringify( + normalisedAssetMap, + null, + 4, + ), ), ), - ), - ); - }, - }, - ], + ); + }, + }, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/images/clean.js b/tools/__tasks__/compile/images/clean.js index 014dbbe07e1..85e4d30a104 100644 --- a/tools/__tasks__/compile/images/clean.js +++ b/tools/__tasks__/compile/images/clean.js @@ -3,8 +3,9 @@ const rimraf = require('rimraf'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clear image build artefacts', + title: 'Clear image build artefacts', task: () => { rimraf.sync(path.resolve(paths.src, 'stylesheets', 'icons')); rimraf.sync(path.resolve(paths.target, 'images')); diff --git a/tools/__tasks__/compile/images/copy.js b/tools/__tasks__/compile/images/copy.js index 79b029180db..0567a1d4ee2 100644 --- a/tools/__tasks__/compile/images/copy.js +++ b/tools/__tasks__/compile/images/copy.js @@ -3,8 +3,9 @@ const cpy = require('cpy'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Copy images', + title: 'Copy images', task: () => cpy(['**/*'], path.resolve(paths.target, 'images'), { cwd: path.resolve(paths.public, 'images'), diff --git a/tools/__tasks__/compile/images/icons.js b/tools/__tasks__/compile/images/icons.js index 2b7e520286d..99d78c71ea0 100644 --- a/tools/__tasks__/compile/images/icons.js +++ b/tools/__tasks__/compile/images/icons.js @@ -92,26 +92,36 @@ const saveSass = (sass, dest, fileName) => ); }); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Create sprites', - task: ['commercial', 'global', 'membership', 'video'].map((target) => ({ - description: `Spriting ${target}`, - concurrent: true, - task: () => { - const srcPath = path.join(paths.src, 'images', target); - const destPath = path.join(paths.src, 'stylesheets', 'icons'); - const fileName = `_${target}-icons-svg.scss`; + title: 'Create sprites', + task: (ctx, task) => + task.newListr( + ['commercial', 'global', 'membership', 'video'].map((target) => ({ + title: `Spriting ${target}`, + task: () => { + const srcPath = path.join(paths.src, 'images', target); + const destPath = path.join( + paths.src, + 'stylesheets', + 'icons', + ); + const fileName = `_${target}-icons-svg.scss`; - const iconPaths = glob.sync(path.join(srcPath, '*.svg')); + const iconPaths = glob.sync(path.join(srcPath, '*.svg')); - mkdirp.sync(destPath); + mkdirp.sync(destPath); - return Promise.all(iconPaths.map(getSVG)) - .then(sortSVGs) - .then((svgs) => svgs.map(generateSassForSVG).join('').trim()) - .then((sass) => saveSass(sass, destPath, fileName)); - }, - })), + return Promise.all(iconPaths.map(getSVG)) + .then(sortSVGs) + .then((svgs) => + svgs.map(generateSassForSVG).join('').trim(), + ) + .then((sass) => saveSass(sass, destPath, fileName)); + }, + })), + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/images/index.js b/tools/__tasks__/compile/images/index.js index c250bc2cf5a..8f3611b1b5e 100644 --- a/tools/__tasks__/compile/images/index.js +++ b/tools/__tasks__/compile/images/index.js @@ -3,15 +3,20 @@ const copy = require('./copy.js'); const icons = require('./icons.js'); const svg = require('./svg.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile images', - task: [ - // prettier: multi-line - clean, - copy, - icons, - svg, - ], + title: 'Compile images', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + copy, + icons, + svg, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/images/svg.js b/tools/__tasks__/compile/images/svg.js index 57558ab87cf..b006d095c99 100644 --- a/tools/__tasks__/compile/images/svg.js +++ b/tools/__tasks__/compile/images/svg.js @@ -11,9 +11,9 @@ const { paths } = require('../../config'); const srcDir = path.resolve(paths.src); +/** @type {import('listr2').ListrTask} */ const task = { - description: - 'Prohibit inline data URIs in svgs and other unoptimised things', + title: 'Prohibit inline data URIs in svgs and other unoptimised things', task: () => Promise.all( glob.sync('**/*.svg', { cwd: srcDir }).map((svgPath) => diff --git a/tools/__tasks__/compile/index.dev.js b/tools/__tasks__/compile/index.dev.js index d26cee3c2e5..2780ef903e5 100644 --- a/tools/__tasks__/compile/index.dev.js +++ b/tools/__tasks__/compile/index.dev.js @@ -4,16 +4,21 @@ const data = require('./data/index.dev.js'); const javascript = require('./javascript/index.dev.js'); const conf = require('./conf/index.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile assets for development', - task: [ - // prettier: multi-line - clean, - css, - data, - javascript, - conf, - ], + title: 'Compile assets for development', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + css, + data, + javascript, + conf, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/index.js b/tools/__tasks__/compile/index.js index 9a5a73e8417..c1af8217c5b 100755 --- a/tools/__tasks__/compile/index.js +++ b/tools/__tasks__/compile/index.js @@ -5,17 +5,22 @@ const javascript = require('./javascript/index.js'); const hash = require('./hash/index.js'); const conf = require('./conf/index.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile assets for production', - task: [ - // prettier: multi-line - clean, - css, - data, - javascript, - hash, - conf, - ], + title: 'Compile assets for production', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + css, + data, + javascript, + hash, + conf, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/index.watch.js b/tools/__tasks__/compile/index.watch.js index e9d781a8c60..cc3d2748744 100644 --- a/tools/__tasks__/compile/index.watch.js +++ b/tools/__tasks__/compile/index.watch.js @@ -4,16 +4,21 @@ const data = require('./data/index.watch.js'); const javascript = require('./javascript/index.watch.js'); const conf = require('./conf/index.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile assets for development', - task: [ - // prettier: multi-line - clean, - css, - data, - javascript, - conf, - ], + title: 'Compile assets for development', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + css, + data, + javascript, + conf, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/inline-svgs/index.js b/tools/__tasks__/compile/inline-svgs/index.js index 39bd64e9a06..0e122826f65 100644 --- a/tools/__tasks__/compile/inline-svgs/index.js +++ b/tools/__tasks__/compile/inline-svgs/index.js @@ -13,8 +13,9 @@ const { paths } = require('../../config'); const srcDir = path.resolve(paths.src, 'inline-svgs'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Prepare inline SVGs', + title: 'Prepare inline SVGs', task: () => Promise.all( glob.sync('**/*.svg', { cwd: srcDir }).map((svgPath) => { diff --git a/tools/__tasks__/compile/javascript/bundle-polyfills.js b/tools/__tasks__/compile/javascript/bundle-polyfills.js index 0344d8970f2..212787c4b98 100644 --- a/tools/__tasks__/compile/javascript/bundle-polyfills.js +++ b/tools/__tasks__/compile/javascript/bundle-polyfills.js @@ -17,8 +17,9 @@ const polyfillURL = fs .readFileSync(path.resolve(paths.src, 'javascripts', 'polyfill.io'), 'utf8') .trim(); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Bundle polyfill.io fallback', + title: 'Bundle polyfill.io fallback', task: () => { mkdirp.sync(dest); // try and get the lastest result from polyfill.io diff --git a/tools/__tasks__/compile/javascript/clean.js b/tools/__tasks__/compile/javascript/clean.js index eb5f6b18851..ef96162b924 100644 --- a/tools/__tasks__/compile/javascript/clean.js +++ b/tools/__tasks__/compile/javascript/clean.js @@ -3,8 +3,9 @@ const rimraf = require('rimraf'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Clear JS build artefacts', + title: 'Clear JS build artefacts', task: () => { rimraf.sync(path.resolve(paths.target, 'javascripts')); rimraf.sync(path.resolve(paths.hash, 'javascripts')); diff --git a/tools/__tasks__/compile/javascript/copy.js b/tools/__tasks__/compile/javascript/copy.js index b31758917fd..00148a8997b 100644 --- a/tools/__tasks__/compile/javascript/copy.js +++ b/tools/__tasks__/compile/javascript/copy.js @@ -3,8 +3,9 @@ const cpy = require('cpy'); const { paths } = require('../../config'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Copy 3rd JS party libraries', + title: 'Copy 3rd JS party libraries', task: () => Promise.all([ cpy( diff --git a/tools/__tasks__/compile/javascript/index.atoms.js b/tools/__tasks__/compile/javascript/index.atoms.js index a2e5dd7e942..5132de6104c 100644 --- a/tools/__tasks__/compile/javascript/index.atoms.js +++ b/tools/__tasks__/compile/javascript/index.atoms.js @@ -2,14 +2,19 @@ const clean = require('./clean'); const inlineSVGs = require('../inline-svgs'); const webpackAtoms = require('./webpack-atoms'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile JS', - task: [ - // prettier: multi-line - clean, - inlineSVGs, - webpackAtoms, - ], + title: 'Compile JS', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + inlineSVGs, + webpackAtoms, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/javascript/index.dev.js b/tools/__tasks__/compile/javascript/index.dev.js index 13edc604a2e..ddfb2d49410 100644 --- a/tools/__tasks__/compile/javascript/index.dev.js +++ b/tools/__tasks__/compile/javascript/index.dev.js @@ -4,16 +4,21 @@ const copy = require('./copy.js'); const webpack = require('./webpack.dev.js'); const bundlePolyfills = require('./bundle-polyfills.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Prepare JS for development', - task: [ - // prettier: multi-line - inlineSVGs, - clean, - copy, - webpack, - bundlePolyfills, - ], + title: 'Prepare JS for development', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + inlineSVGs, + clean, + copy, + webpack, + bundlePolyfills, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/javascript/index.js b/tools/__tasks__/compile/javascript/index.js index 1283f43a338..a361e6f8ed6 100644 --- a/tools/__tasks__/compile/javascript/index.js +++ b/tools/__tasks__/compile/javascript/index.js @@ -5,17 +5,22 @@ const webpack = require('./webpack.js'); const webpackAtoms = require('./webpack-atoms.js'); const bundlePolyfills = require('./bundle-polyfills.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile JS', - task: [ - // prettier: multi-line - clean, - inlineSVGs, - copy, - webpack, - webpackAtoms, - bundlePolyfills, - ], + title: 'Compile JS', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + clean, + inlineSVGs, + copy, + webpack, + webpackAtoms, + bundlePolyfills, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/javascript/index.watch.js b/tools/__tasks__/compile/javascript/index.watch.js index 397b7a74bf7..70e11b5e89a 100644 --- a/tools/__tasks__/compile/javascript/index.watch.js +++ b/tools/__tasks__/compile/javascript/index.watch.js @@ -3,15 +3,20 @@ const clean = require('./clean.js'); const copy = require('./copy.js'); const bundlePolyfills = require('./bundle-polyfills.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Prepare JS for development', - task: [ - // prettier: multi-line - inlineSVGs, - clean, - copy, - bundlePolyfills, - ], + title: 'Prepare JS for development', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + inlineSVGs, + clean, + copy, + bundlePolyfills, + ], + { concurrent: false }, + ), }; module.exports = task; diff --git a/tools/__tasks__/compile/javascript/webpack-atoms.js b/tools/__tasks__/compile/javascript/webpack-atoms.js index 3ef41e062b6..1ee3c86aacc 100644 --- a/tools/__tasks__/compile/javascript/webpack-atoms.js +++ b/tools/__tasks__/compile/javascript/webpack-atoms.js @@ -8,8 +8,9 @@ const chalk = require('chalk'); const config = require('../../../../webpack.config.atoms.js'); const reporter = require('../../../webpack-progress-reporter.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Create Webpack bundles for atoms', + title: 'Create Webpack bundles for atoms', task: () => new Observable((observer) => { config.plugins = [reporter(observer), ...config.plugins]; diff --git a/tools/__tasks__/compile/javascript/webpack.dev.js b/tools/__tasks__/compile/javascript/webpack.dev.js index 76b4f20b279..7d145e84fff 100644 --- a/tools/__tasks__/compile/javascript/webpack.dev.js +++ b/tools/__tasks__/compile/javascript/webpack.dev.js @@ -8,8 +8,9 @@ const chalk = require('chalk'); const config = require('../../../../webpack.config.dev.js'); const reporter = require('../../../webpack-progress-reporter.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Create Webpack bundles', + title: 'Create Webpack bundles', task: () => new Observable((observer) => { config.plugins = [reporter(observer), ...config.plugins]; diff --git a/tools/__tasks__/compile/javascript/webpack.js b/tools/__tasks__/compile/javascript/webpack.js index 606f6bdb9cb..53e66dd06f5 100644 --- a/tools/__tasks__/compile/javascript/webpack.js +++ b/tools/__tasks__/compile/javascript/webpack.js @@ -8,8 +8,9 @@ const chalk = require('chalk'); const config = require('../../../../webpack.config.prod.js'); const reporter = require('../../../webpack-progress-reporter.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Create Webpack bundles', + title: 'Create Webpack bundles', task: () => new Observable((observer) => { config.plugins = [reporter(observer), ...config.plugins]; diff --git a/tools/__tasks__/lib/check-network.js b/tools/__tasks__/lib/check-network.js index b26f4e2defe..153b4e743f1 100644 --- a/tools/__tasks__/lib/check-network.js +++ b/tools/__tasks__/lib/check-network.js @@ -1,8 +1,9 @@ const tcpp = require('tcp-ping'); const pify = require('pify'); -module.exports = (domain, port) => ({ - description: `Probing ${domain} on port ${port}...`, +/** @type {(domain: string, port: number) => import('listr2').ListrTask} */ +const createTask = (domain, port) => ({ + title: `Probing ${domain} on port ${port}...`, task: () => pify(tcpp.probe, { multiArgs: true })(domain, port).then((result) => { if (!result[0]) { @@ -12,3 +13,5 @@ module.exports = (domain, port) => ({ } }), }); + +module.exports = createTask; diff --git a/tools/__tasks__/test/index.js b/tools/__tasks__/test/index.js index 98ee2592270..42c791e142b 100644 --- a/tools/__tasks__/test/index.js +++ b/tools/__tasks__/test/index.js @@ -1,14 +1,20 @@ const data = require('../compile/data/index.js'); const javascript = require('./javascript/index.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Test assets', - task: [ - // prettier: multi-line - data, - javascript, - ], - concurrent: true, + title: 'Test assets', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + data, + javascript, + ], + { + concurrent: false, + }, + ), }; module.exports = task; diff --git a/tools/__tasks__/test/javascript/index.js b/tools/__tasks__/test/javascript/index.js index ffdc62c6a55..fefbc49a444 100644 --- a/tools/__tasks__/test/javascript/index.js +++ b/tools/__tasks__/test/javascript/index.js @@ -18,30 +18,35 @@ const exec = (cmd, args, opts) => { .pipe(rxjsOperators.filter(Boolean)); }; +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Test JS app', - task: [ - { - description: 'Run tests', - task: [ - { - description: 'JS tests', - task: () => - exec('jest', null, { - env: { - /** - * We test some things like relative dates and formatting - * that rely on a specific timezone. We set this here so - * that it's not determined by the machine's timezone. - */ - TZ: 'Europe/London', + title: 'Test JS app', + task: (ctx, task) => + task.newListr([ + { + title: 'Run tests', + task: (ctx, task) => + task.newListr( + [ + { + title: 'JS tests', + task: () => + exec('jest', null, { + env: { + /** + * We test some things like relative dates and formatting + * that rely on a specific timezone. We set this here so + * that it's not determined by the machine's timezone. + */ + TZ: 'Europe/London', + }, + }), }, - }), - }, - ], - concurrent: true, - }, - ], + ], + { concurrent: !!ctx.verbose ? false : true }, + ), + }, + ]), }; module.exports = task; diff --git a/tools/__tasks__/validate-head/index.js b/tools/__tasks__/validate-head/index.js index 71ff7f2b4b5..b1d576f9af4 100644 --- a/tools/__tasks__/validate-head/index.js +++ b/tools/__tasks__/validate-head/index.js @@ -1,14 +1,18 @@ const javascript = require('./javascript.js'); const sass = require('./sass.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Validate commits', - task: [ - // prettier: multi-line - javascript, - sass, - ], - concurrent: true, + title: 'Validate commits', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + javascript, + sass, + ], + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/__tasks__/validate-head/javascript-fix.js b/tools/__tasks__/validate-head/javascript-fix.js index 6c2789bd490..98a91703afd 100644 --- a/tools/__tasks__/validate-head/javascript-fix.js +++ b/tools/__tasks__/validate-head/javascript-fix.js @@ -1,8 +1,9 @@ const execa = require('execa'); const getChangedFiles = require('../lib/get-changed-files'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Fix committed linting errors', + title: 'Fix committed linting errors', task: () => getChangedFiles().then((files) => { const jsFiles = files.filter( diff --git a/tools/__tasks__/validate-head/javascript.js b/tools/__tasks__/validate-head/javascript.js index df20f602a7f..f3d60a3c50c 100644 --- a/tools/__tasks__/validate-head/javascript.js +++ b/tools/__tasks__/validate-head/javascript.js @@ -5,80 +5,87 @@ const getChangedFiles = require('../lib/get-changed-files'); const getCpuCount = () => os.cpus().length; +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Validate committed JS', - task: [ - { - description: 'Lint committed JS', - task: () => - getChangedFiles().then((files) => { - const errors = []; - const jsFiles = files.filter( - (file) => - (file.endsWith('.js') && - !file.endsWith('.scala.js')) || - file.endsWith('.jsx') || - file.startsWith('git-hooks'), - ); - const lint = (proc, batchedFiles) => - proc.then(() => - Promise.all( - batchedFiles.map((filePath) => - execa - .shell( - `git show HEAD:${filePath} | eslint --stdin --stdin-filename ${filePath}`, - ) - .catch((e) => { - errors.push(e); - }), - ), - ), - ); - const batch = (arr, batchSize) => { - const batchFold = (xss, x) => { - if (!xss.length) { - return [[x]]; - } - if (xss[0].length < batchSize) { - return [xss[0].concat(x), ...xss.slice(1)]; - } + title: 'Validate committed JS', + task: (ctx, task) => + task.newListr( + [ + { + title: 'Lint committed JS', + task: () => + getChangedFiles().then((files) => { + const errors = []; + const jsFiles = files.filter( + (file) => + (file.endsWith('.js') && + !file.endsWith('.scala.js')) || + file.endsWith('.jsx') || + file.startsWith('git-hooks'), + ); + const lint = (proc, batchedFiles) => + proc.then(() => + Promise.all( + batchedFiles.map((filePath) => + execa + .shell( + `git show HEAD:${filePath} | eslint --stdin --stdin-filename ${filePath}`, + ) + .catch((e) => { + errors.push(e); + }), + ), + ), + ); + const batch = (arr, batchSize) => { + const batchFold = (xss, x) => { + if (!xss.length) { + return [[x]]; + } + if (xss[0].length < batchSize) { + return [ + xss[0].concat(x), + ...xss.slice(1), + ]; + } - return [[x], ...xss]; - }; + return [[x], ...xss]; + }; - return arr.reduce(batchFold, []); - }; + return arr.reduce(batchFold, []); + }; - return batch(jsFiles, getCpuCount()) - .reduce(lint, Promise.resolve()) - .then(() => { - if (errors.length) { - const error = errors.reduce( - (acc, curr) => { - acc.stdout += curr.stdout; + return batch(jsFiles, getCpuCount()) + .reduce(lint, Promise.resolve()) + .then(() => { + if (errors.length) { + const error = errors.reduce( + (acc, curr) => { + acc.stdout += curr.stdout; - return acc; - }, - { stdout: '' }, - ); + return acc; + }, + { stdout: '' }, + ); - error.stdout += `\n${chalk.red( - `✋ Your changes have not been pushed.\n${chalk.reset( - `You may be able to fix things by running ${chalk.dim( - 'make fix-commits', - )}.`, - )}`, - )}`; + error.stdout += `\n${chalk.red( + `✋ Your changes have not been pushed.\n${chalk.reset( + `You may be able to fix things by running ${chalk.dim( + 'make fix-commits', + )}.`, + )}`, + )}`; - return Promise.reject(error); - } + return Promise.reject(error); + } - return Promise.resolve(); - }); - }), - }, - ], - concurrent: true, + return Promise.resolve(); + }); + }), + }, + ], + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/__tasks__/validate-head/sass.js b/tools/__tasks__/validate-head/sass.js index dcd31b42c4c..f49c9f9332a 100644 --- a/tools/__tasks__/validate-head/sass.js +++ b/tools/__tasks__/validate-head/sass.js @@ -5,72 +5,79 @@ const getChangedFiles = require('../lib/get-changed-files'); const getCpuCount = () => os.cpus().length; +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Validate committed Sass', - task: [ - { - description: 'Lint committed Sass', - task: () => - getChangedFiles().then((files) => { - const errors = []; - const sassFiles = files.filter((file) => - file.endsWith('.scss'), - ); - const lint = (proc, batchedFiles) => - proc.then(() => - Promise.all( - batchedFiles.map((filePath) => - execa - .shell( - `git show HEAD:${filePath} | yarn stylelint --max-warnings 0 '${filePath}'`, - ) - .catch((e) => { - errors.push(e); - }), - ), - ), - ); - const batch = (arr, batchSize) => { - const batchFold = (xss, x) => { - if (!xss.length) { - return [[x]]; - } - if (xss[0].length < batchSize) { - return [xss[0].concat(x), ...xss.slice(1)]; - } + title: 'Validate committed Sass', + task: (ctx, task) => + task.newListr( + [ + { + title: 'Lint committed Sass', + task: () => + getChangedFiles().then((files) => { + const errors = []; + const sassFiles = files.filter((file) => + file.endsWith('.scss'), + ); + const lint = (proc, batchedFiles) => + proc.then(() => + Promise.all( + batchedFiles.map((filePath) => + execa + .shell( + `git show HEAD:${filePath} | yarn stylelint --max-warnings 0 '${filePath}'`, + ) + .catch((e) => { + errors.push(e); + }), + ), + ), + ); + const batch = (arr, batchSize) => { + const batchFold = (xss, x) => { + if (!xss.length) { + return [[x]]; + } + if (xss[0].length < batchSize) { + return [ + xss[0].concat(x), + ...xss.slice(1), + ]; + } - return [[x], ...xss]; - }; + return [[x], ...xss]; + }; - return arr.reduce(batchFold, []); - }; + return arr.reduce(batchFold, []); + }; - return batch(sassFiles, getCpuCount()) - .reduce(lint, Promise.resolve()) - .then(() => { - if (errors.length) { - const error = errors.reduce( - (acc, curr) => { - acc.stdout += curr.stdout; + return batch(sassFiles, getCpuCount()) + .reduce(lint, Promise.resolve()) + .then(() => { + if (errors.length) { + const error = errors.reduce( + (acc, curr) => { + acc.stdout += curr.stdout; - return acc; - }, - { stdout: '' }, - ); + return acc; + }, + { stdout: '' }, + ); - error.stdout += `\n${chalk.red( - `✋ Your changes have not been pushed.`, - )}`; + error.stdout += `\n${chalk.red( + `✋ Your changes have not been pushed.`, + )}`; - return Promise.reject(error); - } + return Promise.reject(error); + } - return Promise.resolve(); - }); - }), - }, - ], - concurrent: true, + return Promise.resolve(); + }); + }), + }, + ], + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/__tasks__/validate/check-for-disallowed-strings.js b/tools/__tasks__/validate/check-for-disallowed-strings.js index e53ec733ef0..8bf6a15e00d 100644 --- a/tools/__tasks__/validate/check-for-disallowed-strings.js +++ b/tools/__tasks__/validate/check-for-disallowed-strings.js @@ -2,8 +2,9 @@ const execa = require('execa'); const chalk = require('chalk'); const disallowedStrings = require('../../../disallowed-strings.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Check for disallowed strings', + title: 'Check for disallowed strings', task: () => Promise.all( disallowedStrings.map( @@ -49,7 +50,6 @@ const task = { }), ), ), - concurrent: true, }; module.exports = task; diff --git a/tools/__tasks__/validate/index.js b/tools/__tasks__/validate/index.js index 02030b2bced..4cfb8327f56 100644 --- a/tools/__tasks__/validate/index.js +++ b/tools/__tasks__/validate/index.js @@ -3,16 +3,22 @@ const typescript = require('./typescript.js'); const sass = require('./sass.js'); const checkForDisallowedStrings = require('./check-for-disallowed-strings.js'); +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Lint assets', - task: [ - // prettier: multi-line - javascript, - typescript, - sass, - checkForDisallowedStrings, - ], - concurrent: true, + title: 'Lint assets', + task: (ctx, task) => + task.newListr( + [ + // prettier: multi-line + javascript, + typescript, + sass, + checkForDisallowedStrings, + ], + { + concurrent: !!ctx.verbose ? false : true, + }, + ), }; module.exports = task; diff --git a/tools/__tasks__/validate/javascript-fix.js b/tools/__tasks__/validate/javascript-fix.js index 5159616aafc..6648439822f 100644 --- a/tools/__tasks__/validate/javascript-fix.js +++ b/tools/__tasks__/validate/javascript-fix.js @@ -6,34 +6,39 @@ const handleSuccess = (ctx) => { ctx.messages.push("Don't forget to commit any fixes..."); }; +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Fix JS linting errors', - task: [ - { - description: 'Fix static/src', - task: (ctx) => - execa( - 'eslint', - ['static/src/javascripts', '--ext=ts,tsx,js'].concat( - config, - ), - ).then(handleSuccess.bind(null, ctx)), - }, - { - description: 'Fix everything else', - task: (ctx) => - execa( - 'eslint', - [ - '*.js', - 'tools/**/*.js', - 'dev/**/*.js', - 'git-hooks/*', - ].concat(config), - ).then(handleSuccess.bind(null, ctx)), - }, - ], - concurrent: true, + title: 'Fix JS linting errors', + task: (ctx, task) => + task.newListr( + [ + { + title: 'Fix static/src', + task: (ctx) => + execa( + 'eslint', + [ + 'static/src/javascripts', + '--ext=ts,tsx,js', + ].concat(config), + ).then(handleSuccess.bind(null, ctx)), + }, + { + title: 'Fix everything else', + task: (ctx) => + execa( + 'eslint', + [ + '*.js', + 'tools/**/*.js', + 'dev/**/*.js', + 'git-hooks/*', + ].concat(config), + ).then(handleSuccess.bind(null, ctx)), + }, + ], + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/__tasks__/validate/javascript.js b/tools/__tasks__/validate/javascript.js index 0b37dc6ac41..c0e2e471eaf 100644 --- a/tools/__tasks__/validate/javascript.js +++ b/tools/__tasks__/validate/javascript.js @@ -1,4 +1,5 @@ const chalk = require('chalk'); +const execa = require('execa'); const config = '--quiet --color'; const error = (ctx) => { @@ -12,26 +13,35 @@ const error = (ctx) => { ); }; +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Lint JS', - task: [ - { - description: 'Static', - task: `eslint static/src/javascripts --ext=ts,tsx,js ${config}`, - onError: error, - }, - { - description: 'Tools etc.', - task: `eslint tools ${config}`, - onError: error, - }, - { - description: 'Git hooks', - task: `eslint git-hooks/* ${config}`, - onError: error, - }, - ], - concurrent: true, + title: 'Lint JS', + task: (ctx, task) => + task.newListr( + [ + { + title: 'Static', + task: () => + execa('eslint', [ + 'static/src/javascripts', + '--ext=ts,tsx,js', + config, + ]), + onError: error, + }, + { + title: 'Tools etc.', + task: () => execa('eslint', ['tools', config]), + onError: error, + }, + { + title: 'Git hooks', + task: () => execa('eslint', ['git-hooks/*', config]), + onError: error, + }, + ], + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/__tasks__/validate/sass.js b/tools/__tasks__/validate/sass.js index 8fa6262a424..1cc7d500238 100644 --- a/tools/__tasks__/validate/sass.js +++ b/tools/__tasks__/validate/sass.js @@ -1,6 +1,9 @@ +const execa = require('execa'); + +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Lint Sass', - task: 'stylelint **/*.scss', + title: 'Lint Sass', + task: () => execa('stylelint', ['**/*.scss']), }; module.exports = task; diff --git a/tools/__tasks__/validate/scalafmt.js b/tools/__tasks__/validate/scalafmt.js index faf5ca543cb..139dcab66b7 100644 --- a/tools/__tasks__/validate/scalafmt.js +++ b/tools/__tasks__/validate/scalafmt.js @@ -1,4 +1,5 @@ const chalk = require('chalk'); +const execa = require('execa'); const config = '--error'; const error = (ctx) => { @@ -7,15 +8,20 @@ const error = (ctx) => { ); }; +/** @type {import('listr2').ListrTask} */ const task = { - description: 'scalafmt check', - task: [ - { - description: 'scalafmtCheckAll', - task: `./sbt scalafmtCheckAll ${config}`, - onError: error, - }, - ], + title: 'Check Scala formatting', + task: (ctx, task) => + task.newListr( + [ + { + title: 'scalafmtCheckAll', + task: () => execa('./sbt', ['scalafmtCheckAll', config]), + onError: error, + }, + ], + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/__tasks__/validate/typescript.js b/tools/__tasks__/validate/typescript.js index 49d254556e0..ff8f708247e 100644 --- a/tools/__tasks__/validate/typescript.js +++ b/tools/__tasks__/validate/typescript.js @@ -1,4 +1,5 @@ const chalk = require('chalk'); +const execa = require('execa'); const error = (ctx) => { ctx.messages.push( @@ -11,16 +12,20 @@ const error = (ctx) => { ); }; +/** @type {import('listr2').ListrTask} */ const task = { - description: 'Compile TS', - task: [ - { - description: 'Compile', - task: `tsc --noEmit`, - onError: error, - }, - ], - concurrent: true, + title: 'Compile TS', + task: (ctx, task) => + task.newListr( + [ + { + title: 'Compile', + task: () => execa('tsc', ['--noEmit']), + onError: error, + }, + ], + { concurrent: !!ctx.verbose ? false : true }, + ), }; module.exports = task; diff --git a/tools/task-runner/runner.mjs b/tools/task-runner/runner.mjs index 0b448a84bc1..5c074107e26 100755 --- a/tools/task-runner/runner.mjs +++ b/tools/task-runner/runner.mjs @@ -4,13 +4,11 @@ process.env.FORCE_COLOR = true; import path from 'node:path'; -import os from 'node:os'; import { fileURLToPath } from 'node:url'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import { Listr } from 'listr2'; -import execa from 'execa'; import chalk from 'chalk'; import figures from 'figures'; import uniq from 'lodash.uniq'; @@ -71,106 +69,9 @@ const taskSrc = path.resolve( tasksDirectory, ); -// we will store tasks that we run in here, to prevent running them more than once -// e.g. if two tasks rely on the same thing -const cache = []; - -// use exaca to run simple terminal commands -const exec = (task, onError, ctx) => { - const [cmd, ...args] = task.trim().split(' '); - - return execa(cmd, args) - .then((result) => { - // store any stdout incase we need it later - if (result.stdout) ctx.stdouts.push(result.stdout); - }) - .catch((e) => { - // if the task supplies an `onError` function, run it - if (typeof onError === 'function') onError(ctx); - // continue with a fake rejected promise - return Promise.reject(e); - }); -}; - -const getCpuCount = () => os.cpus().length; - -// turn a list of our tasks into objects listr can use -function listrify(steps, { concurrent = false } = {}) { - const listrTasks = steps.map((step) => { - const { - description: title, - task, - concurrent: isConcurrent, - onError, - } = step; - - // if another task has included this one, don't run it again - const skip = - cache.indexOf(step) !== -1 - ? () => 'Skipping: already run by another task' - : false; - cache.push(step); - - // if the task is a set of subtasks, prepare them - if (Array.isArray(task)) { - return { - title, - task: () => - listrify( - task.map((_task) => { - if (_task.task) return _task; - if (typeof _task === 'string') - return { - title, - task: (ctx) => exec(_task, onError, ctx), - skip, - }; - return { title, task: _task, skip }; - }), - { - concurrent: VERBOSE - ? false - : isConcurrent - ? getCpuCount() - : false, - }, - ), - skip, - }; - } - - // treat tasks that are strings as terminal commands - if (typeof task === 'string') - return { title, task: (ctx) => exec(task, onError, ctx), skip }; - - // assume the task is a function - // if it's not, listr will blow up anyway, which is fine - return { - title, - task: (ctx) => - new Promise((resolve, reject) => { - try { - resolve(task(ctx)); - } catch (e) { - if (typeof onError === 'function') onError(ctx); - if (VERBOSE) console.log(e); - reject(e); - } - }), - skip, - }; - }); - - const renderer = IS_VERBOSE ? VerboseRenderer : 'default'; - - return new Listr(listrTasks, { - concurrent: concurrent ? getCpuCount() : false, - collapse: true, - renderer, - }); -} - -// resolve the tasks from yargs to actual files +/** + * resolve the tasks from yargs to actual files + */ const getTasksFromModule = async (taskName) => { try { const modulePath = path.resolve(taskSrc, taskName); @@ -185,15 +86,20 @@ const getTasksFromModule = async (taskName) => { } }; -// get a list of the tasks we're going to run +/** get a list of the tasks we're going to run */ const taskModules = await Promise.all(TASKS.map(getTasksFromModule)); // run them! -listrify(taskModules) +new Listr(taskModules, { + collapse: true, + renderer: IS_VERBOSE ? VerboseRenderer : 'default', + concurrent: VERBOSE ? false : true, +}) .run({ - // we're adding these to the [listr context](https://github.com/SamVerschueren/listr#context) + // we're adding these to the [listr context](https://listr2.kilic.dev/listr/context.html) messages: [], stdouts: [], + verbose: VERBOSE, }) .catch((e) => { // something went wrong, so log whatever we have