Skip to content

Commit 3d14654

Browse files
committed
Added release script
1 parent ab6bac1 commit 3d14654

File tree

4 files changed

+144
-4
lines changed

4 files changed

+144
-4
lines changed

CHANGES

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Here you can see the full list of changes between each Flask release.
66
Version 0.7
77
-----------
88

9-
Release date to be announced, codename to be selected
9+
Released on June 27th 2011, codename Grappa
1010

1111
- Added :meth:`~flask.Flask.make_default_options_response`
1212
which can be used by subclasses to alter the default

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ test:
88
audit:
99
python setup.py audit
1010

11+
release:
12+
python scripts/make-release.py
13+
1114
tox-test:
1215
PYTHONDONTWRITEBYTECODE= tox
1316

1417
ext-test:
1518
python tests/flaskext_test.py --browse
1619

17-
release:
18-
python setup.py release sdist upload
19-
2020
clean-pyc:
2121
find . -name '*.pyc' -exec rm -f {} +
2222
find . -name '*.pyo' -exec rm -f {} +

flask/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
:license: BSD, see LICENSE for more details.
1111
"""
1212

13+
__version__ = '0.7'
14+
1315
# utilities we import from Werkzeug and Jinja2 that are unused
1416
# in the module but are exported as public interface.
1517
from werkzeug import abort, redirect

scripts/make-release.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
"""
4+
make-release
5+
~~~~~~~~~~~~
6+
7+
Helper script that performs a release. Does pretty much everything
8+
automatically for us.
9+
10+
:copyright: (c) 2011 by Armin Ronacher.
11+
:license: BSD, see LICENSE for more details.
12+
"""
13+
import sys
14+
import os
15+
import re
16+
from datetime import datetime, date
17+
from subprocess import Popen, PIPE
18+
19+
20+
def parse_changelog():
21+
with open('CHANGES') as f:
22+
lineiter = iter(f)
23+
for line in lineiter:
24+
match = re.search('^Version\s+(.*)', line.strip())
25+
if match is None:
26+
continue
27+
length = len(match.group(1))
28+
version = match.group(1).strip()
29+
if lineiter.next().count('-') != len(match.group(0)):
30+
continue
31+
while 1:
32+
change_info = lineiter.next().strip()
33+
if change_info:
34+
break
35+
36+
match = re.match(r'^released on (\w+\s+\d+\w+\s+\d+)'
37+
r'(?:, codename (.*))?(?i)', change_info)
38+
if match is None:
39+
continue
40+
41+
datestr, codename = match.groups()
42+
return version, parse_date(datestr), codename
43+
44+
45+
def parse_date(string):
46+
string = string.replace('th ', ' ').replace('nd ', ' ') \
47+
.replace('rd ', ' ').replace('st ', ' ')
48+
return datetime.strptime(string, '%B %d %Y')
49+
50+
51+
def set_filename_version(filename, version_number, pattern):
52+
changed = []
53+
def inject_version(match):
54+
before, old, after = match.groups()
55+
changed.append(True)
56+
return before + version_number + after
57+
with open(filename) as f:
58+
contents = re.sub(r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern,
59+
inject_version, f.read())
60+
61+
if not changed:
62+
fail('Could not find %s in %s', pattern, filename)
63+
64+
with open(filename, 'w') as f:
65+
f.write(contents)
66+
67+
68+
def set_init_version(version):
69+
info('Setting __init__.py version to %s', version)
70+
set_filename_version('flask/__init__.py', version, '__version__')
71+
72+
73+
def set_setup_version(version):
74+
info('Setting setup.py version to %s', version)
75+
set_filename_version('setup.py', version, 'version')
76+
77+
78+
def build_and_upload():
79+
Popen([sys.executable, 'setup.py', 'sdist', 'release']).wait()
80+
81+
82+
def fail(message, *args):
83+
print >> sys.stderr, 'Error:', message % args
84+
sys.exit(1)
85+
86+
87+
def info(message, *args):
88+
print >> sys.stderr, message % args
89+
90+
91+
def get_git_tags():
92+
return set(Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines())
93+
94+
95+
def git_is_clean():
96+
return Popen(['git', 'diff', '--quiet']).wait() == 0
97+
98+
99+
def make_git_commit(message, *args):
100+
message = message % args
101+
Popen(['git', 'commit', '-am', message]).wait()
102+
103+
104+
def make_git_tag(tag):
105+
info('Tagging "%s"', tag)
106+
Popen(['git', 'tag', tag]).wait()
107+
108+
109+
def main():
110+
os.chdir(os.path.join(os.path.dirname(__file__), '..'))
111+
112+
rv = parse_changelog()
113+
if rv is None:
114+
fail('Could not parse changelog')
115+
116+
version, release_date, codename = rv
117+
118+
info('Releasing %s (codename %s, release date %s)',
119+
version, codename, release_date.strftime('%d/%m/%Y'))
120+
tags = get_git_tags()
121+
122+
if version in tags:
123+
fail('Version "%s" is already tagged', version)
124+
if release_date.date() != date.today():
125+
fail('Release date is not today (%s != %s)')
126+
127+
if not git_is_clean():
128+
fail('You have uncommitted changes in git')
129+
130+
set_init_version(version)
131+
set_setup_version(version)
132+
make_git_commit('Bump version number to %s', version)
133+
make_git_tag(version)
134+
build_and_upload()
135+
136+
137+
if __name__ == '__main__':
138+
main()

0 commit comments

Comments
 (0)