App bundle for server

Summary:
This bundles up the Flipper Server in a Mac App Bundle which is identically in shape to a regular Desktop bundle. That means we can swap them out transparently without having to keep the layout in sync with Flipper Launcher.

It bundles nodeJS binary which we can later also provide for aarch64.

Reviewed By: aigoncharov

Differential Revision: D36140809

fbshipit-source-id: fb3410626ab172ce0da48f1a4a1489da68450369
This commit is contained in:
Pascal Hartig
2022-05-09 04:19:55 -07:00
committed by Facebook GitHub Bot
parent 39317adfb7
commit 045e0cc9fe
8 changed files with 136 additions and 15 deletions

View File

@@ -24,7 +24,7 @@ import fs from 'fs-extra';
import {downloadIcons} from './build-icons';
import {spawn} from 'promisify-child-process';
import {homedir} from 'os';
import {need} from 'pkg-fetch';
import {need as pkgFetch} from 'pkg-fetch';
// This needs to be tested individually. As of 2022Q2, node17 is not supported.
const SUPPORTED_NODE_PLATFORM = 'node16';
@@ -114,8 +114,6 @@ const argv = yargs
},
linux: {
describe: 'Build a platform-specific bundle for Linux.',
type: 'boolean',
default: false,
},
})
.help()
@@ -337,7 +335,6 @@ async function buildServerRelease() {
await buildBrowserBundle(path.join(dir, 'static'), false);
await modifyPackageManifest(dir, versionNumber, hgRevision, argv.channel);
const archive = await packNpmArchive(dir, versionNumber);
await runPostBuildAction(archive, dir);
const platforms: BuildPlatform[] = [];
@@ -355,7 +352,9 @@ async function buildServerRelease() {
if (platforms.length > 0) {
await yarnInstall(dir);
}
platforms.forEach(bundleServerReleaseForPlatform.bind(null, dir));
platforms.forEach(
bundleServerReleaseForPlatform.bind(null, dir, versionNumber),
);
}
function nodeArchFromBuildPlatform(_platform: BuildPlatform): string {
@@ -376,8 +375,58 @@ function nodePlatformFromBuildPlatform(platform: BuildPlatform): string {
}
}
async function installNodeBinary(outputPath: string, platform: BuildPlatform) {
const nodePath = await buildFolder('flipper-node-download-');
const path = await pkgFetch({
arch: nodeArchFromBuildPlatform(platform),
platform: nodePlatformFromBuildPlatform(platform),
output: nodePath,
nodeRange: SUPPORTED_NODE_PLATFORM,
});
await fs.rename(path, outputPath);
}
async function setUpMacBundle(
outputDir: string,
versionNumber: string,
): Promise<{nodePath: string; resourcesPath: string}> {
console.log(`⚙️ Creating Mac bundle in ${outputDir}`);
await fs.copy(path.join(staticDir, 'flipper-server-app-template'), outputDir);
console.log(`⚙️ Writing plist`);
const pListPath = path.join(
outputDir,
'Flipper.app',
'Contents',
'Info.plist',
);
const pListContents = await fs.readFile(pListPath, 'utf-8');
const updatedPlistContents = pListContents.replace(
'{flipper-server-version}',
versionNumber,
);
await fs.writeFile(pListPath, updatedPlistContents, 'utf-8');
const resourcesOutputDir = path.join(
outputDir,
'Flipper.app',
'Contents',
'Resources',
'server',
);
const nodeOutputPath = path.join(
outputDir,
'Flipper.app',
'Contents',
'MacOS',
'node',
);
return {resourcesPath: resourcesOutputDir, nodePath: nodeOutputPath};
}
async function bundleServerReleaseForPlatform(
dir: string,
versionNumber: string,
platform: BuildPlatform,
) {
console.log(`⚙️ Building platform-specific bundle for ${platform}`);
@@ -387,16 +436,23 @@ async function bundleServerReleaseForPlatform(
);
await fs.mkdirp(outputDir);
console.log(`⚙️ Copying from ${dir} to ${outputDir}`);
await fs.copy(dir, outputDir);
let outputPaths = {
nodePath: path.join(outputDir, 'node'),
resourcesPath: outputDir,
};
// On the mac, we need to set up a resource bundle which expects paths
// to be in different places from Linux/Windows bundles.
if (platform === BuildPlatform.MAC_X64) {
outputPaths = await setUpMacBundle(outputDir, versionNumber);
}
console.log(`⚙️ Copying from ${dir} to ${outputPaths.resourcesPath}`);
await fs.copy(dir, outputPaths.resourcesPath);
console.log(`⚙️ Downloading compatible node version`);
await need({
arch: nodeArchFromBuildPlatform(platform),
platform: nodePlatformFromBuildPlatform(platform),
output: path.join(outputDir, 'node'),
nodeRange: SUPPORTED_NODE_PLATFORM,
});
await installNodeBinary(outputPaths.nodePath, platform);
console.log(`✅ Wrote ${platform}-specific server version to ${outputDir}`);
}

View File

@@ -368,11 +368,13 @@ export async function compileMain() {
die(err);
}
}
export function buildFolder(): Promise<string> {
export function buildFolder(
prefix: string = 'flipper-build-',
): Promise<string> {
// eslint-disable-next-line no-console
console.log('Creating build directory');
return new Promise<string>((resolve, reject) => {
tmp.dir({prefix: 'flipper-build-'}, (err, buildFolder) => {
tmp.dir({prefix}, (err, buildFolder) => {
if (err) {
reject(err);
} else {

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>Flipper</string>
<key>CFBundleIconFile</key>
<string>app.icns</string>
<key>CFBundleIdentifier</key>
<string>com.facebook.flipper.server</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Flipper Server</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>{flipper-server-version}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>{flipper-server-version}</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTSDKBuild</key>
<string>12.0</string>
<key>DTSDKName</key>
<string>macosx12.0</string>
<key>DTXcode</key>
<string>1310</string>
<key>DTXcodeBuild</key>
<string>13A1030d</string>
<key>LSHasLocalizedDisplayName</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>10.11.0</string>
<key>NSAppleScriptEnabled</key>
<true/>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
NODE_PATH="${SCRIPT_PATH}/node"
SERVER_RESOURCES="$SCRIPT_PATH/../Resources/server"
cd "$SERVER_RESOURCES" || exit 1
"$NODE_PATH" .

View File

@@ -0,0 +1 @@
APPL????

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>Flipper Server</string>
<key>CFBundleName</key>
<string>Flipper Server</string>
</dict>
</plist>