|
23 | 23 |
|
24 | 24 | Update.py should be run often enough to catch individual Matlab release updates.
|
25 | 25 | """
|
| 26 | +import pathlib |
26 | 27 | import re
|
27 | 28 | from subprocess import DEVNULL
|
28 | 29 | from subprocess import run
|
29 | 30 | from urllib import request
|
30 | 31 |
|
| 32 | +import chevron |
31 | 33 | from bs4 import BeautifulSoup
|
32 | 34 | from packaging import version
|
| 35 | +from rich import print |
| 36 | + |
33 | 37 |
|
34 | 38 | REL_URL = "https://www.mathworks.com/products/compiler/matlab-runtime.html"
|
35 | 39 | VER_LIMIT = "9.3" # release URLs get weird before that..
|
| 40 | +DRY_RUN = True |
| 41 | + |
| 42 | +variants = [("Dockerfile-full.mustache", ""), ("Dockerfile-core.mustache", "-core")] |
36 | 43 |
|
37 | 44 |
|
38 | 45 | def call(cmd, split=True):
|
39 | 46 | if split:
|
40 | 47 | cmd = cmd.split()
|
| 48 | + print(f"[green]{' '.join(cmd)}[/green]") |
| 49 | + if DRY_RUN: |
| 50 | + return True |
41 | 51 | process = run(cmd, stdout=DEVNULL, stderr=DEVNULL)
|
42 | 52 | return process.returncode == 0
|
43 | 53 |
|
44 | 54 |
|
45 |
| -with request.urlopen(REL_URL) as res: |
46 |
| - if res.status != 200: |
47 |
| - raise RuntimeError("Could not open matlab release URL") |
48 |
| - html = res.read() |
49 |
| - |
50 |
| -soup = BeautifulSoup(html, "html.parser") |
51 |
| -ver_re = re.compile(r"(R2\d{3}.) \((\d\.\d)\)") |
52 |
| -rel_re = re.compile(r"Release/(\d+)/") |
53 |
| - |
54 |
| -dockers = [] |
55 |
| -for row in soup.find_all("table")[0].find_all("tr"): |
56 |
| - tds = row.find_all("td") |
57 |
| - if len(tds) >= 4: |
58 |
| - name = tds[0].text |
59 |
| - match = ver_re.match(name) |
60 |
| - if not match: |
61 |
| - continue |
62 |
| - mcr_name, mcr_ver = match.groups() |
63 |
| - if version.parse(mcr_ver) <= version.parse(VER_LIMIT): |
64 |
| - continue |
65 |
| - try: |
66 |
| - link = tds[2].a.get("href") |
67 |
| - except (KeyError, ValueError): |
68 |
| - raise RuntimeError("Error parsing matlab release page") |
69 |
| - if "glnxa64" not in link: |
70 |
| - raise RuntimeError("Error parsing matlab release page link") |
71 |
| - if match := rel_re.search(link): |
72 |
| - mcr_ver = f"{mcr_ver}.{match.groups()[0]}" |
73 |
| - dockers.append((mcr_name, mcr_ver, link)) |
| 55 | +def add_dockerfile_to_branch(new_tags, docker): |
74 | 56 |
|
75 |
| - |
76 |
| -variants = [("Dockerfile-full.template", ""), ("Dockerfile-core.template", "-core")] |
77 |
| -new_tags = [] |
78 |
| - |
79 |
| -for docker in dockers: |
80 | 57 | mcr_name, mcr_ver, link = docker
|
| 58 | + |
81 | 59 | if len(mcr_ver.split(".")) == 2:
|
82 | 60 | mcr_ver = f"{mcr_ver}.0"
|
83 | 61 | mcr_ver_maj = ".".join(mcr_ver.split(".")[:2])
|
84 | 62 | mcr_ver_dir = f'v{mcr_ver_maj.replace(".", "")}'
|
| 63 | + |
| 64 | + print(f"\n[blue]{mcr_name}[/blue]") |
| 65 | + |
85 | 66 | if not call(f"git checkout {mcr_name}"):
|
86 | 67 | call(f"git checkout -b {mcr_name}")
|
| 68 | + |
87 | 69 | for (template, suffix) in variants:
|
| 70 | + |
88 | 71 | tag = f"{mcr_ver}{suffix}"
|
89 |
| - if call(f"git rev-parse --verify {tag}"): |
90 |
| - print(f"Skipping {mcr_name}/{tag}, already present") |
| 72 | + |
| 73 | + if not DRY_RUN and call(f"git rev-parse --verify {tag}"): |
| 74 | + print(f"[red]Skipping {mcr_name}-{tag}, already present[/red]") |
91 | 75 | continue
|
92 |
| - print(f"Adding {mcr_name}/{tag}") |
| 76 | + print(f"\n[blue]Adding {mcr_name}-{tag}[/blue]") |
| 77 | + |
93 | 78 | if not call("git merge master"):
|
94 | 79 | raise RuntimeError("Merging master failed, will not continue")
|
95 |
| - with open(template) as f: |
96 |
| - lines = f.read() |
97 |
| - lines = lines.replace("%%MATLAB_VERSION%%", mcr_name) |
98 |
| - lines = lines.replace("%%MCR_VERSION%%", mcr_ver_dir) |
99 |
| - lines = lines.replace("%%MCR_LINK%%", link) |
| 80 | + |
| 81 | + lines = pathlib.Path(template).read_text() |
| 82 | + lines = lines.replace("%%MATLAB_VERSION%%", mcr_name) |
| 83 | + lines = lines.replace("%%MCR_VERSION%%", mcr_ver_dir) |
| 84 | + lines = lines.replace("%%MCR_LINK%%", link) |
| 85 | + if not DRY_RUN: |
100 | 86 | with open("Dockerfile", "w+") as f2:
|
101 | 87 | f2.write(lines)
|
102 |
| - call("git add Dockerfile") |
103 |
| - # Tag X.Y.Z[-variant] - see circle CI for shared tag X.Y[-variant] |
104 |
| - call(["git", "commit", "-m", "Auto-Update"], split=False) |
105 |
| - call(f"git tag {tag}") |
106 |
| - new_tags.append(tag) |
| 88 | + |
| 89 | + with open(template) as f: |
| 90 | + content = chevron.render( |
| 91 | + f, |
| 92 | + { |
| 93 | + "MATLAB_VERSION": mcr_name, |
| 94 | + "MCR_VERSION": mcr_ver_dir, |
| 95 | + "MCR_LINK": link, |
| 96 | + }, |
| 97 | + ) |
| 98 | + with open("Dockerfile", "w+") as f2: |
| 99 | + f2.write(content) |
| 100 | + |
| 101 | + call("git add Dockerfile") |
| 102 | + # Tag X.Y.Z[-variant] - see circle CI for shared tag X.Y[-variant] |
| 103 | + call(["git", "commit", "-m", "Auto-Update"], split=False) |
| 104 | + |
| 105 | + call(f"git tag {tag}") |
| 106 | + |
| 107 | + new_tags.append(tag) |
| 108 | + |
107 | 109 | call("git checkout master")
|
108 | 110 |
|
109 |
| -if new_tags: |
110 |
| - print("New tags have been added, verify and update to git with:") |
111 |
| - print("git push --all") |
112 |
| - for tag in reversed(new_tags): |
113 |
| - print(f"git push origin {tag}") |
| 111 | + return new_tags |
| 112 | + |
| 113 | + |
| 114 | +def list_mcr(soup): |
| 115 | + |
| 116 | + ver_re = re.compile(r"(R2\d{3}.) \((\d\.\d+)\)") |
| 117 | + rel_re = re.compile(r"Release/(\d+)/") |
| 118 | + |
| 119 | + dockers = [] |
| 120 | + for row in soup.find_all("table")[0].find_all("tr"): |
| 121 | + |
| 122 | + tds = row.find_all("td") |
| 123 | + |
| 124 | + if len(tds) >= 4: |
| 125 | + name = tds[0].text |
| 126 | + match = ver_re.match(name) |
| 127 | + if not match: |
| 128 | + continue |
| 129 | + mcr_name, mcr_ver = match.groups() |
| 130 | + |
| 131 | + if version.parse(mcr_ver) <= version.parse(VER_LIMIT): |
| 132 | + continue |
| 133 | + try: |
| 134 | + link = tds[2].a.get("href") |
| 135 | + except (KeyError, ValueError) as e: |
| 136 | + raise RuntimeError("Error parsing matlab release page") from e |
| 137 | + |
| 138 | + if "glnxa64" not in link: |
| 139 | + raise RuntimeError("Error parsing matlab release page link") |
| 140 | + |
| 141 | + if match := rel_re.search(link): |
| 142 | + mcr_ver = f"{mcr_ver}.{match.groups()[0]}" |
| 143 | + |
| 144 | + dockers.append((mcr_name, mcr_ver, link)) |
| 145 | + |
| 146 | + return dockers |
| 147 | + |
| 148 | + |
| 149 | +def main(): |
| 150 | + |
| 151 | + with request.urlopen(REL_URL) as res: |
| 152 | + if res.status != 200: |
| 153 | + raise RuntimeError("Could not open matlab release URL") |
| 154 | + html = res.read() |
| 155 | + |
| 156 | + soup = BeautifulSoup(html, "html.parser") |
| 157 | + |
| 158 | + dockers = list_mcr(soup) |
| 159 | + |
| 160 | + new_tags = [] |
| 161 | + for docker in dockers: |
| 162 | + new_tags = add_dockerfile_to_branch(new_tags, docker) |
| 163 | + |
| 164 | + if new_tags: |
| 165 | + print("\nNew tags have been added, verify and update to git with:") |
| 166 | + print("git push --all") |
| 167 | + for tag in reversed(new_tags): |
| 168 | + print(f"git push origin {tag}") |
| 169 | + |
| 170 | + |
| 171 | +if __name__ == "__main__": |
| 172 | + main() |
0 commit comments