github.phpd.cn/thought-machine/please@v12.2.0+incompatible/tools/misc/gen_release.py (about) 1 #!/usr/bin/env python3 2 """Script to create Github releases & generate release notes.""" 3 4 import json 5 import logging 6 import os 7 import subprocess 8 import sys 9 from third_party.python import requests 10 11 12 class ReleaseGen: 13 14 def __init__(self, version): 15 if 'GITHUB_TOKEN' not in os.environ: 16 logging.warning('Unless GITHUB_TOKEN is specified, your requests will likely fail') 17 self.url = 'https://api.github.com' 18 self.session = requests.Session() 19 self.session.headers.update({ 20 'Accept': 'application/vnd.github.v3+json', 21 'Authorization': 'token ' + os.environ.get('GITHUB_TOKEN', ''), 22 }) 23 self.version = version or self.get_current_version() 24 self.version_name = 'Version ' + self.version 25 26 def get_current_version(self): 27 """Loads the current version from the repo.""" 28 with open('VERSION') as f: 29 return f.read().strip() 30 31 def get_latest_release_version(self): 32 """Gets the latest released version from Github.""" 33 response = self.session.get(self.url + '/repos/thought-machine/please/releases/latest') 34 response.raise_for_status() 35 return json.loads(response.text).get('tag_name').lstrip('v') 36 37 def release(self): 38 """Submits a new release to Github.""" 39 tag = self.tag_release(self.get_release_sha()) 40 data = { 41 'tag_name': tag, 42 'name': 'Please v' + self.version, 43 'body': ''.join(self.get_release_notes()), 44 'prerelease': 'a' in self.version or 'b' in self.version, 45 } 46 response = self.session.post(self.url + '/repos/thought-machine/please/releases', json=data) 47 print(response.text) 48 response.raise_for_status() 49 50 def tag_release(self, commit_sha): 51 """Tags the release at the given commit (& matching date).""" 52 tag = 'v' + self.version 53 # Have to tag at the correct time. 54 commit_date = subprocess.check_output(['git', 'show', '-s', '--format=%ci', commit_sha]).decode('utf-8').strip() 55 env = os.environ.copy() 56 env['GIT_COMMITTER_DATE'] = commit_date 57 subprocess.check_call(['git', 'tag', '-a', tag, commit_sha, '-m', 'Please ' + tag], env=env) 58 subprocess.check_call(['git', 'push', 'origin', tag]) 59 return tag 60 61 def get_release_sha(self): 62 """Retrieves the Git commit corresponding to the given release.""" 63 for line in subprocess.check_output(['git', 'blame', 'ChangeLog']).decode('utf-8').split('\n'): 64 if self.version_name in line: 65 # Convert short SHA to full one 66 return subprocess.check_output(['git', 'rev-parse', line.split(' ')[0]]).decode('utf-8').strip() 67 raise Exception("Couldn't determine git sha for " + self.version_name) 68 69 def get_release_notes(self): 70 """Yields the changelog notes for a given version.""" 71 with open('ChangeLog') as f: 72 found_version = False 73 for line in f: 74 if line.startswith(self.version_name): 75 found_version = True 76 yield 'This is Please v%s' % self.version 77 elif line.startswith('------'): 78 continue 79 elif found_version: 80 if line.startswith('Version '): 81 return 82 elif line.startswith(' '): 83 # Markdown comes out nicer if we remove some of the spacing. 84 line = line[3:] 85 yield line 86 raise Exception("Couldn't find release notes for " + self.version_name) 87 88 89 if __name__ == '__main__': 90 r = ReleaseGen(sys.argv[1] if len(sys.argv) >= 2 else None) 91 r.release()