Skip to content

Commit 7a59a68

Browse files
yury-sclaude
andauthored
feat: assemble driver from npm instead of CDN (#1927)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 07b50c8 commit 7a59a68

3 files changed

Lines changed: 105 additions & 48 deletions

File tree

CONTRIBUTING.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ git clone https://github.com/microsoft/playwright-java
2020
cd playwright-java
2121
```
2222

23-
2. Run the following script to download 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).
23+
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).
2424

2525
```bash
2626
scripts/download_driver.sh
2727
```
2828

29+
Each driver is assembled from the [`playwright-core`](https://www.npmjs.com/package/playwright-core) npm package (version pinned in [scripts/DRIVER_VERSION](scripts/DRIVER_VERSION)) and the matching Node.js binary from https://nodejs.org, the same way the upstream Playwright build does it.
30+
2931
### Building and running the tests with Maven
3032

3133
```bash
@@ -39,10 +41,9 @@ BROWSER=chromium mvn test -Dtest=TestPageNetworkSizes
3941

4042
### Generating API
4143

42-
Public Java API is generated from api.json which is produced by `print-api-json` command of playwright CLI. To regenerate Java interfaces for the current driver run the following commands:
44+
Public Java API is generated from api.json, which is generated from the upstream Playwright source at the exact commit that produced the driver version in [scripts/DRIVER_VERSION](scripts/DRIVER_VERSION) (resolved via `npm view playwright@<version> gitHead`). `scripts/generate_api.sh` fetches a minimal upstream checkout automatically; set `PW_SRC_DIR` to reuse an existing `microsoft/playwright` checkout instead. To regenerate Java interfaces for the current driver run:
4345

4446
```bash
45-
./scripts/download_driver.sh
4647
./scripts/generate_api.sh
4748
```
4849

scripts/download_driver.sh

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ cd "$(dirname $0)"
88

99
if [[ ($1 == '-h') || ($1 == '--help') ]]; then
1010
echo ""
11-
echo "This script for downloading playwright driver for all platforms."
12-
echo "The downloaded files will be put under 'driver-bundle/src/main/resources/driver'."
11+
echo "This script downloads and assembles the Playwright driver for all platforms."
12+
echo "Each driver is assembled from the 'playwright-core' npm package and the matching"
13+
echo "Node.js binary from https://nodejs.org, the same way the upstream Playwright build"
14+
echo "does it. The result is put under 'driver-bundle/src/main/resources/driver'."
1315
echo ""
1416
echo "Usage: scripts/download_driver.sh [option]"
1517
echo ""
@@ -19,8 +21,40 @@ if [[ ($1 == '-h') || ($1 == '--help') ]]; then
1921
exit 0
2022
fi
2123

24+
# Ubuntu 24.04-arm64 emulated via qemu has a bug, so we prefer wget over curl.
25+
# See https://github.com/microsoft/playwright-java/issues/1678.
26+
download() {
27+
local url=$1
28+
local out=$2
29+
echo "Downloading $url"
30+
if command -v wget &> /dev/null; then
31+
wget -q -O "$out" "$url"
32+
else
33+
curl --retry 5 --retry-delay 2 -fL -o "$out" "$url"
34+
fi
35+
}
36+
2237
DRIVER_VERSION=$(head -1 ./DRIVER_VERSION)
23-
FILE_PREFIX=playwright-$DRIVER_VERSION
38+
39+
# Resolve the exact upstream commit that produced this driver version, so that the
40+
# bundled Node.js version matches the driver exactly.
41+
GIT_HEAD=$(npm view playwright@"$DRIVER_VERSION" gitHead)
42+
if [[ -z "$GIT_HEAD" ]]; then
43+
echo "Failed to resolve upstream commit (gitHead) for playwright@$DRIVER_VERSION"
44+
exit 1
45+
fi
46+
47+
# The Node.js version is kept in sync with the driver version in the upstream build script.
48+
NODE_VERSION=$(curl -fsSL "https://raw.githubusercontent.com/microsoft/playwright/$GIT_HEAD/utils/build/build-playwright-driver.sh" \
49+
| sed -n 's/^NODE_VERSION="\([^"]*\)".*/\1/p')
50+
if [[ -z "$NODE_VERSION" ]]; then
51+
echo "Failed to determine Node.js version for playwright@$DRIVER_VERSION ($GIT_HEAD)"
52+
exit 1
53+
fi
54+
55+
echo "Driver version: $DRIVER_VERSION"
56+
echo "Upstream commit: $GIT_HEAD"
57+
echo "Node.js version: $NODE_VERSION"
2458

2559
cd ../driver-bundle/src/main/resources
2660

@@ -32,32 +66,41 @@ fi
3266
mkdir -p driver
3367
cd driver
3468

35-
for PLATFORM in mac mac-arm64 linux linux-arm64 win32_x64
69+
# Download the platform-independent driver package (playwright-core) once.
70+
CORE_TGZ="$(pwd)/playwright-core-$DRIVER_VERSION.tgz"
71+
download "https://registry.npmjs.org/playwright-core/-/playwright-core-$DRIVER_VERSION.tgz" "$CORE_TGZ"
72+
73+
# <java platform dir>:<nodejs platform suffix>:<archive extension>
74+
for ENTRY in \
75+
"mac:darwin-x64:tar.gz" \
76+
"mac-arm64:darwin-arm64:tar.gz" \
77+
"linux:linux-x64:tar.gz" \
78+
"linux-arm64:linux-arm64:tar.gz" \
79+
"win32_x64:win-x64:zip"
3680
do
37-
FILE_NAME=$FILE_PREFIX-$PLATFORM.zip
38-
mkdir $PLATFORM
39-
cd $PLATFORM
40-
echo "Downloading driver for $PLATFORM to $(pwd)"
41-
42-
URL=https://cdn.playwright.dev/builds/driver
43-
if [[ "$DRIVER_VERSION" == *-alpha* || "$DRIVER_VERSION" == *-beta* || "$DRIVER_VERSION" == *-next* ]]; then
44-
URL=$URL/next
45-
fi
46-
URL=$URL/$FILE_NAME
47-
echo "Using url: $URL"
48-
# Ubuntu 24.04-arm64 emulated via qemu has a bug, so we prefer wget over curl.
49-
# See https://github.com/microsoft/playwright-java/issues/1678.
50-
if command -v wget &> /dev/null; then
51-
wget $URL
81+
IFS=':' read -r PLATFORM NODE_SUFFIX ARCHIVE <<< "$ENTRY"
82+
echo "Assembling driver for $PLATFORM to $(pwd)/$PLATFORM"
83+
mkdir "$PLATFORM"
84+
85+
# 1. playwright-core package contents -> $PLATFORM/package
86+
tar -xzf "$CORE_TGZ" -C "$PLATFORM"
87+
88+
# 2. Node.js binary and its license from the official Node.js distribution.
89+
NODE_DIR="node-v$NODE_VERSION-$NODE_SUFFIX"
90+
NODE_ARCHIVE="$NODE_DIR.$ARCHIVE"
91+
download "https://nodejs.org/dist/v$NODE_VERSION/$NODE_DIR.$ARCHIVE" "$NODE_ARCHIVE"
92+
if [[ $ARCHIVE == "zip" ]]; then
93+
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/node.exe" -d "$PLATFORM"
94+
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$PLATFORM"
5295
else
53-
curl --retry 5 --retry-delay 2 -fL -O $URL
96+
tar -xzf "$NODE_ARCHIVE" -C "$PLATFORM" --strip-components=2 "$NODE_DIR/bin/node"
97+
tar -xzf "$NODE_ARCHIVE" -C "$PLATFORM" --strip-components=1 "$NODE_DIR/LICENSE"
5498
fi
55-
unzip $FILE_NAME -d .
56-
rm $FILE_NAME
57-
58-
cd -
99+
rm -f "$NODE_ARCHIVE"
59100
done
60101

102+
rm -f "$CORE_TGZ"
103+
61104
echo ""
62-
echo "All drivers have been successfully downloaded."
105+
echo "All drivers have been successfully assembled."
63106
echo ""

scripts/generate_api.sh

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,39 @@ set +x
66
trap 'cd $(pwd -P)' EXIT
77
cd "$(dirname "$0")/.."
88

9-
PLAYWRIGHT_CLI="unknown"
10-
case $(uname) in
11-
Darwin)
12-
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/mac/package/cli.js
13-
;;
14-
Linux)
15-
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/linux/package/cli.js
16-
;;
17-
MINGW64*)
18-
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/win32_x64/package/cli.js
19-
;;
20-
*)
21-
echo "Unknown platform '$(uname)'"
22-
exit 1;
23-
;;
24-
esac
25-
26-
echo "Updating api.json from $($PLAYWRIGHT_CLI --version)"
27-
28-
node $PLAYWRIGHT_CLI print-api-json > ./tools/api-generator/src/main/resources/api.json
9+
DRIVER_VERSION=$(head -1 ./scripts/DRIVER_VERSION)
10+
11+
# api.json is generated from the upstream Playwright source at the exact commit
12+
# that produced this driver version. Set PW_SRC_DIR to reuse an existing upstream
13+
# checkout, otherwise a minimal one is fetched into a temporary directory.
14+
GIT_HEAD=$(npm view playwright@"$DRIVER_VERSION" gitHead)
15+
if [[ -z "$GIT_HEAD" ]]; then
16+
echo "Failed to resolve upstream commit (gitHead) for playwright@$DRIVER_VERSION"
17+
exit 1
18+
fi
19+
20+
CLONED_UPSTREAM=""
21+
if [[ -n "$PW_SRC_DIR" ]]; then
22+
UPSTREAM_DIR="$PW_SRC_DIR"
23+
echo "Using upstream Playwright checkout at $UPSTREAM_DIR (PW_SRC_DIR)"
24+
else
25+
UPSTREAM_DIR=$(mktemp -d)
26+
CLONED_UPSTREAM="$UPSTREAM_DIR"
27+
echo "Fetching upstream Playwright source at $GIT_HEAD"
28+
# generateApiJson.js only needs utils/ and docs/, so fetch just those.
29+
git clone --quiet --filter=blob:none --no-checkout https://github.com/microsoft/playwright.git "$UPSTREAM_DIR"
30+
git -C "$UPSTREAM_DIR" sparse-checkout init --cone
31+
git -C "$UPSTREAM_DIR" sparse-checkout set utils docs
32+
git -C "$UPSTREAM_DIR" checkout --quiet "$GIT_HEAD"
33+
fi
34+
35+
echo "Updating api.json from upstream playwright@$DRIVER_VERSION ($GIT_HEAD)"
36+
API_JSON_MODE=1 node "$UPSTREAM_DIR/utils/doclint/generateApiJson.js" \
37+
> ./tools/api-generator/src/main/resources/api.json
38+
39+
if [[ -n "$CLONED_UPSTREAM" ]]; then
40+
rm -rf "$CLONED_UPSTREAM"
41+
fi
2942

3043
mvn compile -f ./tools/api-generator --no-transfer-progress
3144

0 commit comments

Comments
 (0)