From b05219d09ca45bea5e638cf803c66bb0c2e22f52 Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Mon, 10 Jan 2022 08:56:54 -0800 Subject: [PATCH] Fix release build Summary: This diff fixes the issue where flipper-server didn't properly build when creating a release build, due to plugins being resolved from both source `desktop/plugins` and `desktop/static/defaultPlugins` folders. The `desktop/plugins` folder should not be included in the build, but wasn't sure why not, as it isn't a problem for desktop release either? Anyway solved it for now to unblock releasing by using bundled-plugins, which might actually be better anyway for a bunch of use cases of flipper-server (e.g. when installed to an OD). So I think this is fine for now. It does increase the build to ~40 MB, which is still halve of our unbundled electron build. Reviewed By: aigoncharov Differential Revision: D33427938 fbshipit-source-id: c931c2d1bea1e04c7b1603a488dcb76a41488740 --- .../scripts/build-flipper-server-release.ts | 85 ++++++++++++------- desktop/scripts/build-icons.ts | 3 + desktop/scripts/build-utils.ts | 5 +- 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/desktop/scripts/build-flipper-server-release.ts b/desktop/scripts/build-flipper-server-release.ts index 9440f5fe9..68f25ad5b 100644 --- a/desktop/scripts/build-flipper-server-release.ts +++ b/desktop/scripts/build-flipper-server-release.ts @@ -70,11 +70,18 @@ const argv = yargs 'Load only specified plugins and skip loading rest. This is useful when you are developing only one or few plugins. Plugins to load can be specified as a comma-separated list with either plugin id or name used as identifier, e.g. "--enabled-plugins network,inspector". The flag is not provided by default which means that all plugins loaded.', type: 'array', }, + // options based on build-release channel: { description: 'Release channel for the build', choices: ['stable', 'insiders'], default: 'stable', }, + 'bundled-plugins': { + describe: + 'Enables bundling of plugins into Flipper bundle. Env var FLIPPER_NO_BUNDLED_PLUGINS is equivalent to the command-line option "--no-bundled-plugins".', + type: 'boolean', + default: false, + }, 'default-plugins-dir': { describe: 'Directory with prepared list of default plugins which will be included into the Flipper distribution as "defaultPlugins" dir', @@ -96,12 +103,17 @@ if (isFB) { process.env.FLIPPER_RELEASE_CHANNEL = argv.channel; +if (argv['bundled-plugins'] === false) { + process.env.FLIPPER_NO_BUNDLED_PLUGINS = 'true'; +} else if (argv['bundled-plugins'] === true) { + delete process.env.FLIPPER_NO_BUNDLED_PLUGINS; +} + if (argv['default-plugins'] === true) { delete process.env.FLIPPER_NO_DEFAULT_PLUGINS; } else if (argv['default-plugins'] === false) { process.env.FLIPPER_NO_DEFAULT_PLUGINS = 'true'; } - // Don't rebuild default plugins, mostly to speed up testing if (argv['rebuild-plugins'] === false) { process.env.FLIPPER_NO_REBUILD_PLUGINS = 'true'; @@ -109,6 +121,10 @@ if (argv['rebuild-plugins'] === false) { delete process.env.FLIPPER_NO_REBUILD_PLUGINS; } +if (argv['default-plugins-dir']) { + process.env.FLIPPER_DEFAULT_PLUGINS_DIR = argv['default-plugins-dir']; +} + if (argv['public-build'] === true) { // we use a separate env var for forced_public builds, since // FB_FLIPPER / isFB reflects whether we are running on FB sources / infra @@ -116,8 +132,6 @@ if (argv['public-build'] === true) { // this variable purely overrides whether imports are from `fb` or `fb-stubs` console.log('🐬 Emulating open source build of Flipper'); process.env.FLIPPER_FORCE_PUBLIC_BUILD = 'true'; -} else if (argv['public-build'] === false) { - delete process.env.FLIPPER_FORCE_PUBLIC_BUILD; } if (argv['enabled-plugins'] !== undefined) { @@ -227,32 +241,7 @@ async function modifyPackageManifest( ); } -(async () => { - console.log(`⚙️ Starting build-flipper-server-release`); - console.dir(argv); - const dir = await buildFolder(); - console.log('Created build directory', dir); - - if (dotenv && dotenv.parsed) { - console.log('✅ Loaded env vars from .env file: ', dotenv.parsed); - } - - const versionNumber = getVersionNumber(argv.version); - const hgRevision = await genMercurialRevision(); - console.log( - ` Building version / revision ${versionNumber} ${hgRevision ?? ''}`, - ); - - // create static dir - await fs.mkdirp(path.join(dir, 'static', 'defaultPlugins')); - - await prepareDefaultPlugins(argv.channel === 'insiders'); - await compileServerMain(false); - await buildBrowserBundle(path.join(dir, 'static'), false); - await copyStaticResources(dir); - await downloadIcons(path.join(dir, 'static')); - await modifyPackageManifest(dir, versionNumber, hgRevision, argv.channel); - +async function packNpmArchive(dir: string, versionNumber: any) { console.log(`⚙️ Packing flipper-server.tgz`); const archive = path.resolve(distDir, 'flipper-server.tgz'); await spawn('yarn', ['pack', '--filename', archive], { @@ -263,11 +252,13 @@ async function modifyPackageManifest( console.log( `✅ flipper-release-build completed, version ${versionNumber} in ${dir}`, ); + return archive; +} +async function runPostBuildAction(archive: string, dir: string) { if (argv.npx) { // This is a hack, as npx cached very aggressively if package.version // didn't change - console.log(`⚙️ Installing flipper-server.tgz using npx`); await fs.remove(path.join(homedir(), '.npm', '_npx')); await spawn('npx', [archive, argv.open ? '--open' : '--no-open'], { @@ -283,7 +274,39 @@ async function modifyPackageManifest( stdio: 'inherit', }); } -})().catch((e) => { +} + +async function buildServerRelease() { + console.log(`⚙️ Starting build-flipper-server-release`); + console.dir(argv); + const dir = await buildFolder(); + console.log('Created build directory', dir); + + if (dotenv && dotenv.parsed) { + console.log('✅ Loaded env vars from .env file: ', dotenv.parsed); + } + + const versionNumber = getVersionNumber(argv.version); + const hgRevision = await genMercurialRevision(); + console.log( + ` Building version / revision ${versionNumber} ${hgRevision ?? ''}`, + ); + + // create plugin output dir + await fs.mkdirp(path.join(dir, 'static', 'defaultPlugins')); + + await compileServerMain(false); + await prepareDefaultPlugins(argv.channel === 'insiders'); + await copyStaticResources(dir); + await downloadIcons(path.join(dir, 'static')); + await buildBrowserBundle(path.join(dir, 'static'), false); + await modifyPackageManifest(dir, versionNumber, hgRevision, argv.channel); + const archive = await packNpmArchive(dir, versionNumber); + + await runPostBuildAction(archive, dir); +} + +buildServerRelease().catch((e) => { console.error('Failed to build flipper-server', e, e.stack); process.exit(1); }); diff --git a/desktop/scripts/build-icons.ts b/desktop/scripts/build-icons.ts index 067383b9c..b9b6fdd17 100644 --- a/desktop/scripts/build-icons.ts +++ b/desktop/scripts/build-icons.ts @@ -53,9 +53,12 @@ export async function downloadIcons(buildFolder: string) { const url = getPublicIconUrl(icon); return fetch(url, { retryOptions: { + retryMaxDuration: 30 * 1000, // Be default, only 5xx are retried but we're getting the odd 404 // which goes away on a retry for some reason. retryOnHttpResponse: (res) => res.status >= 400, + // @ts-expect-error not available in typings, but provided in docs (if this errors in future, remove the comment!) + retryOnHttpError: () => true, }, }) .then((res) => { diff --git a/desktop/scripts/build-utils.ts b/desktop/scripts/build-utils.ts index 0b31f7a5b..a6bf91df7 100644 --- a/desktop/scripts/build-utils.ts +++ b/desktop/scripts/build-utils.ts @@ -454,7 +454,7 @@ export async function buildBrowserBundle(outDir: string, dev: boolean) { const baseConfig = await Metro.loadConfig(); const config = Object.assign({}, baseConfig, { - projectRoot: rootDir, + projectRoot: browserUiDir, watchFolders, transformer: { ...baseConfig.transformer, @@ -553,7 +553,8 @@ function assertSaneImport(context: any, moduleName: string) { (moduleName.startsWith('metro') && !moduleName.startsWith('metro-runtime')) || moduleName === 'Metro' || - moduleName.startsWith('babel') || + (moduleName.startsWith('babel') && + !moduleName.startsWith('babel-runtime')) || moduleName.startsWith('typescript') || moduleName.startsWith('electron') || moduleName.startsWith('@testing-library')