diff --git a/packages/build/src/download-center/config.spec.ts b/packages/build/src/download-center/config.spec.ts index 2b278561ff..b1c71686d4 100644 --- a/packages/build/src/download-center/config.spec.ts +++ b/packages/build/src/download-center/config.spec.ts @@ -1,46 +1,42 @@ import type { DownloadCenterConfig } from '@mongodb-js/dl-center/dist/download-center-config'; +import type { PackageInformationProvider } from '../packaging'; import { expect } from 'chai'; import sinon from 'ts-sinon'; import type { PackageVariant } from '../config'; import { - createAndPublishDownloadCenterConfig, + createVersionConfig, createDownloadCenterConfig, + getUpdatedDownloadCenterConfig, + createAndPublishDownloadCenterConfig, } from './config'; -describe('DownloadCenter config', function () { - let config: DownloadCenterConfig; - let packageInformation: any; - - before(function () { - packageInformation = (packageVariant: PackageVariant) => { - const SHARED_OPENSSL_TAG = - /-(openssl\d*)$/.exec(packageVariant)?.[1] || ''; - return { - metadata: { - version: '1.2.2', - name: 'mongosh', - rpmName: - 'mongodb-mongosh' + - (SHARED_OPENSSL_TAG ? `-shared-${SHARED_OPENSSL_TAG}` : ''), - debName: - 'mongodb-mongosh' + - (SHARED_OPENSSL_TAG ? `-shared-${SHARED_OPENSSL_TAG}` : ''), - }, - }; +const packageInformation = (version: string) => + ((packageVariant: PackageVariant) => { + const SHARED_OPENSSL_TAG = /-(openssl\d*)$/.exec(packageVariant)?.[1] || ''; + return { + metadata: { + version: version, + name: 'mongosh', + rpmName: + 'mongodb-mongosh' + + (SHARED_OPENSSL_TAG ? `-shared-${SHARED_OPENSSL_TAG}` : ''), + debName: + 'mongodb-mongosh' + + (SHARED_OPENSSL_TAG ? `-shared-${SHARED_OPENSSL_TAG}` : ''), + }, }; - config = createDownloadCenterConfig(packageInformation); - }); + }) as PackageInformationProvider; - describe('createDownloadCenterConfig', function () { +describe('DownloadCenter config', function () { + describe('createVersionConfig', function () { it('sets the version correctly', function () { - expect(config.versions).to.have.length(1); - const [version] = config.versions; + const version = createVersionConfig(packageInformation('1.2.2')); expect(version._id).to.equal('1.2.2'); expect(version.version).to.equal('1.2.2'); }); it('has an artifact for darwin', function () { - const [version] = config.versions; + const version = createVersionConfig(packageInformation('1.2.2')); const platforms = version.platform.filter((p) => p.os === 'darwin'); expect(platforms).to.have.length(2); expect(platforms[0].download_link).to.include( @@ -52,7 +48,7 @@ describe('DownloadCenter config', function () { }); it('has an artifact for linux', function () { - const [version] = config.versions; + const version = createVersionConfig(packageInformation('1.2.2')); const platforms = version.platform.filter( (p) => p.os === 'linux' && p.arch === 'x64' ); @@ -65,7 +61,7 @@ describe('DownloadCenter config', function () { }); it('has an MSI and ZIP artifacts for windows', function () { - const [version] = config.versions; + const version = createVersionConfig(packageInformation('1.2.2')); const platforms = version.platform.filter( (p) => p.os === 'win32' || p.os === 'win32msi' ); @@ -77,7 +73,7 @@ describe('DownloadCenter config', function () { }); it('has an artifact for rpm', function () { - const [version] = config.versions; + const version = createVersionConfig(packageInformation('1.2.2')); const platforms = version.platform.filter( (p) => p.os === 'rpm' && p.arch === 'x64' ); @@ -90,7 +86,7 @@ describe('DownloadCenter config', function () { }); it('has an artifact for deb', function () { - const [version] = config.versions; + const version = createVersionConfig(packageInformation('1.2.2')); const platforms = version.platform.filter( (p) => p.os === 'deb' && p.arch === 'x64' ); @@ -103,35 +99,193 @@ describe('DownloadCenter config', function () { }); }); + describe('createDownloadCenterConfig', function () { + it('creates a fresh download center config', function () { + const getVersionConfig = sinon.stub().returns({ version: '1.2.2' }); + const config = createDownloadCenterConfig(getVersionConfig); + expect(getVersionConfig).to.be.called; + expect(config).deep.equal({ + versions: [{ version: '1.2.2' }], + manual_link: 'https://docs.mongodb.org/manual/products/mongosh', + release_notes_link: `https://github.com/mongodb-js/mongosh/releases/tag/v1.2.2`, + previous_releases_link: '', + development_releases_link: '', + supported_browsers_link: '', + tutorial_link: 'test', + }); + }); + }); + + describe('getUpdatedDownloadCenterConfig', function () { + context('when the current release is a new major bump', function () { + it('adds a new entry for the current release to the download center config, while keeping the other major versions', function () { + const getVersionConfig1x = sinon.stub().returns({ version: '1.2.2' }); + const getVersionConfig2x = sinon.stub().returns({ version: '2.0.0' }); + const existingDownloadCenterConfig = + createDownloadCenterConfig(getVersionConfig1x); + expect(existingDownloadCenterConfig.versions).to.have.lengthOf(1); + + const updatedConfig = getUpdatedDownloadCenterConfig( + existingDownloadCenterConfig, + getVersionConfig2x + ); + + expect(updatedConfig).to.deep.equal({ + versions: [{ version: '1.2.2' }, { version: '2.0.0' }], + manual_link: 'https://docs.mongodb.org/manual/products/mongosh', + release_notes_link: `https://github.com/mongodb-js/mongosh/releases/tag/v2.0.0`, // Release notes link will point to the current release being made + previous_releases_link: '', + development_releases_link: '', + supported_browsers_link: '', + tutorial_link: 'test', + }); + }); + }); + + context( + 'when the current release is a minor/patch bump to one of earlier released major versions', + function () { + it('replaces the earlier released major version with the current minor/patch bump, while keeping the other major versions', function () { + const getVersionConfig1x = sinon.stub().returns({ version: '1.2.2' }); + const getVersionConfig2x = sinon.stub().returns({ version: '2.0.0' }); + const getVersionConfig21 = sinon.stub().returns({ version: '2.1.0' }); + const existingDownloadCenterConfig = + createDownloadCenterConfig(getVersionConfig1x); + + const configWith2x = getUpdatedDownloadCenterConfig( + existingDownloadCenterConfig, + getVersionConfig2x + ); + + const configWith21x = getUpdatedDownloadCenterConfig( + configWith2x, + getVersionConfig21 + ); + + expect(configWith21x).to.deep.equal({ + versions: [{ version: '1.2.2' }, { version: '2.1.0' }], + manual_link: 'https://docs.mongodb.org/manual/products/mongosh', + release_notes_link: `https://github.com/mongodb-js/mongosh/releases/tag/v2.1.0`, // Release notes link will point to the current release being made + previous_releases_link: '', + development_releases_link: '', + supported_browsers_link: '', + tutorial_link: 'test', + }); + }); + } + ); + }); + describe('createAndPublishDownloadCenterConfig', function () { let dlCenter: sinon.SinonStub; let uploadConfig: sinon.SinonStub; + let downloadConfig: sinon.SinonStub; beforeEach(function () { uploadConfig = sinon.stub(); + downloadConfig = sinon.stub(); dlCenter = sinon.stub(); - dlCenter.returns({ uploadConfig }); + dlCenter.returns({ downloadConfig, uploadConfig }); }); - it('publishes the configuration', async function () { - await createAndPublishDownloadCenterConfig( - packageInformation, - 'accessKey', - 'secretKey', - false, - dlCenter as any - ); + context('when a configuration does not exist', function () { + it('publishes the created configuration', async function () { + await createAndPublishDownloadCenterConfig( + packageInformation('1.2.2'), + 'accessKey', + 'secretKey', + false, + dlCenter as any + ); + + expect(dlCenter).to.have.been.calledWith({ + bucket: 'info-mongodb-com', + accessKeyId: 'accessKey', + secretAccessKey: 'secretKey', + }); - expect(dlCenter).to.have.been.calledWith({ - bucket: 'info-mongodb-com', - accessKeyId: 'accessKey', - secretAccessKey: 'secretKey', + expect(uploadConfig).to.be.calledOnce; + + const [uploadKey, uploadedConfig] = uploadConfig.lastCall.args; + expect(uploadKey).to.equal('com-download-center/mongosh.json'); + + // Versions have platform info as well which we already verify in + // createVersionConfig specs hence trimming it down here + uploadedConfig.versions = ( + uploadedConfig as DownloadCenterConfig + ).versions.map((version) => ({ + ...version, + platform: [], + })); + + expect(uploadedConfig).to.deep.equal({ + versions: [{ _id: '1.2.2', version: '1.2.2', platform: [] }], + manual_link: 'https://docs.mongodb.org/manual/products/mongosh', + release_notes_link: + 'https://github.com/mongodb-js/mongosh/releases/tag/v1.2.2', + previous_releases_link: '', + development_releases_link: '', + supported_browsers_link: '', + tutorial_link: 'test', + }); + }); + }); + + context('when a configuration exists already', function () { + it('publishes an updated version of the existing configuration', async function () { + downloadConfig.returns( + createDownloadCenterConfig( + sinon.stub().returns({ + _id: '1.2.2', + version: '1.2.2', + platform: [], + }) + ) + ); + + await createAndPublishDownloadCenterConfig( + packageInformation('2.0.0'), + 'accessKey', + 'secretKey', + false, + dlCenter as any + ); + + expect(dlCenter).to.have.been.calledWith({ + bucket: 'info-mongodb-com', + accessKeyId: 'accessKey', + secretAccessKey: 'secretKey', + }); + + expect(uploadConfig).to.be.calledOnce; + + const [uploadKey, uploadedConfig] = uploadConfig.lastCall.args; + expect(uploadKey).to.equal('com-download-center/mongosh.json'); + + // Versions have platform info as well which we already verify in + // createVersionConfig specs hence trimming it down here + uploadedConfig.versions = ( + uploadedConfig as DownloadCenterConfig + ).versions.map((version) => ({ + ...version, + platform: [], + })); + + expect(uploadedConfig).to.deep.equal({ + versions: [ + { _id: '1.2.2', version: '1.2.2', platform: [] }, + { _id: '2.0.0', version: '2.0.0', platform: [] }, + ], + manual_link: 'https://docs.mongodb.org/manual/products/mongosh', + release_notes_link: + 'https://github.com/mongodb-js/mongosh/releases/tag/v2.0.0', + previous_releases_link: '', + development_releases_link: '', + supported_browsers_link: '', + tutorial_link: 'test', + }); }); - expect(uploadConfig).to.have.been.calledWith( - 'com-download-center/mongosh.json', - createDownloadCenterConfig(packageInformation) - ); }); }); }); diff --git a/packages/build/src/download-center/config.ts b/packages/build/src/download-center/config.ts index 7704921907..e5c54448cf 100644 --- a/packages/build/src/download-center/config.ts +++ b/packages/build/src/download-center/config.ts @@ -2,6 +2,7 @@ import { DownloadCenter as DownloadCenterCls, validateConfigSchema, } from '@mongodb-js/dl-center'; +import { major as majorVersion } from 'semver'; import type { DownloadCenterConfig } from '@mongodb-js/dl-center/dist/download-center-config'; import { CONFIGURATION_KEY, CONFIGURATIONS_BUCKET } from './constants'; import type { PackageVariant } from '../config'; @@ -21,7 +22,22 @@ export async function createAndPublishDownloadCenterConfig( isDryRun: boolean, DownloadCenter: typeof DownloadCenterCls = DownloadCenterCls ): Promise { - const config = createDownloadCenterConfig(packageInformation); + const dlcenter = new DownloadCenter({ + bucket: CONFIGURATIONS_BUCKET, + accessKeyId: awsAccessKeyId, + secretAccessKey: awsSecretAccessKey, + }); + const existingDownloadCenterConfig = await dlcenter.downloadConfig( + CONFIGURATION_KEY + ); + + const getVersionConfig = () => createVersionConfig(packageInformation); + const config = existingDownloadCenterConfig + ? getUpdatedDownloadCenterConfig( + existingDownloadCenterConfig, + getVersionConfig + ) + : createDownloadCenterConfig(getVersionConfig); console.warn('Created download center config:'); console.dir(config, { depth: Infinity }); @@ -33,41 +49,62 @@ export async function createAndPublishDownloadCenterConfig( return; } - const dlcenter = new DownloadCenter({ - bucket: CONFIGURATIONS_BUCKET, - accessKeyId: awsAccessKeyId, - secretAccessKey: awsSecretAccessKey, + await dlcenter.uploadConfig(CONFIGURATION_KEY, config); +} + +export function getUpdatedDownloadCenterConfig( + downloadedConfig: DownloadCenterConfig, + getVersionConfig: () => ReturnType +): DownloadCenterConfig { + const versionConfig = getVersionConfig(); + const toBeReleasedVersion = versionConfig.version; + const currentVersions = [...downloadedConfig.versions]; + const matchingMajorVersionIdx = currentVersions.findIndex(({ version }) => { + return majorVersion(toBeReleasedVersion) === majorVersion(version); }); - await dlcenter.uploadConfig(CONFIGURATION_KEY, config); + if (matchingMajorVersionIdx === -1) { + currentVersions.push(versionConfig); + } else { + currentVersions[matchingMajorVersionIdx] = versionConfig; + } + + return { + ...downloadedConfig, + versions: currentVersions, + release_notes_link: `https://github.com/mongodb-js/mongosh/releases/tag/v${versionConfig.version}`, + }; } export function createDownloadCenterConfig( - packageInformation: PackageInformationProvider + getVersionConfig: () => ReturnType ): DownloadCenterConfig { - const { version } = packageInformation('linux-x64').metadata; + const versionConfig = getVersionConfig(); return { - versions: [ - { - _id: version, - version: version, - platform: ALL_PACKAGE_VARIANTS.map( - (packageVariant: PackageVariant) => ({ - arch: getArch(packageVariant), - os: getDistro(packageVariant), - name: getDownloadCenterDistroDescription(packageVariant), - download_link: - 'https://downloads.mongodb.com/compass/' + - getPackageFile(packageVariant, packageInformation).path, - }) - ), - }, - ], + versions: [versionConfig], manual_link: 'https://docs.mongodb.org/manual/products/mongosh', - release_notes_link: `https://github.com/mongodb-js/mongosh/releases/tag/v${version}`, + release_notes_link: `https://github.com/mongodb-js/mongosh/releases/tag/v${versionConfig.version}`, previous_releases_link: '', development_releases_link: '', supported_browsers_link: '', tutorial_link: 'test', }; } + +export function createVersionConfig( + packageInformation: PackageInformationProvider +) { + const { version } = packageInformation('linux-x64').metadata; + return { + _id: version, + version: version, + platform: ALL_PACKAGE_VARIANTS.map((packageVariant: PackageVariant) => ({ + arch: getArch(packageVariant), + os: getDistro(packageVariant), + name: getDownloadCenterDistroDescription(packageVariant), + download_link: + 'https://downloads.mongodb.com/compass/' + + getPackageFile(packageVariant, packageInformation).path, + })), + }; +}