123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- #!/usr/bin/env python3
- from datetime import datetime
- import enum
- from pathlib import Path
- import sys
- import requests
- GITLAB = "https://gitlab.torproject.org"
- API_URL = f"{GITLAB}/api/v4"
- PROJECT_ID = 473
- class Platform(enum.IntFlag):
- WINDOWS = 8
- MACOS = 4
- LINUX = 2
- ANDROID = 1
- DESKTOP = 8 | 4 | 2
- ALL_PLATFORMS = 8 | 4 | 2 | 1
- class Issue:
- def __init__(self, j):
- self.title = j["title"]
- self.project, self.number = (
- j["references"]["full"].rsplit("/", 2)[-1].split("#")
- )
- self.platform = 0
- self.num_platforms = 0
- if "Desktop" in j["labels"]:
- self.platform = Platform.DESKTOP
- self.num_platforms += 3
- else:
- if "Windows" in j["labels"]:
- self.platform |= Platform.WINDOWS
- self.num_platforms += 1
- if "MacOS" in j["labels"]:
- self.platform |= Platform.MACOS
- self.num_platforms += 1
- if "Linux" in j["labels"]:
- self.platform |= Platform.LINUX
- self.num_platforms += 1
- if "Android" in j["labels"]:
- self.platform |= Platform.ANDROID
- self.num_platforms += 1
- if not self.platform:
- self.platform = Platform.ALL_PLATFORMS
- self.num_platforms = 4
- self.is_build = "Build System" in j["labels"]
- def get_platforms(self):
- if self.platform == Platform.ALL_PLATFORMS:
- return "All Platforms"
- platforms = []
- if self.platform & Platform.WINDOWS:
- platforms.append("Windows")
- if self.platform & Platform.MACOS:
- platforms.append("macOS")
- if self.platform & Platform.LINUX:
- platforms.append("Linux")
- if self.platform & Platform.ANDROID:
- platforms.append("Android")
- return " + ".join(platforms)
- def __str__(self):
- return f"Bug {self.number}: {self.title} [{self.project}]"
- def __lt__(self, other):
- return self.number < other.number
- def sorted_issues(issues):
- issues = [sorted(v) for v in issues.values()]
- return sorted(
- issues,
- key=lambda group: (group[0].num_platforms << 8) | group[0].platform,
- reverse=True,
- )
- if len(sys.argv) < 2:
- print(f"Usage: {sys.argv[0]} version-to-release or #issue-id")
- sys.exit(1)
- token_file = Path(__file__).parent / ".changelogs_token"
- if not token_file.exists():
- print(
- f"Please add your personal GitLab token (with 'read_api' scope) to {token_file}"
- )
- print(
- f"Please go to {GITLAB}/-/profile/personal_access_tokens and generate it."
- )
- token = input("Please enter the new token: ").strip()
- if not token:
- print("Invalid token!")
- sys.exit(2)
- with token_file.open("w") as f:
- f.write(token)
- with token_file.open() as f:
- token = f.read().strip()
- headers = {"PRIVATE-TOKEN": token}
- version = sys.argv[1]
- r = requests.get(
- f"{API_URL}/projects/{PROJECT_ID}/issues?labels=Release Prep",
- headers=headers,
- )
- if r.status_code == 401:
- print("Unauthorized! Has your token expired?")
- sys.exit(3)
- issue = None
- for i in r.json():
- if i["title"].find(sys.argv[1]) != -1:
- if issue is None:
- issue = i
- else:
- print("More than one matching issue found!")
- print("Please use the issue id.")
- sys.exit(4)
- if not issue:
- iid = version
- version = None
- if iid[0] == "#":
- iid = iid[1:]
- try:
- int(iid)
- r = requests.get(
- f"{API_URL}/projects/{PROJECT_ID}/issues?iids={iid}",
- headers=headers,
- )
- if r.ok and r.json():
- issue = r.json()[0]
- except ValueError:
- pass
- if not issue:
- print(
- "Release preparation issue not found. Please make sure it has ~Release Prep."
- )
- sys.exit(5)
- iid = issue["iid"]
- linked = {}
- linked_build = {}
- r = requests.get(
- f"{API_URL}/projects/{PROJECT_ID}/issues/{iid}/links", headers=headers
- )
- for i in r.json():
- i = Issue(i)
- target = linked_build if i.is_build else linked
- if i.platform not in target:
- target[i.platform] = []
- target[i.platform].append(i)
- linked = sorted_issues(linked)
- linked_build = sorted_issues(linked_build)
- date = datetime.now().strftime("%B %d %Y")
- print(f"Tor Browser {version} - {date}")
- for issues in linked:
- print(f" * {issues[0].get_platforms()}")
- for i in issues:
- print(f" * {i}")
- print(" * Build System")
- for issues in linked_build:
- print(f" * {issues[0].get_platforms()}")
- for i in issues:
- print(f" * {i}")
|