Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32cf6cd18e | |||
| e5135db82c | |||
| 6234e06280 | |||
| 20e4edd73c | |||
| d2d29d446d | |||
| 43d2601be8 | |||
| ace7a1241f | |||
| fddd7c3708 | |||
| 423cbf4cc7 | |||
| e3f2f6fa5b |
@@ -75,7 +75,7 @@ extends:
|
||||
targetPath: $(Build.ArtifactStagingDirectory)/esrp-build
|
||||
steps:
|
||||
- checkout: none
|
||||
- task: EsrpRelease@9
|
||||
- task: EsrpRelease@11
|
||||
inputs:
|
||||
connectedservicename: 'Playwright-ESRP-PME'
|
||||
usemanagedidentity: true
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
environment: Docker
|
||||
if: github.repository == 'microsoft/playwright-java'
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- 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@v6
|
||||
- uses: actions/checkout@v7
|
||||
- run: ./utils/docker/publish_docker.sh stable
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
browser: webkit
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- 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@v6
|
||||
- uses: actions/checkout@v7
|
||||
- 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@v6
|
||||
- uses: actions/checkout@v7
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
|
||||
@@ -13,9 +13,9 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flavor: [jammy, noble]
|
||||
flavor: [jammy, noble, resolute]
|
||||
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@v6
|
||||
- uses: actions/checkout@v7
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
bash utils/docker/build.sh --${{ matrix.arch }} ${{ matrix.flavor }} playwright-java:localbuild-${{ matrix.flavor }}
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
- name: Download drivers
|
||||
run: scripts/download_driver.sh
|
||||
- name: Regenerate APIs
|
||||
|
||||
+1
-1
@@ -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 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).
|
||||
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).
|
||||
|
||||
```bash
|
||||
scripts/download_driver.sh
|
||||
|
||||
+16
-15
@@ -10,22 +10,23 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>driver-bundle</artifactId>
|
||||
<name>Playwright - Drivers For All Platforms</name>
|
||||
<name>Playwright - Node.js For All Platforms</name>
|
||||
<description>
|
||||
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.
|
||||
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).
|
||||
</description>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
</project>
|
||||
|
||||
+16
-1
@@ -12,7 +12,8 @@
|
||||
<artifactId>driver</artifactId>
|
||||
<name>Playwright - Driver</name>
|
||||
<description>
|
||||
This module provides API for discovery and launching of Playwright driver.
|
||||
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.
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
@@ -21,4 +22,18 @@
|
||||
<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,12 +25,14 @@ 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 driver-bundle module if that module is in the classpath.
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
@@ -107,9 +109,12 @@ public abstract class Driver {
|
||||
}
|
||||
|
||||
private static Driver newInstance() throws Exception {
|
||||
String pathFromProperty = System.getProperty("playwright.cli.dir");
|
||||
if (pathFromProperty != null) {
|
||||
return new PreinstalledDriver(Paths.get(pathFromProperty));
|
||||
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 driverImpl =
|
||||
|
||||
+50
-18
@@ -30,17 +30,11 @@ 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 {
|
||||
// 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();
|
||||
this(createTempDriverDir(), true);
|
||||
String nodePath = System.getProperty("playwright.nodejs.path");
|
||||
if (nodePath != null) {
|
||||
preinstalledNodePath = Paths.get(nodePath);
|
||||
@@ -51,6 +45,32 @@ 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)) {
|
||||
@@ -119,7 +139,21 @@ public class DriverJar extends Driver {
|
||||
}
|
||||
|
||||
void extractDriverToTempDir() throws URISyntaxException, IOException {
|
||||
URI originalUri = getDriverResourceURI();
|
||||
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 uri = maybeExtractNestedJar(originalUri);
|
||||
|
||||
// Create zip filesystem if loading from jar.
|
||||
@@ -131,14 +165,8 @@ 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 = driverTempDir.resolve(relative.toString());
|
||||
Path toPath = destDir.resolve(relative.toString());
|
||||
try {
|
||||
if (Files.isDirectory(fromPath)) {
|
||||
Files.createDirectories(toPath);
|
||||
@@ -148,7 +176,9 @@ public class DriverJar extends Driver {
|
||||
toPath.toFile().setExecutable(true, true);
|
||||
}
|
||||
}
|
||||
toPath.toFile().deleteOnExit();
|
||||
if (deleteOnExit) {
|
||||
toPath.toFile().deleteOnExit();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to extract driver from " + uri + ", full uri: " + originalUri, e);
|
||||
}
|
||||
@@ -171,7 +201,9 @@ public class DriverJar extends Driver {
|
||||
Path fromPath = Paths.get(jarUri);
|
||||
Path toPath = driverTempDir.resolve(fromPath.getFileName().toString());
|
||||
Files.copy(fromPath, toPath);
|
||||
toPath.toFile().deleteOnExit();
|
||||
if (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);
|
||||
@@ -0,0 +1,2 @@
|
||||
driver/
|
||||
local-driver/
|
||||
@@ -17,9 +17,12 @@
|
||||
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;
|
||||
@@ -28,7 +31,13 @@ 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 {
|
||||
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;
|
||||
}
|
||||
Driver driver = Driver.ensureDriverInstalled(Collections.emptyMap(), false);
|
||||
ProcessBuilder pb = driver.createProcessBuilder();
|
||||
pb.command().addAll(asList(args));
|
||||
@@ -40,4 +49,17 @@ 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,6 +77,7 @@ 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();
|
||||
@@ -571,6 +572,15 @@ 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,6 +28,7 @@ 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;
|
||||
@@ -533,6 +534,23 @@ 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");
|
||||
|
||||
+24
@@ -132,6 +132,30 @@ 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 +1 @@
|
||||
1.61.0-beta-1781285686000
|
||||
1.61.1
|
||||
|
||||
+31
-26
@@ -9,9 +9,11 @@ cd "$(dirname $0)"
|
||||
if [[ ($1 == '-h') || ($1 == '--help') ]]; then
|
||||
echo ""
|
||||
echo "This script downloads and assembles the Playwright driver for all platforms."
|
||||
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 "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 ""
|
||||
echo "Usage: scripts/download_driver.sh [option]"
|
||||
echo ""
|
||||
@@ -56,20 +58,26 @@ echo "Driver version: $DRIVER_VERSION"
|
||||
echo "Upstream commit: $GIT_HEAD"
|
||||
echo "Node.js version: $NODE_VERSION"
|
||||
|
||||
cd ../driver-bundle/src/main/resources
|
||||
# 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"
|
||||
|
||||
if [[ -d 'driver' ]]; then
|
||||
echo "Deleting existing drivers from $(pwd)"
|
||||
rm -rf driver
|
||||
fi
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
|
||||
mkdir -p driver
|
||||
cd driver
|
||||
|
||||
# Download the platform-independent driver package (playwright-core) once.
|
||||
CORE_TGZ="$(pwd)/playwright-core-$DRIVER_VERSION.tgz"
|
||||
# 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"
|
||||
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" \
|
||||
@@ -79,28 +87,25 @@ for ENTRY in \
|
||||
"win32_x64:win-x64:zip"
|
||||
do
|
||||
IFS=':' read -r PLATFORM NODE_SUFFIX ARCHIVE <<< "$ENTRY"
|
||||
echo "Assembling driver for $PLATFORM to $(pwd)/$PLATFORM"
|
||||
mkdir "$PLATFORM"
|
||||
DEST="$NODE_DEST/$PLATFORM"
|
||||
echo "Assembling Node.js for $PLATFORM to $DEST"
|
||||
rm -rf "$DEST"
|
||||
mkdir -p "$DEST"
|
||||
|
||||
# 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.js binary and its license from the official Node.js distribution.
|
||||
NODE_DIR="node-v$NODE_VERSION-$NODE_SUFFIX"
|
||||
NODE_ARCHIVE="$NODE_DIR.$ARCHIVE"
|
||||
NODE_ARCHIVE="$TMP_DIR/$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 "$PLATFORM"
|
||||
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$PLATFORM"
|
||||
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/node.exe" -d "$DEST"
|
||||
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$DEST"
|
||||
else
|
||||
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"
|
||||
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"
|
||||
fi
|
||||
rm -f "$NODE_ARCHIVE"
|
||||
done
|
||||
|
||||
rm -f "$CORE_TGZ"
|
||||
|
||||
echo ""
|
||||
echo "All drivers have been successfully assembled."
|
||||
echo ""
|
||||
|
||||
@@ -10,7 +10,6 @@ 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
|
||||
|
||||
|
||||
@@ -38,14 +38,19 @@ 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 \
|
||||
@@ -62,4 +67,5 @@ 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_BROWSERS_PATH && \
|
||||
chmod -R 777 $PLAYWRIGHT_DRIVER_DIR
|
||||
|
||||
@@ -38,14 +38,19 @@ 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 \
|
||||
@@ -53,4 +58,5 @@ 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_BROWSERS_PATH && \
|
||||
chmod -R 777 $PLAYWRIGHT_DRIVER_DIR
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
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
|
||||
@@ -3,7 +3,7 @@ set -e
|
||||
set +x
|
||||
|
||||
if [[ ($1 == '--help') || ($1 == '-h') || ($1 == '') || ($2 == '') ]]; then
|
||||
echo "usage: $(basename $0) {--arm64,--amd64} {jammy,noble} playwright:localbuild-noble"
|
||||
echo "usage: $(basename $0) {--arm64,--amd64} {jammy,noble,resolute} 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,4 +34,8 @@ 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" ../../
|
||||
|
||||
@@ -38,6 +38,11 @@ NOBLE_TAGS=(
|
||||
"v${PW_VERSION}-noble"
|
||||
)
|
||||
|
||||
# Ubuntu 26.04
|
||||
RESOLUTE_TAGS=(
|
||||
"v${PW_VERSION}-resolute"
|
||||
)
|
||||
|
||||
tag_and_push() {
|
||||
local source="$1"
|
||||
local target="$2"
|
||||
@@ -74,8 +79,10 @@ 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', or 'noble'"
|
||||
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', 'noble', or 'resolute'"
|
||||
exit 1
|
||||
fi
|
||||
local ARCH="$2"
|
||||
@@ -100,8 +107,10 @@ 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'"
|
||||
echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', 'noble', or 'resolute'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -127,3 +136,7 @@ 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
|
||||
|
||||
Reference in New Issue
Block a user