diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-08-18 22:39:38 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-08-18 22:39:38 +0300 |
| commit | 9fac51722653fa0b0b6a5786166fb18c763424e0 (patch) | |
| tree | a8efd3b30cf29a8fb11138b7444bb9baa0dac2fa /scripts/changelog.py | |
| parent | 0bd445020ea19e0cea13f42a28212db7b2df196d (diff) | |
feat: make Windows generally available
Diffstat (limited to 'scripts/changelog.py')
| -rw-r--r-- | scripts/changelog.py | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/scripts/changelog.py b/scripts/changelog.py index 4d023ccc..9a96ea4e 100644 --- a/scripts/changelog.py +++ b/scripts/changelog.py @@ -19,13 +19,17 @@ DEFAULT_RELEASE_REPO = "herdrdev/herdr" DEFAULT_LATEST_JSON_PATH = Path("website/latest.json") DEFAULT_PRODUCT_ANNOUNCEMENT_PATH = Path("docs/next/product-announcement.json") PROTOCOL_SOURCE_PATH = Path("src/protocol/wire.rs") -ASSET_TARGETS = ( +CORE_ASSET_TARGETS = ( "linux-x86_64", "linux-aarch64", "macos-x86_64", "macos-aarch64", ) -EXPECTED_ASSET_NAMES = {target: f"herdr-{target}" for target in ASSET_TARGETS} +ASSET_TARGETS = (*CORE_ASSET_TARGETS, "windows-x86_64") +EXPECTED_ASSET_NAMES = { + **{target: f"herdr-{target}" for target in CORE_ASSET_TARGETS}, + "windows-x86_64": "herdr-windows-x86_64.zip", +} @dataclass(frozen=True) @@ -169,16 +173,22 @@ def infer_protocol_from_notes(notes: str) -> int | None: return int(match.group(1)) -def normalize_assets(value: Any, label: str) -> dict[str, str]: +def normalize_assets( + value: Any, + label: str, + required_targets: tuple[str, ...] = ASSET_TARGETS, +) -> dict[str, str]: if not isinstance(value, dict): raise ChangelogError(f"{label} must be an object") - missing_targets = [target for target in ASSET_TARGETS if target not in value] + missing_targets = [target for target in required_targets if target not in value] if missing_targets: raise ChangelogError(f"{label} is missing asset URL for {', '.join(missing_targets)}") normalized_assets: dict[str, str] = {} for target in ASSET_TARGETS: + if target not in value: + continue url = value.get(target) if not isinstance(url, str) or not url.strip(): raise ChangelogError(f"{label} is missing asset URL for {target}") @@ -186,12 +196,22 @@ def normalize_assets(value: Any, label: str) -> dict[str, str]: return normalized_assets -def normalize_sha256(value: Any, label: str) -> dict[str, str]: +def normalize_sha256( + value: Any, + label: str, + required_targets: tuple[str, ...] = ASSET_TARGETS, +) -> dict[str, str]: if not isinstance(value, dict): raise ChangelogError(f"{label} must be an object") + missing_targets = [target for target in required_targets if target not in value] + if missing_targets: + raise ChangelogError(f"{label} has invalid SHA-256 for {missing_targets[0]}") + checksums: dict[str, str] = {} for target in ASSET_TARGETS: + if target not in value: + continue checksum = value.get(target) if not isinstance(checksum, str) or re.fullmatch( r"[0-9a-fA-F]{64}", checksum.strip() @@ -225,11 +245,19 @@ def normalize_release_metadata(value: Any, label: str, version: str) -> dict[str if inferred_protocol is not None: metadata["protocol"] = inferred_protocol if "assets" in value: - metadata["assets"] = normalize_assets(value.get("assets"), f"{label}.assets") + metadata["assets"] = normalize_assets( + value.get("assets"), + f"{label}.assets", + required_targets=CORE_ASSET_TARGETS, + ) else: metadata["assets"] = default_release_assets(version) if "sha256" in value: - metadata["sha256"] = normalize_sha256(value.get("sha256"), f"{label}.sha256") + metadata["sha256"] = normalize_sha256( + value.get("sha256"), + f"{label}.sha256", + required_targets=CORE_ASSET_TARGETS, + ) announcement = normalize_announcement(value.get("announcement"), label) if announcement is not None: metadata["announcement"] = announcement @@ -306,11 +334,12 @@ def build_latest_json( def default_release_assets(version: str, repo: str = DEFAULT_RELEASE_REPO) -> dict[str, str]: + """Return legacy release URLs for versions published before Windows stable assets.""" normalized_version = normalize_version(version) tag = f"v{normalized_version}" return { target: f"https://github.com/{repo}/releases/download/{tag}/{EXPECTED_ASSET_NAMES[target]}" - for target in ASSET_TARGETS + for target in CORE_ASSET_TARGETS } @@ -468,12 +497,20 @@ def archived_releases_from_current_manifest(manifest: dict[str, Any]) -> dict[st metadata["protocol"] = protocol assets = manifest.get("assets") if isinstance(assets, dict): - metadata["assets"] = normalize_assets(assets, "current root assets") + metadata["assets"] = normalize_assets( + assets, + "current root assets", + required_targets=CORE_ASSET_TARGETS, + ) else: metadata["assets"] = default_release_assets(normalized_version) sha256 = manifest.get("sha256") if isinstance(sha256, dict): - metadata["sha256"] = normalize_sha256(sha256, "current root sha256") + metadata["sha256"] = normalize_sha256( + sha256, + "current root sha256", + required_targets=CORE_ASSET_TARGETS, + ) announcement = normalize_announcement(manifest.get("announcement"), "current root") if announcement is not None: metadata["announcement"] = announcement |
