mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-27 02:24:18 +00:00
286 lines
8.0 KiB
Plaintext
286 lines
8.0 KiB
Plaintext
|
#!/usr/bin/env python
|
||
|
from __future__ import (
|
||
|
absolute_import, print_function, division, unicode_literals
|
||
|
)
|
||
|
from contextlib import contextmanager
|
||
|
from os.path import dirname, realpath, join, exists, normpath
|
||
|
import os
|
||
|
import shutil
|
||
|
import subprocess
|
||
|
import glob
|
||
|
import re
|
||
|
import shlex
|
||
|
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"
|
||
|
|
||
|
release_dir = join(dirname(realpath(__file__)))
|
||
|
root_dir = join(release_dir, "..")
|
||
|
mitmproxy_dir = join(root_dir, "mitmproxy")
|
||
|
dist_dir = join(mitmproxy_dir, "dist")
|
||
|
test_venv_dir = join(release_dir, "venv")
|
||
|
|
||
|
all_projects = ("netlib", "pathod", "mitmproxy")
|
||
|
tools = {
|
||
|
"mitmproxy": ["mitmproxy", "mitmdump", "mitmweb"],
|
||
|
"pathod": ["pathod", "pathoc"],
|
||
|
"netlib": []
|
||
|
}
|
||
|
if os.name == "nt":
|
||
|
tools["mitmproxy"].remove("mitmproxy")
|
||
|
version_files = {
|
||
|
"mitmproxy": normpath(join(root_dir, "mitmproxy/libmproxy/version.py")),
|
||
|
"pathod": normpath(join(root_dir, "pathod/libpathod/version.py")),
|
||
|
"netlib": normpath(join(root_dir, "netlib/netlib/version.py")),
|
||
|
}
|
||
|
|
||
|
|
||
|
@contextmanager
|
||
|
def empty_pythonpath():
|
||
|
"""
|
||
|
Make sure that the regular python installation is not on the python path,
|
||
|
which would give us access to modules installed outside of our virtualenv.
|
||
|
"""
|
||
|
pythonpath = os.environ["PYTHONPATH"]
|
||
|
os.environ["PYTHONPATH"] = ""
|
||
|
yield
|
||
|
os.environ["PYTHONPATH"] = pythonpath
|
||
|
|
||
|
|
||
|
@contextmanager
|
||
|
def chdir(path):
|
||
|
old_dir = os.getcwd()
|
||
|
os.chdir(path)
|
||
|
yield
|
||
|
os.chdir(old_dir)
|
||
|
|
||
|
|
||
|
@click.group(chain=True)
|
||
|
def cli():
|
||
|
"""
|
||
|
mitmproxy build tool
|
||
|
"""
|
||
|
pass
|
||
|
|
||
|
|
||
|
@cli.command("contributors")
|
||
|
@click.option(
|
||
|
'--project', '-p', 'projects',
|
||
|
multiple=True, type=click.Choice(all_projects), default=all_projects
|
||
|
)
|
||
|
def contributors(projects):
|
||
|
"""
|
||
|
Update CONTRIBUTORS.md
|
||
|
"""
|
||
|
for project in all_projects:
|
||
|
if project not in projects:
|
||
|
continue
|
||
|
with chdir(os.path.join(root_dir, project)):
|
||
|
print("Updating %s/CONTRIBUTORS..."%project)
|
||
|
contributors_data = subprocess.check_output(
|
||
|
shlex.split("git shortlog -n -s")
|
||
|
)
|
||
|
with open("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.option(
|
||
|
'--project', '-p', 'projects',
|
||
|
multiple=True, type=click.Choice(all_projects), default=all_projects
|
||
|
)
|
||
|
@click.argument('version')
|
||
|
def set_version(projects, version):
|
||
|
"""
|
||
|
Update version information
|
||
|
"""
|
||
|
print("Update versions...")
|
||
|
version = ", ".join(version.split("."))
|
||
|
for project, version_file in version_files.items():
|
||
|
if project not in projects:
|
||
|
continue
|
||
|
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.option(
|
||
|
'--project', '-p', 'projects',
|
||
|
multiple=True, type=click.Choice(all_projects), default=all_projects
|
||
|
)
|
||
|
@click.argument('args', nargs=-1, required=True)
|
||
|
def git(projects, 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")
|
||
|
@click.option(
|
||
|
'--project', '-p', 'projects',
|
||
|
multiple=True, type=click.Choice(all_projects), default=all_projects
|
||
|
)
|
||
|
def sdist(projects):
|
||
|
"""
|
||
|
Build a source distribution
|
||
|
"""
|
||
|
with empty_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.option(
|
||
|
'--project', '-p', 'projects',
|
||
|
multiple=True, type=click.Choice(all_projects), default=all_projects
|
||
|
)
|
||
|
@click.pass_context
|
||
|
def test(ctx, projects):
|
||
|
"""
|
||
|
Test the source distribution
|
||
|
"""
|
||
|
if not exists(dist_dir):
|
||
|
ctx.invoke(sdist)
|
||
|
|
||
|
with empty_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")
|
||
|
with chdir(dist_dir):
|
||
|
for project in projects:
|
||
|
print("Installing %s..." % project)
|
||
|
dist = join(root_dir, project)
|
||
|
subprocess.check_call([pip, "install", "-q", dist])
|
||
|
|
||
|
print("Running binaries...")
|
||
|
for project in projects:
|
||
|
for tool in tools[project]:
|
||
|
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 wizard is missing OSX builds and updating mitmproxy.org.
|
||
|
@cli.command("wizard")
|
||
|
@click.option('--version', prompt=True)
|
||
|
@click.option('--username', prompt="PyPI Username")
|
||
|
@click.password_option(confirmation_prompt=False, prompt="PyPI Password")
|
||
|
@click.option('--repository', default="pypi")
|
||
|
@click.option(
|
||
|
'--project', '-p', 'projects',
|
||
|
multiple=True, type=click.Choice(all_projects), default=all_projects
|
||
|
)
|
||
|
@click.pass_context
|
||
|
def wizard(ctx, version, username, password, repository, projects):
|
||
|
"""
|
||
|
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)
|
||
|
|
||
|
# Build test release
|
||
|
ctx.invoke(sdist, projects=projects)
|
||
|
ctx.invoke(test, projects=projects)
|
||
|
click.confirm("Please test the release now. Is it ok?", abort=True)
|
||
|
|
||
|
# bump version, update docs and contributors
|
||
|
ctx.invoke(set_version, version=version, projects=projects)
|
||
|
ctx.invoke(docs)
|
||
|
ctx.invoke(contributors)
|
||
|
|
||
|
# version bump commit + tag
|
||
|
ctx.invoke(
|
||
|
git, args=["commit", "-a", "-m", "bump version"], projects=projects
|
||
|
)
|
||
|
ctx.invoke(git, args=["tag", "v" + version], projects=projects)
|
||
|
ctx.invoke(git, args=["push"], projects=projects)
|
||
|
ctx.invoke(git, args=["push", "--tags"], projects=projects)
|
||
|
|
||
|
# Re-invoke sdist with bumped version
|
||
|
ctx.invoke(sdist, projects=projects)
|
||
|
click.confirm("All good, can upload to PyPI?", abort=True)
|
||
|
ctx.invoke(
|
||
|
upload_release,
|
||
|
username=username, password=password, repository=repository
|
||
|
)
|
||
|
click.echo("All done!")
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
cli()
|