Skip to content
Merged
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
8 changes: 3 additions & 5 deletions .azure-pipelines/publish-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ extends:
echo '{ "data-root": "/mnt/docker" }' | sudo tee /etc/docker/daemon.json
sudo service docker start

# Used by scripts/download_driver.sh on the host. The repository root is the
# Docker build context, so .dockerignore keeps this file out of the images.
# Used by scripts/download_driver.sh on the host. The Docker build context is
# utils/docker (see build.sh), so this file never reaches the images.
- task: Bash@3
displayName: "setup .npmrc"
inputs:
Expand Down Expand Up @@ -115,9 +115,7 @@ extends:
displayName: "Build & publish Docker images"
inputs:
targetType: "inline"
# The authenticated settings.xml is passed to `docker build` as a secret so
# that Maven inside the image also resolves from DevDiv_PublicPackages.
script: MAVEN_SETTINGS_SECRET="$HOME/.m2/settings.xml" ./utils/docker/publish_docker.sh ${{ parameters.releaseChannel }}
script: ./utils/docker/publish_docker.sh ${{ parameters.releaseChannel }}
env:
ACR_CACHE_PREFIX: "playwright.azurecr.io/cached/"
UBUNTU_MIRROR_PREFIX: "azure."
8 changes: 0 additions & 8 deletions .dockerignore

This file was deleted.

12 changes: 5 additions & 7 deletions .github/workflows/test_docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,11 @@ jobs:
- name: Copy repository inside docker container
run: |
docker cp . "$CONTAINER_ID":/home/pwuser/playwright
# /root/.m2 was populated as root during image build; move it to
# pwuser so the locally-installed SNAPSHOT artifacts resolve.
docker exec --user root "$CONTAINER_ID" bash -c '
chown -R pwuser /home/pwuser/playwright
mv /root/.m2 /home/pwuser/.m2
chown -R pwuser /home/pwuser/.m2
'
# build.sh installed the SNAPSHOT artifacts into the local Maven repository
# of the runner; give them to pwuser so the test projects resolve them.
docker exec "$CONTAINER_ID" mkdir -p /home/pwuser/.m2/repository/com/microsoft
docker cp ~/.m2/repository/com/microsoft/playwright "$CONTAINER_ID":/home/pwuser/.m2/repository/com/microsoft/playwright
docker exec --user root "$CONTAINER_ID" chown -R pwuser /home/pwuser/playwright /home/pwuser/.m2

- name: Run smoke tests in container
run: |
Expand Down
11 changes: 11 additions & 0 deletions utils/docker/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This directory is the Docker build context (see build.sh). The image build reads only
# the client jars staged in dist/ and the Maven tarball in maven/; keep everything else,
# such as the oras download of publish_docker.sh, out of the build context.
*
!dist
!maven
# Should the build context ever grow, keep VCS metadata, registry credentials and local
# environment files out of it regardless.
**/.git
**/.npmrc
**/.env*
2 changes: 1 addition & 1 deletion utils/docker/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
oras/

dist/
28 changes: 8 additions & 20 deletions utils/docker/Dockerfile.jammy
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ RUN find /etc/apt -type f \( -name '*.list' -o -name '*.sources' \) \
# Java 25, so we install latest Maven from Apache instead. build.sh
# downloads it into utils/docker/maven.
ARG MAVEN_VERSION
RUN --mount=type=bind,source=utils/docker/maven,target=/tmp/maven \
RUN --mount=type=bind,source=maven,target=/tmp/maven \
tar zxf /tmp/maven/apache-maven-$MAVEN_VERSION-bin.tar.gz -C /opt/ && \
ln -s /opt/apache-maven-$MAVEN_VERSION/bin/mvn /usr/local/bin/

Expand All @@ -50,25 +50,13 @@ ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# it into /tmp on every launch. See https://github.com/microsoft/playwright-java/issues/1268.
ENV PLAYWRIGHT_DRIVER_DIR=/ms-playwright-driver

RUN mkdir /ms-playwright && \
mkdir /tmp/pw-java

COPY . /tmp/pw-java

