1#!/usr/bin/env nix-shell
2#!nix-shell -i bash -p curl gnused common-updater-scripts jq prefetch-npm-deps unzip nix-prefetch
3set -euo pipefail
4
5root="$(dirname "$(readlink -f "$0")")"
6
7version=$(curl ${GITHUB_TOKEN:+" -u \":$GITHUB_TOKEN\""} -s https://api.github.com/repos/microsoft/playwright-python/releases/latest | jq -r '.tag_name | sub("^v"; "")')
8# Most of the time, this should be the latest stable release of the Node-based
9# Playwright version, but that isn't a guarantee, so this needs to be specified
10# as well:
11setup_py_url="https://github.com/microsoft/playwright-python/raw/v${version}/setup.py"
12driver_version=$(curl -Ls "$setup_py_url" | grep '^driver_version =' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+')
13
14# TODO: skip if update-source-version reported the same version
15update-source-version playwright-driver "$driver_version"
16update-source-version python3Packages.playwright "$version"
17
18playwright_dir="$root/../../web/playwright"
19driver_file="$playwright_dir/driver.nix"
20repo_url_prefix="https://github.com/microsoft/playwright/raw"
21
22temp_dir=$(mktemp -d)
23trap 'rm -rf "$temp_dir"' EXIT
24
25
26
27# update binaries of browsers, used by playwright.
28replace_sha() {
29 sed -i "s|$2 = \".\{44,52\}\"|$2 = \"$3\"|" "$1"
30}
31
32prefetch_browser() {
33 # nix-prefetch is used to obtain sha with `stripRoot = false`
34 # doesn't work on macOS https://github.com/msteen/nix-prefetch/issues/53
35 nix-prefetch --option extra-experimental-features flakes -q "{ stdenv, fetchzip }: stdenv.mkDerivation { name=\"browser\"; src = fetchzip { url = \"$1\"; stripRoot = $2; }; }"
36}
37
38update_browser() {
39 name="$1"
40 platform="$2"
41 stripRoot="false"
42 if [ "$platform" = "darwin" ]; then
43 if [ "$name" = "webkit" ]; then
44 suffix="mac-14"
45 else
46 suffix="mac"
47 fi
48 else
49 if [ "$name" = "ffmpeg" ] || [ "$name" = "chromium-headless-shell" ]; then
50 suffix="linux"
51 elif [ "$name" = "firefox" ]; then
52 stripRoot="true"
53 suffix="ubuntu-22.04"
54 else
55 suffix="ubuntu-22.04"
56 fi
57 fi
58 aarch64_suffix="$suffix-arm64"
59 if [ "$name" = "chromium-headless-shell" ]; then
60 buildname="chromium";
61 else
62 buildname="$name"
63 fi
64
65 revision="$(jq -r ".browsers[\"$buildname\"].revision" "$playwright_dir/browsers.json")"
66 replace_sha "$playwright_dir/$name.nix" "x86_64-$platform" \
67 "$(prefetch_browser "https://playwright.azureedge.net/builds/$buildname/$revision/$name-$suffix.zip" $stripRoot)"
68 replace_sha "$playwright_dir/$name.nix" "aarch64-$platform" \
69 "$(prefetch_browser "https://playwright.azureedge.net/builds/$buildname/$revision/$name-$aarch64_suffix.zip" $stripRoot)"
70}
71
72curl -fsSl \
73 "https://raw.githubusercontent.com/microsoft/playwright/v${driver_version}/packages/playwright-core/browsers.json" \
74 | jq '
75 .comment = "This file is kept up to date via update.sh"
76 | .browsers |= (
77 [.[]
78 | select(.installByDefault) | del(.installByDefault)]
79 | map({(.name): . | del(.name)})
80 | add
81 )
82 ' > "$playwright_dir/browsers.json"
83
84# We currently use Chromium from nixpkgs, so we don't need to download it here
85update_browser "chromium-headless-shell" "linux"
86update_browser "firefox" "linux"
87update_browser "webkit" "linux"
88update_browser "ffmpeg" "linux"
89
90update_browser "chromium" "darwin"
91update_browser "chromium-headless-shell" "darwin"
92update_browser "firefox" "darwin"
93update_browser "webkit" "darwin"
94update_browser "ffmpeg" "darwin"
95
96# Update package-lock.json files for all npm deps that are built in playwright
97
98# Function to download `package-lock.json` for a given source path and update hash
99update_hash() {
100 local source_root_path="$1"
101 local existing_hash="$2"
102
103 # Formulate download URL
104 local download_url="${repo_url_prefix}/v${driver_version}${source_root_path}/package-lock.json"
105 # Download package-lock.json to temporary directory
106 curl -fsSL -o "${temp_dir}/package-lock.json" "$download_url"
107
108 # Calculate the new hash
109 local new_hash
110 new_hash=$(prefetch-npm-deps "${temp_dir}/package-lock.json")
111
112 # Update npmDepsHash in the original file
113 sed -i "s|$existing_hash|${new_hash}|" "$driver_file"
114}
115
116while IFS= read -r source_root_line; do
117 [[ "$source_root_line" =~ sourceRoot ]] || continue
118 source_root_path=$(echo "$source_root_line" | sed -e 's/^.*"${src.name}\(.*\)";.*$/\1/')
119 # Extract the current npmDepsHash for this sourceRoot
120 existing_hash=$(grep -A1 "$source_root_line" "$driver_file" | grep 'npmDepsHash' | sed -e 's/^.*npmDepsHash = "\(.*\)";$/\1/')
121
122 # Call the function to download and update the hash
123 update_hash "$source_root_path" "$existing_hash"
124done < "$driver_file"