In order to package robotframework-browser, I came up with this derivation (that seems to work fairly well so far, see few fixes to apply in nixpkgs e.g. in Grpc-tools in node programs tries to access internet while building - #2 by tobiasBora):
{
lib,
stdenv,
buildPythonPackage,
fetchPypi,
pythonOlder,
robotframework,
robotframework-pythonlibcore,
robotframework-assertion-engine,
grpcio,
protobuf,
overrides,
click,
seedir,
wrapt,
npmHooks,
nodejs_latest,
fetchNpmDeps,
fetchFromGitHub,
node-pre-gyp,
grpc-tools,
grpcio-tools, # needed to generate --grpc_python_out + imported
# For inv build
invoke, # cmake-like for python
mypy-protobuf,
robotstatuschecker,
pytest,
beautifulsoup4,
# To provide the binaries
playwright-driver,
}:
let
version = "19.6.0";
pname = "robotframework-browser";
src_orig = fetchFromGitHub {
owner = "MarketSquare";
repo = "robotframework-browser";
rev = "v${version}";
hash = "sha256-kOifD+Fa1WCYbNZSRX89FlZio9oJ7Rh6aXQGVmVPXRI=";
};
src = stdenv.mkDerivation {
inherit pname;
inherit version;
src = src_orig;
patches = [
# Needed to ensure robotframework-browser uses the same version as
# export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers}
# otherwise the version of the browser will be different and this will give an error
# (unless we force the version manually?)
# To generate it:
# $ git clone https://github.com/MarketSquare/robotframework-browser
# $ git checkout v{put here your version like 19.6.0}
# $ sed -i 's/"playwright".*/"playwright": "{put here the version of playwright-driver, e.g. 1.52.0}",/g' package.json
# $ npm i
# $ git diff > pin_playwright_to_nix_playwright_driver_version.diff
# and copy the diff file here
./pin_playwright_to_nix_playwright_driver_version.diff
];
buildPhase = "";
installPhase = ''
mkdir -p $out
cp -Ra . $out
cat $out/package.json
'';
};
in
buildPythonPackage rec {
inherit pname;
inherit version;
disabled = pythonOlder "3.9";
nativeBuildInputs = [
#importNpmLock.npmConfigHook
npmHooks.npmConfigHook
# npmHooks.npmInstallHook
nodejs_latest
node-pre-gyp
grpc-tools
# For inv build
invoke # cmake-like for python
grpcio-tools # needed to generate --grpc_python_out
mypy-protobuf
robotstatuschecker
pytest
beautifulsoup4
];
npmDeps = fetchNpmDeps {
inherit src;
hash = "sha256-5EYZ5t24aPWM12nGbBBu1nwb5QS27eWPCXT76JMIpoA="; # after patch
};
inherit src;
# We fake a run of rfbrowser init
# + grpc_tools_node_protoc already includes the plugin and is not runnable via npm
# since nix directly builds it from C++ sources to avoid to use pre-build binaries
# downloaded by npm
patchPhase = ''
runHook prePatch
substituteInPlace ./Browser/playwright.py \
--replace-fail '(installation_dir / "node_modules").is_dir()' 'True'
substituteInPlace ./tasks.py \
--replace-fail 'c.run("pip install -U pip")' 'return' \
--replace-fail 'npm run grpc_tools_node_protoc' 'grpc_tools_node_protoc' \
--replace-fail ' -- ' ' '
substituteInPlace ./package.json \
--replace-fail '"grpc-tools": "^1.13.0",' ' '
sed -i '/--plugin=protoc-gen-grpc/d' ./tasks.py
runHook postPatch
'';
dependencies = [
robotframework
robotframework-pythonlibcore
robotframework-assertion-engine
grpcio
grpcio-tools
protobuf
overrides
click
seedir
wrapt
];
preBuild = ''
inv build -d -e
'';
# makeWrapperArgs can't be used (not a script here but a library)
postInstall = ''
cp -r node_modules $out/lib
cat >> $out/lib/python3.13/site-packages/Browser/__init__.py <<EOF
import os
if not "PLAYWRIGHT_BROWSERS_PATH" in os.environ:
os.environ["PLAYWRIGHT_BROWSERS_PATH"] = "${playwright-driver.browsers}"
if not "PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS" in os.environ:
os.environ["PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS"] = "true"
EOF
'';
meta = with lib; {
description = "Robot Framework Browser library powered by Playwright. ";
homepage = "https://robotframework-browser.org/";
license = licenses.asl20;
maintainers = with maintainers; [ tobiasBora ];
};
}
This works nicely except one thing I don’t like: playwright-driver.browsers
provides binaries for firefox etc but it only provides a single revision (aka chrome version) for each browser. But playwright
(npm package) seems to hardcode the version of chrome it is compatible with. Of course, since playwright is installed via npm
, the versions do not match. For now, I manually patch the package.json
file locally, then I locally run npm i
to update the lock file, then use git
to create a patch, and apply the patch to all files… but I find this quite dirty (fairly hard to update as I need to re-iterate this whole process) and, most importantly, unstable. For instance, if playwright-driver.browsers
bumps its version, this program will stop working without any notice (unless I code some tests but I don’t know how easy it will be…). What is the recommended solution here to tackle this issue?