Skip to content

Commit

Permalink
feat: update to node 22 SEA
Browse files Browse the repository at this point in the history
  • Loading branch information
bobbyg603 committed Jun 24, 2024
1 parent ed4a660 commit d41a905
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 29 deletions.
8 changes: 5 additions & 3 deletions bin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { basename, join } from 'node:path';
import { safeRemoveTmp, tmpDir } from '../src/tmp';
import { uploadSymbolFiles } from '../src/upload';
import { CommandLineDefinition, argDefinitions, usageDefinitions } from './command-line-definitions';
import { importNodeDumpSyms } from './preload';

(async () => {
let {
Expand Down Expand Up @@ -110,14 +111,15 @@ import { CommandLineDefinition, argDefinitions, usageDefinitions } from './comma
if (dumpSyms) {
try {
// @ts-ignore: Cannot find module
const nodeDumpSyms = (await import('node-dump-syms')).dumpSyms;
const nodeDumpSyms = (await importNodeDumpSyms()).dumpSyms;
symbolFilePaths = symbolFilePaths.map(file => {
console.log(`Dumping syms for ${file}...`);
const symFile = join(tmpDir, `${getSymFileBaseName(file)}.sym`);
nodeDumpSyms(file, symFile);
return symFile;
});
} catch (cause) {
console.error(cause); // TODO BG remove
throw new Error('Can\'t run dump_syms! Please ensure node-dump-syms is installed https://github.com/BugSplat-Git/node-dump-syms', { cause });
}
}
Expand Down Expand Up @@ -158,7 +160,7 @@ async function getCommandLineOptions(argDefinitions: Array<CommandLineDefinition
const options = commandLineArgs(argDefinitions);
let { database, application, version } = options;
let packageJson;

if (!database || !application || !version) {
const packageJsonPath = './package.json';
packageJson = await fileExists(packageJsonPath) ? JSON.parse((await readFile(packageJsonPath)).toString()) : null;
Expand Down Expand Up @@ -189,7 +191,7 @@ async function getCommandLineOptions(argDefinitions: Array<CommandLineDefinition
function getSymFileBaseName(file: string): string {
const linuxSoExtensionPattern = /\.so\.?.*$/gm;
const fileNoExt = file.split('.')[0];
return linuxSoExtensionPattern.test(file) ? basename(file) : basename(fileNoExt);
return linuxSoExtensionPattern.test(file) ? basename(file) : basename(fileNoExt);
}

function logHelpAndExit() {
Expand Down
46 changes: 46 additions & 0 deletions bin/preload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
import { mkdir, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { getAsset, getAssetAsBlob, isSea } from 'node:sea';
import type { dumpSyms } from 'node-dump-syms';
import { createRequire } from "node:module";

export async function importNodeDumpSyms(): Promise<{
dumpSyms: typeof dumpSyms;
}> {
if (!isSea()) {
return import('node-dump-syms');
}

const nativeModuleDir = join(tmpdir(), 'bugsplat');
if (!existsSync(nativeModuleDir)) {
await mkdir(nativeModuleDir, { recursive: true });
}

const nativeModuleStream = getAssetAsBlob('node-dump-syms.js').stream();
const targetPath = join(nativeModuleDir, 'node-dump-syms.js');
await writeFile(targetPath, nativeModuleStream);

// Node SEA's default require is for embedded modules
// Use createRequire because it's compatible with loading modules from the file system
// https://nodejs.org/api/single-executable-applications.html#requireid-in-the-injected-main-script-is-not-file-based
return createRequire(__filename)(targetPath);
};

export function findCompressionWorkerPath(): string {
if (!isSea()) {
return join(__dirname, 'compression.js');
}

const nativeModuleDir = join(tmpdir(), 'bugsplat');
if (!existsSync(nativeModuleDir)) {
mkdirSync(nativeModuleDir, { recursive: true });
}

const nativeModuleStream = getAsset('compression.js');
const targetPath = join(nativeModuleDir, 'compression.js');
writeFileSync(targetPath, Buffer.from((nativeModuleStream)));

return targetPath;
}
55 changes: 46 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 6 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
"clean": "rimraf ./dist",
"prebuild": "npm run clean",
"build": "tsc",
"prebundle": "npm run clean",
"bundle": "ncc build ./bin/index.ts -o ./dist && bpkg ./src/compression.js ./dist/compression.js",
"prerelease": "npm run build",
"release": "npm publish --access public",
"prepkg:linux": "npm run build",
"pkg:linux": "npx pkg package.json --targets node18-linux-x64 --output ./pkg/symbol-upload-linux",
"prepkg:macos": "npm run build",
"pkg:macos": "npx pkg package.json --targets node18-macos-x64 --output ./pkg/symbol-upload-macos",
"prepkg:macos": "npm run bundle && bpkg ./node_modules/node-dump-syms ./dist/node-dump-syms.js",
"pkg:macos": "node --experimental-sea-config sea-config.json && cp $(command -v node) ./dist/symbol-upload && codesign --remove-signature ./dist/symbol-upload && npx postject ./dist/symbol-upload NODE_SEA_BLOB ./dist/sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 --macho-segment-name NODE_SEA && codesign --sign - ./dist/symbol-upload",
"prepkg:windows": "npm run build",
"pkg:windows": "npx pkg package.json --targets node18-win-x64 --output ./pkg/symbol-upload-windows",
"act": "act --secret-file .env"
Expand All @@ -50,24 +52,17 @@
"url": "https://github.com/BugSplat-Git/symbol-upload/issues"
},
"homepage": "https://github.com/BugSplat-Git/symbol-upload#readme",
"pkg": {
"scripts": "./dist/**/*.js",
"compress": "GZip",
"assets": [
"package.json",
"node_modules/node-dump-syms/dist/native/index.node"
]
},
"devDependencies": {
"@types/archiver": "^6.0.2",
"@types/command-line-args": "^5.2.0",
"@types/command-line-usage": "^5.0.2",
"@types/firstline": "^2.0.2",
"@types/glob": "^8.1.0",
"@types/jasmine": "^4.3.1",
"@types/node": "^18.15.10",
"@types/node": "^20.14.8",
"@types/promise-retry": "^1.1.4",
"@types/workerpool": "^6.4.4",
"bpkg": "^0.9.2",
"copyfiles": "^2.4.1",
"dotenv": "^10.0.0",
"extract-zip": "^2.0.1",
Expand Down
9 changes: 9 additions & 0 deletions sea-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"main": "dist/index.js",
"output": "dist/sea-prep.blob",
"disableExperimentalSEAWarning": true,
"assets": {
"node-dump-syms.js": "dist/node-dump-syms.js",
"compression.js": "dist/compression.js"
}
}
11 changes: 5 additions & 6 deletions src/upload.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { ApiClient, SymbolsApiClient, VersionsApiClient } from "@bugsplat/js-api-client";
import { availableParallelism, cpus } from "node:os";
import { basename, extname, join } from "node:path";
import { availableParallelism } from "node:os";
import { basename, extname } from "node:path";
import prettyBytes from "pretty-bytes";
import { pool } from "workerpool";
import { findCompressionWorkerPath } from "../bin/preload";
import { getDSymFileInfos } from './dsym';
import { tryGetElfUUID } from './elf';
import { SymbolFileInfo } from './info';
import { tryGetPdbGuid, tryGetPeGuid } from './pdb';
import { getSymFileInfo } from './sym';
import { createWorkersFromSymbolFiles } from './worker';

// TODO BG re-enable after moving to node 22
// const maxWorkers = availableParallelism();
const maxWorkers = cpus().length - 1;
const workerPool = pool(join(__dirname, 'compression.js'), { maxWorkers });
const maxWorkers = availableParallelism();
const workerPool = pool(findCompressionWorkerPath(), { maxWorkers });

export async function uploadSymbolFiles(bugsplat: ApiClient, database: string, application: string, version: string, symbolFilePaths: Array<string>) {
console.log(`About to upload symbols for ${database}-${application}-${version}...`);
Expand Down

0 comments on commit d41a905

Please sign in to comment.