-
Notifications
You must be signed in to change notification settings - Fork 0
/
release.py
95 lines (75 loc) · 4.03 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
from typing import Optional
import subprocess, sys, itertools, argparse, os, tempfile, shutil
def is_git_clean(root: str) -> Optional[str]:
"""Returns None if Git is clean, else the reason for non-cleanness."""
p = subprocess.run(('git', 'status', '--porcelain=2', '--branch'),
check=True,
stdout=subprocess.PIPE,
cwd=root)
lines = p.stdout.split(b'\n')
header_lines, content_lines = tuple(tuple(i) for (_, i) in itertools.groupby(lines, key=lambda line: line.startswith(b'#')))
content_lines = tuple(l for l in content_lines if l)
(ab_header,) = (l for l in header_lines if l.startswith(b'# branch.ab '))
(_, _, ahead, behind) = ab_header.split(b' ')
if content_lines:
return f'there are some local changes in the repository:\n{content_lines!r}'
if ahead != b'+0':
return 'there are some unpushed changes in the repository'
# TODO: check the tag
return None
def main() -> None:
parser = argparse.ArgumentParser('Release the website to the `release` Git branch.')
parser.add_argument('--no-check-git', dest='check_git',
action='store_false',
help='disable the check of the git status')
args = parser.parse_args()
# First make sure we find the Git directory.
root_dir = os.path.dirname(os.path.abspath(__file__))
git_dir = os.path.join(root_dir, '.git')
if not os.path.exists(git_dir):
print(f'ERROR: {git_dir!r} does not exists', file=sys.stderr)
sys.exit(1)
# Check that Git is clean.
if args.check_git:
opt_err = is_git_clean(root_dir)
if opt_err is not None:
print(f'ERROR: {opt_err}', file=sys.stderr)
sys.exit(1)
# Switch to `master` branch.
print(f'\n** Switch to the `master` branch…', flush=True)
subprocess.run(('git', 'switch', 'master'), check=True, cwd=root_dir)
# Get the Git commit hash.
print(f'\n** Getting current revision…', flush=True)
revision = subprocess.run(('git', 'rev-parse', 'HEAD'),
check=True,
stdout=subprocess.PIPE, encoding='utf-8',
cwd=root_dir).stdout.strip()
print(f'Revision: {revision!r}')
# Create the output in the temporary directory before doing the Git.
with tempfile.TemporaryDirectory() as tmp_dir:
make_args = ('make', f'OUTPUT_DIR={tmp_dir}')
print(f'\n** Creating the output in {tmp_dir!r} running {make_args} in {root_dir!r}…', flush=True)
subprocess.run(make_args, check=True, cwd=root_dir)
index_path = os.path.join(tmp_dir, 'index.html')
print(f'\n** Patch {index_path!r} to update the version…')
with open(index_path, 'rt', encoding='utf-8') as f:
index_content = f.read()
index_updated_content = index_content.replace('<!--version-start-->?<!--version-end-->', revision)
assert index_updated_content != index_content, 'expected changes!'
with open(index_path, 'wt', encoding='utf-8') as f:
f.write(index_updated_content)
print(f'\n** Switch to the `release` branch…', flush=True)
subprocess.run(('git', 'switch', 'release'), check=True, cwd=root_dir)
print(f'\n** Updating the `release` directory (only creating/updating files, not deleting!)…', flush=True)
shutil.copytree(tmp_dir, root_dir, dirs_exist_ok=True)
print(f'\n** Add all files…', flush=True)
for dirpath, _, filenames in os.walk(tmp_dir):
for filename in filenames:
filepath = os.path.relpath(os.path.join(dirpath, filename), tmp_dir)
print(f'\n * adding {filepath}')
subprocess.run(('git', 'add', filepath), check=True, cwd=root_dir)
print(f'\n** Creating the commit…', flush=True)
subprocess.run(('git', 'commit', '-m', f'Updating release from {revision}.'),
check=True, cwd=root_dir)
if __name__ == '__main__':
main()