-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathupdatesource.py
More file actions
95 lines (74 loc) · 3.11 KB
/
Copy pathupdatesource.py
File metadata and controls
95 lines (74 loc) · 3.11 KB
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
#!/usr/bin/env python3
"""Update the StikDebug AltSource entry from the latest GitHub release."""
import json
import re
import sys
from datetime import datetime
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
SOURCE_REPOSITORY = "StephenDev0/StikDebug"
APP_BUNDLE_IDENTIFIER = "com.stik.stikdebug"
MINIMUM_IOS_VERSION = "17.4"
def fetch_latest_release():
request = Request(
f"https://api.github.com/repos/{SOURCE_REPOSITORY}/releases/latest",
headers={"Accept": "application/vnd.github+json", "User-Agent": "StikDebug-source-updater"},
)
try:
with urlopen(request) as response:
return json.load(response)
except (HTTPError, URLError) as error:
raise RuntimeError(f"Unable to fetch the latest StikDebug release: {error}") from error
def clean_description(description):
description = description or "No release notes provided."
description = re.sub(r"<[^>]+>", "", description)
description = re.sub(r"^#{1,6}\s*", "", description, flags=re.MULTILINE)
description = re.sub(r"\*{1,3}([^*]+)\*{1,3}", r"\1", description)
description = description.replace("`", '"')
return description.strip()
def release_version(tag):
match = re.search(r"(\d+\.\d+\.\d+)", tag)
if not match:
raise ValueError(f"Could not find a semantic version in release tag {tag!r}.")
return match.group(1)
def update_index(index_path, release):
with index_path.open() as source_file:
source = json.load(source_file)
app = next(
(app for app in source["apps"] if app.get("bundleIdentifier") == APP_BUNDLE_IDENTIFIER),
None,
)
if app is None:
raise ValueError(f"No app with bundle identifier {APP_BUNDLE_IDENTIFIER} in {index_path}.")
version = release_version(release["tag_name"])
ipa_asset = next(
(asset for asset in release.get("assets", []) if asset["name"].lower().endswith(".ipa")),
None,
)
if ipa_asset is None:
raise ValueError(f"Release {release['tag_name']} has no IPA asset.")
published_at = datetime.fromisoformat(release["published_at"].replace("Z", "+00:00"))
version_entry = {
"version": version,
"date": published_at.date().isoformat(),
"localizedDescription": clean_description(release.get("body")),
"downloadURL": ipa_asset["browser_download_url"],
"size": ipa_asset["size"],
"minOSVersion": MINIMUM_IOS_VERSION,
}
if app.get("versions", [None])[0] == version_entry:
print(f"StikDebug {version} is already current; no changes needed.")
return False
# The source deliberately exposes only the current StikDebug build.
app["versions"] = [version_entry]
with index_path.open("w") as source_file:
json.dump(source, source_file, indent=2)
source_file.write("\n")
print(f"Updated StikDebug source to {version}.")
return True
def main():
index_path = Path(sys.argv[1]) if len(sys.argv) == 2 else Path("index.json")
update_index(index_path, fetch_latest_release())
if __name__ == "__main__":
main()