# The optional Maven settings secret routes dependency resolution through a mirror
# (see .azure-pipelines/publish-docker.yml).
RUN --mount=type=secret,id=mavensettings,target=/root/.m2/settings.xml,required=false \
cd /tmp/pw-java && \
mvn install -D skipTests --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install-driver" -f playwright/pom.xml --no-transfer-progress && \
DEBIAN_FRONTEND=noninteractive mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install-deps" -f playwright/pom.xml --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install" -f playwright/pom.xml --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="mark-docker-image '${DOCKER_IMAGE_NAME_TEMPLATE}'" -f playwright/pom.xml --no-transfer-progress && \
rm -rf /tmp/pw-java && \
# The client jar and its runtime dependencies, staged by build.sh, are only mounted to
# run the CLI; they do not go into the image.
RUN --mount=type=bind,source=dist,target=/tmp/pw-java \
mkdir /ms-playwright && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI install-driver && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI install --with-deps && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \
# 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
Expand Down
28 changes: 8 additions & 20 deletions utils/docker/Dockerfile.noble
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ RUN find /etc/apt -type f \( -name '*.list' -o -name '*.sources' \) \
# Java 25, so we install latest Maven from Apache instead. build.sh
# downloads it into utils/docker/maven.
ARG MAVEN_VERSION
RUN --mount=type=bind,source=utils/docker/maven,target=/tmp/maven \
RUN --mount=type=bind,source=maven,target=/tmp/maven \
tar zxf /tmp/maven/apache-maven-$MAVEN_VERSION-bin.tar.gz -C /opt/ && \
ln -s /opt/apache-maven-$MAVEN_VERSION/bin/mvn /usr/local/bin/

Expand All @@ -50,24 +50,12 @@ ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# it into /tmp on every launch. See https://github.com/microsoft/playwright-java/issues/1268.
ENV PLAYWRIGHT_DRIVER_DIR=/ms-playwright-driver

RUN mkdir /ms-playwright && \
mkdir /tmp/pw-java

COPY . /tmp/pw-java

# The optional Maven settings secret routes dependency resolution through a mirror
# (see .azure-pipelines/publish-docker.yml).
RUN --mount=type=secret,id=mavensettings,target=/root/.m2/settings.xml,required=false \
cd /tmp/pw-java && \
mvn install -D skipTests --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install-driver" -f playwright/pom.xml --no-transfer-progress && \
DEBIAN_FRONTEND=noninteractive mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install-deps" -f playwright/pom.xml --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install" -f playwright/pom.xml --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="mark-docker-image '${DOCKER_IMAGE_NAME_TEMPLATE}'" -f playwright/pom.xml --no-transfer-progress && \
rm -rf /tmp/pw-java && \
# The client jar and its runtime dependencies, staged by build.sh, are only mounted to
# run the CLI; they do not go into the image.
RUN --mount=type=bind,source=dist,target=/tmp/pw-java \
mkdir /ms-playwright && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI install-driver && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI install --with-deps && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \
chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH && \
chmod -R 777 $PLAYWRIGHT_DRIVER_DIR
26 changes: 7 additions & 19 deletions utils/docker/Dockerfile.resolute
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,12 @@ ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# it into /tmp on every launch. See https://github.com/microsoft/playwright-java/issues/1268.
ENV PLAYWRIGHT_DRIVER_DIR=/ms-playwright-driver

RUN mkdir /ms-playwright && \
mkdir /tmp/pw-java

COPY . /tmp/pw-java

# The optional Maven settings secret routes dependency resolution through a mirror
# (see .azure-pipelines/publish-docker.yml).
RUN --mount=type=secret,id=mavensettings,target=/root/.m2/settings.xml,required=false \
cd /tmp/pw-java && \
mvn install -D skipTests --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install-driver" -f playwright/pom.xml --no-transfer-progress && \
DEBIAN_FRONTEND=noninteractive mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install-deps" -f playwright/pom.xml --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="install" -f playwright/pom.xml --no-transfer-progress && \
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI \
-D exec.args="mark-docker-image '${DOCKER_IMAGE_NAME_TEMPLATE}'" -f playwright/pom.xml --no-transfer-progress && \
rm -rf /tmp/pw-java && \
# The client jar and its runtime dependencies, staged by build.sh, are only mounted to
# run the CLI; they do not go into the image.
RUN --mount=type=bind,source=dist,target=/tmp/pw-java \
mkdir /ms-playwright && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI install-driver && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI install --with-deps && \
java -cp '/tmp/pw-java/*' com.microsoft.playwright.CLI mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \
chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH && \
chmod -R 777 $PLAYWRIGHT_DRIVER_DIR
43 changes: 27 additions & 16 deletions utils/docker/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ if [[ ($1 == '--help') || ($1 == '-h') || ($1 == '') || ($2 == '') ]]; then
echo ""
echo " docker run --rm -it playwright:localbuild-noble /bin/bash"
echo ""
echo "NOTE: this requires on Playwright PIP dependencies to be installed"
echo "NOTE: this requires a JDK, Maven and npm on the host: the client is built here"
echo "and the image only runs it to install the browsers."
echo ""
exit 0
fi

