Skip to content

Commit 16e93bc

Browse files
committed
chore: make script work from any directory, organize steps into main and functions, remove rebuild and only use prebuild
1 parent 341789e commit 16e93bc

File tree

2 files changed

+93
-49
lines changed

2 files changed

+93
-49
lines changed

.github/scripts/libmongocrypt.mjs

Lines changed: 93 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,30 @@ import events from 'node:events';
66
import path from 'node:path';
77
import https from 'node:https';
88
import stream from 'node:stream/promises';
9+
import url from 'node:url';
10+
11+
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
12+
13+
/** Resolves to the root of this repository */
14+
function resolveRoot(...paths) {
15+
return path.resolve(__dirname, '..', '..', ...paths);
16+
}
17+
18+
async function exists(fsPath) {
19+
try {
20+
await fs.access(fsPath);
21+
return true;
22+
} catch {
23+
return false;
24+
}
25+
}
926

1027
async function parseArguments() {
11-
const jsonImport = {
12-
[process.version.split('.').at(0) === 'v16' ? 'assert' : 'with']: { type: 'json' }
13-
};
14-
const pkg = (await import('../../package.json', jsonImport)).default;
15-
const libmongocryptVersion = pkg['mongodb:libmongocrypt'];
28+
const pkg = JSON.parse(await fs.readFile(resolveRoot('package.json'), 'utf8'));
1629

1730
const options = {
1831
gitURL: { short: 'u', type: 'string', default: 'https://github.com/mongodb/libmongocrypt.git' },
19-
libVersion: { short: 'l', type: 'string', default: libmongocryptVersion },
32+
libVersion: { short: 'l', type: 'string', default: pkg['mongodb:libmongocrypt'] },
2033
clean: { short: 'c', type: 'boolean', default: false },
2134
build: { short: 'b', type: 'boolean', default: false },
2235
help: { short: 'h', type: 'boolean', default: false }
@@ -44,44 +57,32 @@ async function parseArguments() {
4457
/** `xtrace` style command runner, uses spawn so that stdio is inherited */
4558
async function run(command, args = [], options = {}) {
4659
console.error(`+ ${command} ${args.join(' ')}`, options.cwd ? `(in: ${options.cwd})` : '');
47-
await events.once(child_process.spawn(command, args, { stdio: 'inherit', ...options }), 'exit');
60+
await events.once(
61+
child_process.spawn(command, args, { stdio: 'inherit', cwd: resolveRoot('.'), ...options }),
62+
'exit'
63+
);
4864
}
4965

5066
/** CLI flag maker: `toFlags({a: 1, b: 2})` yields `['-a=1', '-b=2']` */
5167
function toFlags(object) {
5268
return Array.from(Object.entries(object)).map(([k, v]) => `-${k}=${v}`);
5369
}
5470

55-
const args = await parseArguments();
56-
const libmongocryptRoot = path.resolve('_libmongocrypt');
57-
58-
const currentLibMongoCryptBranch = await fs
59-
.readFile(path.join(libmongocryptRoot, '.git', 'HEAD'), 'utf8')
60-
.catch(() => '');
61-
const libmongocryptAlreadyClonedAndCheckedOut = currentLibMongoCryptBranch
62-
.trim()
63-
.endsWith(`r-${args.libmongocrypt.ref}`);
64-
65-
if (args.build && (args.clean || !libmongocryptAlreadyClonedAndCheckedOut)) {
66-
console.error('fetching libmongocrypt...', args.libmongocrypt);
71+
export async function cloneLibMongoCrypt(libmongocryptRoot, { url, ref }) {
72+
console.error('fetching libmongocrypt...', { url, ref });
6773
await fs.rm(libmongocryptRoot, { recursive: true, force: true });
68-
await run('git', ['clone', args.libmongocrypt.url, libmongocryptRoot]);
69-
await run('git', ['fetch', '--tags'], { cwd: libmongocryptRoot });
70-
await run('git', ['checkout', args.libmongocrypt.ref, '-b', `r-${args.libmongocrypt.ref}`], {
71-
cwd: libmongocryptRoot
72-
});
74+
await run('git', ['clone', url, libmongocryptRoot]);
75+
if (ref !== 'latest') {
76+
// Support "latest" as leaving the clone as-is so whatever the default branch name is works
77+
await run('git', ['fetch', '--tags'], { cwd: libmongocryptRoot });
78+
await run('git', ['checkout', ref, '-b', `r-${ref}`], { cwd: libmongocryptRoot });
79+
}
7380
}
7481

75-
const libmongocryptBuiltVersion = await fs
76-
.readFile(path.join(libmongocryptRoot, 'VERSION_CURRENT'), 'utf8')
77-
.catch(() => '');
78-
const libmongocryptAlreadyBuilt = libmongocryptBuiltVersion.trim() === args.libmongocrypt.ref;
79-
80-
if (args.build && (args.clean || !libmongocryptAlreadyBuilt)) {
81-
console.error('building libmongocrypt...\n', args.libmongocrypt);
82+
export async function buildLibMongoCrypt(libmongocryptRoot, nodeDepsRoot) {
83+
console.error('building libmongocrypt...');
8284

83-
const nodeDepsRoot = path.resolve('deps');
84-
const nodeBuildRoot = path.resolve(nodeDepsRoot, 'tmp', 'libmongocrypt-build');
85+
const nodeBuildRoot = resolveRoot(nodeDepsRoot, 'tmp', 'libmongocrypt-build');
8586

8687
await fs.rm(nodeBuildRoot, { recursive: true, force: true });
8788
await fs.mkdir(nodeBuildRoot, { recursive: true });
@@ -137,14 +138,14 @@ if (args.build && (args.clean || !libmongocryptAlreadyBuilt)) {
137138
});
138139
}
139140

140-
if (!args.build) {
141+
export async function downloadLibMongoCrypt(nodeDepsRoot, { ref }) {
141142
const downloadURL =
142-
args.libmongocrypt.ref === 'latest'
143+
ref === 'latest'
143144
? 'https://mciuploads.s3.amazonaws.com/libmongocrypt/all/master/latest/libmongocrypt-all.tar.gz'
144-
: `https://mciuploads.s3.amazonaws.com/libmongocrypt/all/${args.libmongocrypt.ref}/libmongocrypt-all.tar.gz`;
145+
: `https://mciuploads.s3.amazonaws.com/libmongocrypt/all/${ref}/libmongocrypt-all.tar.gz`;
145146

146147
console.error('downloading libmongocrypt...', downloadURL);
147-
const destination = `_libmongocrypt-${args.libmongocrypt.ref}`;
148+
const destination = resolveRoot(`_libmongocrypt-${ref}`);
148149

149150
await fs.rm(destination, { recursive: true, force: true });
150151
await fs.mkdir(destination);
@@ -159,12 +160,15 @@ if (!args.build) {
159160
['win32-x64']: 'windows-test'
160161
};
161162

162-
const platform = platformMatrix[`${process.platform}-${process.arch}`];
163-
if (platform == null) throw new Error(`${process.platform}-${process.arch}`);
163+
const detectedPlatform = `${process.platform}-${process.arch}`;
164+
const prebuild = platformMatrix[detectedPlatform];
165+
if (prebuild == null) throw new Error(`Unsupported: ${detectedPlatform}`);
164166

165-
const unzip = child_process.spawn('tar', ['-xz', '-C', destination, `${platform}/nocrypto`], {
166-
stdio: ['pipe']
167-
});
167+
console.error(`Platform: ${detectedPlatform} Prebuild: ${prebuild}`);
168+
169+
const unzipArgs = ['-xzv', '-C', destination, `${prebuild}/nocrypto`];
170+
console.error(`+ tar ${unzipArgs.join(' ')}`);
171+
const unzip = child_process.spawn('tar', unzipArgs, { stdio: ['pipe', 'inherit'] });
168172

169173
const [response] = await events.once(https.get(downloadURL), 'response');
170174

@@ -174,12 +178,53 @@ if (!args.build) {
174178

175179
console.error(`downloaded libmongocrypt in ${(end - start) / 1000} secs...`);
176180

177-
await fs.rm('deps', { recursive: true, force: true });
178-
await fs.cp(path.join(destination, platform, 'nocrypto'), 'deps', { recursive: true });
179-
if (await fs.access(path.join('deps', 'lib64')).then(() => true, () => false)) {
180-
await fs.rename(path.join('deps', 'lib64'), path.join('deps', 'lib'));
181+
await fs.rm(nodeDepsRoot, { recursive: true, force: true });
182+
await fs.cp(resolveRoot(destination, prebuild, 'nocrypto'), nodeDepsRoot, { recursive: true });
183+
if (await exists(path.join(nodeDepsRoot, 'lib64'))) {
184+
await fs.rename(path.join(nodeDepsRoot, 'lib64'), path.join(nodeDepsRoot, 'lib'));
181185
}
182186
}
183187

184-
await run('npm', ['install', '--ignore-scripts']);
185-
await run('npm', ['run', 'rebuild'], { env: { ...process.env, BUILD_TYPE: 'static' } });
188+
async function main() {
189+
const { libmongocrypt, build, clean } = await parseArguments();
190+
191+
const nodeDepsDir = resolveRoot('deps');
192+
193+
if (build) {
194+
const libmongocryptCloneDir = resolveRoot('_libmongocrypt');
195+
196+
const currentLibMongoCryptBranch = await fs
197+
.readFile(path.join(libmongocryptCloneDir, '.git', 'HEAD'), 'utf8')
198+
.catch(() => '');
199+
const isClonedAndCheckedOut = currentLibMongoCryptBranch
200+
.trim()
201+
.endsWith(`r-${libmongocrypt.ref}`);
202+
203+
if (clean || !isClonedAndCheckedOut) {
204+
await cloneLibMongoCrypt(libmongocryptCloneDir, libmongocrypt);
205+
}
206+
207+
const libmongocryptBuiltVersion = await fs
208+
.readFile(path.join(libmongocryptCloneDir, 'VERSION_CURRENT'), 'utf8')
209+
.catch(() => '');
210+
const isBuilt = libmongocryptBuiltVersion.trim() === libmongocrypt.ref;
211+
212+
if (clean || !isBuilt) {
213+
await buildLibMongoCrypt(libmongocryptCloneDir, nodeDepsDir);
214+
}
215+
} else {
216+
// Download
217+
await downloadLibMongoCrypt(nodeDepsDir, libmongocrypt);
218+
}
219+
220+
await fs.rm(resolveRoot('build'), { force: true, recursive: true });
221+
await fs.rm(resolveRoot('prebuilds'), { force: true, recursive: true });
222+
223+
// install with "ignore-scripts" so that we don't attempt to download a prebuild
224+
await run('npm', ['install', '--ignore-scripts']);
225+
// The prebuild command will make both a .node file in `./build` (local and CI testing will run on current code)
226+
// it will also produce `./prebuild/xx.tgz`. prebuild has GH upload functionality.
227+
await run('npm', ['run', 'prebuild']);
228+
}
229+
230+
await main();

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
"check:clang-format": "clang-format --style=file:.clang-format --dry-run --Werror addon/*",
2323
"test": "mocha test",
2424
"prepare": "tsc",
25-
"rebuild": "prebuild --compile",
2625
"prebuild": "prebuild --runtime napi --strip --verbose --all"
2726
},
2827
"author": {

0 commit comments

Comments
 (0)