lbry-sdk/scripts/release.py

166 lines
4.5 KiB
Python
Raw Normal View History

import os
import re
import io
import sys
import json
import argparse
from datetime import date
from getpass import getpass
try:
import github3
except ImportError:
print('To run release tool you need to install github3.py:')
print('')
print(' $ pip install github3.py')
print('')
sys.exit(1)
AREA_RENAME = {
'api': 'API'
}
def get_github():
config_path = os.path.expanduser('~/.lbry-release-tool.json')
if os.path.exists(config_path):
with open(config_path, 'r') as config_file:
config = json.load(config_file)
return github3.login(token=config['token'])
print('GitHub Credentials')
username = input('username: ')
password = getpass('password: ')
gh = github3.authorize(
username, password, ['repo'], 'lbry release tool',
two_factor_callback=lambda: input('Enter 2FA: ')
)
with open(config_path, 'w') as config_file:
json.dump({'token': gh.token}, config_file)
return github3.login(token=gh.token)
def get_labels(pr, prefix):
for label in pr.labels:
label_name = label['name']
if label_name.startswith(f'{prefix}: '):
yield label_name[len(f'{prefix}: '):]
def get_label(pr, prefix):
for label in get_labels(pr, prefix):
return label
class Version:
def __init__(self, major=0, minor=0, micro=0, rc=None):
self.major = int(major)
self.minor = int(minor)
self.micro = int(micro)
2018-12-12 05:39:08 +01:00
self.rc = rc if rc is None else int(rc)
@classmethod
def from_string(cls, version_string):
(major, minor, micro), rc = version_string.split('.'), None
if 'rc' in micro:
micro, rc = micro.split('rc')
return cls(major, minor, micro, rc)
@classmethod
def from_content(cls, content):
src = content.decoded.decode('utf-8')
version = re.search('__version__ = "(.*?)"', src).group(1)
return cls.from_string(version)
def increment(self, part):
cls = self.__class__
if part == 'major':
return cls(self.major+1)
elif part == 'minor':
return cls(self.major, self.minor+1)
elif part == 'micro':
return cls(self.major, self.minor, self.micro+1)
elif part == 'rc':
if self.rc is None:
return cls(self.major, self.minor, self.micro+1, 1)
else:
return cls(self.major, self.minor, self.micro, self.rc+1)
else:
raise ValueError(f'unknown version part: {part}')
@property
def tag(self):
return f'v{self}'
def __str__(self):
version = '.'.join(str(p) for p in [self.major, self.minor, self.micro])
if self.rc is not None:
version += f'rc{self.rc}'
return version
def release(args):
gh = get_github()
repo = gh.repository('lbryio', 'lbry')
version_file = repo.file_contents('lbrynet/__init__.py')
current_version = Version.from_content(version_file)
print(f'Current Version: {current_version}')
new_version = current_version.increment(args.increment)
print(f' New Version: {new_version}')
current_release = repo.release_from_tag(current_version.tag)
areas = {}
for pr in gh.search_issues(f"merged:>={current_release._json_data['created_at']} repo:lbryio/lbry"):
for area_name in get_labels(pr, 'area'):
area = areas.setdefault(area_name, [])
area.append(f' * [{get_label(pr, "type")}] {pr.title} ({pr.html_url})')
area_names = list(areas.keys())
area_names.sort()
body = io.StringIO()
w = lambda s: body.write(s+'\n')
w(f'## [{new_version}] - {date.today().isoformat()}')
for area in area_names:
prs = areas[area]
area = AREA_RENAME.get(area, area.capitalize())
w('')
w(f'### {area}')
for pr in prs:
w(pr)
commit = version_file.update(
new_version.tag,
version_file.decoded.decode('utf-8').replace(str(current_version), str(new_version)).encode()
)['commit']
repo.create_tag(
tag=new_version.tag,
message=new_version.tag,
sha=commit.sha,
obj_type='commit',
tagger=commit.committer
)
repo.create_release(
new_version.tag,
name=new_version.tag,
body=body.getvalue(),
draft=True,
prerelease=True
)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("increment", choices=['major', 'minor', 'micro', 'rc'])
release(parser.parse_args())
if __name__ == "__main__":
main()