mirror of
https://github.com/certbot/certbot.git
synced 2025-08-09 15:02:48 +03:00
* Create _internal package for Certbot's non-public modules * Move account.py to _internal * Move auth_handler.py to _internal * Move cert_manager.py to _internal * Move client.py to _internal * Move error_handler.py to _internal * Move lock.py to _internal * Move main.py to _internal * Move notify.py to _internal * Move ocsp.py to _internal * Move renewal.py to _internal * Move reporter.py to _internal * Move storage.py to _internal * Move updater.py to _internal * update apache and nginx oldest requirements * Keep the lock file as certbot.lock * nginx oldest tests still need to rely on newer certbot * python doesn't have good dependency resolution, so specify the transitive dependency * update required minimum versions in nginx setup.py
192 lines
7.0 KiB
Python
192 lines
7.0 KiB
Python
#!/usr/bin/env python3
|
|
import contextlib
|
|
import ctypes
|
|
import struct
|
|
import subprocess
|
|
import os
|
|
import sys
|
|
import shutil
|
|
import tempfile
|
|
import time
|
|
|
|
PYTHON_VERSION = (3, 7, 4)
|
|
PYTHON_BITNESS = 32
|
|
PYWIN32_VERSION = 225 # do not forget to edit pywin32 dependency accordingly in setup.py
|
|
NSIS_VERSION = '3.04'
|
|
|
|
|
|
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', '.']
|
|
# 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:
|
|
command = [venv_python, '-m', 'pip', 'wheel', '-w', wheels_path, '--constraint', constraints_file_path]
|
|
command.extend(wheels_project)
|
|
subprocess.check_call(command)
|
|
|
|
|
|
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, 'letsencrypt-auto-source', 'pieces', 'pipstrap.py')])
|
|
subprocess.check_call([venv_python, os.path.join(repo_path, 'tools', 'pip_install.py'), 'pynsist'])
|
|
subprocess.check_call(['choco', 'upgrade', '-y', 'nsis', '--version', NSIS_VERSION])
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def _prepare_constraints(repo_path):
|
|
requirements = os.path.join(repo_path, 'letsencrypt-auto-source', 'pieces', 'dependency-requirements.txt')
|
|
constraints = subprocess.check_output(
|
|
[sys.executable, os.path.join(repo_path, 'tools', 'strip_hashes.py'), requirements],
|
|
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)
|
|
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')
|
|
|
|
pywin32_paths_file = os.path.join(build_path, 'pywin32_paths.py')
|
|
|
|
# Pywin32 uses non-standard folders to hold its packages. We need to instruct pynsist bootstrap
|
|
# explicitly to add them into sys.path. This is done with a custom "pywin32_paths.py" that is
|
|
# referred in the pynsist configuration as an "extra_preamble".
|
|
# Reference example: https://github.com/takluyver/pynsist/tree/master/examples/pywebview
|
|
with open(pywin32_paths_file, 'w') as file_h:
|
|
file_h.write('''\
|
|
pkgdir = os.path.join(os.path.dirname(installdir), 'pkgs')
|
|
|
|
sys.path.extend([
|
|
os.path.join(pkgdir, 'win32'),
|
|
os.path.join(pkgdir, 'win32', 'lib'),
|
|
])
|
|
|
|
# Preload pywintypes and pythoncom
|
|
pwt = os.path.join(pkgdir, 'pywin32_system32', 'pywintypes{0}{1}.dll')
|
|
pcom = os.path.join(pkgdir, 'pywin32_system32', 'pythoncom{0}{1}.dll')
|
|
import warnings
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore")
|
|
import imp
|
|
imp.load_dynamic('pywintypes', pwt)
|
|
imp.load_dynamic('pythoncom', pcom)
|
|
'''.format(PYTHON_VERSION[0], PYTHON_VERSION[1]))
|
|
|
|
installer_cfg_path = os.path.join(build_path, 'installer.cfg')
|
|
|
|
certbot_version = subprocess.check_output([sys.executable, '-c', 'import certbot; print(certbot.__version__)'],
|
|
universal_newlines=True, cwd=repo_path).strip()
|
|
|
|
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._internal.main:main
|
|
extra_preamble=pywin32_paths.py
|
|
'''.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 not 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()
|