Search code examples
bazelbazel-rulesbazel-python

Bazel: install a python dependency for a genrule


I am writing a Bazel macro for uploading python wheels to PyPI. In order to upload the .whl file to PyPI, I'm calling twine as the last step of my macro. Twine is a python package, and it looks like it should be installed separately. However, I want my build to be hermetic, so I would like it to be installed by the build system, and preferably not into the system python or the current virtual environment that may be activated on the user's machine. Is there a way to do so? I tried specifying it as a dependency for my genrule, but it doesn't have the deps parameter, or as a dependency for my py_wheel stage, but then twine was still not available for the upload stage. Is there a good way to do this?

Here's the call to the genrule in question:

    native.genrule(
        name = name + "_upload",
        srcs = [":" + short_name + "_wheel"],
        outs = [short_name + "_twine_upload.log"],
        cmd = "twine upload --disable-progress-bar --skip-existing $(SRCS) -u ........",
        visibility = ["//visibility:public"],
#        deps = [requirement("twine")]
    )

Solution

  • What you are missing is twine in an executable form. rules_python has a mechanism for that:

    load("@my_pip_install//:requirements.bzl", "entry_point")
    
    alias(
        name = "twine",
        actual = entry_point("twine"),
    )
    

    This now generates a "binary" that you can run using bazel run or pass into your genrule().