Permalink
Browse files

Add release script

  • Loading branch information...
1 parent 2d7f9f2 commit 4ec0b8232de519836f8153b1d75788c47a6a3ac1 @mattupstate committed Oct 11, 2012
Showing with 189 additions and 0 deletions.
  1. +189 −0 scripts/release.py
View
@@ -0,0 +1,189 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ make-release
+ ~~~~~~~~~~~~
+
+ Helper script that performs a release. Does pretty much everything
+ automatically for us.
+
+ :copyright: (c) 2011 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+import sys
+import os
+import re
+from datetime import datetime, date
+from subprocess import Popen, PIPE
+
+_date_clean_re = re.compile(r'(\d+)(st|nd|rd|th)')
+
+
+def installed_libraries():
+ return Popen(['pip', 'freeze'], stdout=PIPE).communicate()[0]
+
+
+def has_library_installed(library):
+ return library + '==' in installed_libraries()
+
+
+def parse_changelog():
+ with open('CHANGES') as f:
+ lineiter = iter(f)
+ for line in lineiter:
+ match = re.search('^Version\s+(.*)', line.strip())
+
+ if match is None:
+ continue
+
+ version = match.group(1).strip()
+
+ if lineiter.next().count('-') != len(line.strip()):
+ fail('Invalid hyphen count below version line: %s', line.strip())
+
+ while 1:
+ released = lineiter.next().strip()
+ if released:
+ break
+
+ match = re.search(r'Released (\w+\s+\d+\w+\s+\d+)', released)
+
+ if match is None:
+ fail('Could not find release date in version %s' % version)
+
+ datestr = parse_date(match.group(1).strip())
+
+ return version, datestr
+
+
+def bump_version(version):
+ try:
+ parts = map(int, version.split('.'))
+ except ValueError:
+ fail('Current version is not numeric')
+ parts[-1] += 1
+ return '.'.join(map(str, parts))
+
+
+def parse_date(string):
+ string = _date_clean_re.sub(r'\1', string)
+ return datetime.strptime(string, '%B %d %Y')
+
+
+def set_filename_version(filename, version_number, pattern):
+ changed = []
+
+ def inject_version(match):
+ before, old, after = match.groups()
+ changed.append(True)
+ return before + version_number + after
+
+ with open(filename) as f:
+ contents = re.sub(r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern,
+ inject_version, f.read())
+
+ if not changed:
+ fail('Could not find %s in %s', pattern, filename)
+
+ with open(filename, 'w') as f:
+ f.write(contents)
+
+
+def set_init_version(version):
+ info('Setting __init__.py version to %s', version)
+ set_filename_version('flask_social/__init__.py', version, '__version__')
+
+
+def set_setup_version(version):
+ info('Setting setup.py version to %s', version)
+ set_filename_version('setup.py', version, 'version')
+
+
+def set_docs_version(version):
+ info('Setting docs/conf.py version to %s', version)
+ set_filename_version('docs/conf.py', version, 'version')
+
+
+def build_and_upload():
+ Popen([sys.executable, 'setup.py', 'sdist', 'build_sphinx', 'upload', 'upload_sphinx']).wait()
+
+
+def fail(message, *args):
+ print >> sys.stderr, 'Error:', message % args
+ sys.exit(1)
+
+
+def info(message, *args):
+ print >> sys.stderr, message % args
+
+
+def get_git_tags():
+ return set(Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines())
+
+
+def git_is_clean():
+ return Popen(['git', 'diff', '--quiet']).wait() == 0
+
+
+def make_git_commit(message, *args):
+ message = message % args
+ Popen(['git', 'commit', '-am', message]).wait()
+
+
+def make_git_tag(tag):
+ info('Tagging "%s"', tag)
+ Popen(['git', 'tag', '-a', tag, '-m', '%s release' % tag]).wait()
+ Popen(['git', 'push', '--tags']).wait()
+
+
+def update_version(version):
+ for f in [set_init_version, set_setup_version, set_docs_version]:
+ f(version)
+
+
+def get_branches():
+ return set(Popen(['git', 'branch'], stdout=PIPE).communicate()[0].splitlines())
+
+
+def branch_is(branch):
+ return '* ' + branch in get_branches()
+
+
+def main():
+ os.chdir(os.path.join(os.path.dirname(__file__), '..'))
+
+ rv = parse_changelog()
+
+ if rv is None:
+ fail('Could not parse changelog')
+
+ version, release_date = rv
+
+ tags = get_git_tags()
+
+ for lib in ['Sphinx', 'Sphinx-PyPI-upload']:
+ if not has_library_installed(lib):
+ fail('Build requires that %s be installed', lib)
+
+ if version in tags:
+ fail('Version "%s" is already tagged', version)
+ if release_date.date() != date.today():
+ fail('Release date is not today')
+
+ if not branch_is('master'):
+ fail('You are not on the master branch')
+
+ if not git_is_clean():
+ fail('You have uncommitted changes in git')
+
+ info('Releasing %s (release date %s)',
+ version, release_date.strftime('%d/%m/%Y'))
+
+ update_version(version)
+ make_git_commit('Bump version number to %s', version)
+ make_git_tag(version)
+ build_and_upload()
+
+
+if __name__ == '__main__':
+ main()

0 comments on commit 4ec0b82

Please sign in to comment.