nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at haskell-updates 183 lines 7.2 kB view raw
1#!/usr/bin/env nix-shell 2#!nix-shell -i bash -p curl gnused common-updater-scripts jq prefetch-npm-deps unzip nix-prefetch 3# shellcheck shell=bash 4set -euo pipefail 5 6root="$(dirname "$(readlink -f "$0")")" 7repo_root="$(git -C "$root" rev-parse --show-toplevel)" 8cd "$repo_root" 9 10github_api_curl_args=() 11if [ -n "${GITHUB_TOKEN:-}" ]; then 12 github_api_curl_args=(-u ":$GITHUB_TOKEN") 13fi 14 15playwright_browsers_file="$root/browsers.json" 16playwright_driver_file="$root/driver.nix" 17playwright_raw_repo_url="https://raw.githubusercontent.com/microsoft/playwright" 18playwright_mcp_package_file="$root/../../../by-name/pl/playwright-mcp/package.nix" 19browser_names=(chromium chromium-headless-shell firefox webkit ffmpeg) 20browser_systems=(x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin) 21 22github_api_get() { 23 curl "${github_api_curl_args[@]}" -fsSL "$1" 24} 25 26major_minor() { 27 echo "${1%.*}" 28} 29 30python_version=$(github_api_get https://api.github.com/repos/microsoft/playwright-python/releases/latest | jq -r '.tag_name | sub("^v"; "")') 31# Most of the time, this should be the latest stable release of the Node-based 32# Playwright version, but upstream occasionally ships additional npm-only patch 33# releases. Resolve the latest patch in the same major.minor series. 34setup_py_url="https://github.com/microsoft/playwright-python/raw/v${python_version}/setup.py" 35python_driver_version=$(curl -fsSL "$setup_py_url" | grep '^driver_version =' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+') 36python_major_minor=$(major_minor "$python_driver_version") 37resolve_driver_version_latest_patch() { 38 local mm_escaped 39 mm_escaped=${python_major_minor//./\\.} 40 curl -fsSL "https://registry.npmjs.org/playwright" \ 41 | jq -r '.versions | keys[]' \ 42 | grep -E "^${mm_escaped}\.[0-9]+$" \ 43 | sort -V \ 44 | tail -n1 45} 46driver_version="$(resolve_driver_version_latest_patch)" 47: "${driver_version:?failed to resolve driver version from npm for python major.minor ${python_major_minor}}" 48: "${python_driver_version:?failed to resolve driver_version from ${setup_py_url}}" 49 50# TODO: skip if update-source-version reported the same version 51update-source-version playwright-driver "$driver_version" 52update-source-version python3Packages.playwright "$python_version" 53 54temp_dir=$(mktemp -d) 55trap 'rm -rf "$temp_dir"' EXIT 56 57# Update playwright-mcp package 58driver_major_minor=$(major_minor "$driver_version") 59resolve_mcp_version() { 60 local releases_json 61 local tag_name 62 63 releases_json=$(github_api_get "https://api.github.com/repos/microsoft/playwright-mcp/releases?per_page=100") 64 while IFS= read -r tag_name; do 65 local mcp_version_candidate mcp_npm_url mcp_playwright_dep mcp_major_minor 66 mcp_version_candidate=${tag_name#v} 67 mcp_npm_url="https://registry.npmjs.org/@playwright/mcp/${mcp_version_candidate}" 68 mcp_playwright_dep=$( 69 curl -fsSL "$mcp_npm_url" \ 70 | jq -r '.dependencies.playwright // .dependencies["playwright-core"] // empty' 71 ) || continue 72 mcp_major_minor=$(echo "$mcp_playwright_dep" | grep -Eo '[0-9]+\.[0-9]+' | head -n1 || true) 73 if [ "$mcp_major_minor" = "$driver_major_minor" ]; then 74 echo "$mcp_version_candidate" 75 return 0 76 fi 77 done < <(echo "$releases_json" | jq -r '.[].tag_name') 78 return 1 79} 80mcp_version="$(resolve_mcp_version)" || { 81 echo "Could not find a playwright-mcp release compatible with Playwright driver ${driver_version}" >&2 82 exit 1 83} 84update-source-version playwright-mcp "$mcp_version" 85 86# Update npmDepsHash for playwright-mcp 87mcp_lock_file="${temp_dir}/playwright-mcp-package-lock.json" 88curl -fsSL -o "$mcp_lock_file" "https://raw.githubusercontent.com/microsoft/playwright-mcp/v${mcp_version}/package-lock.json" 89mcp_npm_hash=$(prefetch-npm-deps "$mcp_lock_file") 90 91sed -E -i 's#\bnpmDepsHash = "[^"]*"#npmDepsHash = "'"$mcp_npm_hash"'"#' "$playwright_mcp_package_file" 92 93 94# update binaries of browsers, used by playwright. 95replace_sha() { 96 local target_file="$1" 97 local attr_name="$2" 98 local new_hash="$3" 99 100 sed -i "s|$attr_name = \".\{44,52\}\"|$attr_name = \"$new_hash\"|" "$target_file" 101} 102 103prefetch_browser() { 104 local url="$1" 105 local strip_root="$2" 106 107 # nix-prefetch is used to obtain sha with `stripRoot = false` 108 # doesn't work on macOS https://github.com/msteen/nix-prefetch/issues/53 109 nix-prefetch --option extra-experimental-features flakes -q "{ stdenv, fetchzip }: stdenv.mkDerivation { name=\"browser\"; src = fetchzip { url = \"$url\"; stripRoot = $strip_root; }; }" 110} 111 112browser_download_info() { 113 local name="$1" 114 local revision="$2" 115 local browser_version="$3" 116 117 nix-instantiate --eval --json --strict "$root/browser-downloads.nix" \ 118 --argstr name "$name" \ 119 --argstr revision "$revision" \ 120 --argstr browserVersion "$browser_version" 121} 122 123update_browser() { 124 local name="$1" 125 local revision 126 local browser_version 127 local download_info 128 local system 129 local url 130 local strip_root 131 132 revision="$(jq -r ".browsers[\"$name\"].revision" "$playwright_browsers_file")" 133 browser_version="$(jq -r ".browsers[\"$name\"].browserVersion // empty" "$playwright_browsers_file")" 134 download_info="$(browser_download_info "$name" "$revision" "$browser_version")" 135 136 for system in "${browser_systems[@]}"; do 137 url="$(echo "$download_info" | jq -r --arg system "$system" '.[$system].url')" 138 strip_root="$(echo "$download_info" | jq -r --arg system "$system" '.[$system].stripRoot')" 139 replace_sha "$root/$name.nix" "$system" "$(prefetch_browser "$url" "$strip_root")" 140 done 141} 142 143curl -fsSL \ 144 "https://raw.githubusercontent.com/microsoft/playwright/v${driver_version}/packages/playwright-core/browsers.json" \ 145 | jq ' 146 .comment = "This file is kept up to date via update.sh" 147 | .browsers |= ( 148 [.[] 149 | select(.installByDefault) | del(.installByDefault)] 150 | map({(.name): . | del(.name)}) 151 | add 152 ) 153 ' > "$playwright_browsers_file" 154 155for browser in "${browser_names[@]}"; do 156 update_browser "$browser" 157done 158 159# Update package-lock.json files for all npm deps that are built in playwright 160 161# Download `package-lock.json` for a given sourceRoot path and update its hash. 162update_hash() { 163 local source_root_path="$1" 164 local download_url 165 local lock_file 166 local new_hash 167 local source_root_pattern 168 169 download_url="${playwright_raw_repo_url}/v${driver_version}${source_root_path}/package-lock.json" 170 lock_file="${temp_dir}/$(echo "$source_root_path" | tr '/.' '__').package-lock.json" 171 curl -fsSL -o "$lock_file" "$download_url" 172 new_hash=$(prefetch-npm-deps "$lock_file") 173 174 source_root_pattern=$(printf '%s\n' "$source_root_path" | sed 's/[][\\/.*^$+?(){}|]/\\&/g') 175 sed -E -i "/sourceRoot = \"\\\$\\{src.name\\}${source_root_pattern}\";/,/npmDepsHash = / s#npmDepsHash = \"[^\"]*\";#npmDepsHash = \"${new_hash}\";#" "$playwright_driver_file" 176} 177 178while IFS= read -r source_root_path; do 179 update_hash "$source_root_path" 180done < <( 181 # shellcheck disable=SC2016 182 sed -n 's#^[[:space:]]*sourceRoot = "${src.name}\(.*\)";.*$#\1#p' "$playwright_driver_file" 183)