This repository has been archived by the owner on Feb 22, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Matt Wright
committed
Oct 11, 2012
1 parent
2d7f9f2
commit 4ec0b82
Showing
1 changed file
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |