Skip to content

chore(e2e): add Dockerfile for e2e test runner CLOUDP-274595 #6790

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
101 changes: 101 additions & 0 deletions packages/compass-e2e-tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# This Dockerfile builds and image that allows you to run compass e2e tests
# in a docker container without the need to do all the extra setup
#
# Usage:
#
# # build the image first, by default compass repo will by pulled from remote
# docker build \
# --platform=linux/amd64 \
# -f ./packages/compass-e2e-tests/Dockerfile .
#
# # you can build from a specific compass repo revision
# docker build \
# --platform=linux/amd64 \
# --build-arg="COMPASS_VERSION=#v1.45.0" \
# -f ./packages/compass-e2e-tests/Dockerfile .
#
# # you can also build from local
# docker build \
# --platform=linux/amd64 \
# --build-arg="COMPASS_REPO=./" \
# -f ./packages/compass-e2e-tests/Dockerfile .
#
# # run all web tests (default command)
# docker run --rm -it <image id>
#
# # run with a custom command (this runs filtered tests for desktop)
# docker run --rm -it <image id> desktop --test-filter=time-to-first-query
#
# # e2e env configuration is also supported (this runs filtered web tests)
# docker run -e COMPASS_E2E_TEST_FILTER="time-to-first-query" --rm -it <image id>

FROM ubuntu:20.04
USER root

ARG NVM_VERSION="0.40.1"
ARG NODE_VERSION="20.16.0"
ENV NODE_VERSION=${NODE_VERSION}
ARG NPM_VERSION="10.2.4"
ENV NPM_VERSION=${NPM_VERSION}
# By default will pull compass from git, can be overriden with a local path
ARG COMPASS_REPO="https://github.com/mongodb-js/compass.git"
# When COMPASS_REPO points to the git repository, can be used to fetch repo with
# a certain tag / branch. Should start with #: `#v1.42.0`
ARG COMPASS_VERSION=""

WORKDIR /tmp/compass

ADD ${COMPASS_REPO}${COMPASS_VERSION} .
ADD https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh install_nvm.sh

ENV DEBIAN_FRONTEND=noninteractive
# Default address, this will become available before we start running tests
ENV DBUS_SESSION_BUS_ADDRESS=unix:path=/var/run/dbus/system_bus_socket
# Required by some compass deps
ENV CXX=gcc-11

RUN <<EOF
# Add toolchain repo
apt-get update
apt-get install -y software-properties-common
add-apt-repository -y ppa:ubuntu-toolchain-r/test
# Update again so we can install build deps
apt-get update
apt-get upgrade -y
# Now finally install the deps (build and electron / chromium runtime)
bash .evergreen/retry-with-backoff.sh apt-get install -y \
xvfb curl python3 build-essential libkrb5-dev libsecret-1-dev gcc-11 g++-11 \
xorg dbus-x11 libgtk-3-0 libnss3-dev libxss-dev libgbm-dev libasound2
EOF

ENV NVM_DIR=/root/.nvm
ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}"
ENV NODE_OPTIONS="--max-old-space-size=4096"

RUN <<EOF
# Install node, npm
bash install_nvm.sh
. "${NVM_DIR}/nvm.sh"
nvm install ${NODE_VERSION}
npm i -g npm@${NPM_VERSION}
node --version
npm --version
# Install monorepo deps and bootstrap compass-e2e-tests package
bash .evergreen/retry-with-backoff.sh .evergreen/npm_ci.sh
npx lerna run bootstrap --scope compass-e2e-tests --include-dependencies
# Prepare entrypoint file
echo "#! /usr/bin/env bash\n" \
"set -e\n" \
"service dbus start\n" \
"npm run -w compass-e2e-tests test -- \$@" >./entrypoint.sh
chmod +x ./entrypoint.sh
EOF

ENV DEBUG="compass-e2e-tests*,electron*,hadron*,mongo*"
ENV MONGODB_VERSION="8.0.x-enterprise"
ENV MONGODB_RUNNER_VERSION="8.0.x-enterprise"
ENV COMPASS_E2E_WEBDRIVER_WAITFOR_TIMEOUT="240000"
ENV COMPASS_E2E_WEBDRIVER_WAITFOR_INTERVAL="1000"

