-
-
Notifications
You must be signed in to change notification settings - Fork 7
feat: show newer pre-release on downloads page (robust, from real assets) #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,42 +1,68 @@ | ||
| version: v0.12.2 | ||
|
|
||
| platforms: | ||
| # Generated by scripts/update-downloads.py — do not edit by hand. | ||
| stable: | ||
| version: v0.13.2 | ||
| platforms: | ||
| - name: Windows | ||
| assets: | ||
| - title: Installer | ||
| description: " (recommended)" | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.12.2/activitywatch-v0.12.2-windows-x86_64-setup.exe | ||
| - title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.12.2/activitywatch-v0.12.2-windows-x86_64.zip | ||
| - title: Chocolatey | ||
| url: https://chocolatey.org/packages/activitywatch | ||
|
|
||
| - title: Installer | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-windows-x86_64-setup.exe | ||
| description: ' (recommended)' | ||
| - title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-windows-x86_64.zip | ||
| - title: Chocolatey | ||
| url: https://chocolatey.org/packages/activitywatch | ||
| - name: Linux | ||
| assets: | ||
| - title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.12.2/activitywatch-v0.12.2-linux-x86_64.zip | ||
| - title: .AppImage | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.12.2/activitywatch-linux-x86_64.AppImage | ||
| - title: AUR | ||
| description: ", for Arch Linux and Manjaro" | ||
| url: https://aur.archlinux.org/packages/activitywatch-bin/ | ||
| - title: nixpkgs | ||
| description: ", for NixOS" | ||
| url: https://search.nixos.org/packages?query=activitywatch&show=activitywatch | ||
|
|
||
| - title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-linux-x86_64.zip | ||
| - title: .AppImage | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-linux-x86_64.AppImage | ||
| - title: .deb | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-linux-x86_64.deb | ||
| - title: AUR | ||
| description: ', for Arch Linux and Manjaro' | ||
| url: https://aur.archlinux.org/packages/activitywatch-bin/ | ||
| - title: nixpkgs | ||
| description: ', for NixOS' | ||
| url: https://search.nixos.org/packages?query=activitywatch&show=activitywatch | ||
| - name: macOS | ||
| assets: | ||
| - title: .dmg | ||
| description: " (recommended)" | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.12.2/activitywatch-v0.12.2-macos-x86_64.dmg | ||
| - type: zip | ||
| title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.12.2/activitywatch-v0.12.2-macos-x86_64.zip | ||
| - title: Homebrew | ||
| url: https://formulae.brew.sh/cask/activitywatch | ||
|
|
||
| - title: .dmg | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-macos-x86_64.dmg | ||
| description: ' (recommended) (Intel)' | ||
| - title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-macos-x86_64.zip | ||
| description: ' (Intel)' | ||
| - title: Homebrew | ||
| url: https://formulae.brew.sh/cask/activitywatch | ||
| - name: Android | ||
| assets: | ||
| - title: Play Store | ||
| description: " (beta)" | ||
| url: https://play.google.com/store/apps/details?id=net.activitywatch.android | ||
| - title: Play Store | ||
| description: ' (beta)' | ||
| url: https://play.google.com/store/apps/details?id=net.activitywatch.android | ||
| prerelease: | ||
| version: v0.14.0b1 | ||
| platforms: | ||
| - name: Windows | ||
| assets: | ||
| - title: Installer | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.14.0b1/activitywatch-v0.14.0b1-windows-x86_64-setup.exe | ||
| description: ' (recommended)' | ||
| - title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.14.0b1/activitywatch-v0.14.0b1-windows-x86_64.zip | ||
| - name: Linux | ||
| assets: | ||
| - title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.14.0b1/activitywatch-v0.14.0b1-linux-x86_64.zip | ||
| - title: .AppImage | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.14.0b1/activitywatch-linux-x86_64.AppImage | ||
| - title: .deb | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.14.0b1/activitywatch-v0.14.0b1-linux-x86_64.deb | ||
| - name: macOS | ||
| assets: | ||
| - title: .dmg | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.14.0b1/activitywatch-v0.14.0b1-macos-arm64.dmg | ||
| description: ' (recommended) (Apple Silicon)' | ||
| - title: .zip | ||
| url: https://github.com/ActivityWatch/activitywatch/releases/download/v0.14.0b1/activitywatch-v0.14.0b1-macos-arm64.zip | ||
| description: ' (Apple Silicon)' | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,43 +1,153 @@ | ||
| #!/usr/bin/env python3 | ||
| """Regenerate _data/downloads.yml from the ActivityWatch GitHub releases. | ||
|
|
||
| Writes the latest stable release, plus — when it is newer than that stable — | ||
| the latest pre-release, so betas/nightlies newer than stable are surfaced too. | ||
|
|
||
| Download links are built from each release's *actual* assets rather than by | ||
| substituting a version number into a fixed template, so it survives asset | ||
| naming changes between versions (e.g. the v0.14 `tauri` builds and macOS | ||
| moving from x86_64 to arm64). | ||
| """ | ||
|
|
||
| import os | ||
| import re | ||
| from datetime import datetime, timedelta, timezone | ||
| from pathlib import Path | ||
|
|
||
| import requests | ||
| import yaml | ||
|
|
||
| API = "https://api.github.com/repos/ActivityWatch/activitywatch/releases" | ||
|
|
||
| def is_older(dt: str, td: timedelta): | ||
| now = datetime.now(tz=timezone.utc) | ||
| created_at = datetime.fromisoformat(dt.strip("Z")).replace(tzinfo=timezone.utc) | ||
| return created_at < now - td | ||
| # Static (non-GitHub) distribution links, appended per platform for the stable | ||
| # release only — package managers and the Play Store track stable, not betas. | ||
| PACKAGE_LINKS = { | ||
| "Windows": [ | ||
| {"title": "Chocolatey", "url": "https://chocolatey.org/packages/activitywatch"}, | ||
| ], | ||
| "Linux": [ | ||
| {"title": "AUR", "description": ", for Arch Linux and Manjaro", | ||
| "url": "https://aur.archlinux.org/packages/activitywatch-bin/"}, | ||
| {"title": "nixpkgs", "description": ", for NixOS", | ||
| "url": "https://search.nixos.org/packages?query=activitywatch&show=activitywatch"}, | ||
| ], | ||
| "macOS": [ | ||
| {"title": "Homebrew", "url": "https://formulae.brew.sh/cask/activitywatch"}, | ||
| ], | ||
| } | ||
|
|
||
| # Android has no GitHub release assets; it's always just the Play Store link. | ||
| ANDROID = { | ||
| "name": "Android", | ||
| "assets": [ | ||
| {"title": "Play Store", "description": " (beta)", | ||
| "url": "https://play.google.com/store/apps/details?id=net.activitywatch.android"}, | ||
| ], | ||
| } | ||
|
|
||
| if __name__ == "__main__": | ||
| r = requests.get( | ||
| "https://api.github.com/repos/ActivityWatch/activitywatch/releases" | ||
| ) | ||
| data = r.json() | ||
| # Per platform: (asset-name regex, button title, extra description). | ||
| # description may be a callable taking the matched asset. | ||
| PLATFORM_SPECS = { | ||
| "Windows": [ | ||
| (r"windows.*setup\.exe$", "Installer", " (recommended)"), | ||
| (r"windows.*\.zip$", ".zip", ""), | ||
| ], | ||
| "Linux": [ | ||
| (r"linux.*x86_64\.zip$", ".zip", ""), | ||
| (r"\.AppImage$", ".AppImage", ""), | ||
| (r"\.deb$", ".deb", ""), | ||
| ], | ||
| "macOS": [ | ||
| (r"macos.*\.dmg$", ".dmg", lambda a: " (recommended)" + _arch(a)), | ||
| (r"macos.*\.zip$", ".zip", lambda a: _arch(a)), | ||
| ], | ||
| } | ||
|
|
||
| # Filter away prereleases | ||
| data = filter(lambda r: not r["prerelease"] and not r["draft"], data) | ||
|
|
||
| # Filter away very recent releases (<1h old) | ||
| data = filter(lambda r: is_older(r["created_at"], timedelta(hours=1)), data) | ||
| def _arch(asset: dict) -> str: | ||
| name = asset["name"].lower() | ||
| if "arm64" in name or "aarch64" in name: | ||
| return " (Apple Silicon)" | ||
| if "x86_64" in name or "amd64" in name: | ||
| return " (Intel)" | ||
| return "" | ||
|
|
||
| data = sorted(data, key=lambda r: r["created_at"]) | ||
| latest_release = data[-1]["tag_name"] | ||
| print(f"Latest release: {latest_release}") | ||
|
|
||
| p = Path("_data/downloads.yml") | ||
| def _pick(assets: list, pattern: str): | ||
| """First asset matching pattern, preferring the plain (non-tauri) build.""" | ||
| cands = [a for a in assets if re.search(pattern, a["name"], re.I)] | ||
| cands.sort(key=lambda a: ("tauri" in a["name"].lower(), len(a["name"]))) | ||
| return cands[0] if cands else None | ||
|
|
||
|
|
||
| def platforms_for(release: dict, include_packages: bool) -> list: | ||
| assets = release["assets"] | ||
| platforms = [] | ||
| for name, specs in PLATFORM_SPECS.items(): | ||
| entries = [] | ||
| for pattern, title, desc in specs: | ||
| a = _pick(assets, pattern) | ||
| if not a: | ||
| continue | ||
| entry = {"title": title, "url": a["browser_download_url"]} | ||
| d = desc(a) if callable(desc) else desc | ||
| if d: | ||
| entry["description"] = d | ||
| entries.append(entry) | ||
| if include_packages: | ||
| entries += PACKAGE_LINKS.get(name, []) | ||
| if entries: | ||
| platforms.append({"name": name, "assets": entries}) | ||
| return platforms | ||
|
|
||
|
|
||
| def build_block(release: dict, include_packages: bool, with_android: bool) -> dict: | ||
| platforms = platforms_for(release, include_packages) | ||
| if with_android: | ||
| platforms.append(ANDROID) | ||
| return {"version": release["tag_name"], "platforms": platforms} | ||
|
|
||
|
|
||
| with open(p, "r") as f: | ||
| orig = f.read() | ||
| new = re.sub(r"v[0-9.]+[abrc]*[0-9]*", latest_release, orig) | ||
| def is_older(dt: str, td: timedelta) -> bool: | ||
| created = datetime.fromisoformat(dt.replace("Z", "+00:00")) | ||
| return created < datetime.now(tz=timezone.utc) - td | ||
|
|
||
| if new == orig: | ||
| print("No change") | ||
|
|
||
| if __name__ == "__main__": | ||
| headers = {"Accept": "application/vnd.github+json"} | ||
| token = os.getenv("GITHUB_TOKEN") | ||
| if token: | ||
| headers["Authorization"] = f"Bearer {token}" | ||
| resp = requests.get(API, headers=headers, timeout=30) | ||
| resp.raise_for_status() # fail loudly on rate-limit/auth/5xx, don't parse an error body | ||
| releases = resp.json() | ||
| if not isinstance(releases, list): | ||
| raise SystemExit(f"Unexpected GitHub API response (not a release list): {releases}") | ||
|
|
||
| # Ignore drafts and anything <1h old (assets may still be uploading). | ||
| releases = [r for r in releases | ||
| if not r["draft"] and is_older(r["created_at"], timedelta(hours=1))] | ||
| releases.sort(key=lambda r: r["created_at"]) | ||
|
|
||
| stable = [r for r in releases if not r["prerelease"]] | ||
| if not stable: | ||
| raise SystemExit("No stable release found") | ||
| latest_stable = stable[-1] | ||
|
|
||
| data = {"stable": build_block(latest_stable, include_packages=True, with_android=True)} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When this script writes only
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in e4749b4. Updated |
||
|
|
||
| # Surface the latest pre-release only if it's newer than the latest stable. | ||
| newer_pre = [r for r in releases | ||
| if r["prerelease"] and r["created_at"] > latest_stable["created_at"]] | ||
| if newer_pre: | ||
| latest_pre = newer_pre[-1] | ||
| data["prerelease"] = build_block(latest_pre, include_packages=False, with_android=False) | ||
| print(f"Stable: {latest_stable['tag_name']}; newer pre-release: {latest_pre['tag_name']}") | ||
| else: | ||
| with open(p, "w") as f: | ||
| f.write(new) | ||
| print(f"Wrote to {p}") | ||
| print(f"Stable: {latest_stable['tag_name']} (no newer pre-release)") | ||
|
|
||
| p = Path("_data/downloads.yml") | ||
| header = "# Generated by scripts/update-downloads.py — do not edit by hand.\n" | ||
| p.write_text(header + yaml.safe_dump(data, sort_keys=False, allow_unicode=True)) | ||
| print(f"Wrote {p}") | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the downloads data now lives under
stable, the existing consumers that still readsite.data.downloads.versionandsite.data.downloads.platformslose their inputs. On the homepage download button,_includes/download-url.jsparses the missingplatformsvalue and then calls.filter(...), so visitors with a detected OS hit a JS error instead of getting a direct platform download;_includes/schema-index.htmlalso emits an empty software version and no per-platform entry points. Please either preserve the old top-level aliases or update those includes to readsite.data.downloads.stable.*.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in e4749b4. Updated
_includes/download-url.js(download button) and_includes/schema-index.html(JSON-LD) to readsite.data.downloads.stable.*. Verified no flatdownloads.version/downloads.platformsreferences remain anywhere in the repo.