mirror of
https://github.com/certbot/certbot.git
synced 2025-08-08 04:02:10 +03:00
Enable again build isolation with proper pinning of build dependencies (#8443)
Fixes #8256 First let's sum up the problem to solve. We disabled the build isolation available in pip>=19 because it could potential break certbot build without a control on our side. Basically builds are not reproductible. Indeed the build isolation triggers build of PEP-517 enabled transitive dependencies (like `cryptography`) with the build dependencies defined in their `pyproject.toml`. For `cryptography` in particular these requirements include `setuptools>=40.6.0`, and quite logically pip will install the latest version of `setuptools` for the build. And when `setuptools` broke with the version 50, our build did the same. But disabling the build isolation is not a long term solution, as more and more project will migrate on this approach and it basically provides a lot of benefit in how dependencies are built. The ideal solution would be to be able to apply version constraints on our side on the build dependencies, in order to pin `setuptools` for instance, and decide precisely when we upgrade to a newer version. However for now pip does not provide a mechanism for that (like a `--build-constraint` flag or propagation of existing `--constraint` flag). Until I saw https://github.com/pypa/pip/issues/9081 and https://github.com/pypa/pip/issues/8439. Apart the fact that https://github.com/pypa/pip/issues/9081 shows that pip maintainers are working on this issue, it explains how pip works regarding PEP-517 and infers which workaround can be used to still pin the build dependencies. It turns out that pip invokes itself in each build isolation to install the build dependencies. It means that even if some flags (like `--constraint`) are not explicitly passed to the pip sub call, the global environment remains, in particular the environment variables. Thus it is known that every pip flag can alternatively be set by environment variable using the following pattern for the variable name: `PIP_[FLAG_NAME_UPPERCASE]`. So for `--constraint`, it is `PIP_CONSTRAINT`. And so you can pass a constraint file to the pip sub call through that mechanism. I made some tests with a constraint file containing pinning for `setuptools`: indeed under isolation zone, the constraint file has been honored and the provided pinned version has been used to build the dependencies (I tested it with `cryptography`). Finally this PR takes advantage of this mechanism, by setting `PIP_CONSTRAINT` to `pip_install`, the snap building process, the Dockerfiles and the windows installer building process. I also extracted out the requirements of the new `pipstrap.py` to be reusable in these various build processes. * Use workaround to fix build requirements in build isolation, and renable build isolation * Clean imports in pipstrap * Externalize pipstrap reqs to be reusable * Inject pipstrap constraints during pip_install * Update docker build * Update snapcraft build * Prepare installer build * Fix pipstrap constraints in snap build * Add back --no-build-cache option in Docker images build * Update snap/snapcraft.yaml * Use proper flags with pip Co-authored-by: Brad Warren <bmw@users.noreply.github.com>
This commit is contained in:
@@ -1,46 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
"""Uses pip to upgrade Python packaging tools to pinned versions."""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import pip_install
|
||||
|
||||
|
||||
# We include the hashes of the packages here for extra verification of
|
||||
# the packages downloaded from PyPI. This is especially valuable in our
|
||||
# builds of Certbot that we ship to our users such as our Docker images.
|
||||
#
|
||||
# An older version of setuptools is currently used here in order to keep
|
||||
# compatibility with Python 2 since newer versions of setuptools have dropped
|
||||
# support for it.
|
||||
REQUIREMENTS = r"""
|
||||
pip==20.2.4 \
|
||||
--hash=sha256:51f1c7514530bd5c145d8f13ed936ad6b8bfcb8cf74e10403d0890bc986f0033 \
|
||||
--hash=sha256:85c99a857ea0fb0aedf23833d9be5c40cf253fe24443f0829c7b472e23c364a1
|
||||
setuptools==44.1.1 \
|
||||
--hash=sha256:27a714c09253134e60a6fa68130f78c7037e5562c4f21f8f318f2ae900d152d5 \
|
||||
--hash=sha256:c67aa55db532a0dadc4d2e20ba9961cbd3ccc84d544e9029699822542b5a476b
|
||||
wheel==0.35.1 \
|
||||
--hash=sha256:497add53525d16c173c2c1c733b8f655510e909ea78cc0e29d374243544b77a2 \
|
||||
--hash=sha256:99a22d87add3f634ff917310a3d87e499f19e663413a52eb9232c447aa646c9f
|
||||
"""
|
||||
_REQUIREMENTS_PATH = os.path.join(os.path.dirname(__file__), "pipstrap_constraints.txt")
|
||||
|
||||
|
||||
def main():
|
||||
with pip_install.temporary_directory() as tempdir:
|
||||
requirements_filepath = os.path.join(tempdir, 'reqs.txt')
|
||||
with open(requirements_filepath, 'w') as f:
|
||||
f.write(REQUIREMENTS)
|
||||
pip_install_args = '--requirement ' + requirements_filepath
|
||||
# We don't disable build isolation because we may have an older
|
||||
# version of pip that doesn't support the flag disabling it. We
|
||||
# expect these packages to already have usable wheels available
|
||||
# anyway so no building should be required.
|
||||
pip_install.pip_install_with_print(pip_install_args,
|
||||
disable_build_isolation=False)
|
||||
pip_install_args = '--requirement "{0}"'.format(_REQUIREMENTS_PATH)
|
||||
pip_install.pip_install_with_print(pip_install_args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Reference in New Issue
Block a user