mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-07 18:14:10 +00:00
243 lines
5.8 KiB
Python
243 lines
5.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
invoke script for releasing jupyterhub
|
|
|
|
usage:
|
|
|
|
invoke release 1.2.3 [--upload]
|
|
|
|
This does:
|
|
|
|
- clone into /tmp/jupyterhub-repo
|
|
- patches version.py with release version
|
|
- creates tag (push if uploading)
|
|
- makes a virtualenv with python3.4 (PYTHON_EXE env to override)
|
|
- builds an sdist (optionally uploads)
|
|
- patches version.py with post-release version (X.Y+1.Z.dev) (push if uploading)
|
|
- unpacks sdist to /tmp/jupyterhub-release
|
|
- builds bdist_wheel from sdist (optional upload)
|
|
|
|
"""
|
|
# derived from PyZMQ release/tasks.py (used under BSD)
|
|
|
|
# Copyright (c) Jupyter Developers
|
|
# Distributed under the terms of the Modified BSD License.
|
|
|
|
import glob
|
|
import os
|
|
import pipes
|
|
import shutil
|
|
|
|
from contextlib import contextmanager
|
|
from distutils.version import LooseVersion as V
|
|
|
|
from invoke import task, run as invoke_run
|
|
|
|
pjoin = os.path.join
|
|
here = os.path.dirname(__file__)
|
|
|
|
repo = "git@github.com:jupyter/jupyterhub"
|
|
pkg = repo.rsplit('/', 1)[-1]
|
|
|
|
py_exe = os.environ.get('PYTHON_EXE', 'python3.4')
|
|
|
|
tmp = "/tmp"
|
|
env_root = os.path.join(tmp, 'envs')
|
|
repo_root = pjoin(tmp, '%s-repo' % pkg)
|
|
sdist_root = pjoin(tmp, '%s-release' % pkg)
|
|
|
|
|
|
def run(cmd, **kwargs):
|
|
"""wrapper around invoke.run that accepts a Popen list"""
|
|
if isinstance(cmd, list):
|
|
cmd = " ".join(pipes.quote(s) for s in cmd)
|
|
kwargs.setdefault('echo', True)
|
|
return invoke_run(cmd, **kwargs)
|
|
|
|
|
|
@contextmanager
|
|
def cd(path):
|
|
"""Context manager for temporary CWD"""
|
|
cwd = os.getcwd()
|
|
os.chdir(path)
|
|
try:
|
|
yield
|
|
finally:
|
|
os.chdir(cwd)
|
|
|
|
|
|
@task
|
|
def clone_repo(reset=False):
|
|
"""Clone the repo"""
|
|
if os.path.exists(repo_root) and reset:
|
|
shutil.rmtree(repo_root)
|
|
if os.path.exists(repo_root):
|
|
with cd(repo_root):
|
|
run("git pull")
|
|
else:
|
|
run("git clone %s %s" % (repo, repo_root))
|
|
|
|
|
|
@task
|
|
def patch_version(vs, path=pjoin(here, '..')):
|
|
"""Patch zmq/sugar/version.py for the current release"""
|
|
v = parse_vs(vs)
|
|
version_py = pjoin(path, 'jupyterhub', 'version.py')
|
|
print("patching %s with %s" % (version_py, vs))
|
|
# read version.py, minus version parts
|
|
with open(version_py) as f:
|
|
pre_lines = []
|
|
post_lines = []
|
|
for line in f:
|
|
pre_lines.append(line)
|
|
if line.startswith("version_info"):
|
|
break
|
|
for line in f:
|
|
if line.startswith(')'):
|
|
post_lines.append(line)
|
|
break
|
|
for line in f:
|
|
post_lines.append(line)
|
|
|
|
# write new version.py
|
|
with open(version_py, 'w') as f:
|
|
for line in pre_lines:
|
|
f.write(line)
|
|
for part in v:
|
|
f.write(' %r,\n' % part)
|
|
for line in post_lines:
|
|
f.write(line)
|
|
|
|
# verify result
|
|
ns = {}
|
|
with open(version_py) as f:
|
|
exec(f.read(), {}, ns)
|
|
assert ns['__version__'] == vs, "%r != %r" % (ns['__version__'], vs)
|
|
|
|
|
|
@task
|
|
def tag(vs, push=False):
|
|
"""Make the tagged release commit"""
|
|
patch_version(vs, repo_root)
|
|
with cd(repo_root):
|
|
run('git commit -a -m "release {}"'.format(vs))
|
|
run('git tag -a -m "release {0}" {0}'.format(vs))
|
|
if push:
|
|
run('git push')
|
|
run('git push --tags')
|
|
|
|
|
|
@task
|
|
def untag(vs, push=False):
|
|
"""Make the post-tag 'back to dev' commit"""
|
|
v2 = parse_vs(vs)
|
|
v2.append('dev')
|
|
v2[1] += 1
|
|
v2[2] = 0
|
|
vs2 = unparse_vs(v2)
|
|
patch_version(vs2, repo_root)
|
|
with cd(repo_root):
|
|
run('git commit -a -m "back to dev"')
|
|
if push:
|
|
run('git push')
|
|
|
|
|
|
def make_env(*packages):
|
|
"""Make a virtualenv
|
|
|
|
Assumes `which python` has the `virtualenv` package
|
|
"""
|
|
if not os.path.exists(env_root):
|
|
os.makedirs(env_root)
|
|
|
|
env = os.path.join(env_root, os.path.basename(py_exe))
|
|
py = pjoin(env, 'bin', 'python')
|
|
# new env
|
|
if not os.path.exists(py):
|
|
run('python -m virtualenv {} -p {}'.format(
|
|
pipes.quote(env),
|
|
pipes.quote(py_exe),
|
|
))
|
|
py = pjoin(env, 'bin', 'python')
|
|
run([py, '-V'])
|
|
install(py, 'pip', 'setuptools')
|
|
if packages:
|
|
install(py, *packages)
|
|
return py
|
|
|
|
|
|
def build_sdist(py):
|
|
"""Build sdists
|
|
|
|
Returns the path to the tarball
|
|
"""
|
|
with cd(repo_root):
|
|
cmd = [py, 'setup.py', 'sdist', '--formats=zip,gztar']
|
|
run(cmd)
|
|
|
|
return glob.glob(pjoin(repo_root, 'dist', '*.tar.gz'))[0]
|
|
|
|
|
|
@task
|
|
def sdist(vs, upload=False):
|
|
clone_repo()
|
|
tag(vs, push=upload)
|
|
py = make_env()
|
|
tarball = build_sdist(py)
|
|
if upload:
|
|
with cd(repo_root):
|
|
install(py, 'twine')
|
|
run([py, '-m', 'twine', 'upload', 'dist/*'])
|
|
|
|
untag(vs, push=upload)
|
|
return untar(tarball)
|
|
|
|
|
|
def install(py, *packages):
|
|
run([py, '-m', 'pip', 'install', '--upgrade'] + list(packages))
|
|
|
|
|
|
def parse_vs(vs):
|
|
"""version string to list"""
|
|
return V(vs).version
|
|
|
|
|
|
def unparse_vs(tup):
|
|
"""version list to string"""
|
|
return '.'.join(map(str, tup))
|
|
|
|
|
|
def untar(tarball):
|
|
"""extract sdist, returning path to unpacked package directory"""
|
|
if os.path.exists(sdist_root):
|
|
shutil.rmtree(sdist_root)
|
|
os.makedirs(sdist_root)
|
|
with cd(sdist_root):
|
|
run(['tar', '-xzf', tarball])
|
|
|
|
return glob.glob(pjoin(sdist_root, '*'))[0]
|
|
|
|
|
|
def bdist():
|
|
"""build a wheel, optionally uploading it"""
|
|
py = make_env('wheel')
|
|
run([py, 'setup.py', 'bdist_wheel'])
|
|
|
|
|
|
@task
|
|
def release(vs, upload=False):
|
|
"""Release the package"""
|
|
# start from scrach with clone and envs
|
|
clone_repo(reset=True)
|
|
if os.path.exists(env_root):
|
|
shutil.rmtree(env_root)
|
|
|
|
path = sdist(vs, upload=upload)
|
|
print("Working in %r" % path)
|
|
with cd(path):
|
|
bdist()
|
|
if upload:
|
|
py = make_env('twine')
|
|
run([py, '-m', 'twine', 'upload', 'dist/*'])
|
|
|