1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
#!/usr/bin/python3
import os
import sys
import subprocess
import re
from packaging import version
DRYRUN = "" # '--dry-run'
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def error(msg: str):
print(bcolors.FAIL + "Error: ", msg, bcolors.ENDC, file=sys.stderr)
sys.exit(-1)
def get_input(msg):
return input(bcolors.OKBLUE + msg + ": " + bcolors.ENDC)
def header(msg):
print(bcolors.HEADER + msg, bcolors.ENDC)
def run(cmd):
res = subprocess.run(cmd, shell=True)
res.check_returncode()
def generate_lines_that_equal(string, fp):
for line in fp:
if line == string:
yield line
def lines_that_equal(line_to_match, fp):
return [line for line in fp if line == line_to_match]
def lines_that_contain(string, fp):
return [line for line in fp if string in line]
def lines_that_start_with(string, fp):
return [line for line in fp if line.startswith(string)]
def lines_that_end_with(string, fp):
return [line for line in fp if line.endswith(string)]
header(bcolors.BOLD + "QMapShack Release Script")
source_repo_path = os.getcwd()
header("Pull latest version")
run("git checkout dev")
run("git pull")
header("Create offline help")
asw = get_input("Do you want to update the offline help? [Y/n]") or "Y"
if asw.upper() == "Y":
wiki_repo_path = get_input("Where is the Wiki loacted? [../QMapShack_Wiki]") or "../QMapShack_Wiki"
if not os.path.exists(wiki_repo_path):
error("Wiki path does not exist!")
# update wiki and create help files
os.chdir(wiki_repo_path)
run('git pull')
run('make VERBOSE=YES -f Makefile.make HELPGENERATOR=qcollectiongenerator-qt5 ASSISTANT=assistant-qt5 all')
# move help files to source repo
os.chdir(source_repo_path)
run(f'mv -v {wiki_repo_path}/doc/qms/QMSHelp.qch src/qmapshack/doc/')
run(f'mv -v {wiki_repo_path}/doc/qms/QMSHelp.qhc src/qmapshack/doc/')
run(f'mv -v {wiki_repo_path}/doc/qmt/QMTHelp.qch src/qmaptool/doc/')
run(f'mv -v {wiki_repo_path}/doc/qmt/QMTHelp.qhc src/qmaptool/doc/')
# commit updated help files
run(f'git commit {DRYRUN} -a -v -m "Update help files."')
print(bcolors.OKGREEN + "Updated help files successfully" + bcolors.ENDC)
header("Update Version")
current_version = None
with open('CMakeLists.txt') as fp:
for line in lines_that_start_with("project(QMapShack VERSION ", fp):
res = re.match('.*([0-9]+\.[0-9]+\.[0-9]).*', line)
if res:
current_version = version.parse(res.group(1))
break
if not current_version:
error("Could not find current version!")
next_version = version.parse(get_input(f"The current version is '{current_version}'. What is the next version?"))
if next_version <= current_version:
error("Bad new version")
print('Replace version string in CMakeLists.txt.')
with open('CMakeLists.txt') as fp:
newText = fp.read().replace(str(current_version), str(next_version))
with open('CMakeLists.txt', 'w') as fp:
fp.write(newText)
print('Reset version suffix in CMakeLists.txt.')
with open('CMakeLists.txt') as fp:
newText = re.sub(
r'^set\(DEVELOPMENT_VERSION.*$',
'set(DEVELOPMENT_VERSION OFF)',
fp.read(),
flags=re.MULTILINE
)
with open('CMakeLists.txt', 'w') as fp:
fp.write(newText)
print('Replace version string in changelog.txt.')
with open('changelog.txt') as fp:
newText = fp.read().replace("V1.XX.X", "V" + str(next_version))
with open('changelog.txt', 'w') as fp:
fp.write(newText)
print('Update list of contributors.')
subprocess.run("./collect_copyright.py", shell=True)
print("Commit changes.")
run(f'git commit {DRYRUN} -a -v -m "Update version to {next_version}"')
print(bcolors.OKGREEN + f"Successfully updated version to {next_version}" + bcolors.ENDC)
header("Merge Changes to Master")
asw = get_input("Do you want ot merge to master and create a tag? [Y/n]") or "Y"
if asw.upper() == "Y":
run('git checkout master')
run('git pull')
run('git checkout dev')
run('git merge master')
run('git checkout master')
run(f'git merge -m "Release V{next_version}" --log dev')
# run(f'git commit -a -v -m "Release V{next_version}"')
run(f'git tag -a V_{next_version} -m "Release V{next_version}"')
print(bcolors.OKGREEN + f"Successfully merged into master." + bcolors.ENDC)
header("Final Push to GitHub?")
print("Nothing is pushed yet. Please check logs in 'dev' and 'master' to be correct.")
asw = get_input("Do you want to do the push? [y/N]") or "N"
if asw.upper() == "Y":
run('git checkout master')
run('git push')
run('git checkout dev')
run('git push')
else:
asw = get_input("Do you want to revert the release? [Y/n]") or "Y"
if asw.upper() == "Y":
run('git checkout master')
run('git reset --hard origin/master')
run(f'git tag -d V_{next_version}')
run('git checkout dev')
run('git reset --hard origin/dev')
print(bcolors.OKGREEN + f"Release done!" + bcolors.ENDC)
|