forked from OpenAstroTech/OpenAstroTracker-Firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
/
version_check.py
executable file
·121 lines (90 loc) · 4.44 KB
/
version_check.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
#!/usr/bin/env python3
import sys
import argparse
from typing import Optional, Dict
import mistune
import CppHeaderParser
import semver
import git
parser = argparse.ArgumentParser(description='''Check that the versioning of the repo has been correctly changed.
Intended to run in a PR CI''')
parser.add_argument('branchspec', default='origin/develop', nargs='?',
help='Git branch specification for previous file versions (default: %(default)s)')
def die(*args, error_code=1, **kwargs):
print('ERROR: ', end='', file=sys.stderr)
print(*args, **kwargs, file=sys.stderr)
exit(error_code)
class SemVerWithVPrefix(semver.VersionInfo):
@classmethod
def parse(cls, version):
if version[0] != 'V':
raise ValueError(f"{version}: not a valid semantic version tag. Must start with 'v' or 'V'")
self = super(SemVerWithVPrefix, cls).parse(version[1:])
return self
def __str__(self):
return 'V' + super(SemVerWithVPrefix, self).__str__()
def get_header_defines(header_contents: str) -> Dict[str, str]:
defines_detail = CppHeaderParser.CppHeader(header_contents, argType='string').defines_detail
return dict(d['value'].split(' ', maxsplit=1) for d in defines_detail)
def find_child_text(node: dict) -> Optional[str]:
if 'children' in node.keys():
if node['children'] and isinstance(node['children'], list):
return find_child_text(node['children'][0])
elif 'text' in node.keys():
return node['text']
return None
def get_header_version(version_header_contents: str) -> semver.VersionInfo:
version_defines = get_header_defines(version_header_contents)
try:
version_str = next(v.strip('"') for k, v in version_defines.items() if 'version' in k.lower())
except StopIteration:
die(f'Could not find version define in\n{version_header_contents}: {version_defines}')
try:
version = SemVerWithVPrefix.parse(version_str)
except ValueError as e:
die(f'SemVer error: {e}')
print(f'Version is {version}')
return version
def get_changelog_version(changelog_markdown_path: str) -> str:
markdown = mistune.create_markdown(renderer=mistune.AstRenderer())
with open(changelog_markdown_path, 'r') as f:
changelog_lines = f.read()
changelog_ast = markdown(changelog_lines)
first_heading_has_list = (changelog_ast[1]['type'] == 'list')
if not first_heading_has_list:
die(f'Latest changelog entry does not include a _list_ of what has changed')
first_heading_str = find_child_text(changelog_ast[0])
if not first_heading_str:
die(f'Could not find the latest changelog heading: {changelog_ast[0]}')
print(f'Latest changelog heading: {first_heading_str}')
return first_heading_str
def get_previous_header_version(version_header_path: str, refspec: str) -> semver.VersionInfo:
repo = git.Repo('.')
previous_header_contents = repo.git.show(f'{refspec}:{version_header_path}')
print(f'Checking previous header version from {refspec}:{version_header_path}')
previous_version = get_header_version(previous_header_contents)
print(f'Read previous header version: {previous_version}')
return previous_version
def main():
version_header_path = './Version.h'
# Get the current version from the header
print(f'Checking current header version from {version_header_path}')
with open(version_header_path, 'r') as fp:
version_header_contents = fp.read()
header_version = get_header_version(version_header_contents)
# Get the previous version (using git)
previous_header_version = get_previous_header_version(version_header_path, args.branchspec)
# Check that the version has been increased
if header_version <= previous_header_version:
die(f'Header version must be greater than the previous version {header_version} <= {previous_header_version}')
changelog_markdown_path = './Changelog.md'
# Get a string from the changelog, should have a version in the latest entry
changelog_version = get_changelog_version(changelog_markdown_path)
# Check that the header and the changelog match
if str(header_version).lower() not in changelog_version.lower():
die(f'Header version ("{header_version}" in {version_header_path}) does \
not match changelog version ("{changelog_version}" in {changelog_markdown_path})')
if __name__ == '__main__':
args = parser.parse_args()
main()
print('Finished version check!')