feat: Support constraints in pip_compile (#2916)
This adds in support to pass in a constraints file to pip-compile.
This is extremly useful when you want to uprade an indirect/intermediate
dependency to pull in security fixes but don't want to add said
dependency to
the requirements.in file.
---------
Signed-off-by: Vihang Mehta <vihang@gimletlabs.ai>
Co-authored-by: Ignas Anikevicius <240938+aignas@users.noreply.github.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a113c74..355f1fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -111,6 +111,9 @@
and activated with custom flags. See the [Registering custom runtimes]
docs and {obj}`single_version_platform_override()` API docs for more
information.
+* (rules) Added support for a using constraints files with `compile_pip_requirements`.
+ Useful when an intermediate dependency needs to be upgraded to pull in
+ security patches.
{#v0-0-0-removed}
### Removed
diff --git a/examples/pip_parse/BUILD.bazel b/examples/pip_parse/BUILD.bazel
index 8bdbd94..6ed8d26 100644
--- a/examples/pip_parse/BUILD.bazel
+++ b/examples/pip_parse/BUILD.bazel
@@ -57,6 +57,10 @@
compile_pip_requirements(
name = "requirements",
src = "requirements.in",
+ constraints = [
+ "constraints_certifi.txt",
+ "constraints_urllib3.txt",
+ ],
requirements_txt = "requirements_lock.txt",
requirements_windows = "requirements_windows.txt",
)
diff --git a/examples/pip_parse/constraints_certifi.txt b/examples/pip_parse/constraints_certifi.txt
new file mode 100644
index 0000000..7dc4eac
--- /dev/null
+++ b/examples/pip_parse/constraints_certifi.txt
@@ -0,0 +1 @@
+certifi>=2025.1.31
\ No newline at end of file
diff --git a/examples/pip_parse/constraints_urllib3.txt b/examples/pip_parse/constraints_urllib3.txt
new file mode 100644
index 0000000..3818262
--- /dev/null
+++ b/examples/pip_parse/constraints_urllib3.txt
@@ -0,0 +1 @@
+urllib3>1.26.18
diff --git a/examples/pip_parse/requirements_lock.txt b/examples/pip_parse/requirements_lock.txt
index aeac61e..dc34b45 100644
--- a/examples/pip_parse/requirements_lock.txt
+++ b/examples/pip_parse/requirements_lock.txt
@@ -12,10 +12,12 @@
--hash=sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900 \
--hash=sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed
# via sphinx
-certifi==2024.7.4 \
- --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \
- --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90
- # via requests
+certifi==2025.4.26 \
+ --hash=sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6 \
+ --hash=sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3
+ # via
+ # -c ./constraints_certifi.txt
+ # requests
chardet==4.0.0 \
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
@@ -218,10 +220,12 @@
# via
# -r requirements.in
# sphinx
-urllib3==1.26.18 \
- --hash=sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07 \
- --hash=sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0
- # via requests
+urllib3==1.26.20 \
+ --hash=sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e \
+ --hash=sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32
+ # via
+ # -c ./constraints_urllib3.txt
+ # requests
yamllint==1.28.0 \
--hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \
--hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b
diff --git a/examples/pip_parse/requirements_windows.txt b/examples/pip_parse/requirements_windows.txt
index 61a6682..78c1a45 100644
--- a/examples/pip_parse/requirements_windows.txt
+++ b/examples/pip_parse/requirements_windows.txt
@@ -12,10 +12,12 @@
--hash=sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900 \
--hash=sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed
# via sphinx
-certifi==2024.7.4 \
- --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \
- --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90
- # via requests
+certifi==2025.4.26 \
+ --hash=sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6 \
+ --hash=sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3
+ # via
+ # -c ./constraints_certifi.txt
+ # requests
chardet==4.0.0 \
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
@@ -222,10 +224,12 @@
# via
# -r requirements.in
# sphinx
-urllib3==1.26.18 \
- --hash=sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07 \
- --hash=sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0
- # via requests
+urllib3==1.26.20 \
+ --hash=sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e \
+ --hash=sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32
+ # via
+ # -c ./constraints_urllib3.txt
+ # requests
yamllint==1.28.0 \
--hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \
--hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b
diff --git a/python/private/pypi/pip_compile.bzl b/python/private/pypi/pip_compile.bzl
index 9782d3c..c989950 100644
--- a/python/private/pypi/pip_compile.bzl
+++ b/python/private/pypi/pip_compile.bzl
@@ -38,6 +38,7 @@
requirements_windows = None,
visibility = ["//visibility:private"],
tags = None,
+ constraints = [],
**kwargs):
"""Generates targets for managing pip dependencies with pip-compile.
@@ -77,6 +78,7 @@
requirements_windows: File of windows specific resolve output to check validate if requirement.in has changes.
tags: tagging attribute common to all build rules, passed to both the _test and .update rules.
visibility: passed to both the _test and .update rules.
+ constraints: a list of files containing constraints to pass to pip-compile with `--constraint`.
**kwargs: other bazel attributes passed to the "_test" rule.
"""
if len([x for x in [srcs, src, requirements_in] if x != None]) > 1:
@@ -100,7 +102,7 @@
visibility = visibility,
)
- data = [name, requirements_txt] + srcs + [f for f in (requirements_linux, requirements_darwin, requirements_windows) if f != None]
+ data = [name, requirements_txt] + srcs + [f for f in (requirements_linux, requirements_darwin, requirements_windows) if f != None] + constraints
# Use the Label constructor so this is expanded in the context of the file
# where it appears, which is to say, in @rules_python
@@ -122,6 +124,8 @@
args.append("--requirements-darwin={}".format(loc.format(requirements_darwin)))
if requirements_windows:
args.append("--requirements-windows={}".format(loc.format(requirements_windows)))
+ for constraint in constraints:
+ args.append("--constraint=$(location {})".format(constraint))
args.extend(extra_args)
deps = [