-
Notifications
You must be signed in to change notification settings - Fork 64
/
release.py
executable file
·174 lines (129 loc) · 5.05 KB
/
release.py
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 ASSISTANT=assistant 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)