import re from datetime import datetime from pathlib import Path from common import endoflife from common.git import Git """Fetch apache versions from its git repository. Every branch formatted like 2.4.x has a STATUS file which contains a version history. Not every version was released, the lines are filtered with (?:Released|Announced) to get the released versions only (they were not consistent in the past with the wording, it seems better now). """ PRODUCT = "apache-http-server" REPO_URL = "https://github.com/apache/httpd.git" def parse(date: str) -> str: date = date.replace("Feburary", "February") for format in ["%B %d, %Y", "%B %d, %Y", "%b %d, %Y", "%b. %d, %Y"]: try: return datetime.strptime(date, format).strftime("%Y-%m-%d") except ValueError: pass raise ValueError(f"Unknown date format for '{date}'") def fetch_versions_from_file(release_notes_file: Path, versions: dict): if not release_notes_file.exists(): return {} with open(release_notes_file, "rb") as f: plain = f.read().decode("utf-8", errors="ignore") # for most versions for (version, date_str) in re.findall(r"\s+(?P\d+\.\d+\.\d+)\s*:.*(?:Released|Announced|Released and Retired)\s(?:on\s)?(?P\w+\s\d\d?,\s\d{4})", plain): date = parse(date_str) versions[version] = date print(f"{version}: {date}") # for older 2.0.x versions (only GA versions are considered) for (version, date_str) in re.findall(r"\s+(?P\d+\.\d+\.\d+)\s*:.*released\s(?P\w+\s\d\d?,\s\d{4}) as GA", plain): date = parse(date_str) versions[version] = date print(f"{version}: {date}") # for older 1.3.x versions, we take the date of the tag and not the date of the release (too difficult to parse) for (version, date_str) in re.findall(r"\s+(?P\d+\.\d+\.\d+)\s*:.*Tagged and [rR]olled\s(?:on\s)?(?P\w+\.?\s\d\d?,\s\d{4})", plain): date = parse(date_str) versions[version] = date print(f"{version}: {date}") git = Git(REPO_URL) git.setup() versions = {} print(f"::group::{PRODUCT}") for branch in git.list_branches("refs/heads/?.?.x"): status_file = "STATUS" git.checkout(branch, file_list=[status_file]) fetch_versions_from_file(git.repo_dir / status_file, versions) print("::endgroup::") endoflife.write_releases( PRODUCT, dict( # sort by date then version (desc) sorted(versions.items(), key=lambda x: (x[1], x[0]), reverse=True) ), )