Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
11 changes: 8 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"name": "DoenetML Node & Rust DevContainer",
// 2026-05-18: Playwright doesn't currently support Ubuntu 26.04. When it does, this can be updated.
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04",
"remoteEnv": {
"DISPLAY": ""
},
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "lts"
Expand All @@ -11,14 +14,16 @@
},
// Install vim from apt using an existing community feature.
"ghcr.io/devcontainers-extra/features/apt-packages:1": {
"packages": "vim"
"packages": "vim libgtk-3-0 xvfb"
},
// Install files needed for WebDriver tests (e.g. doenetml-to-prefigure tests)
"./features/webdriver-libs": {},
// Avoid erronious connections to the host's debug environment.
// Avoid erroneous connections to the host's debug environment.
"./features/shell-init-rc": {},
// Install files needed for Python bundling
"./features/python": {}
"./features/python": {},
// Install files needed for Chrome for Cypress testing.
"./features/chrome": {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Rename this chromium

},
"containerEnv": {
"NODE_OPTIONS": " --max-old-space-size=6144 "
Expand Down
7 changes: 7 additions & 0 deletions .devcontainer/features/chrome/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"id": "chrome",
"version": "1.0.0",
"name": "Google Chrome",
"description": "Installs Google Chrome Stable and supporting dependencies for Cypress browser testing.",
"installsAfter": ["ghcr.io/devcontainers/features/common-utils"]
}
26 changes: 26 additions & 0 deletions .devcontainer/features/chrome/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail

export DEBIAN_FRONTEND=noninteractive

apt-get update

apt-get install -y \
wget \
gnupg \
ca-certificates

mkdir -p /etc/apt/keyrings

wget -qO- https://dl.google.com/linux/linux_signing_key.pub \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we don't need keys, can we remove these lines?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

After digging into this further, I noticed we're already installing a Playwright-managed Chromium browser as part of the Python feature:

PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers playwright install chromium

and I was able to verify that Cypress can successfully run against that Chromium binary directly.

Given that, I'm going to spend some time tomorrow exploring a Chromium-based implementation that reuses the existing Playwright installation instead of adding a separate system Chrome install.

There are still some challenges to work through:

  • Playwright installs Chromium in a versioned location (e.g. chromium-1234), so we'd need a stable way for Cypress to discover and launch it.
  • We'd need to validate the full Cypress workflow and ensure the solution is reliable across devcontainer rebuilds.
  • Browser lifecycle and versioning would become tied to Playwright's browser management rather than OS package management.
  • We'd effectively be wiring together two separate ecosystems that were not designed to manage each other's browser lifecycle.

For the current implementation, however, the PGP key setup is still required. The key is necessary for APT to trust Google's repository and perform the initial installation:

apt-get update
apt-get install -y --no-install-recommends google-chrome-stable

Without the key, that installation path would fail signature verification and Chrome would not install successfully. So if we keep the current APT-based approach, the keyring configuration needs to stay.

If we move entirely to the Playwright-managed Chromium approach, we could remove the Google repository and associated keys altogether. However, I expect that solution to be more fragile in the long term because it will require bridging Cypress' browser discovery and execution model with Playwright's browser installation and version-management model, introducing additional coordination, maintenance, and potential failure modes compared to a traditional system-installed browser.

That said, I still don't fully understand the objections to the system-browser approach. I would be perfectly happy to make that installation Chromium instead of Chrome if there were a reliable way to do so in this environment. Unfortunately, on Linux ARM64, the options we've explored so far have either been unavailable, Snap-based, unmaintained, or otherwise problematic.

Given those constraints, I still lean toward a stable system-installed browser. It keeps browser management at the operating-system level, aligns with how Cypress expects to discover and launch browsers, uses the same browser as GitHub Actions CI testing, and avoids introducing an implicit dependency between Cypress and Playwright-managed browser assets. I'll evaluate the Playwright Chromium approach tomorrow since it's already present and appears functional, but at the moment I view it as a workaround worth investigating in response to the concerns raised about the system-level install rather than a clearly cleaner or more maintainable solution than a conventional system-installed browser.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are you running on a mac? I thought the dev container was set up as an x86 container.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@siefkenj Yes, I am running on Mac. I could force the x86 build through emulation, but it would be much slower.

| gpg --dearmor \
> /etc/apt/keyrings/google-chrome.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/google-chrome.gpg] https://dl.google.com/linux/chrome/deb/ stable main" \
> /etc/apt/sources.list.d/google-chrome.list

apt-get update

