From a38b9aa6ed8d00c3ce276ea150204737d451b582 Mon Sep 17 00:00:00 2001 From: gagik Date: Tue, 23 Sep 2025 17:30:14 +0200 Subject: [PATCH 1/3] feat(mongodb-runner): add downloadDir option There are cases where the place we want to manage the place to download and store binaries ourselves. For example in mongosh this is useful in making sure each `mongodb-runner` has its own temporary directory for all other files but refers to only 1 download directory for the database binaries. --- packages/mongodb-runner/README.md | 1 + packages/mongodb-runner/src/cli.ts | 5 +++ .../mongodb-runner/src/mongocluster.spec.ts | 35 +++++++++++++++++++ packages/mongodb-runner/src/mongocluster.ts | 13 +++++-- 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/packages/mongodb-runner/README.md b/packages/mongodb-runner/README.md index 17aef942..03954e19 100644 --- a/packages/mongodb-runner/README.md +++ b/packages/mongodb-runner/README.md @@ -37,6 +37,7 @@ Options: --version MongoDB server version to use [string] --logDir Directory to store server log files in [string] --binDir Directory containing mongod/mongos binaries [string] + --downloadDir Directory to store downloaded MongoDB versions in [string] --tmpDir Directory for temporary files [string] [default: "/tmp"] --runnerDir Directory for storing cluster metadata [string] [default: "/home/addaleax/.mongodb/runner2"] diff --git a/packages/mongodb-runner/src/cli.ts b/packages/mongodb-runner/src/cli.ts index 0e7c23e2..6fdf2c6f 100644 --- a/packages/mongodb-runner/src/cli.ts +++ b/packages/mongodb-runner/src/cli.ts @@ -49,6 +49,11 @@ import * as utilities from './index'; default: os.tmpdir(), describe: 'Directory for temporary files', }) + .option('downloadDir', { + type: 'string', + describe: + 'Directory for downloading and caching MongoDB binaries (uses tmpDir if not specified)', + }) .option('runnerDir', { type: 'string', default: defaultRunnerDir, diff --git a/packages/mongodb-runner/src/mongocluster.spec.ts b/packages/mongodb-runner/src/mongocluster.spec.ts index 156b3ea7..4f17611b 100644 --- a/packages/mongodb-runner/src/mongocluster.spec.ts +++ b/packages/mongodb-runner/src/mongocluster.spec.ts @@ -4,6 +4,7 @@ import { promises as fs } from 'fs'; import path from 'path'; import os from 'os'; import createDebug from 'debug'; +import sinon from 'sinon'; if (process.env.CI) { createDebug.enable('mongodb-runner,mongodb-downloader'); @@ -36,6 +37,40 @@ describe('MongoCluster', function () { afterEach(async function () { await cluster?.close(); + sinon.restore(); + }); + + it('can use custom downloadDir option for binary downloads', async function () { + const customDownloadDir = path.join(tmpDir, 'custom-downloads'); + await fs.mkdir(customDownloadDir, { recursive: true }); + + sinon + .stub(MongoCluster, 'downloadMongoDb' as any) + .resolves(customDownloadDir); + + try { + cluster = await MongoCluster.start({ + version: '6.x', + topology: 'standalone', + tmpDir, + downloadDir: customDownloadDir, + downloadOptions: { + platform: 'linux', + arch: 'x64', + }, + }); + } catch (err) { + // This will error because no actual binary gets downloaded + } + + expect(MongoCluster['downloadMongoDb']).to.have.been.calledWith( + customDownloadDir, + '6.x', + { + platform: 'linux', + arch: 'x64', + }, + ); }); it('can spawn a 6.x standalone mongod', async function () { diff --git a/packages/mongodb-runner/src/mongocluster.ts b/packages/mongodb-runner/src/mongocluster.ts index 406377f0..18f35b8c 100644 --- a/packages/mongodb-runner/src/mongocluster.ts +++ b/packages/mongodb-runner/src/mongocluster.ts @@ -17,6 +17,7 @@ export interface MongoClusterOptions secondaries?: number; shards?: number; version?: string; + downloadDir?: string; downloadOptions?: DownloadOptions; } @@ -30,6 +31,14 @@ export class MongoCluster { /* see .start() */ } + private static downloadMongoDb( + tmpdir: string, + targetVersionSemverSpecifier?: string | undefined, + options?: DownloadOptions | undefined, + ): Promise { + return downloadMongoDb(tmpdir, targetVersionSemverSpecifier, options); + } + serialize(): unknown /* JSON-serializable */ { return { topology: this.topology, @@ -84,8 +93,8 @@ export class MongoCluster { const cluster = new MongoCluster(); cluster.topology = options.topology; if (!options.binDir) { - options.binDir = await downloadMongoDb( - options.tmpDir, + options.binDir = await MongoCluster.downloadMongoDb( + options.downloadDir ?? options.tmpDir, options.version, options.downloadOptions, ); From 4be25dd6b869a110b9b03c91cfe3cd5e6da724eb Mon Sep 17 00:00:00 2001 From: gagik Date: Tue, 23 Sep 2025 17:35:49 +0200 Subject: [PATCH 2/3] chore: remove folder creation --- packages/mongodb-runner/src/mongocluster.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/mongodb-runner/src/mongocluster.spec.ts b/packages/mongodb-runner/src/mongocluster.spec.ts index 4f17611b..9447a979 100644 --- a/packages/mongodb-runner/src/mongocluster.spec.ts +++ b/packages/mongodb-runner/src/mongocluster.spec.ts @@ -42,7 +42,6 @@ describe('MongoCluster', function () { it('can use custom downloadDir option for binary downloads', async function () { const customDownloadDir = path.join(tmpDir, 'custom-downloads'); - await fs.mkdir(customDownloadDir, { recursive: true }); sinon .stub(MongoCluster, 'downloadMongoDb' as any) From de48b4793e865f6c1369935e470422b449821311 Mon Sep 17 00:00:00 2001 From: Gagik Amaryan Date: Wed, 24 Sep 2025 11:43:58 +0200 Subject: [PATCH 3/3] Apply suggestion from @addaleax Co-authored-by: Anna Henningsen --- packages/mongodb-runner/src/mongocluster.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mongodb-runner/src/mongocluster.ts b/packages/mongodb-runner/src/mongocluster.ts index 18f35b8c..4d698087 100644 --- a/packages/mongodb-runner/src/mongocluster.ts +++ b/packages/mongodb-runner/src/mongocluster.ts @@ -93,7 +93,7 @@ export class MongoCluster { const cluster = new MongoCluster(); cluster.topology = options.topology; if (!options.binDir) { - options.binDir = await MongoCluster.downloadMongoDb( + options.binDir = await this.downloadMongoDb( options.downloadDir ?? options.tmpDir, options.version, options.downloadOptions,