Commit 88652000 authored by Jason Madden's avatar Jason Madden

Remove old release scripts that no longer work and document the new workflow in development.rst.

[skip ci]
parent f9e578fc
......@@ -3,7 +3,7 @@ recursive-include examples *
recursive-include src/gevent *
recursive-include docs *
recursive-include deps *
recursive-include util *
include LICENSE
include NOTICE
......
......@@ -205,3 +205,34 @@ monitor test coverage.
.. _coverage.py: https://pypi.python.org/pypi/coverage/
.. _coveralls.io: https://coveralls.io/github/gevent/gevent
.. _AppVeyor: https://ci.appveyor.com/project/denik/gevent
Releasing gevent
================
.. note:: This is a semi-organized collection of notes for gevent
maintainers.
gevent is released using `zest.releaser
<https://pypi.org/project/zest.releaser/>`_. The general flow is
something like this:
1. Push all relevant changes to master.
2. From the gevent working copy, run ``prerelease``. Fix any issues it
brings up. Let it bump the version number (or enter the correct
one) and commit.
3. Run ``release``. Let it create the tag and commit it; let it create
an sdist, but **do not** let it upload it.
4. Push the tag and master to github.
5. Let appveyor build the tag. Download all the built wheels from that
release. The easiest way to do that is with Ned Batchelder's
`appveyor-download.py script
<https://bitbucket.org/ned/coveragepy/src/tip/ci/download_appveyor.py>`_.
6. Meanwhile, spin up docker and from the root of the gevent checkout
run ``scripts/releases/make-manylinux``. This creates wheels in
``wheelhouse/``.
7. If on a mac, ``cd scripts/releases && ./geventreleases.sh``. This
creates wheels in ``/tmp/gevent/``.
8. Upload the Appveyor, manylinux, and mac wheels to pypi using
``twine``. Also be sure to upload the sdist!
9. Run ``postrelease``, let it bump the version and push the changes
to github.
This diff is collapsed.
#!/bin/bash
set -e
CWD=`pwd`
rm -fr /tmp/build_gevent_deb
set -x
mkdir /tmp/build_gevent_deb
#util/makedist.py --dest /tmp/build_gevent_deb/gevent.tar.gz --version dev
cd /tmp/build_gevent_deb
tar -xf $CWD/dist/gevent-1.0.tar.gz
fpm --no-python-dependencies -s python -t deb gevent*/setup.py
mkdir -p $CWD/build
mv *.deb $CWD/build/
#!/usr/bin/python
# Copyright (C) 2012 Denis Bilenko (http://denisbilenko.com)
"""
Create a source distribution of gevent.
Does the following:
- Clones the repo into a temporary location.
- Run set_version.py that will update gevent/__init__.py.
- Run 'python setup.py sdist'.
"""
from __future__ import print_function
import sys
import os
import glob
import argparse
from os.path import exists, join, abspath, basename
from pipes import quote
TMPDIR = '/tmp/gevent-make-dist'
def system(cmd, noisy=True):
if noisy:
print(cmd)
res = os.system(cmd)
if res:
sys.exit('%r failed with %s' % (cmd, res))
def makedist(*args, **kwargs):
cwd = os.getcwd()
try:
return _makedist(*args, **kwargs)
finally:
os.chdir(cwd)
def _makedist(version=None, dest=None):
assert exists('gevent/__init__.py'), 'Where am I?'
basedir = abspath(os.getcwd())
version = version or 'dev'
set_version_command = 'util/set_version.py --version %s ./gevent/__init__.py' % version
os.chdir('/tmp')
system('rm -fr ' + TMPDIR)
os.mkdir(TMPDIR)
os.chdir(TMPDIR)
system('git clone %s gevent' % basedir)
directory = os.listdir('.')
assert len(directory) == 1, directory
os.chdir(directory[0])
system('git branch')
system(set_version_command)
system('git diff', noisy=False)
system('python setup.py -q sdist')
dist_filename = glob.glob('dist/gevent-*.tar.gz')
assert len(dist_filename) == 1, dist_filename
dist_path = abspath(dist_filename[0])
dist_filename = basename(dist_path)
if dest:
if os.path.isdir(dest):
dest = join(dest, dist_filename)
else:
if not exists(join(basedir, 'dist')):
os.mkdir(join(basedir, 'dist'))
dest = join(basedir, 'dist', dist_filename)
copy(dist_path, dest)
return dist_path
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--dest')
parser.add_argument('--version')
options = parser.parse_args()
return makedist(options.version, dest=options.dest)
def copy(source, dest):
system('cp -a %s %s' % (quote(source), quote(dest)))
if __name__ == '__main__':
main()
#!/usr/bin/python
"""Update __version__, version_info and add __changeset__.
'dev' in version_info should be replaced with alpha|beta|candidate|final
'dev' in __version__ should be replaced with a|b|rc|<empty string>
"""
from __future__ import print_function
import sys
import os
import re
from argparse import ArgumentParser
from distutils.version import LooseVersion
version_re = re.compile("^__version__\s*=\s*'([^']+)'", re.M)
version_info_re = re.compile(r"^version_info\s*=\s*([^\n]+)", re.M)
strict_version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', re.VERBOSE)
def read(command):
popen = os.popen(command)
data = popen.read()
retcode = popen.close()
if retcode:
sys.exit('Failed (%s) to run %r' % (retcode, command))
return data.strip()
def get_changeset():
return read('git describe --tags --always --dirty --long')
def get_version_info(version):
"""
>>> get_version_info('0.13.6')
(0, 13, 6, 'final', 0)
>>> get_version_info('1.1')
(1, 1, 0, 'final', 0)
>>> get_version_info('1')
(1, 0, 0, 'final', 0)
>>> get_version_info('1.0dev1')
(1, 0, 0, 'dev', 1)
>>> get_version_info('1.0a3')
(1, 0, 0, 'alpha', 3)
>>> get_version_info('1.0rc1')
(1, 0, 0, 'candidate', 1)
"""
repl = {'a': 'alpha',
'b': 'beta',
'rc': 'candidate',
'dev': 'dev'}
components = LooseVersion(version).version
result = []
for component in components:
if isinstance(component, int):
result.append(component)
else:
while len(result) < 3:
result.append(0)
component = repl[component]
result.append(component)
while len(result) < 3:
result.append(0)
if len(result) == 3:
result.append('final')
result.append(0)
return tuple(result)
def modify_version(filename, new_version):
# return (current_contents, modified_contents, is_match)
original_data = open(filename).read()
assert '__changeset__' not in original_data, 'Must revert the old update first'
data = original_data
if new_version:
new_version_info = get_version_info(new_version)
def repl_version_info(m):
return 'version_info = %s' % (new_version_info, )
data, count = version_info_re.subn(repl_version_info, data)
if not count:
raise AssertionError('version_info not found in %s' % filename)
if count != 1:
raise AssertionError('version_info found more than once in %s' % filename)
def repl_version(m):
result = m.group(0).replace(m.group(1), new_version or m.group(1))
result += "\n__changeset__ = '%s'" % get_changeset()
return result
data, count = version_re.subn(repl_version, data)
if not count:
raise AssertionError('__version__ not found in %s' % filename)
if count != 1:
raise AssertionError('__version__ found more than once in %s' % filename)
return original_data, data
def unlink(path):
try:
os.unlink(path)
except OSError as ex:
if ex.errno == 2: # No such file or directory
return
raise
def write(filename, data):
# intentionally breaking links here so that util/makedist.py can use "cp --link"
tmpname = filename + '.tmp.%s' % os.getpid()
f = open(tmpname, 'w')
try:
f.write(data)
f.flush()
os.fsync(f.fileno())
f.close()
os.rename(tmpname, filename)
except:
unlink(tmpname)
raise
def main():
global options
parser = ArgumentParser()
parser.add_argument('--version', default='dev')
parser.add_argument('--dry-run', action='store_true')
parser.add_argument('filename')
options = parser.parse_args()
version = options.version
if version.lower() == 'dev':
version = ''
if version and strict_version_re.match(version) is None:
sys.stderr.write('WARNING: Not a strict version: %r (bdist_msi will fail)' % version)
original_content, new_content = modify_version(options.filename, version)
if options.dry_run:
tmpname = '/tmp/' + os.path.basename(options.filename) + '.set_version'
write(tmpname, new_content)
if not os.system('diff -u %s %s' % (options.filename, tmpname)):
sys.exit('No differences applied')
else:
write(options.filename, new_content)
print('Updated %s' % options.filename)
if __name__ == '__main__':
main()
#!/usr/bin/python -u
"""
Unix utilities must be installed on target machine for this to work: http://unxutils.sourceforge.net/
"""
import sys
import os
import argparse
def system(cmd, exit=True):
sys.stderr.write('+ %s\n' % cmd)
retcode = os.system(cmd)
if retcode:
if exit:
sys.exit('%r failed' % cmd)
return retcode
parser = argparse.ArgumentParser()
parser.add_argument('--host')
parser.add_argument('--username', default='Administrator')
parser.add_argument('--source')
parser.add_argument('--dist', action='store_true')
parser.add_argument('--python', default='27')
parser.add_argument('args', nargs='*')
options = parser.parse_args()
args = options.args
def prepare():
source_name = args[1]
tar_name = source_name.rsplit('.', 1)[0]
dir_name = tar_name.rsplit('.', 1)[0]
system('rm -fr %s %s' % (tar_name, dir_name))
system('gzip -d %s && tar -xf %s' % (source_name, tar_name))
os.chdir(dir_name)
os.environ.setdefault('VS90COMNTOOLS', 'C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\Tools\\')
if args[0:1] == ['test']:
prepare()
system('%s setup.py build' % sys.executable)
os.chdir('greentest')
os.environ['PYTHONPATH'] = '.;..;../..'
system('%s testrunner.py --config ../known_failures.py' % sys.executable)
elif args[0:1] == ['dist']:
prepare()
success = 0
for command in ['bdist_egg', 'bdist_wininst', 'bdist_msi']:
cmd = sys.executable + ' setup.py ' + command
if not system(cmd, exit=False):
success += 1
if not success:
sys.exit('bdist_egg bdist_wininst and bdist_msi all failed')
elif not args:
assert options.host
if not options.source:
import makedist
options.source = makedist.makedist()
options.source_name = os.path.basename(options.source)
options.script_path = os.path.abspath(__file__)
options.script_name = os.path.basename(__file__)
if options.python.isdigit():
options.python = 'C:/Python' + options.python + '/python.exe'
tar_name = options.source_name.rsplit('.', 1)[0]
dir_name = tar_name.rsplit('.', 1)[0]
options.dir_name = dir_name
system('scp %(source)s %(script_path)s %(username)s@%(host)s:' % options.__dict__)
if options.dist:
system('ssh %(username)s@%(host)s %(python)s -u %(script_name)s dist %(source_name)s' % options.__dict__)
try:
os.mkdir('dist')
except OSError:
pass
system('scp -r %(username)s@%(host)s:%(dir_name)s/dist/ dist' % options.__dict__)
else:
system('ssh %(username)s@%(host)s C:/Python27/python.exe -u %(script_name)s test %(source_name)s' % options.__dict__)
else:
sys.exit('Invalid args: %r' % (args, ))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment