Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .evergreen/buildvariants-and-tasks.in.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ buildvariants:
run_on: ubuntu2204-large
tasks:
- name: publish
- name: publish-web
- name: publish-dev-release-info

- name: static-analysis
Expand Down Expand Up @@ -410,6 +411,21 @@ tasks:
- func: get-all-artifacts
- func: publish

- name: publish-web
# Publish both on PRs and on main (if it gets too noisy and won't be used
# much we can probably disable for PRs)
tags: ['run-on-pr']
depends_on:
- name: '.required-for-publish'
variant: '*'
commands:
- func: prepare
- func: install
- func: bootstrap
vars:
scope: "@mongodb-js/compass-web"
- func: publish-web

- name: publish-dev-release-info
tags: []
depends_on:
Expand Down
16 changes: 15 additions & 1 deletion .evergreen/buildvariants-and-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ buildvariants:
- name: test-packaged-app-macos-15-x64
display_name: Test Packaged App MacOS x64 15
run_on: macos-15-amd64-gui
patchable: true
Copy link
Collaborator Author

@gribnoysup gribnoysup Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drive-by fix: at some point we updated the template (the .in file), but not the actual config

patchable: false
depends_on:
- name: package-compass
variant: package-macos-x64
Expand All @@ -242,6 +242,7 @@ buildvariants:
run_on: ubuntu2204-large
tasks:
- name: publish
- name: publish-web
- name: publish-dev-release-info
- name: static-analysis
display_name: Create Static Analysis Report
Expand Down Expand Up @@ -415,6 +416,19 @@ tasks:
scope: mongodb-compass
- func: get-all-artifacts
- func: publish
- name: publish-web
tags:
- run-on-pr
depends_on:
- name: .required-for-publish
variant: '*'
commands:
- func: prepare
- func: install
- func: bootstrap
vars:
scope: '@mongodb-js/compass-web'
- func: publish-web
- name: publish-dev-release-info
tags: []
depends_on:
Expand Down
27 changes: 23 additions & 4 deletions .evergreen/functions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ variables:
GITHUB_TOKEN: ${devtoolsbot_github_token}
DOWNLOAD_CENTER_AWS_ACCESS_KEY_ID: ${aws_key_evergreen_integrations}
DOWNLOAD_CENTER_AWS_SECRET_ACCESS_KEY: ${aws_secret_evergreen_integrations}
DOWNLOAD_CENTER_NEW_AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a bit of an overkill moving it here taking into account we will be using a different bucket, but this anyway seems more consistent with how we do it for other variables

Copy link
Contributor

@lerouxb lerouxb Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems OK. I have no real opinion.

DOWNLOAD_CENTER_NEW_AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
DOWNLOAD_CENTER_NEW_AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN}
EVERGREEN_BUCKET_NAME: mciuploads
EVERGREEN_BUCKET_KEY_PREFIX: ${project}/${revision}_${revision_order_id}
MONGODB_RUNNER_LOG_DIR: ${workdir}/src/.testserver/
Expand Down Expand Up @@ -504,23 +507,39 @@ functions:
publish:
- command: ec2.assume_role
params:
role_arn: 'arn:aws:iam::119629040606:role/s3-access.cdn-origin-compass'
role_arn: ${downloads_bucket_role_arn}
- command: shell.exec
params:
working_dir: src
shell: bash
env:
<<: *compass-env
DOWNLOAD_CENTER_NEW_AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
DOWNLOAD_CENTER_NEW_AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
DOWNLOAD_CENTER_NEW_AWS_SESSION_TOKEN: ${AWS_SESSION_TOKEN}
script: |
set -e
# Load environment variables
eval $(.evergreen/print-compass-env.sh)
echo "Uploading release assets to S3 and GitHub if needed..."
npm run --workspace mongodb-compass upload

publish-web:
- command: ec2.assume_role
params:
role_arn: ${downloads_bucket_role_arn}
- command: shell.exec
params:
working_dir: src
shell: bash
env:
<<: *compass-env
script: |
set -e
# Load environment variables
eval $(.evergreen/print-compass-env.sh)
echo "Compiling compass-web"
npm run --workspace @mongodb-js/compass-web compile
echo "Uploading release assets to S3"
npm run --workspace @mongodb-js/compass-web upload

