From ce72c8be45327014c4a3e0f794a4e5b30d2c6873 Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Tue, 21 Jan 2025 16:15:31 +0000 Subject: [PATCH 1/6] download and test with the latest release --- .../compass-smoke-tests/src/build-info.ts | 14 +++- packages/compass-smoke-tests/src/cli.ts | 83 +++++++++++++++++++ packages/compass-smoke-tests/src/downloads.ts | 12 ++- 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/packages/compass-smoke-tests/src/build-info.ts b/packages/compass-smoke-tests/src/build-info.ts index 44b8846925a..124a4bd0130 100644 --- a/packages/compass-smoke-tests/src/build-info.ts +++ b/packages/compass-smoke-tests/src/build-info.ts @@ -8,6 +8,8 @@ import { type PackageKind } from './packages'; import { type SmokeTestsContext } from './context'; import { pick } from 'lodash'; +const SUPPORTED_CHANNELS = ['dev', 'beta', 'stable'] as const; + function assertObjectHasKeys( obj: unknown, name: string, @@ -25,13 +27,21 @@ function assertObjectHasKeys( // subsets of the hadron-build info result -export const commonKeys = ['productName'] as const; -export type CommonBuildInfo = Record; +export const commonKeys = ['productName', 'channel'] as const; +export type CommonBuildInfo = Record & { + channel: 'dev' | 'beta' | 'stable'; +}; export function assertCommonBuildInfo( buildInfo: unknown ): asserts buildInfo is CommonBuildInfo { assertObjectHasKeys(buildInfo, 'buildInfo', commonKeys); + assert( + SUPPORTED_CHANNELS.includes((buildInfo as any).channel), + `Expected ${(buildInfo as any).channel} to be in ${SUPPORTED_CHANNELS.join( + ',' + )}` + ); } export const windowsFilenameKeys = [ diff --git a/packages/compass-smoke-tests/src/cli.ts b/packages/compass-smoke-tests/src/cli.ts index bba6710ec44..4aa4395e443 100755 --- a/packages/compass-smoke-tests/src/cli.ts +++ b/packages/compass-smoke-tests/src/cli.ts @@ -145,6 +145,60 @@ async function getTestSubject( } } +type Arch = 'arm64' | 'x64'; + +type PlatformShortName = + | 'darwin-arm64' + | 'darwin-x64' + | 'windows' + | 'linux_deb' + | 'linux_rpm'; + +function getPlatformShortName( + arch: Arch, + kind: PackageKind +): PlatformShortName { + if (arch === 'arm64') { + if (kind === 'osx_dmg' || kind === 'osx_zip') { + return 'darwin-arm64'; + } + } + if (arch === 'x64') { + if (kind === 'osx_dmg' || kind === 'osx_zip') { + return 'darwin-x64'; + } + if ( + kind === 'windows_setup' || + kind === 'windows_msi' || + kind === 'windows_zip' + ) { + return 'windows'; + } + if (kind === 'linux_deb' || kind === 'linux_tar') { + return 'linux_deb'; + } + if (kind === 'linux_rpm' || kind === 'rhel_tar') { + return 'linux_rpm'; + } + } + + throw new Error(`Unsupported arch/kind combo: ${arch}/${kind}`); +} + +async function getLatestRelease( + channel: 'dev' | 'beta' | 'stable', + arch: Arch, + kind: PackageKind, + forceDownload?: boolean +): Promise { + const shortName = getPlatformShortName(arch, kind); + + return await downloadFile({ + url: `http://compass.mongodb.com/api/v2/download/latest/compass/${channel}/${shortName}`, + clearCache: forceDownload, + }); +} + function getInstaller(kind: PackageKind) { if (kind === 'osx_dmg') { return installMacDMG; @@ -179,6 +233,8 @@ async function run() { const install = getInstaller(kind); try { + console.log('downgrade from this package to latest release'); + const appName = buildInfo.productName; const { appPath, uninstall } = install({ @@ -196,6 +252,33 @@ async function run() { console.log('Cleaning up sandbox'); fs.rmSync(context.sandboxPath, { recursive: true }); } + + console.log('update from latest release to this package'); + const releasepath = await getLatestRelease( + buildInfo.channel, + context.arch, + kind, + context.forceDownload + ); + + try { + const appName = buildInfo.productName; + + const { appPath, uninstall } = install({ + appName, + filepath: releasepath, + destinationPath: context.sandboxPath, + }); + + try { + runTest({ appName, appPath }); + } finally { + await uninstall(); + } + } finally { + console.log('Cleaning up sandbox'); + fs.rmSync(context.sandboxPath, { recursive: true }); + } } type RunTestOptions = { diff --git a/packages/compass-smoke-tests/src/downloads.ts b/packages/compass-smoke-tests/src/downloads.ts index 49ed7815cf8..b8d1e76051b 100644 --- a/packages/compass-smoke-tests/src/downloads.ts +++ b/packages/compass-smoke-tests/src/downloads.ts @@ -7,7 +7,7 @@ import { ensureDownloadsDirectory } from './directories'; type DownloadFileOptions = { url: string; - targetFilename: string; + targetFilename?: string; clearCache?: boolean; }; @@ -18,6 +18,14 @@ export async function downloadFile({ }: DownloadFileOptions): Promise { const response = await fetch(url); + if (!targetFilename) { + // if no filename was specified, work out the filename based on the final + // URL the way a browser would + targetFilename = path.basename(new URL(response.url).pathname); + } + + assert(targetFilename, 'Expected a filename'); + const etag = response.headers.get('etag'); assert(etag, 'Expected an ETag header'); const cleanEtag = etag.match(/[0-9a-fA-F]/g)?.join(''); @@ -50,5 +58,7 @@ export async function downloadFile({ fs.createWriteStream(outputPath) ); + console.log(outputPath); + return outputPath; } From c07abf31d2c50dd73682879fe0d539e7ac52575a Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Wed, 22 Jan 2025 09:05:47 +0000 Subject: [PATCH 2/6] Update packages/compass-smoke-tests/src/build-info.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kræn Hansen --- packages/compass-smoke-tests/src/build-info.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/compass-smoke-tests/src/build-info.ts b/packages/compass-smoke-tests/src/build-info.ts index 124a4bd0130..23b68ab0aa1 100644 --- a/packages/compass-smoke-tests/src/build-info.ts +++ b/packages/compass-smoke-tests/src/build-info.ts @@ -9,6 +9,7 @@ import { type SmokeTestsContext } from './context'; import { pick } from 'lodash'; const SUPPORTED_CHANNELS = ['dev', 'beta', 'stable'] as const; +type Channel = typeof SUPPORTED_CHANNELS[number]; function assertObjectHasKeys( obj: unknown, From 9488ffd5f35c2c5b4be24e04b94fc35accaa8ac2 Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Wed, 22 Jan 2025 09:06:12 +0000 Subject: [PATCH 3/6] Update packages/compass-smoke-tests/src/build-info.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kræn Hansen --- packages/compass-smoke-tests/src/build-info.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/compass-smoke-tests/src/build-info.ts b/packages/compass-smoke-tests/src/build-info.ts index 23b68ab0aa1..477c439e677 100644 --- a/packages/compass-smoke-tests/src/build-info.ts +++ b/packages/compass-smoke-tests/src/build-info.ts @@ -30,7 +30,7 @@ function assertObjectHasKeys( export const commonKeys = ['productName', 'channel'] as const; export type CommonBuildInfo = Record & { - channel: 'dev' | 'beta' | 'stable'; + channel: Channel; }; export function assertCommonBuildInfo( From 866c367cc05b52a805a26cc9ba1abf78209971ec Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Wed, 22 Jan 2025 09:11:09 +0000 Subject: [PATCH 4/6] different cast --- packages/compass-smoke-tests/src/build-info.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/compass-smoke-tests/src/build-info.ts b/packages/compass-smoke-tests/src/build-info.ts index 477c439e677..bb9e24e6760 100644 --- a/packages/compass-smoke-tests/src/build-info.ts +++ b/packages/compass-smoke-tests/src/build-info.ts @@ -38,10 +38,10 @@ export function assertCommonBuildInfo( ): asserts buildInfo is CommonBuildInfo { assertObjectHasKeys(buildInfo, 'buildInfo', commonKeys); assert( - SUPPORTED_CHANNELS.includes((buildInfo as any).channel), - `Expected ${(buildInfo as any).channel} to be in ${SUPPORTED_CHANNELS.join( - ',' - )}` + SUPPORTED_CHANNELS.includes((buildInfo as { channel: Channel }).channel), + `Expected ${ + (buildInfo as { channel: Channel }).channel + } to be in ${SUPPORTED_CHANNELS.join(',')}` ); } From 07c5ad05f39adfb69eb20551f7e2d3c00c9804ad Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Wed, 22 Jan 2025 13:34:03 +0000 Subject: [PATCH 5/6] no need to fret about the correct filename --- packages/compass-smoke-tests/src/cli.ts | 55 +---------- packages/compass-smoke-tests/src/downloads.ts | 10 +- packages/compass-smoke-tests/src/releases.ts | 91 +++++++++++++++++++ 3 files changed, 93 insertions(+), 63 deletions(-) create mode 100644 packages/compass-smoke-tests/src/releases.ts diff --git a/packages/compass-smoke-tests/src/cli.ts b/packages/compass-smoke-tests/src/cli.ts index 4aa4395e443..63ecebf0189 100755 --- a/packages/compass-smoke-tests/src/cli.ts +++ b/packages/compass-smoke-tests/src/cli.ts @@ -16,6 +16,7 @@ import { import { createSandbox } from './directories'; import { downloadFile } from './downloads'; import { type PackageKind, SUPPORTED_PACKAGES } from './packages'; +import { getLatestRelease } from './releases'; import { type SmokeTestsContext } from './context'; import { installMacZIP } from './installers/mac-zip'; @@ -145,60 +146,6 @@ async function getTestSubject( } } -type Arch = 'arm64' | 'x64'; - -type PlatformShortName = - | 'darwin-arm64' - | 'darwin-x64' - | 'windows' - | 'linux_deb' - | 'linux_rpm'; - -function getPlatformShortName( - arch: Arch, - kind: PackageKind -): PlatformShortName { - if (arch === 'arm64') { - if (kind === 'osx_dmg' || kind === 'osx_zip') { - return 'darwin-arm64'; - } - } - if (arch === 'x64') { - if (kind === 'osx_dmg' || kind === 'osx_zip') { - return 'darwin-x64'; - } - if ( - kind === 'windows_setup' || - kind === 'windows_msi' || - kind === 'windows_zip' - ) { - return 'windows'; - } - if (kind === 'linux_deb' || kind === 'linux_tar') { - return 'linux_deb'; - } - if (kind === 'linux_rpm' || kind === 'rhel_tar') { - return 'linux_rpm'; - } - } - - throw new Error(`Unsupported arch/kind combo: ${arch}/${kind}`); -} - -async function getLatestRelease( - channel: 'dev' | 'beta' | 'stable', - arch: Arch, - kind: PackageKind, - forceDownload?: boolean -): Promise { - const shortName = getPlatformShortName(arch, kind); - - return await downloadFile({ - url: `http://compass.mongodb.com/api/v2/download/latest/compass/${channel}/${shortName}`, - clearCache: forceDownload, - }); -} - function getInstaller(kind: PackageKind) { if (kind === 'osx_dmg') { return installMacDMG; diff --git a/packages/compass-smoke-tests/src/downloads.ts b/packages/compass-smoke-tests/src/downloads.ts index b8d1e76051b..37833568818 100644 --- a/packages/compass-smoke-tests/src/downloads.ts +++ b/packages/compass-smoke-tests/src/downloads.ts @@ -7,7 +7,7 @@ import { ensureDownloadsDirectory } from './directories'; type DownloadFileOptions = { url: string; - targetFilename?: string; + targetFilename: string; clearCache?: boolean; }; @@ -18,14 +18,6 @@ export async function downloadFile({ }: DownloadFileOptions): Promise { const response = await fetch(url); - if (!targetFilename) { - // if no filename was specified, work out the filename based on the final - // URL the way a browser would - targetFilename = path.basename(new URL(response.url).pathname); - } - - assert(targetFilename, 'Expected a filename'); - const etag = response.headers.get('etag'); assert(etag, 'Expected an ETag header'); const cleanEtag = etag.match(/[0-9a-fA-F]/g)?.join(''); diff --git a/packages/compass-smoke-tests/src/releases.ts b/packages/compass-smoke-tests/src/releases.ts new file mode 100644 index 00000000000..e2ce93c0054 --- /dev/null +++ b/packages/compass-smoke-tests/src/releases.ts @@ -0,0 +1,91 @@ +import { downloadFile } from './downloads'; +import { type PackageKind } from './packages'; + +type Arch = 'arm64' | 'x64'; + +type PlatformShortName = + | 'darwin-arm64' + | 'darwin-x64' + | 'windows' + | 'linux_deb' + | 'linux_rpm'; + +function getPlatformShortName( + arch: Arch, + kind: PackageKind +): PlatformShortName { + if (arch === 'arm64') { + if (kind === 'osx_dmg' || kind === 'osx_zip') { + return 'darwin-arm64'; + } + } + if (arch === 'x64') { + if (kind === 'osx_dmg' || kind === 'osx_zip') { + return 'darwin-x64'; + } + if ( + kind === 'windows_setup' || + kind === 'windows_msi' || + kind === 'windows_zip' + ) { + return 'windows'; + } + if (kind === 'linux_deb' || kind === 'linux_tar') { + return 'linux_deb'; + } + if (kind === 'linux_rpm' || kind === 'rhel_tar') { + return 'linux_rpm'; + } + } + + throw new Error(`Unsupported arch/kind combo: ${arch}/${kind}`); +} + +type PlatformExtension = 'dmg' | 'exe' | 'deb' | 'rpm'; + +function getPlatformExtension( + arch: Arch, + kind: PackageKind +): PlatformExtension { + if (arch === 'arm64') { + if (kind === 'osx_dmg' || kind === 'osx_zip') { + return 'dmg'; + } + } + if (arch === 'x64') { + if (kind === 'osx_dmg' || kind === 'osx_zip') { + return 'dmg'; + } + if ( + kind === 'windows_setup' || + kind === 'windows_msi' || + kind === 'windows_zip' + ) { + return 'exe'; + } + if (kind === 'linux_deb' || kind === 'linux_tar') { + return 'deb'; + } + if (kind === 'linux_rpm' || kind === 'rhel_tar') { + return 'rpm'; + } + } + + throw new Error(`Unsupported arch/kind combo: ${arch}/${kind}`); +} + +export async function getLatestRelease( + channel: 'dev' | 'beta' | 'stable', + arch: Arch, + kind: PackageKind, + forceDownload?: boolean +): Promise { + const shortName = getPlatformShortName(arch, kind); + const extension = getPlatformExtension(arch, kind); + + return await downloadFile({ + url: `http://compass.mongodb.com/api/v2/download/latest/compass/${channel}/${shortName}`, + targetFilename: `latest-${channel}.${extension}`, + clearCache: forceDownload, + }); +} From e5ff95369c62ea39382b9e6d3b8db33ae3053a3c Mon Sep 17 00:00:00 2001 From: Le Roux Bodenstein Date: Wed, 22 Jan 2025 13:42:52 +0000 Subject: [PATCH 6/6] use debug, not console.log --- packages/compass-smoke-tests/package.json | 1 + packages/compass-smoke-tests/src/build-info.ts | 7 +++++-- packages/compass-smoke-tests/src/cli.ts | 15 +++++++++------ packages/compass-smoke-tests/src/downloads.ts | 10 ++++++---- .../compass-smoke-tests/src/installers/mac-dmg.ts | 6 +++++- .../compass-smoke-tests/src/installers/mac-zip.ts | 6 +++++- 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/compass-smoke-tests/package.json b/packages/compass-smoke-tests/package.json index 23f971f9b6f..46580e74ee7 100644 --- a/packages/compass-smoke-tests/package.json +++ b/packages/compass-smoke-tests/package.json @@ -34,6 +34,7 @@ "@mongodb-js/eslint-config-compass": "^1.2.2", "@mongodb-js/prettier-config-compass": "^1.1.2", "@mongodb-js/tsconfig-compass": "^1.1.2", + "debug": "^4.3.4", "depcheck": "^1.4.1", "eslint": "^7.25.0", "hadron-build": "^25.6.2", diff --git a/packages/compass-smoke-tests/src/build-info.ts b/packages/compass-smoke-tests/src/build-info.ts index 703fb97ba0f..3a6d702cc4e 100644 --- a/packages/compass-smoke-tests/src/build-info.ts +++ b/packages/compass-smoke-tests/src/build-info.ts @@ -2,12 +2,15 @@ import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; +import createDebug from 'debug'; import { handler as writeBuildInfo } from 'hadron-build/commands/info'; import { type PackageKind } from './packages'; import { type SmokeTestsContext } from './context'; import { pick } from 'lodash'; +const debug = createDebug('compass-smoke-tests:build-info'); + const SUPPORTED_CHANNELS = ['dev', 'beta', 'stable'] as const; type Channel = typeof SUPPORTED_CHANNELS[number]; @@ -242,11 +245,11 @@ export function writeAndReadPackageDetails( arch: context.arch, out: path.resolve(context.sandboxPath, 'target.json'), }; - console.log({ infoArgs }); + debug({ infoArgs }); // These are known environment variables that will affect the way // writeBuildInfo works. Log them as a reminder and for our own sanity - console.log( + debug( 'info env vars', pick(process.env, [ 'HADRON_DISTRIBUTION', diff --git a/packages/compass-smoke-tests/src/cli.ts b/packages/compass-smoke-tests/src/cli.ts index be06ef58f01..cf30245878d 100755 --- a/packages/compass-smoke-tests/src/cli.ts +++ b/packages/compass-smoke-tests/src/cli.ts @@ -6,6 +6,7 @@ import path from 'node:path'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import { pick } from 'lodash'; +import createDebug from 'debug'; import { execute } from './execute'; import { type PackageDetails, @@ -22,6 +23,8 @@ import { installMacDMG } from './installers/mac-dmg'; import { installMacZIP } from './installers/mac-zip'; import { installWindowsZIP } from './installers/windows-zip'; +const debug = createDebug('compass-smoke-tests'); + const SUPPORTED_PLATFORMS = ['win32', 'darwin', 'linux'] as const; const SUPPORTED_ARCHS = ['x64', 'arm64'] as const; @@ -166,9 +169,9 @@ async function run() { sandboxPath: createSandbox(), }; - console.log(`Running tests in ${context.sandboxPath}`); + debug(`Running tests in ${context.sandboxPath}`); - console.log( + debug( 'context', pick(context, [ 'forceDownload', @@ -196,11 +199,11 @@ async function run() { await uninstall(); } } finally { - console.log('Cleaning up sandbox'); + debug('Cleaning up sandbox'); fs.rmSync(context.sandboxPath, { recursive: true }); } - console.log('update from latest release to this package'); + debug('update from latest release to this package'); const releasepath = await getLatestRelease( buildInfo.channel, context.arch, @@ -223,7 +226,7 @@ async function run() { await uninstall(); } } finally { - console.log('Cleaning up sandbox'); + debug('Cleaning up sandbox'); fs.rmSync(context.sandboxPath, { recursive: true }); } } @@ -259,7 +262,7 @@ function runTest({ appName, appPath }: RunTestOptions) { run() .then(function () { - console.log('done'); + debug('done'); }) .catch(function (err) { console.error(err.stack); diff --git a/packages/compass-smoke-tests/src/downloads.ts b/packages/compass-smoke-tests/src/downloads.ts index 37833568818..053fadcfcf7 100644 --- a/packages/compass-smoke-tests/src/downloads.ts +++ b/packages/compass-smoke-tests/src/downloads.ts @@ -3,8 +3,12 @@ import fs from 'node:fs'; import path from 'node:path'; import stream from 'node:stream'; +import createDebug from 'debug'; + import { ensureDownloadsDirectory } from './directories'; +const debug = createDebug('compass-smoke-tests:downloads'); + type DownloadFileOptions = { url: string; targetFilename: string; @@ -33,7 +37,7 @@ export async function downloadFile({ if (clearCache) { fs.rmSync(cacheDirectoryPath, { recursive: true, force: true }); } else { - console.log('Skipped downloading', url, '(cache existed)'); + debug(`Skipped downloading ${url} (cache existed)`); return outputPath; } } @@ -44,13 +48,11 @@ export async function downloadFile({ // Write the response to file assert(response.body, 'Expected a response body'); - console.log('Downloading', url); + debug(`Downloading ${url} to ${outputPath}`); await stream.promises.pipeline( response.body, fs.createWriteStream(outputPath) ); - console.log(outputPath); - return outputPath; } diff --git a/packages/compass-smoke-tests/src/installers/mac-dmg.ts b/packages/compass-smoke-tests/src/installers/mac-dmg.ts index 4cccabd71cf..38ec501c397 100644 --- a/packages/compass-smoke-tests/src/installers/mac-dmg.ts +++ b/packages/compass-smoke-tests/src/installers/mac-dmg.ts @@ -1,9 +1,13 @@ import path from 'node:path'; import fs from 'node:fs'; +import createDebug from 'debug'; + import type { InstalledAppInfo, InstallablePackage } from './types'; import { execute } from '../execute'; +const debug = createDebug('compass-smoke-tests:installers:mac-dmg'); + export function installMacDMG({ appName, filepath, @@ -35,7 +39,7 @@ export function installMacDMG({ ); if (fs.existsSync(settingsDir)) { - console.log(`${settingsDir} already exists. Removing.`); + debug(`${settingsDir} already exists. Removing.`); fs.rmSync(settingsDir, { recursive: true }); } } diff --git a/packages/compass-smoke-tests/src/installers/mac-zip.ts b/packages/compass-smoke-tests/src/installers/mac-zip.ts index 083ba5869c4..12a272350f9 100644 --- a/packages/compass-smoke-tests/src/installers/mac-zip.ts +++ b/packages/compass-smoke-tests/src/installers/mac-zip.ts @@ -1,9 +1,13 @@ import path from 'node:path'; import fs from 'node:fs'; +import createDebug from 'debug'; + import type { InstalledAppInfo, InstallablePackage } from './types'; import { execute } from '../execute'; +const debug = createDebug('compass-smoke-tests:installers:mac-zip'); + export function installMacZIP({ appName, filepath, @@ -25,7 +29,7 @@ export function installMacZIP({ ); if (fs.existsSync(settingsDir)) { - console.log(`${settingsDir} already exists. Removing.`); + debug(`${settingsDir} already exists. Removing.`); fs.rmSync(settingsDir, { recursive: true }); } }