Fix flipper server prod build

Summary: Make flipper-server link local flipper-* deps for intern prod build. Update flipper-* deps versions for public builds so `npx` pulls them from npm

Reviewed By: lblasa

Differential Revision: D39497944

fbshipit-source-id: ca2674a4ac8f5b6c3efa9546b631f2526bf48f8e
This commit is contained in:
Andrey Goncharov
2022-09-15 10:02:19 -07:00
committed by Facebook GitHub Bot
parent ed93dfe978
commit 9dda947371
3 changed files with 4365 additions and 17 deletions

View File

@@ -18,7 +18,13 @@ import {
prepareDefaultPlugins, prepareDefaultPlugins,
moveServerSourceMaps, moveServerSourceMaps,
} from './build-utils'; } from './build-utils';
import {defaultPluginsDir, distDir, serverDir, staticDir} from './paths'; import {
defaultPluginsDir,
distDir,
serverDir,
staticDir,
rootDir,
} from './paths';
import isFB from './isFB'; import isFB from './isFB';
import yargs from 'yargs'; import yargs from 'yargs';
import fs from 'fs-extra'; import fs from 'fs-extra';
@@ -113,6 +119,13 @@ const argv = yargs
'Unique build identifier to be used as the version patch part for the build', 'Unique build identifier to be used as the version patch part for the build',
type: 'number', type: 'number',
}, },
// On intern we ship flipper-server with node_modules (no big internet behind the firewall). yarn.lock makes sure that a CI that builds flipper-server installs the same dependencies all the time.
'generate-lock': {
describe:
'Generate a new yarn.lock file for flipper-server prod build. It is used for reproducible builds of the final artifact for the intern.',
type: 'boolean',
default: false,
},
mac: { mac: {
describe: 'Build a platform-specific bundle for MacOS.', describe: 'Build a platform-specific bundle for MacOS.',
type: 'boolean', type: 'boolean',
@@ -216,7 +229,7 @@ async function copyStaticResources(outDir: string, versionNumber: string) {
console.log(`⚙️ Copying package resources...`); console.log(`⚙️ Copying package resources...`);
// static folder, without the things that are only for Electron // static folder, without the things that are only for Electron
const packageFilesToCopy = ['README.md', 'package.json', 'server.js', 'lib']; const packageFilesToCopy = ['README.md', 'server.js', 'lib'];
await Promise.all( await Promise.all(
packageFilesToCopy.map((e) => packageFilesToCopy.map((e) =>
@@ -253,7 +266,44 @@ async function copyStaticResources(outDir: string, versionNumber: string) {
console.log('✅ Copied static resources.'); console.log('✅ Copied static resources.');
} }
async function modifyPackageManifest( async function linkLocalDeps(buildFolder: string) {
// eslint-disable-next-line no-console
console.log('Creating package.json manifest to link local deps');
const manifest = await fs.readJSON(path.resolve(serverDir, 'package.json'));
const resolutions = {
'flipper-doctor': `file:${rootDir}/doctor`,
'flipper-common': `file:${rootDir}/flipper-common`,
'flipper-frontend-core': `file:${rootDir}/flipper-frontend-core`,
'flipper-plugin-core': `file:${rootDir}/flipper-plugin-core`,
'flipper-server-companion': `file:${rootDir}/flipper-server-companion`,
'flipper-server-core': `file:${rootDir}/flipper-server-core`,
'flipper-pkg-lib': `file:${rootDir}/pkg-lib`,
'flipper-plugin-lib': `file:${rootDir}/plugin-lib`,
};
manifest.resolutions = resolutions;
for (const depName of Object.keys(manifest.dependencies)) {
if (depName in resolutions) {
manifest.dependencies[depName] =
resolutions[depName as keyof typeof resolutions];
}
}
delete manifest.scripts;
delete manifest.devDependencies;
await fs.writeFile(
path.join(buildFolder, 'package.json'),
JSON.stringify(manifest, null, ' '),
);
await yarnInstall(buildFolder);
console.log('✅ Linked local deps');
}
async function modifyPackageManifestForPublishing(
buildFolder: string, buildFolder: string,
versionNumber: string, versionNumber: string,
hgRevision: string | null, hgRevision: string | null,
@@ -261,8 +311,7 @@ async function modifyPackageManifest(
) { ) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log('Creating package.json manifest'); console.log('Creating package.json manifest');
// eslint-disable-next-line flipper/no-relative-imports-across-packages const manifest = await fs.readJSON(path.resolve(serverDir, 'package.json'));
const manifest = require('../flipper-server/package.json');
manifest.version = versionNumber; manifest.version = versionNumber;
manifest.private = false; // make this package npm-publishable manifest.private = false; // make this package npm-publishable
@@ -273,8 +322,15 @@ async function modifyPackageManifest(
// not needed in public builds // not needed in public builds
delete manifest.scripts; delete manifest.scripts;
delete manifest.devDependencies; delete manifest.devDependencies;
// TODO: Remove me later
delete manifest.dependencies; // update local monorepo dependencies' versions
// we will need them for npx to work
for (const depName of Object.keys(manifest.dependencies)) {
if (depName.startsWith('flipper')) {
manifest.dependencies[depName] = versionNumber;
}
}
await fs.writeFile( await fs.writeFile(
path.join(buildFolder, 'package.json'), path.join(buildFolder, 'package.json'),
JSON.stringify(manifest, null, ' '), JSON.stringify(manifest, null, ' '),
@@ -315,7 +371,6 @@ async function runPostBuildAction(archive: string, dir: string) {
); );
} else if (argv.start) { } else if (argv.start) {
console.log(`⚙️ Starting flipper-server from build dir`); console.log(`⚙️ Starting flipper-server from build dir`);
await yarnInstall(dir);
await spawn( await spawn(
'./server.js', './server.js',
[argv.open ? '--open' : '--no-open', argv.tcp ? '--tcp' : '--no-tcp'], [argv.open ? '--open' : '--no-open', argv.tcp ? '--tcp' : '--no-tcp'],
@@ -328,10 +383,40 @@ async function runPostBuildAction(archive: string, dir: string) {
} }
async function yarnInstall(dir: string) { async function yarnInstall(dir: string) {
console.log(`⚙️ Running yarn install in ${dir}`); console.log(
await spawn('yarn', ['install', '--production', '--no-lockfile'], { `⚙️ Running yarn install in ${dir}. package.json: ${await fs.readFile(
path.resolve(dir, 'package.json'),
)}`,
);
if (!argv['generate-lock']) {
await fs.copyFile(
path.resolve(rootDir, 'yarn.flipper-server.lock'),
path.resolve(dir, 'yarn.lock'),
);
}
await spawn(
'yarn',
[
'install',
'--production',
...(process.env.SANDCASTLE ? ['--offline'] : []),
],
{
cwd: dir, cwd: dir,
}); stdio: 'inherit',
},
);
if (argv['generate-lock']) {
await fs.copyFile(
path.resolve(dir, 'yarn.lock'),
path.resolve(rootDir, 'yarn.flipper-server.lock'),
);
}
await fs.rm(path.resolve(dir, 'yarn.lock'));
} }
async function buildServerRelease() { async function buildServerRelease() {
@@ -356,10 +441,16 @@ async function buildServerRelease() {
await prepareDefaultPlugins(argv.channel === 'insiders'); await prepareDefaultPlugins(argv.channel === 'insiders');
await compileServerMain(false); await compileServerMain(false);
await copyStaticResources(dir, versionNumber); await copyStaticResources(dir, versionNumber);
await linkLocalDeps(dir);
await downloadIcons(path.join(dir, 'static')); await downloadIcons(path.join(dir, 'static'));
await buildBrowserBundle(path.join(dir, 'static'), false); await buildBrowserBundle(path.join(dir, 'static'), false);
await moveServerSourceMaps(dir, argv['source-map-dir']); await moveServerSourceMaps(dir, argv['source-map-dir']);
await modifyPackageManifest(dir, versionNumber, hgRevision, argv.channel); await modifyPackageManifestForPublishing(
dir,
versionNumber,
hgRevision,
argv.channel,
);
const archive = await packNpmArchive(dir, versionNumber); const archive = await packNpmArchive(dir, versionNumber);
await runPostBuildAction(archive, dir); await runPostBuildAction(archive, dir);
@@ -375,9 +466,6 @@ async function buildServerRelease() {
platforms.push(BuildPlatform.WINDOWS); platforms.push(BuildPlatform.WINDOWS);
} }
if (platforms.length > 0) {
await yarnInstall(dir);
}
platforms.forEach( platforms.forEach(
bundleServerReleaseForPlatform.bind(null, dir, versionNumber), bundleServerReleaseForPlatform.bind(null, dir, versionNumber),
); );

View File

@@ -345,8 +345,9 @@ export function genMercurialRevision(): Promise<string | null> {
} }
export async function compileServerMain(dev: boolean) { export async function compileServerMain(dev: boolean) {
console.log('⚙️ Compiling server sources...');
await exec(`cd ${serverDir} && yarn build`); await exec(`cd ${serverDir} && yarn build`);
console.log('✅ Compiled server bundle.'); console.log('✅ Compiled server sources.');
} }
// TODO: needed? // TODO: needed?

File diff suppressed because it is too large Load Diff