diff --git a/.evergreen.yml b/.evergreen.yml index 278feed0bc..dc9c7cffb4 100644 --- a/.evergreen.yml +++ b/.evergreen.yml @@ -4295,10 +4295,17 @@ functions: params: file: tmp/expansions.yaml redacted: true + - command: ec2.assume_role + params: + role_arn: "arn:aws:iam::119629040606:role/s3-access.cdn-origin-compass" - command: shell.exec params: working_dir: src shell: bash + env: + DOWNLOAD_CENTER_AWS_KEY_NEW: ${AWS_ACCESS_KEY_ID} + DOWNLOAD_CENTER_AWS_SECRET_NEW: ${AWS_SECRET_ACCESS_KEY} + DOWNLOAD_CENTER_AWS_SESSION_TOKEN_NEW: ${AWS_SESSION_TOKEN} script: | set -e { @@ -4362,6 +4369,9 @@ functions: params: file: tmp/expansions.yaml redacted: true + - command: ec2.assume_role + params: + role_arn: "arn:aws:iam::119629040606:role/s3-access.cdn-origin-compass" - command: shell.exec # silent: true params: @@ -4370,6 +4380,9 @@ functions: env: devtoolsbot_npm_token: ${devtoolsbot_npm_token} node_js_version: ${node_js_version} + DOWNLOAD_CENTER_AWS_KEY_NEW: ${AWS_ACCESS_KEY_ID} + DOWNLOAD_CENTER_AWS_SECRET_NEW: ${AWS_SECRET_ACCESS_KEY} + DOWNLOAD_CENTER_AWS_SESSION_TOKEN_NEW: ${AWS_SESSION_TOKEN} script: | set -e export PUPPETEER_SKIP_DOWNLOAD="true" diff --git a/.github/workflows/update-cta.yml b/.github/workflows/update-cta.yml index 369134d29a..e02a917a0c 100644 --- a/.github/workflows/update-cta.yml +++ b/.github/workflows/update-cta.yml @@ -19,6 +19,7 @@ on: default: CTA-Production permissions: + id-token: write contents: read jobs: @@ -34,16 +35,27 @@ jobs: DOWNLOAD_CENTER_AWS_SECRET: ${{ secrets.DOWNLOAD_CENTER_AWS_SECRET }} steps: - uses: actions/checkout@v4 + - name: configure aws credentials + uses: aws-actions/configure-aws-credentials@v4.1.0 + with: + role-to-assume: arn:aws:iam::119629040606:role/s3-access.cdn-origin-compass + aws-region: us-east-1 + - name: Sts GetCallerIdentity + run: | + aws sts get-caller-identity - uses: actions/setup-node@v4 with: node-version: ^20.x cache: "npm" - - name: Install Dependencies and Compile run: | npm ci npm run compile - name: Update greeting CTA + env: + DOWNLOAD_CENTER_AWS_KEY_NEW: "${{ env.AWS_ACCESS_KEY_ID }}" + DOWNLOAD_CENTER_AWS_SECRET_NEW: "${{ env.AWS_SECRET_KEY }}" + DOWNLOAD_CENTER_AWS_SESSION_TOKEN_NEW: "${{ env.AWS_SESSION_TOKEN }}" run: | npm run update-cta ${{ github.event.inputs.dry-run && '-- --dry-run' || '' }} diff --git a/config/build.conf.js b/config/build.conf.js index a45ae8bf0b..bdfd3d574d 100644 --- a/config/build.conf.js +++ b/config/build.conf.js @@ -97,6 +97,9 @@ module.exports = { evgAwsSecret: process.env.AWS_SECRET, downloadCenterAwsKey: process.env.DOWNLOAD_CENTER_AWS_KEY, downloadCenterAwsSecret: process.env.DOWNLOAD_CENTER_AWS_SECRET, + downloadCenterAwsKeyNew: process.env.DOWNLOAD_CENTER_AWS_KEY_NEW, + downloadCenterAwsSecretNew: process.env.DOWNLOAD_CENTER_AWS_SECRET_NEW, + downloadCenterAwsSessionTokenNew: process.env.DOWNLOAD_CENTER_AWS_SESSION_TOKEN_NEW, injectedJsonFeedFile: path.join(ROOT, 'config', 'mongosh-versions.json'), githubToken: process.env.GITHUB_TOKEN, segmentKey: process.env.SEGMENT_API_KEY, diff --git a/package-lock.json b/package-lock.json index 3c5193a266..71aa5916cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5751,7 +5751,9 @@ } }, "node_modules/@mongodb-js/dl-center": { - "version": "1.1.1", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/dl-center/-/dl-center-1.3.0.tgz", + "integrity": "sha512-5fsbPhmok5uyTdr3G3wf8YUWJm/TQnBHBeqRQV4CsSW15MguAv8YEx8cF8YXB20G01izkHT72xkqb/Ry4SiHcg==", "license": "Apache-2.0", "dependencies": { "ajv": "^6.12.5", diff --git a/packages/build/src/config/config.ts b/packages/build/src/config/config.ts index 35c514b764..78ff7d8017 100644 --- a/packages/build/src/config/config.ts +++ b/packages/build/src/config/config.ts @@ -41,6 +41,9 @@ export interface Config { evgAwsSecret?: string; downloadCenterAwsKey?: string; downloadCenterAwsSecret?: string; + downloadCenterAwsKeyNew?: string; + downloadCenterAwsSecretNew?: string; + downloadCenterAwsSessionTokenNew?: string; injectedJsonFeedFile?: string; githubToken?: string; segmentKey?: string; diff --git a/packages/build/src/download-center/artifacts.ts b/packages/build/src/download-center/artifacts.ts index 013c111736..1e7a0ef2db 100644 --- a/packages/build/src/download-center/artifacts.ts +++ b/packages/build/src/download-center/artifacts.ts @@ -1,7 +1,11 @@ import { DownloadCenter as DownloadCenterCls } from '@mongodb-js/dl-center'; import * as fs from 'fs'; import path from 'path'; -import { ARTIFACTS_BUCKET, ARTIFACTS_FOLDER } from './constants'; +import { + ARTIFACTS_BUCKET, + ARTIFACTS_BUCKET_NEW, + ARTIFACTS_FOLDER, +} from './constants'; export async function uploadArtifactToDownloadCenter( filePath: string, @@ -20,3 +24,23 @@ export async function uploadArtifactToDownloadCenter( fs.createReadStream(filePath) ); } + +export async function uploadArtifactToDownloadCenterNew( + filePath: string, + awsAccessKeyId: string, + awsSecretAccessKey: string, + awsSessionToken: string, + DownloadCenter: typeof DownloadCenterCls = DownloadCenterCls +): Promise { + const dlcenter = new DownloadCenter({ + bucket: ARTIFACTS_BUCKET_NEW, + accessKeyId: awsAccessKeyId, + secretAccessKey: awsSecretAccessKey, + sessionToken: awsSessionToken, + }); + + await dlcenter.uploadAsset( + `${ARTIFACTS_FOLDER}/${path.basename(filePath)}`, + fs.createReadStream(filePath) + ); +} diff --git a/packages/build/src/download-center/config.spec.ts b/packages/build/src/download-center/config.spec.ts index f9dee525cd..86ede99f2f 100644 --- a/packages/build/src/download-center/config.spec.ts +++ b/packages/build/src/download-center/config.spec.ts @@ -40,6 +40,7 @@ const packageInformation = (version: string) => const DUMMY_ACCESS_KEY = 'accessKey'; const DUMMY_SECRET_KEY = 'secretKey'; +const DUMMY_SESSION_TOKEN = 'sessionToken'; const DUMMY_CTA_CONFIG: CTAConfig = {}; describe('DownloadCenter config', function () { @@ -273,6 +274,9 @@ describe('DownloadCenter config', function () { packageInformation('2.0.1'), DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, '', false, DUMMY_CTA_CONFIG, @@ -290,6 +294,12 @@ describe('DownloadCenter config', function () { accessKeyId: DUMMY_ACCESS_KEY, secretAccessKey: DUMMY_SECRET_KEY, }); + expect(dlCenter).to.have.been.calledWith({ + bucket: 'cdn-origin-compass', + accessKeyId: DUMMY_ACCESS_KEY, + secretAccessKey: DUMMY_SECRET_KEY, + sessionToken: DUMMY_SESSION_TOKEN, + }); expect(uploadConfig).to.be.calledOnce; @@ -321,7 +331,7 @@ describe('DownloadCenter config', function () { tutorial_link: 'test', }); - expect(uploadAsset).to.be.calledOnce; + expect(uploadAsset).to.be.calledTwice; const [assetKey] = uploadAsset.lastCall.args; expect(assetKey).to.equal('compass/mongosh.json'); }); @@ -332,6 +342,9 @@ describe('DownloadCenter config', function () { packageInformation('1.2.2'), DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, '', false, DUMMY_CTA_CONFIG, @@ -349,6 +362,12 @@ describe('DownloadCenter config', function () { accessKeyId: DUMMY_ACCESS_KEY, secretAccessKey: DUMMY_SECRET_KEY, }); + expect(dlCenter).to.have.been.calledWith({ + bucket: 'cdn-origin-compass', + accessKeyId: DUMMY_ACCESS_KEY, + secretAccessKey: DUMMY_SECRET_KEY, + sessionToken: DUMMY_SESSION_TOKEN, + }); expect(uploadConfig).to.be.calledOnce; @@ -377,7 +396,7 @@ describe('DownloadCenter config', function () { tutorial_link: 'test', }); - expect(uploadAsset).to.be.calledOnce; + expect(uploadAsset).to.be.calledTwice; const [assetKey, uploadedAsset] = uploadAsset.lastCall.args; expect(assetKey).to.equal('compass/mongosh.json'); const jsonFeedData = JSON.parse(uploadedAsset); @@ -431,6 +450,9 @@ describe('DownloadCenter config', function () { packageInformation('2.0.0'), DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, path.resolve( __dirname, '..', @@ -455,6 +477,12 @@ describe('DownloadCenter config', function () { accessKeyId: DUMMY_ACCESS_KEY, secretAccessKey: DUMMY_SECRET_KEY, }); + expect(dlCenter).to.have.been.calledWith({ + bucket: 'cdn-origin-compass', + accessKeyId: DUMMY_ACCESS_KEY, + secretAccessKey: DUMMY_SECRET_KEY, + sessionToken: DUMMY_SESSION_TOKEN, + }); expect(uploadConfig).to.be.calledOnce; @@ -486,7 +514,7 @@ describe('DownloadCenter config', function () { tutorial_link: 'test', }); - expect(uploadAsset).to.be.calledOnce; + expect(uploadAsset).to.be.calledTwice; const [assetKey, uploadedAsset] = uploadAsset.lastCall.args; expect(assetKey).to.equal('compass/mongosh.json'); const jsonFeedData = JSON.parse(uploadedAsset); @@ -593,6 +621,9 @@ describe('DownloadCenter config', function () { config, DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, dryRun, dlCenter as any ); @@ -630,6 +661,9 @@ describe('DownloadCenter config', function () { config, DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, false, dlCenter as any ); @@ -655,6 +689,9 @@ describe('DownloadCenter config', function () { ctas, DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, false, dlCenter as any ); @@ -677,6 +714,9 @@ describe('DownloadCenter config', function () { config, DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, false, dlCenter as any ); @@ -699,6 +739,9 @@ describe('DownloadCenter config', function () { config, DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, false, dlCenter as any ); @@ -721,6 +764,9 @@ describe('DownloadCenter config', function () { config, DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, false, dlCenter as any ); @@ -750,6 +796,9 @@ describe('DownloadCenter config', function () { config, DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, false, dlCenter as any ); @@ -779,6 +828,9 @@ describe('DownloadCenter config', function () { config, DUMMY_ACCESS_KEY, DUMMY_SECRET_KEY, + DUMMY_ACCESS_KEY, + DUMMY_SECRET_KEY, + DUMMY_SESSION_TOKEN, false, dlCenter as any ); diff --git a/packages/build/src/download-center/config.ts b/packages/build/src/download-center/config.ts index 09e0d75481..b3c325dd58 100644 --- a/packages/build/src/download-center/config.ts +++ b/packages/build/src/download-center/config.ts @@ -9,6 +9,7 @@ import type { } from '@mongodb-js/dl-center/dist/download-center-config'; import { ARTIFACTS_BUCKET, + ARTIFACTS_BUCKET_NEW, JSON_FEED_ARTIFACT_KEY, ARTIFACTS_URL_PUBLIC_BASE, CONFIGURATION_KEY, @@ -55,6 +56,9 @@ export async function createAndPublishDownloadCenterConfig( packageInformation: PackageInformationProvider, awsAccessKeyId: string, awsSecretAccessKey: string, + awsAccessKeyIdNew: string, + awsSecretAccessKeyNew: string, + awsSessionTokenNew: string, injectedJsonFeedFile: string, isDryRun: boolean, ctaConfig: CTAConfig, @@ -100,6 +104,13 @@ export async function createAndPublishDownloadCenterConfig( secretAccessKey: awsSecretAccessKey, }); + const dlcenterArtifactsNew = new DownloadCenter({ + bucket: ARTIFACTS_BUCKET_NEW, + accessKeyId: awsAccessKeyIdNew, + secretAccessKey: awsSecretAccessKeyNew, + sessionToken: awsSessionTokenNew, + }); + const existingJsonFeed = await getCurrentJsonFeed(dlcenterArtifacts); const injectedJsonFeed: JsonFeed | undefined = injectedJsonFeedFile ? JSON.parse(await fs.readFile(injectedJsonFeedFile, 'utf8')) @@ -135,12 +146,20 @@ export async function createAndPublishDownloadCenterConfig( JSON.stringify(newJsonFeed, null, 2) ), ]); + + await dlcenterArtifactsNew.uploadAsset( + JSON_FEED_ARTIFACT_KEY, + JSON.stringify(newJsonFeed, null, 2) + ); } export async function updateJsonFeedCTA( config: CTAConfig, awsAccessKeyId: string, awsSecretAccessKey: string, + awsAccessKeyIdNew: string, + awsSecretAccessKeyNew: string, + awsSessionTokenNew: string, isDryRun: boolean, DownloadCenter: typeof DownloadCenterCls = DownloadCenterCls ) { @@ -150,6 +169,13 @@ export async function updateJsonFeedCTA( secretAccessKey: awsSecretAccessKey, }); + const dlcenterArtifactsNew = new DownloadCenter({ + bucket: ARTIFACTS_BUCKET_NEW, + accessKeyId: awsAccessKeyIdNew, + secretAccessKey: awsSecretAccessKeyNew, + sessionToken: awsSessionTokenNew, + }); + const jsonFeed = await getCurrentJsonFeed(dlcenterArtifacts); if (!jsonFeed) { throw new Error('No existing JSON feed found'); @@ -165,6 +191,10 @@ export async function updateJsonFeedCTA( } await dlcenterArtifacts.uploadAsset(JSON_FEED_ARTIFACT_KEY, patchedJsonFeed); + await dlcenterArtifactsNew.uploadAsset( + JSON_FEED_ARTIFACT_KEY, + patchedJsonFeed + ); } function populateJsonFeedCTAs(jsonFeed: JsonFeed, ctas: CTAConfig) { diff --git a/packages/build/src/download-center/constants.ts b/packages/build/src/download-center/constants.ts index 5ba6a4d773..f31e7acc1f 100644 --- a/packages/build/src/download-center/constants.ts +++ b/packages/build/src/download-center/constants.ts @@ -16,6 +16,11 @@ export const CONFIGURATION_KEY = */ export const ARTIFACTS_BUCKET = 'downloads.10gen.com'; +/** + * The S3 bucket for download center artifacts. + */ +export const ARTIFACTS_BUCKET_NEW = 'cdn-origin-compass'; + /** * The S3 "folder" for uploaded artifacts. */ diff --git a/packages/build/src/index.ts b/packages/build/src/index.ts index f818ee6eda..847fcd3ebd 100644 --- a/packages/build/src/index.ts +++ b/packages/build/src/index.ts @@ -81,6 +81,9 @@ if (require.main === module) { ctaConfig, downloadCenterAwsKey, downloadCenterAwsSecret, + downloadCenterAwsKeyNew, + downloadCenterAwsSecretNew, + downloadCenterAwsSessionTokenNew, isDryRun, } = getBuildConfig(); @@ -88,10 +91,21 @@ if (require.main === module) { throw new Error('Missing AWS credentials for download center'); } + if ( + !downloadCenterAwsKeyNew || + !downloadCenterAwsSecretNew || + !downloadCenterAwsSessionTokenNew + ) { + throw new Error('Missing AWS credentials for new download center'); + } + await updateJsonFeedCTA( ctaConfig, downloadCenterAwsKey, downloadCenterAwsSecret, + downloadCenterAwsKeyNew, + downloadCenterAwsSecretNew, + downloadCenterAwsSessionTokenNew, !!isDryRun ); break; diff --git a/packages/build/src/publish-mongosh.ts b/packages/build/src/publish-mongosh.ts index 79472f1372..4ad027a18f 100644 --- a/packages/build/src/publish-mongosh.ts +++ b/packages/build/src/publish-mongosh.ts @@ -123,6 +123,9 @@ export class MongoshPublisher { config.packageInformation as PackageInformationProvider, config.downloadCenterAwsKey || '', config.downloadCenterAwsSecret || '', + config.downloadCenterAwsKeyNew || '', + config.downloadCenterAwsSecretNew || '', + config.downloadCenterAwsSessionTokenNew || '', config.injectedJsonFeedFile || '', !!config.isDryRun, config.ctaConfig diff --git a/packages/build/src/release.ts b/packages/build/src/release.ts index dddea420f6..ca50e64d24 100644 --- a/packages/build/src/release.ts +++ b/packages/build/src/release.ts @@ -2,7 +2,10 @@ import { Octokit } from '@octokit/rest'; import { runCompile } from './compile'; import type { Config } from './config'; import { getReleaseVersionFromTag, redactConfig } from './config'; -import { uploadArtifactToDownloadCenter } from './download-center'; +import { + uploadArtifactToDownloadCenter, + uploadArtifactToDownloadCenterNew, +} from './download-center'; import { downloadArtifactFromEvergreen, uploadArtifactToEvergreen, @@ -95,6 +98,7 @@ export async function release( githubRepo, new PackageBumper(), uploadArtifactToDownloadCenter, + uploadArtifactToDownloadCenterNew, downloadArtifactFromEvergreen ); } else if (command === 'download-and-list-artifacts') { diff --git a/packages/build/src/run-draft.spec.ts b/packages/build/src/run-draft.spec.ts index 593fde76ca..39883da8b2 100644 --- a/packages/build/src/run-draft.spec.ts +++ b/packages/build/src/run-draft.spec.ts @@ -2,7 +2,10 @@ import chai, { expect } from 'chai'; import sinon from 'sinon'; import type { Config } from './config'; import { ALL_PACKAGE_VARIANTS } from './config'; -import type { uploadArtifactToDownloadCenter as uploadArtifactToDownloadCenterFn } from './download-center'; +import type { + uploadArtifactToDownloadCenter as uploadArtifactToDownloadCenterFn, + uploadArtifactToDownloadCenterNew as uploadArtifactToDownloadCenterFnNew, +} from './download-center'; import type { downloadArtifactFromEvergreen as downloadArtifactFromEvergreenFn } from './evergreen'; import type { generateChangelog as generateChangelogFn } from './git'; import { GithubRepo } from '@mongodb-js/devtools-github-repo'; @@ -26,12 +29,14 @@ describe('draft', function () { let config: Config; let githubRepo: GithubRepo; let uploadArtifactToDownloadCenter: typeof uploadArtifactToDownloadCenterFn; + let uploadArtifactToDownloadCenterNew: typeof uploadArtifactToDownloadCenterFnNew; let downloadArtifactFromEvergreen: typeof downloadArtifactFromEvergreenFn; beforeEach(function () { config = { ...dummyConfig }; uploadArtifactToDownloadCenter = sinon.spy(); + uploadArtifactToDownloadCenterNew = sinon.spy(); downloadArtifactFromEvergreen = sinon.spy(() => Promise.resolve('filename') ); @@ -66,6 +71,7 @@ describe('draft', function () { githubRepo, packageBumper, uploadArtifactToDownloadCenter, + uploadArtifactToDownloadCenterNew, downloadArtifactFromEvergreen, ensureGithubReleaseExistsAndUpdateChangelog ); @@ -111,6 +117,7 @@ describe('draft', function () { githubRepo, packageBumper, uploadArtifactToDownloadCenter, + uploadArtifactToDownloadCenterNew, downloadArtifactFromEvergreen, ensureGithubReleaseExistsAndUpdateChangelog ); @@ -135,6 +142,7 @@ describe('draft', function () { githubRepo, packageBumper, uploadArtifactToDownloadCenter, + uploadArtifactToDownloadCenterNew, downloadArtifactFromEvergreen, ensureGithubReleaseExistsAndUpdateChangelog ); diff --git a/packages/build/src/run-draft.ts b/packages/build/src/run-draft.ts index ac4ea7fcd6..afb3c2f650 100644 --- a/packages/build/src/run-draft.ts +++ b/packages/build/src/run-draft.ts @@ -3,6 +3,7 @@ import path from 'path'; import type { Config } from './config'; import { ALL_PACKAGE_VARIANTS, getReleaseVersionFromTag } from './config'; import { uploadArtifactToDownloadCenter as uploadArtifactToDownloadCenterFn } from './download-center'; +import { uploadArtifactToDownloadCenterNew as uploadArtifactToDownloadCenterFnNew } from './download-center'; import { downloadArtifactFromEvergreen as downloadArtifactFromEvergreenFn } from './evergreen'; import { generateChangelog as generateChangelogFn } from './git'; import { getPackageFile } from './packaging'; @@ -14,6 +15,7 @@ export async function runDraft( githubRepo: GithubRepo, packageBumper: PackageBumper, uploadToDownloadCenter: typeof uploadArtifactToDownloadCenterFn = uploadArtifactToDownloadCenterFn, + uploadToDownloadCenterNew: typeof uploadArtifactToDownloadCenterFnNew = uploadArtifactToDownloadCenterFnNew, downloadArtifactFromEvergreen: typeof downloadArtifactFromEvergreenFn = downloadArtifactFromEvergreenFn, ensureGithubReleaseExistsAndUpdateChangelog: typeof ensureGithubReleaseExistsAndUpdateChangelogFn = ensureGithubReleaseExistsAndUpdateChangelogFn ): Promise { @@ -88,6 +90,13 @@ export async function runDraft( contentType, }), ]); + + await uploadToDownloadCenterNew( + downloadedArtifact, + config.downloadCenterAwsKeyNew as string, + config.downloadCenterAwsSecretNew as string, + config.downloadCenterAwsSessionTokenNew as string + ); }) ); }