diff --git a/examples/typical/BUILD.bazel b/examples/typical/BUILD.bazel index 78ebe63..8c33e64 100644 --- a/examples/typical/BUILD.bazel +++ b/examples/typical/BUILD.bazel @@ -1,5 +1,5 @@ load("@rules_uv//uv:pip.bzl", "pip_compile") -load("@rules_uv//uv:venv.bzl", "create_venv") +load("@rules_uv//uv:venv.bzl", "create_venv", "sync_venv") pip_compile(name = "generate_requirements_txt") @@ -25,3 +25,8 @@ create_venv( "site_packages_extra/sitecustomize.py", ], ) + +sync_venv( + name = "sync-venv", + destination_folder = ".sync-venv", +) diff --git a/uv/private/BUILD.bazel b/uv/private/BUILD.bazel index fdbd36c..ea5e282 100644 --- a/uv/private/BUILD.bazel +++ b/uv/private/BUILD.bazel @@ -4,6 +4,7 @@ exports_files([ "create_venv.sh", "pip_compile_test.sh", "pip_compile.sh", + "sync_venv.sh", ]) bzl_library( diff --git a/uv/private/create_venv.sh b/uv/private/create_venv.sh index d2f23db..10edaf4 100644 --- a/uv/private/create_venv.sh +++ b/uv/private/create_venv.sh @@ -26,9 +26,9 @@ then exit -1 fi -"$UV" venv "$BUILD_WORKSPACE_DIRECTORY/$target" --python "$PYTHON" --allow-existing +"$UV" venv "$BUILD_WORKSPACE_DIRECTORY/$target" --python "$PYTHON" source "$BUILD_WORKSPACE_DIRECTORY/$target/bin/activate" -"$UV" pip sync "$REQUIREMENTS_TXT" {{args}} +"$UV" pip install -r "$REQUIREMENTS_TXT" {{args}} site_packages_extra_files=({{site_packages_extra_files}}) if [ ! -z ${site_packages_extra_files+x} ]; then diff --git a/uv/private/sync_venv.sh b/uv/private/sync_venv.sh new file mode 100644 index 0000000..d2f23db --- /dev/null +++ b/uv/private/sync_venv.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +set -euo pipefail + +UV="{{uv}}" +RESOLVED_PYTHON="{{resolved_python}}" +REQUIREMENTS_TXT="{{requirements_txt}}" + +PYTHON="$(realpath "$RESOLVED_PYTHON")" + +bold="$(tput bold)" +normal="$(tput sgr0)" + +if [ $# -gt 1 ]; then + echo "create-venv takes one optional argument, the path to the virtual environment." + exit -1 +elif [ $# == 0 ] || [ -z "$1" ]; then + target="{{destination_folder}}" +else + target="$1" +fi + +if [ "${target}" == "/" ] || [ "${target}" == "." ] +then + echo "${bold}Invalid venv target '${target}'${normal}" + exit -1 +fi + +"$UV" venv "$BUILD_WORKSPACE_DIRECTORY/$target" --python "$PYTHON" --allow-existing +source "$BUILD_WORKSPACE_DIRECTORY/$target/bin/activate" +"$UV" pip sync "$REQUIREMENTS_TXT" {{args}} + +site_packages_extra_files=({{site_packages_extra_files}}) +if [ ! -z ${site_packages_extra_files+x} ]; then + site_packages_dir=$(find "$BUILD_WORKSPACE_DIRECTORY/$target/lib" -type d -name 'site-packages') + for file in "${site_packages_extra_files[@]}"; do + cp "$file" "$site_packages_dir"/ + done +fi + +echo "${bold}Created '${target}', to activate run:${normal}" +echo " source ${target}/bin/activate" diff --git a/uv/private/venv.bzl b/uv/private/venv.bzl index 77e7907..1ec9035 100644 --- a/uv/private/venv.bzl +++ b/uv/private/venv.bzl @@ -31,7 +31,7 @@ def _runfiles(ctx): def _venv_impl(ctx): executable = ctx.actions.declare_file(ctx.attr.name) - _uv_template(ctx, ctx.file._template, executable) + _uv_template(ctx, ctx.file.template, executable) return DefaultInfo( executable = executable, runfiles = _runfiles(ctx), @@ -43,7 +43,7 @@ _venv = rule( "site_packages_extra_files": attr.label_list(default = [], doc = "Files to add to the site-packages folder inside the virtual environment. Useful for adding `sitecustomize.py` or `.pth` files", allow_files = True), "requirements_txt": attr.label(mandatory = True, allow_single_file = True), "_uv": attr.label(default = "@multitool//tools/uv", executable = True, cfg = transition_to_target), - "_template": attr.label(default = "//uv/private:create_venv.sh", allow_single_file = True), + "template": attr.label(allow_single_file = True), "uv_args": attr.string_list(default = []), }, toolchains = [_PY_TOOLCHAIN], @@ -59,4 +59,16 @@ def create_venv(name, requirements_txt = None, target_compatible_with = None, de requirements_txt = requirements_txt or "//:requirements.txt", target_compatible_with = target_compatible_with, uv_args = uv_args, + template = "@rules_uv//uv/private:create_venv.sh", + ) + +def sync_venv(name, requirements_txt = None, target_compatible_with = None, destination_folder = None, site_packages_extra_files = [], uv_args = []): + _venv( + name = name, + destination_folder = destination_folder, + site_packages_extra_files = site_packages_extra_files, + requirements_txt = requirements_txt or "//:requirements.txt", + target_compatible_with = target_compatible_with, + uv_args = uv_args, + template = "@rules_uv//uv/private:sync_venv.sh", ) diff --git a/uv/venv.bzl b/uv/venv.bzl index 12dbed0..6ff6b59 100644 --- a/uv/venv.bzl +++ b/uv/venv.bzl @@ -1,5 +1,6 @@ "uv based virtual env generation" -load("//uv/private:venv.bzl", _create_venv = "create_venv") +load("//uv/private:venv.bzl", _create_venv = "create_venv", _sync_venv = "sync_venv") create_venv = _create_venv +sync_venv = _sync_venv