function cleanup() {
:
rm -rf dist
}

trap "cleanup; cd $(pwd -P)" EXIT
Expand All @@ -34,21 +35,32 @@ fi

PW_TARGET_ARCH=$(echo $1 | cut -c3-)

# Assemble the driver on the host where npm is available; the Dockerfile picks
# it up via `COPY . /tmp/pw-java`.
../../scripts/download_driver.sh
# In the release pipeline ~/.m2/settings.xml routes all Maven downloads through the
# DevDiv_PublicPackages feed instead of Maven Central, which the agent cannot reach.
MVN=(mvn --no-transfer-progress)

# The jammy and noble images install this Maven (see the Dockerfiles). Fetch it with the
# host's Maven so that it resolves through the configured mirror: the release pipeline
# cannot reach Maven Central directly (see .azure-pipelines/settings.xml).
MAVEN_VERSION=3.9.12
mvn dependency:copy -Dartifact="org.apache.maven:apache-maven:${MAVEN_VERSION}:tar.gz:bin" \
-DoutputDirectory=maven --no-transfer-progress -q
# Like the other language ports, build the client on the host, where npm, a JDK and
# Maven are available, and stage the client jar and its runtime dependencies under
# dist/. The Dockerfile runs the CLI from there to install the browsers and their
# dependencies. The build context is this directory, so nothing else reaches the image.
../../scripts/download_driver.sh
"${MVN[@]}" -B install -D skipTests -f ../../pom.xml

SECRET_ARGS=()
if [[ -n "${MAVEN_SETTINGS_SECRET:-}" ]]; then
SECRET_ARGS+=(--secret "id=mavensettings,src=${MAVEN_SETTINGS_SECRET}")
if ! PW_VERSION=$("${MVN[@]}" -q -N -f ../../pom.xml exec:exec -D exec.executable=echo \
-D exec.args='${project.version}'); then
# With -q Maven prints its errors to stdout, which was captured above.
echo "ERROR: failed to read the project version: ${PW_VERSION}"
exit 1
fi
rm -rf dist
"${MVN[@]}" -q -f ../../playwright/pom.xml dependency:copy-dependencies \
-D includeScope=runtime -D outputDirectory="$PWD/dist"
cp "../../playwright/target/playwright-$PW_VERSION.jar" dist/

# The jammy and noble images install this Maven (see the Dockerfiles).
MAVEN_VERSION=3.9.12
"${MVN[@]}" -q dependency:copy -D artifact="org.apache.maven:apache-maven:${MAVEN_VERSION}:tar.gz:bin" \
-D outputDirectory=maven

# Keep each arch image a plain single-platform manifest without the unknown/unknown platform entry.
export BUILDX_NO_DEFAULT_ATTESTATIONS=1
Expand All @@ -69,8 +81,7 @@ for ((attempt = 1; attempt <= MAX_ATTEMPTS; attempt++)); do
--build-arg "MAVEN_VERSION=${MAVEN_VERSION}" \
--build-arg ACR_CACHE_PREFIX="${ACR_CACHE_PREFIX}" \
--build-arg UBUNTU_MIRROR_PREFIX="${UBUNTU_MIRROR_PREFIX}" \
"${SECRET_ARGS[@]}" \
-t "$3" -f "Dockerfile.$2" ../../; then
-t "$3" -f "Dockerfile.$2" .; then
exit 0
fi
if (( attempt < MAX_ATTEMPTS )); then
Expand Down
Loading