From 611c35306009dec81e530f1e79638ac1be691f29 Mon Sep 17 00:00:00 2001 From: krzys-h Date: Fri, 10 Nov 2017 11:01:09 +0100 Subject: [PATCH] Update release script --- tools/release.py | 111 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 26 deletions(-) mode change 100644 => 100755 tools/release.py diff --git a/tools/release.py b/tools/release.py old mode 100644 new mode 100755 index 81392726..6ab155af --- a/tools/release.py +++ b/tools/release.py @@ -1,9 +1,10 @@ +#!/usr/bin/env python3 + # Script to use when releasing new versions # Run from main repo directory with data submodule pulled in data/ # -# Note: this has not yet been tested thoughtly, VERIFY EVERYTHING THIS SCRIPT DOES MANUALLY -# # Will automatically: +# * Make sure you don't have any uncommited local changes # * Make sure you don't forget to pull any changes before you start # * Get current version number from CMakeLists.txt # * Merge dev -> master in the data submodule @@ -13,26 +14,48 @@ # * Bump version number in main repo # * Tag release in main repo # * Update dev in main repo to point to the new merge commit +# * Push everything to remote +# * Create release drafts on GitHub # # After finished, verify everything is correct and push the changes import os import re +import sys +import subprocess +import io + +try: + git_root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip() +except subprocess.CalledProcessError: + print('\033[1;31m[!] Not inside a git repository!\033[0m') + sys.exit(1) +os.chdir(git_root) +while not os.path.isdir('.git'): + # Likely inside a submodule + # TODO: There is a command called `git rev-parse --show-superproject-working-tree` but it's quite new so not always available :/ + os.chdir('..') + +print('\033[1;34m[*] Make sure you don\'t have any uncommited local changes...\033[0m') +if subprocess.check_output(['git', 'status', '--porcelain']): # This also handles data subdirectory automatically + print('\033[1;31m[!] You have uncommited local changes!\033[0m') + os.system('git status') # Show the changes + sys.exit(1) print('\033[1;34m[*] Make sure all remote changes are pulled...\033[0m') -os.system('git checkout dev') -os.system('git pull --ff') -os.system('git checkout master') -os.system('git pull --ff') +subprocess.check_call(['git', 'checkout', 'dev']) +subprocess.check_call(['git', 'pull', '--ff']) +subprocess.check_call(['git', 'checkout', 'master']) +subprocess.check_call(['git', 'pull', '--ff']) os.chdir('data') -os.system('git checkout dev') -os.system('git pull --ff') -os.system('git checkout master') -os.system('git pull --ff') +subprocess.check_call(['git', 'checkout', 'dev']) +subprocess.check_call(['git', 'pull', '--ff']) +subprocess.check_call(['git', 'checkout', 'master']) +subprocess.check_call(['git', 'pull', '--ff']) os.chdir('..') print('\033[1;34m[*] Get version numbers...\033[0m') -os.system('git checkout dev') +subprocess.check_call(['git', 'checkout', 'dev']) major = None minor = None revision = None @@ -40,7 +63,7 @@ codename = None data = open('CMakeLists.txt', 'r').readlines() for i in range(len(data)): - m = re.match(r'^set\(COLOBOT_VERSION_(MAJOR|MINOR|REVISION)( +)([0-9])+\)$', data[i]) + m = re.match(r'^set\(COLOBOT_VERSION_(MAJOR|MINOR|REVISION)( +)([0-9]+)\)$', data[i]) if m: x = int(m.group(3)) if m.group(1) == 'MAJOR': @@ -60,43 +83,79 @@ for i in range(len(data)): codename = m.group(4) data[i] = ('#' if comment else '')+'set(COLOBOT_VERSION_'+m.group(2)+m.group(3)+'"'+m.group(4)+'")\n' -os.system('git checkout master') +subprocess.check_call(['git', 'checkout', 'master']) version = '%d.%d.%d%s' % (major, minor, revision, codename) +version_human = '%s %d.%d.%d' % (codename.strip('-'), major, minor, revision) print('\033[1;32m[+] Building version '+version+'\033[0m') print('\033[1;34m[*] Merge data...\033[0m') os.chdir('data') -os.system('git merge dev --no-ff -m "Release '+version+': Merge branch \'dev\'"') +subprocess.check_call(['git', 'merge', 'dev', '--no-ff', '-m', 'Release '+version+': Merge branch \'dev\'']) print('\033[1;34m[*] Tag data...\033[0m') -os.system('git tag colobot-gold-'+version) +subprocess.check_call(['git', 'tag', 'colobot-gold-'+version]) print('\033[1;34m[*] Update dev on data...\033[0m') -os.system('git checkout dev') -os.system('git merge master --ff') -os.system('git checkout master') +subprocess.check_call(['git', 'checkout', 'dev']) +subprocess.check_call(['git', 'merge', 'master', '--ff']) +subprocess.check_call(['git', 'checkout', 'master']) print('\033[1;34m[*] Merge main...\033[0m') os.chdir('..') -os.system('git merge dev --no-ff -m "Release '+version+': Merge branch \'dev\'"') +subprocess.check_call(['git', 'merge', 'dev', '--no-ff', '-m', 'Release '+version+': Merge branch \'dev\'']) print('\033[1;34m[*] Bump version number\033[0m') open('CMakeLists.txt', 'w').writelines(data) -os.system('git commit data CMakeLists.txt -m "Release '+version+': Bump version"') +subprocess.check_call(['git', 'commit', 'data', 'CMakeLists.txt', '-m', 'Release '+version+': Bump version']) print('\033[1;34m[*] Tag main...\033[0m') -os.system('git tag colobot-gold-'+version) +subprocess.check_call(['git', 'tag', 'colobot-gold-'+version]) print('\033[1;34m[*] Update dev on main...\033[0m') -os.system('git checkout dev') -os.system('git merge master --ff') +subprocess.check_call(['git', 'checkout', 'dev']) +subprocess.check_call(['git', 'merge', 'master', '--ff']) for i in range(len(data)): m = re.match(r'^(#?)set\(COLOBOT_VERSION_(UNRELEASED|RELEASE_CODENAME)(.*)\)$', data[i]) if m: comment = (m.group(2) == 'RELEASE_CODENAME') data[i] = ('#' if comment else '')+'set(COLOBOT_VERSION_'+m.group(2)+m.group(3)+')\n' open('CMakeLists.txt', 'w').writelines(data) -os.system('git commit CMakeLists.txt -m "Post-release '+version+'"') -os.system('git checkout master') +subprocess.check_call(['git', 'commit', 'CMakeLists.txt', '-m', 'Post-release '+version]) +subprocess.check_call(['git', 'checkout', 'master']) -print('\033[1;32m[+] Done! Push when ready\033[0m') +print('\033[1;32m[+] Done preparing!\033[0m') +resp = "" +while resp != "yes": + resp = input("\033[1;35m[?] Ready to push? (type \'yes\'): \033[0m") + +print('\033[1;34m[*] Pushing...\033[0m') +os.chdir('data') +subprocess.check_call(['git', 'push', 'origin', 'master', 'dev', 'colobot-gold-'+version]) +os.chdir('..') +subprocess.check_call(['git', 'push', 'origin', 'master', 'dev', 'colobot-gold-'+version]) + +hub_available = True +try: + subprocess.check_call(['hub', '--version']) +except subprocess.CalledProcessError: + hub_available = False + print('\033[1;33m[!] hub is not available, will skip creating release drafts!\033[0m') + +if hub_available: + print('\033[1;34m[*] Making release drafts on GitHub...\033[0m') + os.chdir('data') + release_notes = io.StringIO() + release_notes.write('Colobot: Gold Edition - '+version_human+' - data files\n') + release_notes.write('\n') + release_notes.write('Data files for release '+version) + subprocess.check_call(['hub', 'release', 'create', '--draft', '-m', release_notes.getvalue(), 'colobot-gold-'+version]) + os.chdir('..') + release_notes = io.StringIO() + release_notes.write('Colobot: Gold Edition - '+version_human+'\n') + release_notes.write('\n') + release_notes.write('Release '+version+'\n') + release_notes.write('\n') + release_notes.write('[put release notes URL here]') + subprocess.check_call(['hub', 'release', 'create', '--draft', '-m', release_notes.getvalue(), 'colobot-gold-'+version]) + +print('\033[1;32m[+] Done!\033[0m')