apt-get install -y google-chrome-stable

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's change this to a chromium install. It's best to stay away from any "features" that chrome adds.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@siefkenj I tried the Ubuntu chromium-browser package, but on Ubuntu 24.04 ARM64 it resolves to a Snap-based stub rather than installing a working browser. As a result, Cypress is unable to detect any Chromium browser after installation and only sees Electron.

The previous Google Chrome feature worked correctly and allowed the existing Cypress workflows to run after addressing the DISPLAY issue. It also aligns with what the GitHub Actions CI jobs are currently using, since the Cypress diagnostics reported google-chrome as the browser executable for the CI test runs.

If Chromium is preferred, we'll likely need a different installation mechanism, such as a Playwright-managed Chromium install or another non-Snap Chromium distribution. Which direction would you like me to take?


google-chrome --version
47 changes: 47 additions & 0 deletions .devcontainer/features/chrome_for_testing/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
set -euo pipefail

export DEBIAN_FRONTEND=noninteractive

apt-get update
apt-get install -y --no-install-recommends \
wget \
unzip \
ca-certificates

mkdir -p /opt/chrome-for-testing

ARCH=$(dpkg --print-architecture)

case "$ARCH" in
amd64)
PLATFORM="linux64"
;;
arm64)
PLATFORM="linux-arm64"
;;
*)
echo "Unsupported architecture: $ARCH"
exit 1
;;
esac

URL="https://storage.googleapis.com/chrome-for-testing-public/LATEST_RELEASE_${PLATFORM}"

VERSION=$(wget -qO- "$URL")

wget -q \
"https://storage.googleapis.com/chrome-for-testing-public/${VERSION}/${PLATFORM}/chrome-${PLATFORM}.zip" \
-O /tmp/chrome.zip

unzip -q /tmp/chrome.zip -d /opt/chrome-for-testing

CHROME_BIN=$(find /opt/chrome-for-testing -type f -name chrome | head -n1)

ln -sf "${CHROME_BIN}" /usr/local/bin/google-chrome
ln -sf "${CHROME_BIN}" /usr/local/bin/google-chrome-stable

"${CHROME_BIN}" --version

rm -f /tmp/chrome.zip
rm -rf /var/lib/apt/lists/*
7 changes: 7 additions & 0 deletions .devcontainer/features/chromium/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"id": "chromium",
"version": "1.0.0",
"name": "Chromium",
"description": "Installs Chromium and supporting dependencies for Cypress browser testing.",
"installsAfter": ["ghcr.io/devcontainers/features/common-utils"]
}
27 changes: 27 additions & 0 deletions .devcontainer/features/chromium/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail

export DEBIAN_FRONTEND=noninteractive

apt-get update
apt-get install -y --no-install-recommends \
chromium-browser

# On Ubuntu, the `chromium-browser` package in the APT repositories is
# typically just a transitional package that redirects installation to
# the Snap version of Chromium. It does not install a standalone Chromium
# binary from APT, which can be problematic in containers and other
# environments where Snap is unavailable or unsupported.

# Cypress CI scripts currently use:
# cypress run -b chrome
#
# Provide Chrome-compatible executable names backed by Chromium so
# existing scripts continue to work.

ln -sf /usr/bin/chromium-browser /usr/local/bin/google-chrome
ln -sf /usr/bin/chromium-browser /usr/local/bin/google-chrome-stable

google-chrome --version

rm -rf /var/lib/apt/lists/*
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"prettier:format": "prettier --write .",
"publish": "npm run publish -w packages/doenetml -w packages/standalone -w packages/doenetml-iframe -w packages/v06-to-v07",
"test": "npm run test -ws --if-present -- run",
"test:preview": "npm run preview --workspace packages/test-cypress",
"test:all-no-worker-js": "echo \"NOTE: 'test:all-no-worker-js' uses a hard-coded workspace list; update this list when adding or removing workspaces.\" && npm --if-present run test -w packages/codemirror -w packages/debug-hooks -w packages/docs-nextra -w packages/doenetml -w packages/doenetml-iframe -w packages/doenetml-prototype -w packages/doenetml-to-pretext -w packages/doenetml-worker -w packages/doenetml-worker-rust -w packages/i18n -w packages/lsp -w packages/lsp-tools -w packages/memory-benchmark -w packages/parser -w packages/prefigure -w packages/standalone -w packages/static-assets -w packages/test-cypress -w packages/test-viewer -w packages/ui-components -w packages/utils -w packages/v06-to-v07 -w packages/virtual-keyboard -w packages/webwork-to-doenetml -w @doenet/vscode-extension -- run",
"test:e2e-group1": "npm run test:group1 -w packages/test-cypress",
"test:e2e-group2": "npm run test:group2 -w packages/test-cypress",
Expand Down