Skip to content

Commit 32b0053

Browse files
authored
fix: update correct requirements lock file when using os specific lock files (#1123)
Currently the dependency_resolver.py ignores that you give requirement lock files for different os's, except when checking if the golden file needs updating. This causes dependecy_resolver.py to update the wrong lock i.e the non platform specific one if ran in "update mode".
1 parent b228f60 commit 32b0053

File tree

6 files changed

+109
-26
lines changed

6 files changed

+109
-26
lines changed

.bazelci/presubmit.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,12 @@ tasks:
435435
- "! git diff --exit-code"
436436
- "bazel run //:requirements.update"
437437
- "git diff --exit-code"
438+
# Make a change to the locked requirements and then assert that //:os_specific_requirements.update does the
439+
# right thing.
440+
- "echo '' > requirements_lock_linux.txt"
441+
- "! git diff --exit-code"
442+
- "bazel run //:os_specific_requirements.update"
443+
- "git diff --exit-code"
438444
integration_test_compile_pip_requirements_debian:
439445
<<: *reusable_build_test_all
440446
name: compile_pip_requirements integration tests on Debian
@@ -447,6 +453,12 @@ tasks:
447453
- "! git diff --exit-code"
448454
- "bazel run //:requirements.update"
449455
- "git diff --exit-code"
456+
# Make a change to the locked requirements and then assert that //:os_specific_requirements.update does the
457+
# right thing.
458+
- "echo '' > requirements_lock_linux.txt"
459+
- "! git diff --exit-code"
460+
- "bazel run //:os_specific_requirements.update"
461+
- "git diff --exit-code"
450462
integration_test_compile_pip_requirements_macos:
451463
<<: *reusable_build_test_all
452464
name: compile_pip_requirements integration tests on macOS
@@ -459,6 +471,12 @@ tasks:
459471
- "! git diff --exit-code"
460472
- "bazel run //:requirements.update"
461473
- "git diff --exit-code"
474+
# Make a change to the locked requirements and then assert that //:os_specific_requirements.update does the
475+
# right thing.
476+
- "echo '' > requirements_lock_darwin.txt"
477+
- "! git diff --exit-code"
478+
- "bazel run //:os_specific_requirements.update"
479+
- "git diff --exit-code"
462480
integration_test_compile_pip_requirements_windows:
463481
<<: *reusable_build_test_all
464482
name: compile_pip_requirements integration tests on Windows
@@ -471,6 +489,12 @@ tasks:
471489
- "! git diff --exit-code"
472490
- "bazel run //:requirements.update"
473491
- "git diff --exit-code"
492+
# Make a change to the locked requirements and then assert that //:os_specific_requirements.update does the
493+
# right thing.
494+
- "echo '' > requirements_lock_windows.txt"
495+
- "! git diff --exit-code"
496+
- "bazel run //:os_specific_requirements.update"
497+
- "git diff --exit-code"
474498

475499
integration_test_pip_repository_entry_points_ubuntu_min:
476500
<<: *minimum_supported_version

python/pip_install/tools/dependency_resolver/dependency_resolver.py

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -95,25 +95,30 @@ def _locate(bazel_runfiles, file):
9595
requirements_windows = parse_str_none(sys.argv.pop(1))
9696
update_target_label = sys.argv.pop(1)
9797

98+
requirements_file = _select_golden_requirements_file(
99+
requirements_txt=requirements_txt, requirements_linux=requirements_linux,
100+
requirements_darwin=requirements_darwin, requirements_windows=requirements_windows
101+
)
102+
98103
resolved_requirements_in = _locate(bazel_runfiles, requirements_in)
99-
resolved_requirements_txt = _locate(bazel_runfiles, requirements_txt)
104+
resolved_requirements_file = _locate(bazel_runfiles, requirements_file)
100105

101106
# Files in the runfiles directory has the following naming schema:
102107
# Main repo: __main__/<path_to_file>
103108
# External repo: <workspace name>/<path_to_file>
104109
# We want to strip both __main__ and <workspace name> from the absolute prefix
105110
# to keep the requirements lock file agnostic.
106-
repository_prefix = requirements_txt[: requirements_txt.index("/") + 1]
107-
absolute_path_prefix = resolved_requirements_txt[
108-
: -(len(requirements_txt) - len(repository_prefix))
111+
repository_prefix = requirements_file[: requirements_file.index("/") + 1]
112+
absolute_path_prefix = resolved_requirements_file[
113+
: -(len(requirements_file) - len(repository_prefix))
109114
]
110115

111116
# As requirements_in might contain references to generated files we want to
112117
# use the runfiles file first. Thus, we need to compute the relative path
113118
# from the execution root.
114119
# Note: Windows cannot reference generated files without runfiles support enabled.
115-
requirements_in_relative = requirements_in[len(repository_prefix) :]
116-
requirements_txt_relative = requirements_txt[len(repository_prefix) :]
120+
requirements_in_relative = requirements_in[len(repository_prefix):]
121+
requirements_file_relative = requirements_file[len(repository_prefix):]
117122

118123
# Before loading click, set the locale for its parser.
119124
# If it leaks through to the system setting, it may fail:
@@ -135,11 +140,11 @@ def _locate(bazel_runfiles, file):
135140
sys.argv.append(os.environ["TEST_TMPDIR"])
136141
# Make a copy for pip-compile to read and mutate.
137142
requirements_out = os.path.join(
138-
os.environ["TEST_TMPDIR"], os.path.basename(requirements_txt) + ".out"
143+
os.environ["TEST_TMPDIR"], os.path.basename(requirements_file) + ".out"
139144
)
140145
# Those two files won't necessarily be on the same filesystem, so we can't use os.replace
141146
# or shutil.copyfile, as they will fail with OSError: [Errno 18] Invalid cross-device link.
142-
shutil.copy(resolved_requirements_txt, requirements_out)
147+
shutil.copy(resolved_requirements_file, requirements_out)
143148

144149
update_command = os.getenv("CUSTOM_COMPILE_COMMAND") or "bazel run %s" % (
145150
update_target_label,
@@ -150,7 +155,7 @@ def _locate(bazel_runfiles, file):
150155

151156
sys.argv.append("--generate-hashes")
152157
sys.argv.append("--output-file")
153-
sys.argv.append(requirements_txt_relative if UPDATE else requirements_out)
158+
sys.argv.append(requirements_file_relative if UPDATE else requirements_out)
154159
sys.argv.append(
155160
requirements_in_relative
156161
if Path(requirements_in_relative).exists()
@@ -159,28 +164,28 @@ def _locate(bazel_runfiles, file):
159164
print(sys.argv)
160165

161166
if UPDATE:
162-
print("Updating " + requirements_txt_relative)
167+
print("Updating " + requirements_file_relative)
163168
if "BUILD_WORKSPACE_DIRECTORY" in os.environ:
164169
workspace = os.environ["BUILD_WORKSPACE_DIRECTORY"]
165-
requirements_txt_tree = os.path.join(workspace, requirements_txt_relative)
166-
# In most cases, requirements_txt will be a symlink to the real file in the source tree.
167-
# If symlinks are not enabled (e.g. on Windows), then requirements_txt will be a copy,
170+
requirements_file_tree = os.path.join(workspace, requirements_file_relative)
171+
# In most cases, requirements_file will be a symlink to the real file in the source tree.
172+
# If symlinks are not enabled (e.g. on Windows), then requirements_file will be a copy,
168173
# and we should copy the updated requirements back to the source tree.
169-
if not os.path.samefile(resolved_requirements_txt, requirements_txt_tree):
174+
if not os.path.samefile(resolved_requirements_file, requirements_file_tree):
170175
atexit.register(
171176
lambda: shutil.copy(
172-
resolved_requirements_txt, requirements_txt_tree
177+
resolved_requirements_file, requirements_file_tree
173178
)
174179
)
175180
cli()
176-
requirements_txt_relative_path = Path(requirements_txt_relative)
177-
content = requirements_txt_relative_path.read_text()
181+
requirements_file_relative_path = Path(requirements_file_relative)
182+
content = requirements_file_relative_path.read_text()
178183
content = content.replace(absolute_path_prefix, "")
179-
requirements_txt_relative_path.write_text(content)
184+
requirements_file_relative_path.write_text(content)
180185
else:
181186
# cli will exit(0) on success
182187
try:
183-
print("Checking " + requirements_txt)
188+
print("Checking " + requirements_file)
184189
cli()
185190
print("cli() should exit", file=sys.stderr)
186191
sys.exit(1)
@@ -194,13 +199,7 @@ def _locate(bazel_runfiles, file):
194199
)
195200
sys.exit(1)
196201
elif e.code == 0:
197-
golden_filename = _select_golden_requirements_file(
198-
requirements_txt,
199-
requirements_linux,
200-
requirements_darwin,
201-
requirements_windows,
202-
)
203-
golden = open(_locate(bazel_runfiles, golden_filename)).readlines()
202+
golden = open(_locate(bazel_runfiles, requirements_file)).readlines()
204203
out = open(requirements_out).readlines()
205204
out = [line.replace(absolute_path_prefix, "") for line in out]
206205
if golden != out:

tests/compile_pip_requirements/BUILD.bazel

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,33 @@ compile_pip_requirements(
3232
requirements_in = "requirements.txt",
3333
requirements_txt = "requirements_lock.txt",
3434
)
35+
36+
genrule(
37+
name = "generate_os_specific_requirements_in",
38+
srcs = [],
39+
outs = ["requirements_os_specific.in"],
40+
cmd = """
41+
cat > $@ <<EOF
42+
pip==22.3.0 ; sys_platform == "linux"
43+
pip==22.2.2 ; sys_platform == "darwin"
44+
pip==22.2.1 ; sys_platform == "win32"
45+
EOF
46+
""",
47+
)
48+
49+
compile_pip_requirements(
50+
name = "os_specific_requirements",
51+
data = [
52+
"requirements_extra.in",
53+
"requirements_os_specific.in",
54+
],
55+
extra_args = [
56+
"--allow-unsafe",
57+
"--resolver=backtracking",
58+
],
59+
requirements_darwin = "requirements_lock_darwin.txt",
60+
requirements_in = "requirements_os_specific.in",
61+
requirements_linux = "requirements_lock_linux.txt",
62+
requirements_txt = "requirements_lock.txt",
63+
requirements_windows = "requirements_lock_windows.txt",
64+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.9
3+
# by the following command:
4+
#
5+
# bazel run //:os_specific_requirements.update
6+
#
7+
pip==22.2.2 ; sys_platform == "darwin" \
8+
--hash=sha256:3fd1929db052f056d7a998439176d3333fa1b3f6c1ad881de1885c0717608a4b \
9+
--hash=sha256:b61a374b5bc40a6e982426aede40c9b5a08ff20e640f5b56977f4f91fed1e39a
10+
# via -r requirements_os_specific.in
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.9
3+
# by the following command:
4+
#
5+
# bazel run //:os_specific_requirements.update
6+
#
7+
pip==22.3 ; sys_platform == "linux" \
8+
--hash=sha256:1daab4b8d3b97d1d763caeb01a4640a2250a0ea899e257b1e44b9eded91e15ab \
9+
--hash=sha256:8182aec21dad6c0a49a2a3d121a87cd524b950e0b6092b181625f07ebdde7530
10+
# via -r requirements_os_specific.in
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.9
3+
# by the following command:
4+
#
5+
# bazel run //:os_specific_requirements.update
6+
#
7+
pip==22.2.1 ; sys_platform == "win32" \
8+
--hash=sha256:0bbbc87dfbe6eed217beff0021f8b7dea04c8f4a0baa9d31dc4cff281ffc5b2b \
9+
--hash=sha256:50516e47a2b79e77446f0d05649f0d53772c192571486236b1905492bfc24bac
10+
# via -r requirements_os_specific.in

0 commit comments

Comments
 (0)