Skip to content

Commit 7c72cf6

Browse files
committed
Add release tooling to common repo
This is a fork of the .org release tooling.
1 parent 6e48aba commit 7c72cf6

File tree

3 files changed

+151
-1
lines changed

3 files changed

+151
-1
lines changed

changelog.hbs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{{header}}
2+
{{toHeader header "-"}}
3+
4+
:Date: {{date}}
5+
6+
{{#issues}}* `@{{user.login}} <http://github.com/{{user.login}}>`_: {{title}} (`#{{number}} <{{html_url}}>`_)
7+
{{/issues}}

common.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ default: link pre-commit
1616

1717
# Config rules
1818
CONFIG = \
19-
prospector.yml
19+
prospector.yml \
20+
tasks.py
2021

2122
CONFIG_HIDDEN = \
2223
.eslintrc \

tasks.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# -*- coding: utf-8 -*-
2+
"""Read the Docs invoke tasks."""
3+
4+
from __future__ import division, print_function, unicode_literals
5+
6+
import os
7+
import textwrap
8+
9+
from dateutil.parser import parse
10+
from future.moves.configparser import RawConfigParser, NoSectionError
11+
from invoke import task, Exit
12+
13+
14+
# This is the symlink path in the repo
15+
REPO_PATH = os.path.dirname(__file__)
16+
SETUP_SECTION = 'tool:release'
17+
18+
19+
@task
20+
def prepare(ctx, version, since=None):
21+
"""
22+
Prepare the next release version by updating files.
23+
24+
This will stage a few updates for manual review and commit:
25+
26+
* Prepend the most recent PRs and issues that were closed to CHANGELOG.rst.
27+
* Update the setup.cfg version
28+
29+
Changelog uses the file modification date to track the last time it was
30+
updated. New entries will end up at the top of the file, under a heading
31+
for the new version.
32+
"""
33+
print('Updating release version in setup.cfg')
34+
setupcfg_path = os.path.join(REPO_PATH, 'setup.cfg')
35+
config = RawConfigParser()
36+
config.read(setupcfg_path)
37+
38+
release_config = get_config(config)
39+
if release_config['github_private'] and 'GITHUB_TOKEN' not in os.environ.keys():
40+
print('\n'.join(textwrap.wrap(
41+
'In order to grab pull request information from a private repository '
42+
'you will need to set the GITHUB_TOKEN env variable with a personal '
43+
'access token from GitHub.'
44+
)))
45+
return False
46+
47+
# Set the release number
48+
config.set('metadata', 'version', version)
49+
with open(setupcfg_path, 'wb') as configfile:
50+
config.write(configfile)
51+
52+
# Install and run
53+
print('Installing github-changelog')
54+
ctx.run('npm install git+https://github.com/agjohnson/github-changelog.git')
55+
if not since:
56+
# Get last modified date from Git instead of assuming the file metadata is
57+
# correct. This can change depending on git reset, etc.
58+
git_log = ctx.run('git log -1 --format="%ad" -- CHANGELOG.rst')
59+
since = parse(git_log.stdout.strip()).strftime('%Y-%m-%d')
60+
changelog_path = os.path.join(REPO_PATH, 'CHANGELOG.rst')
61+
template_path = os.path.join(
62+
REPO_PATH,
63+
'common',
64+
'changelog.hbs',
65+
)
66+
bin_path = os.path.join(REPO_PATH, 'node_modules', '.bin')
67+
cmd = (
68+
'{bin_path}/gh-changelog '
69+
'-o {owner} -r {repository} '
70+
'--file {changelog_path} '
71+
'--since {since} '
72+
'--template {template_path} '
73+
'--header "Version {version}" '
74+
'--merged '
75+
).format(
76+
bin_path=bin_path,
77+
owner=release_config['github_owner'],
78+
repository=release_config['github_repo'],
79+
version=version,
80+
template_path=template_path,
81+
changelog_path=changelog_path,
82+
since=since,
83+
) # yapf: disable
84+
try:
85+
token = os.environ['GITHUB_TOKEN']
86+
cmd += '--token ' + token + ' '
87+
except KeyError:
88+
print('')
89+
print(
90+
'\n'.join(
91+
textwrap.wrap(
92+
'In order to avoid rate limiting on the GitHub API, you can specify '
93+
'an environment variable `GITHUB_TOKEN` with a personal access token. '
94+
'There is no need for the token to have any permissions unless the '
95+
'repoistory is private.')))
96+
print('')
97+
print('Updating changelog')
98+
ctx.run(cmd)
99+
100+
101+
@task
102+
def release(ctx, version):
103+
"""
104+
Tag release of Read the Docs.
105+
106+
Do this after prepare task and manual cleanup/commit
107+
"""
108+
# Ensure we're on the master branch first
109+
git_rev_parse = ctx.run('git rev-parse --abbrev-ref HEAD', hide=True)
110+
current_branch = git_rev_parse.stdout.strip()
111+
if current_branch != 'master':
112+
print('You must be on master branch!')
113+
raise Exit(1)
114+
ctx.run(
115+
('git tag {version} && '
116+
'git push --tags').format(version=version))
117+
118+
119+
def get_config(config=None):
120+
release_config = {
121+
'github_owner': 'rtfd',
122+
'github_private': False,
123+
}
124+
125+
if config is None:
126+
config = RawConfigParser()
127+
128+
setupcfg_path = os.path.join(REPO_PATH, 'setup.cfg')
129+
if not os.path.exists(setupcfg_path):
130+
print(
131+
'Missing setup.cfg! '
132+
'Make sure you are running invoke from your repository path.'
133+
)
134+
return False
135+
config.read(setupcfg_path)
136+
137+
try:
138+
release_config.update(config.items(SETUP_SECTION))
139+
except NoSectionError:
140+
pass
141+
142+
return release_config

0 commit comments

Comments
 (0)