mitmproxy/release/build.py
2015-07-22 02:43:45 +02:00

214 lines
5.7 KiB
Python
Executable File

#!/usr/bin/env python
from os.path import dirname, realpath, join, exists, normpath
from os import chdir
import os
import shutil
import subprocess
import glob
import re
from shlex import split
import click
# https://virtualenv.pypa.io/en/latest/userguide.html#windows-notes
# scripts and executables on Windows go in ENV\Scripts\ instead of ENV/bin/
if os.name == "nt":
venv_bin = "Scripts"
else:
venv_bin = "bin"
root_dir = join(dirname(realpath(__file__)), "..", "..")
mitmproxy_dir = join(root_dir, "mitmproxy")
dist_dir = join(mitmproxy_dir, "dist")
test_venv_dir = join(root_dir, "venv.mitmproxy-release")
projects = ("netlib", "pathod", "mitmproxy")
tools = ["mitmproxy", "mitmdump", "mitmweb", "pathod", "pathoc"]
if os.name == "nt":
tools.remove("mitmproxy")
version_files = (join(root_dir, x) for x in (
"mitmproxy/libmproxy/version.py",
"pathod/libpathod/version.py",
"netlib/netlib/version.py"
))
@click.group(chain=True)
def cli():
"""
mitmproxy build tool
"""
pass
@cli.command("contributors")
def contributors():
"""
Update CONTRIBUTORS.md
"""
print("Updating CONTRIBUTORS.md...")
contributors_data = subprocess.check_output(split("git shortlog -n -s"))
with open(join(mitmproxy_dir, "CONTRIBUTORS"), "w") as f:
f.write(contributors_data)
@cli.command("docs")
def docs():
"""
Render the docs
"""
print("Rendering the docs...")
subprocess.check_call([
"cshape",
join(mitmproxy_dir, "doc-src"),
join(mitmproxy_dir, "doc")
])
@cli.command("set-version")
@click.argument('version')
def set_version(version):
"""
Update version information
"""
print("Update versions...")
version = ", ".join(version.split("."))
for version_file in version_files:
print("Update %s..." % version_file)
with open(version_file, "rb") as f:
content = f.read()
new_content = re.sub(r"IVERSION\s*=\s*\([\d,\s]+\)", "IVERSION = (%s)" % version, content)
with open(version_file, "wb") as f:
f.write(new_content)
@cli.command("git")
@click.argument('args', nargs=-1, required=True)
def git(args):
"""
Run a git command on every project
"""
args = ["git"] + list(args)
for project in projects:
print("%s> %s..." % (project, " ".join(args)))
subprocess.check_call(
args,
cwd=join(root_dir, project)
)
@cli.command("sdist")
def sdist():
"""
Build a source distribution
"""
# Make sure that the regular python installation is not on the python path!
os.environ["PYTHONPATH"] = ""
print("Building release...")
if exists(dist_dir):
shutil.rmtree(dist_dir)
for project in projects:
print("Creating %s source distribution..." % project)
subprocess.check_call(
["python", "./setup.py", "-q", "sdist", "--dist-dir", dist_dir, "--formats=gztar"],
cwd=join(root_dir, project)
)
@cli.command("test")
@click.pass_context
def test(ctx):
"""
Test the source distribution
"""
if not exists(dist_dir):
ctx.invoke(sdist)
# Make sure that the regular python installation is not on the python path!
os.environ["PYTHONPATH"] = ""
print("Creating virtualenv for test install...")
if exists(test_venv_dir):
shutil.rmtree(test_venv_dir)
subprocess.check_call(["virtualenv", "-q", test_venv_dir])
pip = join(test_venv_dir, venv_bin, "pip")
chdir(dist_dir)
for project in projects:
print("Installing %s..." % project)
dist = glob.glob("./%s*" % project)[0]
subprocess.check_call([pip, "install", "-q", dist])
print("Running binaries...")
for tool in tools:
tool = join(test_venv_dir, venv_bin, tool)
print(tool)
print(subprocess.check_output([tool, "--version"]))
print("Virtualenv available for further testing:")
print("source %s" % normpath(join(test_venv_dir, venv_bin, "activate")))
@cli.command("upload")
@click.option('--username', prompt=True)
@click.password_option(confirmation_prompt=False)
@click.option('--repository', default="pypi")
def upload_release(username, password, repository):
"""
Upload source distributions to PyPI
"""
print("Uploading distributions...")
subprocess.check_call([
"twine",
"upload",
"-u", username,
"-p", password,
"-r", repository,
"%s/*" % dist_dir
])
"""
TODO: Fully automate build process.
This skeleton is missing OSX builds and updating mitmproxy.org.
@cli.command("wizard")
@click.option('--version', prompt=True)
@click.option('--username', prompt=True)
@click.password_option(confirmation_prompt=False)
@click.option('--repository', default="pypi")
@click.option('--test/--no-test', default=True)
@click.pass_context
def wizard(ctx, version, username, password, repository, test):
""
Interactive Release Wizard
""
for project in projects:
if subprocess.check_output(["git", "status", "--porcelain"], cwd=join(root_dir, project)):
raise RuntimeError("%s repository is not clean." % project)
if test:
ctx.invoke(sdist)
ctx.invoke(test)
click.confirm("Please test the release now. Is it ok?", abort=True)
ctx.invoke(set_version, version=version)
ctx.invoke(docs)
ctx.invoke(contributors)
ctx.invoke(git, args=["commit", "-a", "-m", "bump version"])
ctx.invoke(git, args=["tag", "v" + version])
ctx.invoke(git, args=["push", "--tags"])
ctx.invoke(sdist)
ctx.invoke(upload_release, username=username, password=password, repository=repository)
click.echo("All done!")
"""
if __name__ == "__main__":
cli()