diff --git a/utils/docker/Dockerfile.jammy b/utils/docker/Dockerfile.jammy index 626bdb48c69ef..3a13ca2f7a348 100644 --- a/utils/docker/Dockerfile.jammy +++ b/utils/docker/Dockerfile.jammy @@ -11,7 +11,6 @@ ENV LC_ALL=C.UTF-8 # === INSTALL Node.js === RUN apt-get update && \ - # Install Node.js apt-get install -y curl wget gpg ca-certificates && \ mkdir -p /etc/apt/keyrings && \ curl -sL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ @@ -27,33 +26,28 @@ RUN apt-get update && \ adduser pwuser # === BAKE BROWSERS INTO IMAGE === +# Browsers are split into separate layers to enable parallel pulls. ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright # 1. Add tip-of-tree Playwright package to install its browsers. # The package should be built beforehand from tip-of-tree Playwright. COPY ./playwright-core.tar.gz /tmp/playwright-core.tar.gz +COPY ./install_browsers.sh /tmp/install_browsers.sh -# 2. Bake in browsers & deps. -# Browsers will be downloaded in `/ms-playwright`. -# Note: make sure to set 777 to the registry so that any user can access -# registry. -RUN mkdir /ms-playwright && \ - mkdir /ms-playwright-agent && \ - cd /ms-playwright-agent && npm init -y && \ - npm i /tmp/playwright-core.tar.gz && \ - npm exec --no -- playwright-core mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \ - npm exec --no -- playwright-core install --with-deps && rm -rf /var/lib/apt/lists/* && \ +# 2. Set up playwright-core and install all system dependencies in one layer. +RUN /tmp/install_browsers.sh install-deps && \ # Workaround for https://github.com/microsoft/playwright/issues/27313 # While the gstreamer plugin load process can be in-process, it ended up throwing # an error that it can't have libsoup2 and libsoup3 in the same process because # libgstwebrtc is linked against libsoup2. So we just remove the plugin. - if [ "$(uname -m)" = "aarch64" ]; then \ - rm /usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstwebrtc.so; \ - else \ - rm /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstwebrtc.so; \ - fi && \ - rm /tmp/playwright-core.tar.gz && \ - rm -rf /ms-playwright-agent && \ - rm -rf ~/.npm/ && \ - chmod -R 777 /ms-playwright + /tmp/install_browsers.sh remove-gstwebrtc + +# 3. Install each browser binary in its own layer for parallel pulling. +# Note: installing chromium also installs chromium-headless-shell and ffmpeg. +RUN /tmp/install_browsers.sh chromium + +RUN /tmp/install_browsers.sh firefox + +RUN /tmp/install_browsers.sh webkit && \ + /tmp/install_browsers.sh cleanup diff --git a/utils/docker/Dockerfile.noble b/utils/docker/Dockerfile.noble index 74bf34c0ac862..3b373faba7dff 100644 --- a/utils/docker/Dockerfile.noble +++ b/utils/docker/Dockerfile.noble @@ -11,7 +11,6 @@ ENV LC_ALL=C.UTF-8 # === INSTALL Node.js === RUN apt-get update && \ - # Install Node.js apt-get install -y curl wget gpg ca-certificates && \ mkdir -p /etc/apt/keyrings && \ curl -sL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ @@ -27,24 +26,23 @@ RUN apt-get update && \ adduser pwuser # === BAKE BROWSERS INTO IMAGE === +# Browsers are split into separate layers to enable parallel pulls. ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright # 1. Add tip-of-tree Playwright package to install its browsers. # The package should be built beforehand from tip-of-tree Playwright. COPY ./playwright-core.tar.gz /tmp/playwright-core.tar.gz +COPY ./install_browsers.sh /tmp/install_browsers.sh -# 2. Bake in browsers & deps. -# Browsers will be downloaded in `/ms-playwright`. -# Note: make sure to set 777 to the registry so that any user can access -# registry. -RUN mkdir /ms-playwright && \ - mkdir /ms-playwright-agent && \ - cd /ms-playwright-agent && npm init -y && \ - npm i /tmp/playwright-core.tar.gz && \ - npm exec --no -- playwright-core mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \ - npm exec --no -- playwright-core install --with-deps && rm -rf /var/lib/apt/lists/* && \ - rm /tmp/playwright-core.tar.gz && \ - rm -rf /ms-playwright-agent && \ - rm -rf ~/.npm/ && \ - chmod -R 777 /ms-playwright +# 2. Set up playwright-core and install all system dependencies in one layer. +RUN /tmp/install_browsers.sh install-deps + +# 3. Install each browser binary in its own layer for parallel pulling. +# Note: installing chromium also installs chromium-headless-shell and ffmpeg. +RUN /tmp/install_browsers.sh chromium + +RUN /tmp/install_browsers.sh firefox + +RUN /tmp/install_browsers.sh webkit && \ + /tmp/install_browsers.sh cleanup diff --git a/utils/docker/Dockerfile.resolute b/utils/docker/Dockerfile.resolute index 654c66edf9ed7..9ad8e1d951614 100644 --- a/utils/docker/Dockerfile.resolute +++ b/utils/docker/Dockerfile.resolute @@ -27,24 +27,23 @@ RUN apt-get update && \ adduser pwuser # === BAKE BROWSERS INTO IMAGE === +# Browsers are split into separate layers to enable parallel pulls. ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright # 1. Add tip-of-tree Playwright package to install its browsers. # The package should be built beforehand from tip-of-tree Playwright. COPY ./playwright-core.tar.gz /tmp/playwright-core.tar.gz +COPY ./install_browsers.sh /tmp/install_browsers.sh -# 2. Bake in browsers & deps. -# Browsers will be downloaded in `/ms-playwright`. -# Note: make sure to set 777 to the registry so that any user can access -# registry. -RUN mkdir /ms-playwright && \ - mkdir /ms-playwright-agent && \ - cd /ms-playwright-agent && npm init -y && \ - npm i /tmp/playwright-core.tar.gz && \ - npm exec --no -- playwright-core mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \ - npm exec --no -- playwright-core install --with-deps && rm -rf /var/lib/apt/lists/* && \ - rm /tmp/playwright-core.tar.gz && \ - rm -rf /ms-playwright-agent && \ - rm -rf ~/.npm/ && \ - chmod -R 777 /ms-playwright +# 2. Set up playwright-core and install all system dependencies in one layer. +RUN /tmp/install_browsers.sh install-deps + +# 3. Install each browser binary in its own layer for parallel pulling. +# Note: installing chromium also installs chromium-headless-shell and ffmpeg. +RUN /tmp/install_browsers.sh chromium + +RUN /tmp/install_browsers.sh firefox + +RUN /tmp/install_browsers.sh webkit && \ + /tmp/install_browsers.sh cleanup diff --git a/utils/docker/install_browsers.sh b/utils/docker/install_browsers.sh new file mode 100755 index 0000000000000..d64a1751e1e31 --- /dev/null +++ b/utils/docker/install_browsers.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -euo pipefail + +case "${1:-}" in + install-deps) + install -d -m 777 /ms-playwright /ms-playwright/.links + mkdir /ms-playwright-agent + cd /ms-playwright-agent + npm init -y + npm i /tmp/playwright-core.tar.gz + npm exec --no -- playwright-core mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" + npm exec --no -- playwright-core install-deps + rm -rf /var/lib/apt/lists/* + ;; + remove-gstwebrtc) + if [ "$(uname -m)" = "aarch64" ]; then + rm /usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstwebrtc.so + else + rm /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstwebrtc.so + fi + ;; + chromium) + cd /ms-playwright-agent + npm exec --no -- playwright-core install chromium + chmod -R 777 /ms-playwright/chromium-* /ms-playwright/chromium_headless_shell-* /ms-playwright/ffmpeg-* + ;; + firefox) + cd /ms-playwright-agent + npm exec --no -- playwright-core install firefox + chmod -R 777 /ms-playwright/firefox-* + ;; + webkit) + cd /ms-playwright-agent + npm exec --no -- playwright-core install webkit + chmod -R 777 /ms-playwright/webkit-* + ;; + cleanup) + rm /tmp/playwright-core.tar.gz + rm -rf /ms-playwright-agent + rm -rf ~/.npm/ + rm /tmp/install_browsers.sh + ;; + *) + echo "usage: $(basename "$0") {install-deps|remove-gstwebrtc|chromium|firefox|webkit|cleanup}" + exit 1 + ;; +esac diff --git a/utils/docker/test_docker.sh b/utils/docker/test_docker.sh new file mode 100755 index 0000000000000..448569571cbfd --- /dev/null +++ b/utils/docker/test_docker.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ $# -lt 1 ]]; then + echo "usage: $(basename "$0") {jammy,noble,resolute} [amd64|arm64]" + exit 1 +fi + +FLAVOR="$1" +ARCH="${2:-amd64}" + +if [[ "$FLAVOR" != "jammy" && "$FLAVOR" != "noble" && "$FLAVOR" != "resolute" ]]; then + echo "ERROR: unknown flavor '$FLAVOR' (expected jammy, noble, or resolute)" + exit 1 +fi + +if [[ "$ARCH" != "amd64" && "$ARCH" != "arm64" ]]; then + echo "ERROR: unknown arch '$ARCH' (expected amd64 or arm64)" + exit 1 +fi + +ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)" +IMAGE_TAG="playwright:localbuild-${FLAVOR}-${ARCH}" +CONTAINER_NAME="docker-tests-${FLAVOR}-${ARCH}" + +cleanup() { + docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 || true +} + +trap cleanup EXIT + +cd "${ROOT_DIR}/utils/docker" +./build.sh "--${ARCH}" "${FLAVOR}" "${IMAGE_TAG}" + +docker run \ + --rm \ + --name "${CONTAINER_NAME}" \ + --platform "linux/${ARCH}" \ + --user=pwuser \ + --workdir /home/pwuser \ + --env CI \ + --env INSIDE_DOCKER=1 \ + -v ~/.azure:/root/.azure \ + -d \ + -t \ + "${IMAGE_TAG}" /bin/bash + +docker cp "${ROOT_DIR}" "${CONTAINER_NAME}:/home/pwuser/playwright" +docker exec --user root "${CONTAINER_NAME}" chown -R pwuser /home/pwuser/playwright +docker exec \ + --user root \ + --workdir /home/pwuser/playwright "${CONTAINER_NAME}" /bin/bash -c ' + git config --global --add safe.directory /home/pwuser/playwright + ' + +docker exec --workdir /home/pwuser/playwright "${CONTAINER_NAME}" npm ci +docker exec --workdir /home/pwuser/playwright "${CONTAINER_NAME}" npm run build +docker exec --workdir /home/pwuser/playwright "${CONTAINER_NAME}" xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" npm run test -- --grep "@smoke"