mirror of
https://github.com/certbot/certbot.git
synced 2026-01-27 19:42:53 +03:00
* Refactor to not depend on certbot-auto dependencies pinning anymore * Update constraints * Replaces references * Upgrade AWS dependencies pinning * Fix script * Fix Windows installer builds * Fixing sdists letstest script * Pin cryptography on 3.1.1 specifically for RHEL/CentOS 7 to avoid build failures during test_sdists test. * Finish fix * Fix VERSION_ID in RHEL 7
191 lines
7.5 KiB
Python
191 lines
7.5 KiB
Python
#!/usr/bin/env python3
|
|
import contextlib
|
|
import ctypes
|
|
import os
|
|
import re
|
|
import shutil
|
|
import struct
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import time
|
|
|
|
PYTHON_VERSION = (3, 8, 8)
|
|
PYTHON_BITNESS = 32
|
|
PYWIN32_VERSION = 300 # do not forget to edit pywin32 dependency accordingly in setup.py
|
|
NSIS_VERSION = '3.06.1'
|
|
|
|
|
|
def main():
|
|
build_path, repo_path, venv_path, venv_python = _prepare_environment()
|
|
|
|
_copy_assets(build_path, repo_path)
|
|
|
|
installer_cfg_path = _generate_pynsist_config(repo_path, build_path)
|
|
|
|
_prepare_build_tools(venv_path, venv_python, repo_path)
|
|
_compile_wheels(repo_path, build_path, venv_python)
|
|
_build_installer(installer_cfg_path, venv_path)
|
|
|
|
print('Done')
|
|
|
|
|
|
def _build_installer(installer_cfg_path, venv_path):
|
|
print('Build the installer')
|
|
subprocess.check_call([os.path.join(venv_path, 'Scripts', 'pynsist.exe'), installer_cfg_path])
|
|
|
|
|
|
def _compile_wheels(repo_path, build_path, venv_python):
|
|
print('Compile wheels')
|
|
|
|
wheels_path = os.path.join(build_path, 'wheels')
|
|
os.makedirs(wheels_path)
|
|
|
|
certbot_packages = ['acme', 'certbot']
|
|
# Uncomment following line to include all DNS plugins in the installer
|
|
# certbot_packages.extend([name for name in os.listdir(repo_path) if name.startswith('certbot-dns-')])
|
|
wheels_project = [os.path.join(repo_path, package) for package in certbot_packages]
|
|
|
|
with _prepare_constraints(repo_path) as constraints_file_path:
|
|
env = os.environ.copy()
|
|
env['PIP_CONSTRAINT'] = constraints_file_path
|
|
command = [venv_python, '-m', 'pip', 'wheel', '-w', wheels_path]
|
|
command.extend(wheels_project)
|
|
subprocess.check_call(command, env=env)
|
|
|
|
# Cryptography uses now a unique wheel name "cryptography-VERSION-cpXX-abi3-win32.whl where
|
|
# cpXX is the lowest supported version of Python (eg. cp36 says that the wheel is compatible
|
|
# with Python 3.6+). While technically valid to describe a wheel compliant with the Stable
|
|
# Application Binary Interface, this naming convention makes pynsist falsely think that the
|
|
# wheel is compatible with Python 3.6 only.
|
|
# Let's trick pynsist by renaming the wheel until this is fixed upstream.
|
|
for file in os.listdir(wheels_path):
|
|
# Given that our Python version is 3.8, this rename files like
|
|
# cryptography-VERSION-cpXX-abi3-win32.whl into cryptography-VERSION-cp38-abi3-win32.whl
|
|
renamed = re.sub(r'^(.*)-cp\d+-abi3-(\w+)\.whl$', r'\1-cp{0}{1}-abi3-\2.whl'
|
|
.format(PYTHON_VERSION[0], PYTHON_VERSION[1]), file)
|
|
print(renamed)
|
|
if renamed != file:
|
|
os.replace(os.path.join(wheels_path, file), os.path.join(wheels_path, renamed))
|
|
|
|
|
|
def _prepare_build_tools(venv_path, venv_python, repo_path):
|
|
print('Prepare build tools')
|
|
subprocess.check_call([sys.executable, '-m', 'venv', venv_path])
|
|
subprocess.check_call([venv_python, os.path.join(repo_path, 'tools', 'pipstrap.py')])
|
|
subprocess.check_call([venv_python, os.path.join(repo_path, 'tools', 'pip_install.py'), 'pynsist'])
|
|
subprocess.check_call(['choco', 'upgrade', '--allow-downgrade', '-y', 'nsis', '--version', NSIS_VERSION])
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def _prepare_constraints(repo_path):
|
|
reqs_certbot = os.path.join(repo_path, 'tools', 'certbot_constraints.txt')
|
|
reqs_pipstrap = os.path.join(repo_path, 'tools', 'pipstrap_constraints.txt')
|
|
constraints_certbot = subprocess.check_output(
|
|
[sys.executable, os.path.join(repo_path, 'tools', 'strip_hashes.py'), reqs_certbot],
|
|
universal_newlines=True)
|
|
constraints_pipstrap = subprocess.check_output(
|
|
[sys.executable, os.path.join(repo_path, 'tools', 'strip_hashes.py'), reqs_pipstrap],
|
|
universal_newlines=True)
|
|
workdir = tempfile.mkdtemp()
|
|
try:
|
|
constraints_file_path = os.path.join(workdir, 'constraints.txt')
|
|
with open(constraints_file_path, 'a') as file_h:
|
|
file_h.write(constraints_pipstrap)
|
|
file_h.write(constraints_certbot)
|
|
file_h.write('pywin32=={0}'.format(PYWIN32_VERSION))
|
|
yield constraints_file_path
|
|
finally:
|
|
shutil.rmtree(workdir)
|
|
|
|
|
|
def _copy_assets(build_path, repo_path):
|
|
print('Copy assets')
|
|
if os.path.exists(build_path):
|
|
os.rename(build_path, '{0}.{1}.bak'.format(build_path, int(time.time())))
|
|
os.makedirs(build_path)
|
|
shutil.copy(os.path.join(repo_path, 'windows-installer', 'certbot.ico'), build_path)
|
|
shutil.copy(os.path.join(repo_path, 'windows-installer', 'run.bat'), build_path)
|
|
shutil.copy(os.path.join(repo_path, 'windows-installer', 'template.nsi'), build_path)
|
|
shutil.copy(os.path.join(repo_path, 'windows-installer', 'renew-up.ps1'), build_path)
|
|
shutil.copy(os.path.join(repo_path, 'windows-installer', 'renew-down.ps1'), build_path)
|
|
|
|
|
|
def _generate_pynsist_config(repo_path, build_path):
|
|
print('Generate pynsist configuration')
|
|
|
|
installer_cfg_path = os.path.join(build_path, 'installer.cfg')
|
|
|
|
certbot_pkg_path = os.path.join(repo_path, 'certbot')
|
|
certbot_version = subprocess.check_output([sys.executable, '-c', 'import certbot; print(certbot.__version__)'],
|
|
universal_newlines=True, cwd=certbot_pkg_path).strip()
|
|
|
|
# If we change the installer name from `certbot-beta-installer-win32.exe`, it should
|
|
# also be changed in tools/create_github_release.py
|
|
with open(installer_cfg_path, 'w') as file_h:
|
|
file_h.write('''\
|
|
[Application]
|
|
name=Certbot
|
|
version={certbot_version}
|
|
icon=certbot.ico
|
|
publisher=Electronic Frontier Foundation
|
|
target=$INSTDIR\\run.bat
|
|
|
|
[Build]
|
|
directory=nsis
|
|
nsi_template=template.nsi
|
|
installer_name=certbot-beta-installer-{installer_suffix}.exe
|
|
|
|
[Python]
|
|
version={python_version}
|
|
bitness={python_bitness}
|
|
|
|
[Include]
|
|
local_wheels=wheels\\*.whl
|
|
files=run.bat
|
|
renew-up.ps1
|
|
renew-down.ps1
|
|
|
|
[Command certbot]
|
|
entry_point=certbot.main:main
|
|
'''.format(certbot_version=certbot_version,
|
|
installer_suffix='win_amd64' if PYTHON_BITNESS == 64 else 'win32',
|
|
python_bitness=PYTHON_BITNESS,
|
|
python_version='.'.join(str(item) for item in PYTHON_VERSION)))
|
|
|
|
return installer_cfg_path
|
|
|
|
|
|
def _prepare_environment():
|
|
print('Prepare environment')
|
|
try:
|
|
subprocess.check_output(['choco', '--version'])
|
|
except subprocess.CalledProcessError:
|
|
raise RuntimeError('Error: Chocolatey (https://chocolatey.org/) needs '
|
|
'to be installed to run this script.')
|
|
script_path = os.path.realpath(__file__)
|
|
repo_path = os.path.dirname(os.path.dirname(script_path))
|
|
build_path = os.path.join(repo_path, 'windows-installer', 'build')
|
|
venv_path = os.path.join(build_path, 'venv-config')
|
|
venv_python = os.path.join(venv_path, 'Scripts', 'python.exe')
|
|
|
|
return build_path, repo_path, venv_path, venv_python
|
|
|
|
|
|
if __name__ == '__main__':
|
|
if os.name != 'nt':
|
|
raise RuntimeError('This script must be run under Windows.')
|
|
|
|
if ctypes.windll.shell32.IsUserAnAdmin() == 0:
|
|
# Administrator privileges are required to properly install NSIS through Chocolatey
|
|
raise RuntimeError('This script must be run with administrator privileges.')
|
|
|
|
if sys.version_info[:2] != PYTHON_VERSION[:2]:
|
|
raise RuntimeError('This script must be run with Python {0}'
|
|
.format('.'.join(str(item) for item in PYTHON_VERSION[0:2])))
|
|
|
|
if struct.calcsize('P') * 8 != PYTHON_BITNESS:
|
|
raise RuntimeError('This script must be run with a {0} bit version of Python.'
|
|
.format(PYTHON_BITNESS))
|
|
main()
|