From ac6575850ea11354b4ef7a5683f50bca4f99b366 Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Sun, 4 Nov 2018 04:34:12 -0800 Subject: [PATCH] Fail build when plugins don't compile Summary: This adds an option to the compilePlugin function that allows specifying whether or not to throw an exception if compiling a plugin fails. While this seems like a sensible default while development, it seems like a pretty bad idea when building releases. Reviewed By: jknoxville Differential Revision: D12904570 fbshipit-source-id: aee365074af129296a9d493804b959cb9513f9cc --- scripts/build-release.js | 23 ++++++++------- static/compilePlugins.js | 62 ++++++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 22 deletions(-) diff --git a/scripts/build-release.js b/scripts/build-release.js index aefb03336..8882503e0 100755 --- a/scripts/build-release.js +++ b/scripts/build-release.js @@ -190,17 +190,20 @@ function compileDefaultPlugins(buildFolder) { path.join(__dirname, '..', 'src', 'fb', 'plugins'), ], defaultPluginDir, - ).then(defaultPlugins => - fs.writeFileSync( - path.join(defaultPluginDir, 'index.json'), - JSON.stringify( - defaultPlugins.map(plugin => ({ - ...plugin, - out: path.join(defaultPluginFolder, path.parse(plugin.out).base), - })), + {force: true, failSilently: false}, + ) + .then(defaultPlugins => + fs.writeFileSync( + path.join(defaultPluginDir, 'index.json'), + JSON.stringify( + defaultPlugins.map(plugin => ({ + ...plugin, + out: path.join(defaultPluginFolder, path.parse(plugin.out).base), + })), + ), ), - ), - ); + ) + .catch(die); } (async () => { diff --git a/static/compilePlugins.js b/static/compilePlugins.js index 8b0f6bcf7..ccb53aa5d 100644 --- a/static/compilePlugins.js +++ b/static/compilePlugins.js @@ -3,6 +3,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * @format + * @flow */ const path = require('path'); @@ -12,15 +13,38 @@ const util = require('util'); const recursiveReaddir = require('recursive-readdir'); const HOME_DIR = require('os').homedir(); -module.exports = async (reloadCallback, pluginPaths, pluginCache) => { +/* eslint-disable prettier/prettier */ +/*:: +type CompileOptions = {| + force: boolean, + failSilently: boolean, +|}; +*/ + +const DEFAULT_COMPILE_OPTIONS /*: CompileOptions */ = { + force: false, + failSilently: true, +}; + +module.exports = async ( + reloadCallback, + pluginPaths, + pluginCache, + options = DEFAULT_COMPILE_OPTIONS, +) => { const plugins = pluginEntryPoints(pluginPaths); if (!fs.existsSync(pluginCache)) { fs.mkdirSync(pluginCache); } - watchChanges(plugins, reloadCallback, pluginCache); + watchChanges(plugins, reloadCallback, pluginCache, options); const dynamicPlugins = []; for (let plugin of Object.values(plugins)) { - const compiledPlugin = await compilePlugin(plugin, false, pluginCache); + const dynamicOptions = Object.assign(options, {force: false}); + const compiledPlugin = await compilePlugin( + plugin, + pluginCache, + dynamicOptions, + ); if (compiledPlugin) { dynamicPlugins.push(compiledPlugin); } @@ -29,7 +53,12 @@ module.exports = async (reloadCallback, pluginPaths, pluginCache) => { return dynamicPlugins; }; -function watchChanges(plugins, reloadCallback, pluginCache) { +function watchChanges( + plugins, + reloadCallback, + pluginCache, + options = DEFAULT_COMPILE_OPTIONS, +) { // eslint-disable-next-line no-console console.log('🕵️‍ Watching for plugin changes'); @@ -40,7 +69,8 @@ function watchChanges(plugins, reloadCallback, pluginCache) { if (!filename.startsWith('.')) { // eslint-disable-next-line no-console console.log(`🕵️‍ Detected changes in ${plugin.name}`); - compilePlugin(plugin, true, pluginCache).then(reloadCallback); + const watchOptions = Object.assign(options, {force: true}); + compilePlugin(plugin, pluginCache, watchOptions).then(reloadCallback); } }), ); @@ -139,15 +169,19 @@ function mostRecentlyChanged(dir) { } async function compilePlugin( {rootDir, name, entry, packageJSON}, - force, pluginCache, + options/*: CompileOptions */, ) { const fileName = `${name}@${packageJSON.version || '0.0.0'}.js`; const out = path.join(pluginCache, fileName); const result = Object.assign({}, packageJSON, {rootDir, name, entry, out}); // check if plugin needs to be compiled const rootDirCtime = await mostRecentlyChanged(rootDir); - if (!force && fs.existsSync(out) && rootDirCtime < fs.lstatSync(out).ctime) { + if ( + !options.force && + fs.existsSync(out) && + rootDirCtime < fs.lstatSync(out).ctime + ) { // eslint-disable-next-line no-console console.log(`🥫 Using cached version of ${name}...`); return result; @@ -181,11 +215,15 @@ async function compilePlugin( }, ); } catch (e) { - console.error( - `❌ Plugin ${name} is ignored, because it could not be compiled.`, - ); - console.error(e); - return null; + if (options.failSilently) { + console.error( + `❌ Plugin ${name} is ignored, because it could not be compiled.`, + ); + console.error(e); + return null; + } else { + throw e; + } } return result; }