repomatic.github.releases module¶
GitHub Releases API client.
The single home for reading GitHub Releases: raw cached API access (tags,
versions, single bodies), tag-to-version extraction, tag-to-SHA resolution, and
the range-to-release-notes fetch shared by the dependency updaters. The
repomatic.release.version_sync adapters and repomatic.deps.dep_report
release-notes helper build on top of these reads.
One write helper lives here too: edit_release_notes(), the shared
gh release edit path behind the dev pre-release sync
(repomatic.github.dev_release) and the changelog-to-release-notes sync
(repomatic.github.release_sync), so both writers carry the same
arguments and failure contract.
- repomatic.github.releases.GITHUB_API_RELEASES_URL = 'https://api.github.com/repos/{owner}/{repo}/releases'¶
GitHub API URL for fetching all releases for a repository.
- repomatic.github.releases.GITHUB_API_TAG_REF_URL = 'https://api.github.com/repos/{owner}/{repo}/git/ref/tags/{tag}'¶
GitHub API URL for resolving a tag name to its git object.
- repomatic.github.releases.GITHUB_API_TAG_OBJECT_URL = 'https://api.github.com/repos/{owner}/{repo}/git/tags/{sha}'¶
GitHub API URL for dereferencing an annotated tag object to its commit.
- repomatic.github.releases.GITHUB_API_RELEASE_BY_TAG_URL = 'https://api.github.com/repos/{owner}/{repo}/releases/tags/{tag}'¶
GitHub API URL for fetching a single release by tag name.
- repomatic.github.releases.owner_repo(repo_url)[source]¶
Extract
(owner, repo)from a GitHub repository URL.
Bases:
RuntimeErrorRaised when the GitHub Releases API call could not complete cleanly.
Signals a transient failure (network error, timeout, JSON parse error, or pagination breaking mid-stream) where the result cannot safely be treated as “no releases.”
Callers that drive destructive operations (rewriting the changelog, deleting tags, etc.) must catch this and refuse to act, rather than silently rewriting state with a corrupted or empty view of release history.
- class repomatic.github.releases.GitHubRelease(date: str, body: str)[source]¶
Bases:
NamedTupleRelease metadata for a single version from GitHub.
Create new instance of GitHubRelease(date, body)
- class repomatic.github.releases.ReleaseAsset(name: str, size: int, sha256: str, download_url: str)[source]¶
Bases:
NamedTupleA single downloadable asset attached to a GitHub release.
Create new instance of ReleaseAsset(name, size, sha256, download_url)
- class repomatic.github.releases.ReleaseWithAssets(tag: str, date: str, draft: bool, prerelease: bool, assets: tuple[ReleaseAsset, ...], body: str = '', html_url: str = '')[source]¶
Bases:
NamedTupleFull release metadata including its assets and visibility flags.
Create new instance of ReleaseWithAssets(tag, date, draft, prerelease, assets, body, html_url)
- assets: tuple[ReleaseAsset, ...]¶
Assets attached to the release, in API order.
- body: str¶
Release notes body (markdown).
Carried so
sync-binaries --backfill-recordscan recover detection snapshots from the legacy VirusTotal tables that release notes held before the scan history file existed.
- html_url: str¶
Browser URL of the release page.
For a draft release this is the only resolvable link: drafts have no public
releases/tag/<tag>URL, so GitHub serves them at an unguessablereleases/tag/untagged-<hash>path exposed only in this field. The prepare-release PR body links the rolling dev pre-release through it (seedev_release_url_and_previous_version()).
- repomatic.github.releases.get_github_releases(repo_url, *, force_refresh=False)[source]¶
Get versions and dates for all GitHub releases.
Fetches all releases via the GitHub API with pagination. Extracts version numbers by stripping the
vprefix from tag names. Usespublished_at(falling back tocreated_at) for the date.- Parameters:
- Return type:
- Returns:
Dict mapping version strings to
GitHubReleasetuples. Empty dict only when the repository genuinely has no releases (the API returned an empty page) or whenrepo_urldoes not parse to anowner/repopair.- Raises:
GitHubReleasesUnavailable – When any page fetch fails or returns unparsable JSON. An empty return value from this function means “the repo has no releases”; a raised exception means “the answer is unknown.”
- repomatic.github.releases.get_release_tags(repo_url)[source]¶
Get all releases keyed by their raw, unstripped tag name.
get_github_releases()keeps onlyv-prefixed tags (and strips thev), which drops tools whose release tags use another scheme (lychee’slychee-v…, biome’s@biomejs/biome@…).sync-tool-versionsandsync-action-pinsneed every tag, so the version can be extracted with a per-tool pattern.- Parameters:
repo_url (
str) – Repository URL.- Return type:
- Returns:
Dict mapping raw tag names to
GitHubReleasetuples. Empty only when the repository has no releases orrepo_urldoes not parse to anowner/repopair.- Raises:
GitHubReleasesUnavailable – When any page fetch fails or returns unparsable JSON.
- repomatic.github.releases.get_releases_with_assets(repo_url)[source]¶
Get every release with its assets, visibility flags, and digests.
Deliberately uncached, unlike
get_github_releases(): the main consumer issync-binaries, which runs minutes after a release is published and must see the assets that were just uploaded. A cached view would regenerate the binaries page from a pre-release snapshot.- Parameters:
repo_url (
str) – Repository URL (e.g.https://github.com/user/repo).- Return type:
- Returns:
One
ReleaseWithAssetsper release (drafts and pre-releases included, for the caller to filter), in API order (newest first). Empty when the repository has no releases or repo_url does not parse to anowner/repopair.- Raises:
GitHubReleasesUnavailable – When any page fetch fails or returns unparsable JSON.
- repomatic.github.releases.parse_release_version(tag)[source]¶
Parse a release tag as a version, or
Nonefor foreign tag schemes.- Return type:
Version|None
- repomatic.github.releases.dev_release_url_and_previous_version(repo_url, version)[source]¶
Look up the two release references the prepare-release PR body links to.
A single
get_releases_with_assets()fetch yields both:Dev pre-release URL: the
html_urlof the draft pre-release whose version shares version’s release segment (the rollingv{version}.dev0draft). Drafts are visible only to authenticated maintainers, so an unauthenticated or token-less caller getsNonehere even when the draft exists.Previous version: the highest final release (draft, pre-release, and
.devtags excluded) already published. At prepare-release time the tag for version does not exist yet, so this is the release the new one supersedes, used for thev{previous}...maincomparison link.
- Parameters:
- Return type:
- Returns:
An
(dev_release_url, previous_version)pair. Either element isNonewhen its release cannot be found or the API is unavailable, so the caller degrades each list item independently.
- repomatic.github.releases.resolve_tag_to_sha(repo_url, tag)[source]¶
Resolve a release tag to its 40-character commit SHA.
Reads the tag’s git reference. An annotated tag points at an intermediate tag object, dereferenced one hop to the commit it targets; a lightweight tag points straight at the commit.
- repomatic.github.releases.extract_version(tag, tag_pattern)[source]¶
Extract a version from a GitHub release tag.
- repomatic.github.releases.edit_release_notes(tag, repository, body, *, title='')[source]¶
Edit a release’s notes (and optionally its title) in place.
The one
gh release editpath shared by every release writer, so the dev pre-release sync and the changelog-to-release-notes sync carry the same arguments and failure contract. Assets are never touched.- Parameters:
- Return type:
- Returns:
Truewhen the edit landed,Falsewhen the release does not exist or the edit failed.
- repomatic.github.releases.get_github_release_body(repo_url, version)[source]¶
Fetch the release notes body for a specific version from GitHub.
Tries
v{version}first (most common for Python packages), then the bare{version}tag.
- repomatic.github.releases.fetch_github_release_notes(items)[source]¶
Fetch GitHub release notes for a batch of version bumps.
For each item, lists the repository’s releases (a cached call, already warm from a prior candidate sweep) and keeps those whose extracted version lands in the half-open range
(old, new], oldest first. Non-GitHub datasources (npm, PyPI workflow literals) contribute no item here and render no notes.- Parameters:
items (
list[tuple[str,str,str,str,str|None]]) – One(name, repo_url, old, new, tag_pattern)tuple per bumped pin, where old and new are bare versions and tag_pattern is the per-tool extraction regex (orNonefor thevX.Y.Zscheme).- Return type:
- Returns:
A dict mapping names to
(repo_url, versions)tuples, the same shaperepomatic.deps.dep_report.fetch_release_notes()returns, sorepomatic.deps.dep_report.format_release_notes()renders it unchanged. Only entries with at least one non-empty release body are included.