Combined index¶
End-to-end pipeline: fetch → filter → extract → build → emit. Uses structured assets when present, falls back to URLs scraped from release-notes prose.
examples/04_combined_index.py
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "ocx-mirror-sdk @ git+https://github.com/ocx-sh/ocx-mirror-sdk@v0.3.0",
# ]
# ///
"""End-to-end generator: fetch → filter → extract → build → emit.
Fetches Bun releases, filters non-stable + draft, prefers structured
release assets, falls back to URLs scraped from release notes.
Usage:
uv run examples/04_combined_index.py > bun.json
"""
import re
from ocx_mirror_sdk import IndexBuilder, extract_urls, list_releases
# Match the structured Bun release-asset filenames we want to publish.
ASSET_RE = re.compile(r"^bun-(linux|darwin|windows)-(x64|aarch64)\.zip$")
def main() -> None:
releases = list_releases(
"oven-sh",
"bun",
include_prereleases=False,
include_drafts=False,
)
builder = IndexBuilder()
for r in releases:
version = r.tag_name.lstrip("bun-v")
assets: dict[str, str] = {}
# Prefer structured assets
for asset in r.assets:
if ASSET_RE.match(asset.name):
assets[asset.name] = asset.browser_download_url
# Fall back to URLs in release notes if none matched
if not assets and r.body:
for url in extract_urls(r.body, pattern=ASSET_RE.pattern):
name = url.rsplit("/", 1)[-1]
assets[name] = url
builder.add_version(version, assets=assets)
builder.emit()
if __name__ == "__main__":
main()
Run:
Shape of the pattern¶
This is the canonical "real" generator. The pieces:
- Fetch —
github.list_releases(...), filtered to stable. - Discriminate — asset-name regex picks the structured assets we want to publish.
- Fallback — if structured assets are absent,
extract_urlsonr.bodyrecovers any URLs in the release notes. - Build —
IndexBuilder.add_version(...)accumulates each version's assets. - Emit —
builder.emit()writes theurl_indexJSON to stdout.
For error handling around this pattern, see
examples/05_error_handling.py.