1
0
mirror of synced 2026-07-18 06:15:06 +00:00

Compare commits

..

4 Commits

Author SHA1 Message Date
Yury Semikhatsky 9d712e6f8c test: fix remaining windows bot failures
- accept all close-time error message variants in
  waitForNavigation-after-disconnect, the surfaced message depends on
  which call hits the closed connection first
- shouldDetachWhenPageCloses: only check that detach throws, like the
  upstream test
- skip @TempDir cleanup for user data dirs: on Windows Chromium 149
  keeps chrome_debug.log locked briefly after close
2026-06-12 13:20:30 -07:00
Yury Semikhatsky 4fb8a95178 chore: trim comments 2026-06-12 12:56:46 -07:00
Yury Semikhatsky 1d06a09651 test: fix failures on firefox, webkit and windows bots
- connectOverCDP is now supported in WebKit: skip the not-chromium test
  there and expect the new error message
- accept all close-time messages in waitForNavigation-after-disconnect
- wait 2s for page errors to accumulate, mirrors upstream #38378
- regenerate firefox screenshot expectations for Firefox 151
2026-06-12 12:56:46 -07:00
Yury Semikhatsky 0e3b273fbf chore: roll driver to 1.61.0-beta-1781285686000
Ported upstream changes:
- #40843 page.localStorage()/sessionStorage() (WebStorage API)
- #40849 context.credentials() WebAuthn virtual authenticator
- #40932 APIResponse.securityDetails()/serverAddr()
- #41162 ScreencastFrame.timestamp()
- #40916 screencast cursor and size options
- #40844 comma-separated testIdAttribute (getByTestId now uses internal:testid)
- #40718 waitForEventInfo replaced with fire-and-forget __waitInfo__
- #40780 protocol Page.close split into close and runBeforeUnload
- #40801 Frame.expect failures are now protocol errors with errorDetails
- #41014 connectOverCDP allowed for WebKit, artifactsDir option
2026-06-12 12:25:16 -07:00
24 changed files with 87 additions and 311 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ extends:
targetPath: $(Build.ArtifactStagingDirectory)/esrp-build
steps:
- checkout: none
- task: EsrpRelease@11
- task: EsrpRelease@9
inputs:
connectedservicename: 'Playwright-ESRP-PME'
usemanagedidentity: true
+2 -2
View File
@@ -13,7 +13,7 @@ jobs:
environment: Docker
if: github.repository == 'microsoft/playwright-java'
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Azure login
uses: azure/login@v3
with:
@@ -26,5 +26,5 @@ jobs:
uses: docker/setup-qemu-action@v4
with:
platforms: arm64
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- run: ./utils/docker/publish_docker.sh stable
+3 -3
View File
@@ -28,7 +28,7 @@ jobs:
browser: webkit
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Set up JDK 1.8
uses: actions/setup-java@v5
with:
@@ -73,7 +73,7 @@ jobs:
browser-channel: msedge
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Install Media Pack
if: matrix.os == 'windows-latest'
shell: powershell
@@ -108,7 +108,7 @@ jobs:
browser: [chromium, firefox, webkit]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
+2 -2
View File
@@ -13,9 +13,9 @@ jobs:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Cache Maven packages
uses: actions/cache@v6
uses: actions/cache@v5
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+2 -2
View File
@@ -26,7 +26,7 @@ jobs:
strategy:
fail-fast: false
matrix:
flavor: [jammy, noble, resolute]
flavor: [jammy, noble]
runs-on: [ubuntu-24.04, ubuntu-24.04-arm]
include:
- runs-on: ubuntu-24.04
@@ -34,7 +34,7 @@ jobs:
- runs-on: ubuntu-24.04-arm
arch: arm64
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Build Docker image
run: |
bash utils/docker/build.sh --${{ matrix.arch }} ${{ matrix.flavor }} playwright-java:localbuild-${{ matrix.flavor }}
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v6
- name: Download drivers
run: scripts/download_driver.sh
- name: Regenerate APIs
+1 -1
View File
@@ -20,7 +20,7 @@ git clone https://github.com/microsoft/playwright-java
cd playwright-java
```
2. Run the following script to download and assemble the Playwright driver. The platform-independent `playwright-core` package is assembled once into `driver/src/main/resources/driver/package/`, and the Node.js binary for each platform into `driver-bundle/src/main/resources/driver/<platform>/` (browser binaries for Chromium, Firefox and WebKit will be automatically downloaded later on first Playwright run).
2. Run the following script to download and assemble the Playwright driver for all platforms into `driver-bundle/src/main/resources/driver/` directory (browser binaries for Chromium, Firefox and WebKit will be automatically downloaded later on first Playwright run).
```bash
scripts/download_driver.sh
+15 -16
View File
@@ -10,23 +10,22 @@
</parent>
<artifactId>driver-bundle</artifactId>
<name>Playwright - Node.js For All Platforms</name>
<name>Playwright - Drivers For All Platforms</name>
<description>
Node.js binaries for the Playwright driver on every supported platform. Can be excluded when
Node.js is preinstalled on the host (see PLAYWRIGHT_NODEJS_PATH).
This module includes Playwright driver and related utilities for all supported platforms.
It is intended to be used on the systems where Playwright driver is not preinstalled.
</description>
<build>
<plugins>
<!-- The Node.js binaries for all platforms live in src/main/resources and must not
be packaged into the sources JAR (see issue #1913). -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<configuration>
<excludeResources>true</excludeResources>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>driver</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
</dependencies>
</project>
@@ -30,11 +30,17 @@ public class DriverJar extends Driver {
private static final String PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = "PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD";
private static final String SELENIUM_REMOTE_URL = "SELENIUM_REMOTE_URL";
private final Path driverTempDir;
private final boolean deleteOnExit;
private Path preinstalledNodePath;
public DriverJar() throws IOException {
this(createTempDriverDir(), true);
// Allow specifying custom path for the driver installation
// See https://github.com/microsoft/playwright-java/issues/728
String alternativeTmpdir = System.getProperty("playwright.driver.tmpdir");
String prefix = "playwright-java-";
driverTempDir = alternativeTmpdir == null
? Files.createTempDirectory(prefix)
: Files.createTempDirectory(Paths.get(alternativeTmpdir), prefix);
driverTempDir.toFile().deleteOnExit();
String nodePath = System.getProperty("playwright.nodejs.path");
if (nodePath != null) {
preinstalledNodePath = Paths.get(nodePath);
@@ -45,32 +51,6 @@ public class DriverJar extends Driver {
logMessage("created DriverJar: " + driverTempDir);
}
private DriverJar(Path driverDir, boolean deleteOnExit) {
this.driverTempDir = driverDir;
this.deleteOnExit = deleteOnExit;
if (deleteOnExit) {
driverTempDir.toFile().deleteOnExit();
}
}
private static Path createTempDriverDir() throws IOException {
// Allow specifying custom path for the driver installation
// See https://github.com/microsoft/playwright-java/issues/728
String alternativeTmpdir = System.getProperty("playwright.driver.tmpdir");
String prefix = "playwright-java-";
return alternativeTmpdir == null
? Files.createTempDirectory(prefix)
: Files.createTempDirectory(Paths.get(alternativeTmpdir), prefix);
}
// Extracts the driver (playwright-core package and the Node.js binary for the current platform)
// into the given directory, persistently. Point playwright.cli.dir / PLAYWRIGHT_DRIVER_DIR at it
// to run without extracting to a temp directory on every launch. See issue #1268.
public static void installDriverTo(Path driverDir) throws IOException, URISyntaxException {
Files.createDirectories(driverDir);
new DriverJar(driverDir, false).extractDriverToTempDir();
}
@Override
protected void initialize(Boolean installBrowsers) throws Exception {
if (preinstalledNodePath == null && env.containsKey(PLAYWRIGHT_NODEJS_PATH)) {
@@ -139,21 +119,7 @@ public class DriverJar extends Driver {
}
void extractDriverToTempDir() throws URISyntaxException, IOException {
extractResourceToDir("driver/package", driverTempDir.resolve("package"));
if (preinstalledNodePath == null) {
String platformResource = "driver/" + platformDir();
if (DriverJar.class.getClassLoader().getResource(platformResource) == null) {
throw new RuntimeException("Failed to find the bundled Node.js for platform '" + platformDir()
+ "'. Add the com.microsoft.playwright:driver-bundle dependency, or set the "
+ PLAYWRIGHT_NODEJS_PATH + " environment variable (or the playwright.nodejs.path system "
+ "property) to point at a preinstalled Node.js.");
}
extractResourceToDir(platformResource, driverTempDir);
}
}
private void extractResourceToDir(String resourcePath, Path destDir) throws URISyntaxException, IOException {
URI originalUri = DriverJar.class.getClassLoader().getResource(resourcePath).toURI();
URI originalUri = getDriverResourceURI();
URI uri = maybeExtractNestedJar(originalUri);
// Create zip filesystem if loading from jar.
@@ -165,8 +131,14 @@ public class DriverJar extends Driver {
// See https://github.com/microsoft/playwright-java/issues/306
Path srcRootDefaultFs = Paths.get(srcRoot.toString());
Files.walk(srcRoot).forEach(fromPath -> {
if (preinstalledNodePath != null) {
String fileName = fromPath.getFileName().toString();
if ("node.exe".equals(fileName) || "node".equals(fileName)) {
return;
}
}
Path relative = srcRootDefaultFs.relativize(Paths.get(fromPath.toString()));
Path toPath = destDir.resolve(relative.toString());
Path toPath = driverTempDir.resolve(relative.toString());
try {
if (Files.isDirectory(fromPath)) {
Files.createDirectories(toPath);
@@ -176,9 +148,7 @@ public class DriverJar extends Driver {
toPath.toFile().setExecutable(true, true);
}
}
if (deleteOnExit) {
toPath.toFile().deleteOnExit();
}
toPath.toFile().deleteOnExit();
} catch (IOException e) {
throw new RuntimeException("Failed to extract driver from " + uri + ", full uri: " + originalUri, e);
}
@@ -201,9 +171,7 @@ public class DriverJar extends Driver {
Path fromPath = Paths.get(jarUri);
Path toPath = driverTempDir.resolve(fromPath.getFileName().toString());
Files.copy(fromPath, toPath);
if (deleteOnExit) {
toPath.toFile().deleteOnExit();
}
toPath.toFile().deleteOnExit();
return new URI("jar:" + toPath.toUri() + JAR_URL_SEPARATOR + parts[2]);
} catch (IOException e) {
throw new RuntimeException("Failed to extract driver's nested .jar from " + jarUri + "; full uri: " + uri, e);
@@ -132,30 +132,6 @@ public class TestInstall {
}
@Test
void canInstallDriverToDirectoryAndReuseIt(@TempDir Path tmpDir) throws Exception {
Path driverDir = tmpDir.resolve("driver");
DriverJar.installDriverTo(driverDir);
// The directory is self-contained: the playwright-core package and the Node.js binary.
assertTrue(Files.exists(driverDir.resolve("package").resolve("cli.js")));
assertTrue(Files.exists(driverDir.resolve(isWindows() ? "node.exe" : "node")));
// Pointing playwright.cli.dir at it must reuse it as-is, without extracting to a temp directory.
System.setProperty("playwright.cli.dir", driverDir.toString());
Driver driver = Driver.createAndInstall(Collections.emptyMap(), false);
assertEquals(driverDir, driver.driverDir());
ProcessBuilder pb = driver.createProcessBuilder();
pb.command().add("--version");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
Path out = tmpDir.resolve("out.txt");
pb.redirectOutput(out.toFile());
Process p = pb.start();
assertTrue(p.waitFor(1, TimeUnit.MINUTES), "Timed out waiting for version to be printed");
String stdout = new String(Files.readAllBytes(out), StandardCharsets.UTF_8);
assertTrue(stdout.contains("Version "), stdout);
}
private static String extractNodeJsToTemp() throws URISyntaxException, IOException {
DriverJar auxDriver = new DriverJar();
auxDriver.extractDriverToTempDir();
+1 -16
View File
@@ -12,8 +12,7 @@
<artifactId>driver</artifactId>
<name>Playwright - Driver</name>
<description>
API for launching the Playwright driver. Bundles the platform-independent playwright-core
package; the Node.js binary comes from the driver-bundle module or a preinstalled Node.js.
This module provides API for discovery and launching of Playwright driver.
</description>
<dependencies>
@@ -22,18 +21,4 @@
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- The playwright-core package lives in src/main/resources and must not be packaged
into the sources JAR (see issue #1913). -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<configuration>
<excludeResources>true</excludeResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -25,14 +25,12 @@ import static com.microsoft.playwright.impl.driver.DriverLogging.logWithTimestam
/**
* This class provides access to playwright-cli. It can be either preinstalled
* in the host system and its path is passed as a system property, or it can be
* loaded from the classpath: the platform-independent driver code ships in the
* driver module and the Node.js binary in the optional driver-bundle module.
* in the host system and its path is passed as a system property or it can be
* loaded from the driver-bundle module if that module is in the classpath.
*/
public abstract class Driver {
protected final Map<String, String> env = new LinkedHashMap<>(System.getenv());
public static final String PLAYWRIGHT_NODEJS_PATH = "PLAYWRIGHT_NODEJS_PATH";
public static final String PLAYWRIGHT_DRIVER_DIR = "PLAYWRIGHT_DRIVER_DIR";
private static Driver instance;
@@ -109,12 +107,9 @@ public abstract class Driver {
}
private static Driver newInstance() throws Exception {
String driverDir = System.getProperty("playwright.cli.dir");
if (driverDir == null) {
driverDir = System.getenv(PLAYWRIGHT_DRIVER_DIR);
}
if (driverDir != null) {
return new PreinstalledDriver(Paths.get(driverDir));
String pathFromProperty = System.getProperty("playwright.cli.dir");
if (pathFromProperty != null) {
return new PreinstalledDriver(Paths.get(pathFromProperty));
}
String driverImpl =
-2
View File
@@ -1,2 +0,0 @@
driver/
local-driver/
@@ -17,12 +17,9 @@
package com.microsoft.playwright;
import com.microsoft.playwright.impl.driver.Driver;
import com.microsoft.playwright.impl.driver.jar.DriverJar;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import static java.util.Arrays.asList;
@@ -31,13 +28,7 @@ import static java.util.Arrays.asList;
* Use this class to launch playwright cli.
*/
public class CLI {
public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException {
// Extract the driver into a fixed directory instead of running the playwright CLI. This is
// handled in Java because it must not require an already-extracted driver. See issue #1268.
if (args.length > 0 && "install-driver".equals(args[0])) {
installDriver(args);
return;
}
public static void main(String[] args) throws IOException, InterruptedException {
Driver driver = Driver.ensureDriverInstalled(Collections.emptyMap(), false);
ProcessBuilder pb = driver.createProcessBuilder();
pb.command().addAll(asList(args));
@@ -49,17 +40,4 @@ public class CLI {
Process process = pb.start();
System.exit(process.waitFor());
}
private static void installDriver(String[] args) throws IOException, URISyntaxException {
String dir = args.length > 1 ? args[1] : System.getenv(Driver.PLAYWRIGHT_DRIVER_DIR);
if (dir == null) {
System.err.println("Usage: install-driver <dir> (or set the " + Driver.PLAYWRIGHT_DRIVER_DIR
+ " environment variable)");
System.exit(1);
return;
}
Path driverDir = Paths.get(dir);
DriverJar.installDriverTo(driverDir);
System.out.println("Installed Playwright driver into " + driverDir.toAbsolutePath());
}
}
@@ -77,7 +77,6 @@ class Serialization {
static final Gson jsonDataSerializer = new GsonBuilder().disableHtmlEscaping()
.registerTypeAdapter(Date.class, new DateSerializer())
.registerTypeAdapter(LocalDate.class, new LocalDateSerializer())
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer())
.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeSerializer())
.serializeNulls().create();
@@ -572,15 +571,6 @@ class Serialization {
}
}
private static class LocalDateSerializer implements JsonSerializer<LocalDate> {
@Override
public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
// LocalDate has no time or zone, so emit the ISO-8601 date (yyyy-MM-dd) as-is to
// avoid shifting the calendar date when converting through a time zone.
return new JsonPrimitive(src.toString());
}
}
private static class LocalDateTimeSerializer implements JsonSerializer<LocalDateTime> {
@Override
public JsonElement serialize(LocalDateTime src, Type typeOfSrc, JsonSerializationContext context) {
@@ -28,7 +28,6 @@ import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
@@ -534,23 +533,6 @@ public class TestBrowserContextFetch extends TestBase {
assertEquals("{\"date\":\"2024-07-10T18:15:30.000Z\"}", new String(body));
}
public static class LocalDateData {
public String name;
public LocalDate date;
}
@Test
void shouldSupportLocalDateInData() throws ExecutionException, InterruptedException {
APIRequestContext request = playwright.request().newContext();
LocalDateData testData = new LocalDateData();
testData.name = "foo";
testData.date = LocalDate.of(2022, 12, 23);
Future<Server.Request> serverRequest = server.futureRequest("/empty.html");
request.post(server.EMPTY_PAGE, RequestOptions.create().setData(testData));
byte[] body = serverRequest.get().postBody;
assertEquals("{\"name\":\"foo\",\"date\":\"2022-12-23\"}", new String(body));
}
@Test
void shouldSupportApplicationXWwwFormUrlencoded() throws ExecutionException, InterruptedException {
Future<Server.Request> req = server.futureRequest("/empty.html");
+1 -1
View File
@@ -1 +1 @@
1.61.1
1.61.0-beta-1781285686000
+26 -31
View File
@@ -9,11 +9,9 @@ cd "$(dirname $0)"
if [[ ($1 == '-h') || ($1 == '--help') ]]; then
echo ""
echo "This script downloads and assembles the Playwright driver for all platforms."
echo "The platform-independent 'playwright-core' npm package is assembled once into the driver"
echo "module ('driver/src/main/resources/driver/package'), and the matching Node.js binary from"
echo "https://nodejs.org for each platform goes into the driver-bundle module"
echo "('driver-bundle/src/main/resources/driver/<platform>'), the same way the upstream"
echo "Playwright build does it."
echo "Each driver is assembled from the 'playwright-core' npm package and the matching"
echo "Node.js binary from https://nodejs.org, the same way the upstream Playwright build"
echo "does it. The result is put under 'driver-bundle/src/main/resources/driver'."
echo ""
echo "Usage: scripts/download_driver.sh [option]"
echo ""
@@ -58,26 +56,20 @@ echo "Driver version: $DRIVER_VERSION"
echo "Upstream commit: $GIT_HEAD"
echo "Node.js version: $NODE_VERSION"
# The platform-independent driver code (playwright-core) is assembled once into the driver module;
# the Node.js binary for each platform is assembled into the driver-bundle module. See issue #1196.
ROOT="$(cd .. && pwd)"
CORE_DEST="$ROOT/driver/src/main/resources/driver"
NODE_DEST="$ROOT/driver-bundle/src/main/resources/driver"
cd ../driver-bundle/src/main/resources
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
if [[ -d 'driver' ]]; then
echo "Deleting existing drivers from $(pwd)"
rm -rf driver
fi
# 1. playwright-core package -> driver module (once, shared by every platform).
echo "Assembling playwright-core package to $CORE_DEST/package"
rm -rf "$CORE_DEST/package"
mkdir -p "$CORE_DEST"
CORE_TGZ="$TMP_DIR/playwright-core-$DRIVER_VERSION.tgz"
mkdir -p driver
cd driver
# Download the platform-independent driver package (playwright-core) once.
CORE_TGZ="$(pwd)/playwright-core-$DRIVER_VERSION.tgz"
download "https://registry.npmjs.org/playwright-core/-/playwright-core-$DRIVER_VERSION.tgz" "$CORE_TGZ"
# The npm tarball has a top-level package/ directory, so this creates $CORE_DEST/package.
tar -xzf "$CORE_TGZ" -C "$CORE_DEST"
rm -f "$CORE_TGZ"
# 2. Node.js binary for each platform -> driver-bundle module.
# <java platform dir>:<nodejs platform suffix>:<archive extension>
for ENTRY in \
"mac:darwin-x64:tar.gz" \
@@ -87,25 +79,28 @@ for ENTRY in \
"win32_x64:win-x64:zip"
do
IFS=':' read -r PLATFORM NODE_SUFFIX ARCHIVE <<< "$ENTRY"
DEST="$NODE_DEST/$PLATFORM"
echo "Assembling Node.js for $PLATFORM to $DEST"
rm -rf "$DEST"
mkdir -p "$DEST"
echo "Assembling driver for $PLATFORM to $(pwd)/$PLATFORM"
mkdir "$PLATFORM"
# Node.js binary and its license from the official Node.js distribution.
# 1. playwright-core package contents -> $PLATFORM/package
tar -xzf "$CORE_TGZ" -C "$PLATFORM"
# 2. Node.js binary and its license from the official Node.js distribution.
NODE_DIR="node-v$NODE_VERSION-$NODE_SUFFIX"
NODE_ARCHIVE="$TMP_DIR/$NODE_DIR.$ARCHIVE"
NODE_ARCHIVE="$NODE_DIR.$ARCHIVE"
download "https://nodejs.org/dist/v$NODE_VERSION/$NODE_DIR.$ARCHIVE" "$NODE_ARCHIVE"
if [[ $ARCHIVE == "zip" ]]; then
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/node.exe" -d "$DEST"
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$DEST"
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/node.exe" -d "$PLATFORM"
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$PLATFORM"
else
tar -xzf "$NODE_ARCHIVE" -C "$DEST" --strip-components=2 "$NODE_DIR/bin/node"
tar -xzf "$NODE_ARCHIVE" -C "$DEST" --strip-components=1 "$NODE_DIR/LICENSE"
tar -xzf "$NODE_ARCHIVE" -C "$PLATFORM" --strip-components=2 "$NODE_DIR/bin/node"
tar -xzf "$NODE_ARCHIVE" -C "$PLATFORM" --strip-components=1 "$NODE_DIR/LICENSE"
fi
rm -f "$NODE_ARCHIVE"
done
rm -f "$CORE_TGZ"
echo ""
echo "All drivers have been successfully assembled."
echo ""
@@ -10,6 +10,7 @@ cd "$(dirname $0)"
PROJECT_DIR=$(mktemp -d)
echo "Creating project in $PROJECT_DIR"
cp -R . $PROJECT_DIR
cp -R ../../driver-bundle/src/test/ $PROJECT_DIR/src/
cp -R ../../playwright/src/test/ $PROJECT_DIR/src/
cd $PROJECT_DIR
+2 -8
View File
@@ -38,19 +38,14 @@ ENV JAVA_HOME=/usr/lib/jvm/java-25-openjdk-${PW_TARGET_ARCH}
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# Extract the Playwright driver into the image once so the library reuses it instead of unpacking
# 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
RUN cd /tmp/pw-java && \
./scripts/download_driver.sh && \
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 \
@@ -67,5 +62,4 @@ RUN cd /tmp/pw-java && \
else \
rm /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstwebrtc.so; \
fi && \
chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH && \
chmod -R 777 $PLAYWRIGHT_DRIVER_DIR
chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH
+2 -8
View File
@@ -38,19 +38,14 @@ ENV JAVA_HOME=/usr/lib/jvm/java-25-openjdk-${PW_TARGET_ARCH}
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# Extract the Playwright driver into the image once so the library reuses it instead of unpacking
# 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
RUN cd /tmp/pw-java && \
./scripts/download_driver.sh && \
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 \
@@ -58,5 +53,4 @@ RUN cd /tmp/pw-java && \
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 && \
chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH && \
chmod -R 777 $PLAYWRIGHT_DRIVER_DIR
chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH
-62
View File
@@ -1,62 +0,0 @@
FROM ubuntu:resolute
ARG DEBIAN_FRONTEND=noninteractive
ARG TZ=America/Los_Angeles
ARG DOCKER_IMAGE_NAME_TEMPLATE="mcr.microsoft.com/playwright/java:v%version%-resolute"
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
# === INSTALL JDK and Maven ===
RUN apt-get update && \
apt-get install -y --no-install-recommends openjdk-25-jdk \
# Install utilities required for downloading browsers
wget \
# Install utilities required for downloading driver
unzip \
# For the MSEdge install script
gpg && \
rm -rf /var/lib/apt/lists/* && \
# Create the pwuser
useradd -m -s /bin/bash pwuser
# Ubuntu 22.04 and earlier come with Maven 3.6.3 which fails with
# Java 25, so we install latest Maven from Apache instead.
RUN VERSION=3.9.12 && \
wget -O - https://archive.apache.org/dist/maven/maven-3/$VERSION/binaries/apache-maven-$VERSION-bin.tar.gz | tar zxfv - -C /opt/ && \
ln -s /opt/apache-maven-$VERSION/bin/mvn /usr/local/bin/
ARG PW_TARGET_ARCH
ENV JAVA_HOME=/usr/lib/jvm/java-25-openjdk-${PW_TARGET_ARCH}
# === BAKE BROWSERS INTO IMAGE ===
# Browsers will remain downloaded in `/ms-playwright`.
# Note: make sure to set 777 to the registry so that any user can access
# registry.
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
# Extract the Playwright driver into the image once so the library reuses it instead of unpacking
# 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
RUN 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 && \
chmod -R 777 $PLAYWRIGHT_BROWSERS_PATH && \
chmod -R 777 $PLAYWRIGHT_DRIVER_DIR
+1 -5
View File
@@ -3,7 +3,7 @@ set -e
set +x
if [[ ($1 == '--help') || ($1 == '-h') || ($1 == '') || ($2 == '') ]]; then
echo "usage: $(basename $0) {--arm64,--amd64} {jammy,noble,resolute} playwright:localbuild-noble"
echo "usage: $(basename $0) {--arm64,--amd64} {jammy,noble} playwright:localbuild-noble"
echo
echo "Build Playwright docker image and tag it as 'playwright:localbuild-noble'."
echo "Once image is built, you can run it with"
@@ -34,8 +34,4 @@ 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
docker build --platform "${PLATFORM}" --build-arg "PW_TARGET_ARCH=${PW_TARGET_ARCH}" -t "$3" -f "Dockerfile.$2" ../../
+2 -15
View File
@@ -38,11 +38,6 @@ NOBLE_TAGS=(
"v${PW_VERSION}-noble"
)
# Ubuntu 26.04
RESOLUTE_TAGS=(
"v${PW_VERSION}-resolute"
)
tag_and_push() {
local source="$1"
local target="$2"
@@ -79,10 +74,8 @@ publish_docker_images_with_arch_suffix() {
TAGS=("${JAMMY_TAGS[@]}")
elif [[ "$FLAVOR" == "noble" ]]; then
TAGS=("${NOBLE_TAGS[@]}")
elif [[ "$FLAVOR" == "resolute" ]]; then
TAGS=("${RESOLUTE_TAGS[@]}")
else
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', 'noble', or 'resolute'"
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', or 'noble'"
exit 1
fi
local ARCH="$2"
@@ -107,10 +100,8 @@ publish_docker_manifest () {
TAGS=("${JAMMY_TAGS[@]}")
elif [[ "$FLAVOR" == "noble" ]]; then
TAGS=("${NOBLE_TAGS[@]}")
elif [[ "$FLAVOR" == "resolute" ]]; then
TAGS=("${RESOLUTE_TAGS[@]}")
else
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', 'noble', or 'resolute'"
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', 'noble'"
exit 1
fi
@@ -136,7 +127,3 @@ publish_docker_manifest jammy amd64 arm64
publish_docker_images_with_arch_suffix noble amd64
publish_docker_images_with_arch_suffix noble arm64
publish_docker_manifest noble amd64 arm64
publish_docker_images_with_arch_suffix resolute amd64
publish_docker_images_with_arch_suffix resolute arm64
publish_docker_manifest resolute amd64 arm64