ENTRYPOINT ["./entrypoint.sh"]
CMD ["web"]
27 changes: 15 additions & 12 deletions packages/compass-e2e-tests/helpers/chrome-startup-flags.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copied from https://github.com/webdriverio/webdriverio/blob/1825c633aead82bc650dff1f403ac30cff7c7cb3/packages/devtools/src/constants.ts
// These are the default flags that webdriverio uses to start Chrome driver.
// NOTE: this has since been removed along with the devtools automation protocol https://github.com/webdriverio/webdriverio/commit/28e64e439ffc36a95f24aeda9f1d21111429dfa3#diff-6ea151d6c0687197931735239f397b7f5f0140a588c5b2b82ff584bbe73be069
const DEFAULT_WEBDRIVER_FLAGS = [
export const DEFAULT_WEBDRIVER_FLAGS = [
// suppresses Save Password prompt window
'--enable-automation',
// do not block popups
Expand Down Expand Up @@ -45,7 +45,7 @@ const DEFAULT_WEBDRIVER_FLAGS = [
];

// These flags are used to start Chrome driver based on the CI requirements.
const CI_FLAGS = [
export const CI_FLAGS = [
// Chromecast feature that is enabled by default in some chrome versions
// and breaks the app on Ubuntu
'--media-router=0',
Expand All @@ -55,21 +55,24 @@ const CI_FLAGS = [
// Seeing gpu init related errors on at least RHEL, especially when starting
// the CLI
'--disable-gpu',
'--num-raster-threads=0',
// Seems like disabling gpu is not always enough to prevent chromium from
// spawning it anyway, activating in process gpu seems to help with that
//
// See https://github.com/electron/electron/issues/28164 and
// https://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome/
'--in-process-gpu',
];

// These flags are used to start Chrome driver based on the Compass requirements.
const COMPASS_FLAGS = [
// The shared set of flags that are used to start Chrome when running Compass
// desktop and web tests in CLI or GUI mode.
export const CHROME_STARTUP_FLAGS = [...DEFAULT_WEBDRIVER_FLAGS, ...CI_FLAGS];

// These flags are used to start Chrome based on the Compass requirements.
export const COMPASS_FLAGS = [
// Allow options such as --user-data-dir to pass through the command line
// flag validation code.
'--ignore-additional-command-line-flags',
// Use the Atlas dev server for generative ai and atlas requests (cloud-dev).
'--atlasServiceBackendPreset=atlas-dev',
];

// The shared set of flags that are used to start Chrome driver when running Compass
// tests in CLI or GUI mode.
export const CHROME_STARTUP_FLAGS = [
...DEFAULT_WEBDRIVER_FLAGS,
...CI_FLAGS,
...COMPASS_FLAGS,
];
15 changes: 13 additions & 2 deletions packages/compass-e2e-tests/helpers/compass-web-sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from './test-runner-paths';
import type { ConnectionInfo } from '@mongodb-js/connection-info';
import ConnectionString from 'mongodb-connection-string-url';
import { CHROME_STARTUP_FLAGS } from './chrome-startup-flags';

const debug = Debug('compass-e2e-tests:compass-web-sandbox');

Expand All @@ -31,7 +32,16 @@ const wait = (ms: number) => {
export function spawnCompassWebSandbox() {
const proc = crossSpawn.spawn(
'npm',
['run', '--unsafe-perm', 'start', '--workspace', '@mongodb-js/compass-web'],
[
'run',
'--unsafe-perm',
'--workspace',
'@mongodb-js/compass-web',
'start',
'--',
'--no-sandbox',
'--in-process-gpu',
],
{ env: process.env }
);
proc.stdout.pipe(process.stdout);
Expand All @@ -56,7 +66,7 @@ export async function waitForCompassWebSandboxToBeReady(
}
// No point in trying to fetch sandbox URL right away, give the spawn script
// some time to run
await wait(2000);
await wait(5000);
try {
const res = await fetch(sandboxUrl);
serverReady = res.ok;
Expand Down Expand Up @@ -90,6 +100,7 @@ export async function spawnCompassWebSandboxAndSignInToAtlas(
'goog:chromeOptions': {
binary: ELECTRON_PATH,
args: [
...CHROME_STARTUP_FLAGS,
`--user-data-dir=${COMPASS_WEB_WDIO_USER_DATA_PATH}`,
`--app=${COMPASS_WEB_SANDBOX_RUNNER_PATH}`,
],
Expand Down
9 changes: 7 additions & 2 deletions packages/compass-e2e-tests/helpers/compass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type { CompassBrowser } from './compass-browser';
import type { LogEntry } from './telemetry';
import Debug from 'debug';
import semver from 'semver';
import { CHROME_STARTUP_FLAGS } from './chrome-startup-flags';
import { CHROME_STARTUP_FLAGS, COMPASS_FLAGS } from './chrome-startup-flags';
import {
DEFAULT_CONNECTION_STRINGS,
DEFAULT_CONNECTION_NAMES,
Expand Down Expand Up @@ -494,6 +494,7 @@ export async function runCompassOnce(args: string[], timeout = 30_000) {
// When running binary without webdriver, we need to pass the same flags
// as we pass when running with webdriverio to have similar behaviour.
...CHROME_STARTUP_FLAGS,
...COMPASS_FLAGS,
`--user-data-dir=${String(defaultUserDataDir)}`,
...args,
],
Expand Down Expand Up @@ -598,6 +599,8 @@ async function startCompassElectron(
const { needsCloseWelcomeModal, webdriverOptions, wdioOptions, chromeArgs } =
await processCommonOpts(opts);

chromeArgs.push(...COMPASS_FLAGS);

if (!testPackagedApp) {
// https://www.electronjs.org/docs/latest/tutorial/automated-testing#with-webdriverio
chromeArgs.push(`--app=${COMPASS_DESKTOP_PATH}`);
Expand Down Expand Up @@ -761,14 +764,16 @@ export async function startBrowser(
assertTestingWeb(context);

runCounter++;
const { webdriverOptions, wdioOptions } = await processCommonOpts();
const { webdriverOptions, wdioOptions, chromeArgs } =
await processCommonOpts();

const browserCapabilities: Record<string, Record<string, unknown>> = {
chrome: {
'goog:chromeOptions': {
prefs: {
'download.default_directory': downloadPath,
},
args: chromeArgs,
},
},
firefox: {
Expand Down
1 change: 1 addition & 0 deletions packages/compass-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"scripts": {
"prepublishOnly": "npm run compile && compass-scripts check-exports-exist",
"compile": "npm run webpack -- --mode production",
"prewebpack": "echo \"making sure compass webpack config is up to date...\" && npm run compile --workspace=@mongodb-js/webpack-config-compass",
"webpack": "webpack-compass",
"postcompile": "npm run typescript",
"typescript": "tsc -p tsconfig-build.json --emitDeclarationOnly",
Expand Down
2 changes: 1 addition & 1 deletion packages/compass-web/scripts/electron-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ void electronApp.dock?.hide();

logger.log('[electron-proxy] starting proxy server on port %s', PROXY_PORT);

const proxyServer = expressProxy.listen(PROXY_PORT, 'localhost');
const proxyServer = expressProxy.listen(PROXY_PORT, '0.0.0.0');

/**
* Keeping a track of websocket proxy sockets so that we can clean them up on
Expand Down
2 changes: 1 addition & 1 deletion packages/compass-web/scripts/ws-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { WebSocketServer } = require('ws');
* every follow-up message is directly written to the opened socket stream
*/
function createWebSocketProxy(port = 1337, logger = console) {
const wsServer = new WebSocketServer({ host: 'localhost', port }, () => {
const wsServer = new WebSocketServer({ host: '0.0.0.0', port }, () => {
logger.log('ws server listening at %s', wsServer.options.port);
});

Expand Down
3 changes: 2 additions & 1 deletion packages/compass/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,13 @@
"scripts": {
"install": "node scripts/download-fonts.js && node scripts/download-csfle.js",
"electron-rebuild": "node scripts/electron-rebuild.js",
"prestart": "npm run electron-rebuild && npm run compile --workspace=@mongodb-js/webpack-config-compass",
"prestart": "npm run electron-rebuild",
"start": "HADRON_DISTRIBUTION=${HADRON_DISTRIBUTION:-compass} npm run webpack serve -- --mode development",
"test-electron": "npm run test-main && npm run test-renderer",
"test-main": "xvfb-maybe electron-mocha --no-sandbox \"./src/main/**/*.spec.*\" \"./src/main/**/*.test.*\"",
"test-renderer": "xvfb-maybe electron-mocha --no-sandbox --config ./.mocharc.renderer.js \"./src/app/**/*.spec.*\"",
"check": "npm run typecheck && npm run lint && npm run depcheck",
"prewebpack": "echo \"making sure compass webpack config is up to date...\" && npm run compile --workspace=@mongodb-js/webpack-config-compass",
"webpack": "webpack-compass",
"compile": "npm run webpack -- --mode production",
"postcompile": "npm run generate-3rd-party-notices",
Expand Down
Loading