publish-dev-release-info:
- command: shell.exec
params:
Expand Down
9 changes: 6 additions & 3 deletions configs/webpack-config-compass/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import {
sourceLoader,
cssLoader,
lessLoader,
assetsLoader,
fontLoader,
imageLoader,
resourceLoader,
sharedObjectLoader,
} from './loaders';
Expand Down Expand Up @@ -225,7 +226,8 @@ export function createElectronRendererConfig(
nodeLoader(opts),
cssLoader(opts),
lessLoader(opts),
assetsLoader(opts),
fontLoader(opts),
imageLoader(opts),
sharedObjectLoader(opts),
sourceLoader(opts),
],
Expand Down Expand Up @@ -370,7 +372,8 @@ export function createWebConfig(args: Partial<ConfigArgs>): WebpackConfig {
nodeLoader(opts),
cssLoader(opts, true),
lessLoader(opts),
assetsLoader(opts),
fontLoader(opts),
imageLoader(opts),
sourceLoader(opts),
],
parser: {
Expand Down
24 changes: 13 additions & 11 deletions configs/webpack-config-compass/src/loaders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,16 +187,18 @@ export const lessLoader = (args: ConfigArgs) => ({
});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const assetsLoader = (_args: ConfigArgs) => ({
test: /\.(jpe?g|png|svg|gif|woff|woff2|ttf|eot|otf)(\?.+?)?$/,
// asset (or asset auto) will either compile as data-uri or to a file path
// based on the size, this is a good strategy for loading assets in the GUI
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 2 * 1024, // 2kb
},
},
export const fontLoader = (_args: ConfigArgs) => ({
test: /\.(woff|woff2|ttf|eot|otf)(\?.+?)?$/,
// fonts are always big and should be emitted as a separate file
type: 'asset/resource',
});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const imageLoader = (_args: ConfigArgs) => ({
test: /\.(jpe?g|png|svg|gif)(\?.+?)?$/,
// it's convenient to inline images as data-urls to make sure that publised
// library artifacts only produce importable javascript assets
type: 'asset/inline',
Copy link
Collaborator Author

@gribnoysup gribnoysup Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just easier not to deal with them for compass-web which is published as a library, they are all relatively small (the biggest is like 5kb) so data-urls work well enough

});

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -223,7 +225,7 @@ export const sourceLoader = (args: ConfigArgs) => ({
nodeLoader(args).test,
cssLoader(args).test,
lessLoader(args).test,
assetsLoader(args).test,
resourceLoader(args).test,
sharedObjectLoader(args).test,
// Produced by html-webpack-plugin and should not be handled
/\.(ejs|html)$/,
Expand Down
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/compass-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@
"test-cov": "nyc --compact=false --produce-source-map=false -x \"**/*.spec.*\" --reporter=lcov --reporter=text --reporter=html npm run test",
"test-watch": "npm run test -- --watch",
"test-ci": "npm run test-cov",
"reformat": "npm run eslint . -- --fix && npm run prettier -- --write ."
"reformat": "npm run eslint . -- --fix && npm run prettier -- --write .",
"upload": "node --experimental-strip-types scripts/upload.mts"
},
"peerDependencies": {
"react": "^17.0.2",
Expand Down Expand Up @@ -114,6 +115,7 @@
"@types/react": "^17.0.5",
"@types/react-dom": "^17.0.10",
"@types/sinon-chai": "^3.2.5",
"aws-sdk": "^2.1692.0",
"browser-process-hrtime": "^1.0.0",
"bson": "^6.10.4",
"buffer": "^6.0.3",
Expand Down
89 changes: 89 additions & 0 deletions packages/compass-web/scripts/upload.mts
Copy link
Collaborator Author

@gribnoysup gribnoysup Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is maybe an argument for this code to be a part of hadron-build upload script, but I didn't want to add to the code we already know we need to heavily refactor in the future. Keeping it closer to compass-web seems reasonable to me for now, we can move this all to one place later down the road

Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import fs from 'fs';
import path from 'path';
import child_process from 'child_process';
import { brotliCompressSync } from 'zlib';
import { promisify } from 'util';
import S3 from 'aws-sdk/clients/s3.js';

// TODO(SRE-4971): replace with a compass-web-only bucket when provisioned
const DOWNLOADS_BUCKET = 'cdn-origin-compass';

const DIST_DIR = path.resolve(import.meta.dirname, '..', 'dist');

const HEAD = child_process
.spawnSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf8' })
.stdout.trim();

function getCredentials() {
if (
!process.env.DOWNLOAD_CENTER_NEW_AWS_ACCESS_KEY_ID ||
!process.env.DOWNLOAD_CENTER_NEW_AWS_SECRET_ACCESS_KEY ||
!process.env.DOWNLOAD_CENTER_NEW_AWS_SESSION_TOKEN
) {
throw new Error('Missing required env variables');
}
return {
accessKeyId: process.env.DOWNLOAD_CENTER_NEW_AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.DOWNLOAD_CENTER_NEW_AWS_SECRET_ACCESS_KEY,
sessionToken: process.env.DOWNLOAD_CENTER_NEW_AWS_SESSION_TOKEN,
};
}

const artifacts = await fs.promises.readdir(DIST_DIR);

if (!artifacts.length) {
throw new Error('No artifact files found');
}

const contentTypeForExt: Record<string, string> = {
'.mjs': 'text/javascript',
'.txt': 'text/plain', // extracted third party license info
'.ts': 'text/typescript', // type definitions
'.json': 'application/json', // tsdoc meta
};

const ALLOWED_EXTS = Object.keys(contentTypeForExt);

for (const file of artifacts) {
if (!ALLOWED_EXTS.includes(path.extname(file))) {
throw new Error(`Unexpected artifact file extension for ${file}`);
}
}

const s3Client = new S3({
credentials: getCredentials(),
});

for (const file of artifacts) {
const filePath = path.join(DIST_DIR, file);
// NB: important that upload root directory is always `compass/`
const objectKey = `compass/web/${HEAD}/${file}`;

console.log(
'Uploading compass-web/dist/%s to s3://%s/%s ...',
file,
DOWNLOADS_BUCKET,
objectKey
);

const fileContent = fs.readFileSync(filePath, 'utf8');
const compressedFileContent = brotliCompressSync(fileContent);

const asyncPutObject: (
params: S3.Types.PutObjectRequest
) => Promise<S3.Types.PutObjectOutput> = promisify(
s3Client.putObject.bind(s3Client)
);

const res = await asyncPutObject({
ACL: 'private',
Bucket: DOWNLOADS_BUCKET,
Key: objectKey,
Body: compressedFileContent,
ContentType: contentTypeForExt[path.extname(file)],
ContentEncoding: 'br',
ContentLength: compressedFileContent.byteLength,
});

console.log('Successfully uploaded %s (ETag: %s)', file, res.ETag);
}
Loading