Stateless HTTP client for GitHub Releases.
Library-shape: no host dependencies. The progress callback is the only seam; consumers translate it into PubSub broadcasts.
Rate limiting
Anonymous requests are limited to 60/hr per source IP. Pass an
If-None-Match ETag (returned in the previous latest_release/2
response under :etag) — 304 responses do not count against quota.
See: https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api
Summary
Functions
Streams an asset to dest_path, writing atomically (.part → rename).
Fetches the latest release for owner_repo (e.g. "bbangert/universal_proxy").
Types
Functions
Streams an asset to dest_path, writing atomically (.part → rename).
Reports progress through opts[:progress] as {:downloading, percent}
every ≥ 262144 bytes and once on completion.
Options
:expected_sha256— optional hex digest (either case) checked against a SHA-256 computed incrementally while streaming. Verified before the.part→ dest rename; on mismatch the.partfile is deleted and{:error, {:sha256_mismatch, expected: ..., actual: ...}}is returned (both hex strings lowercase). Omit to skip hashing entirely.
A hard size ceiling always applies — max(expected_size * 2, 268435456) bytes — so a runaway or malicious response
can't fill the download dir even when :expected_size is
0/absent. Exceeding it aborts the stream and returns
{:error, {:download_too_large, limit}}.
Returns :ok on success; on failure deletes the partial file and
returns {:error, term()}.
@spec latest_release( String.t(), keyword() ) :: {:ok, release()} | {:ok, :not_modified} | {:error, term()}
Fetches the latest release for owner_repo (e.g. "bbangert/universal_proxy").
Options
:channel—:stable(default) or:prerelease.:stablehits the/releases/latestendpoint — GitHub's "latest" excludes prereleases and drafts by definition, so the existing prerelease guard is just belt-and-suspenders.:prereleasehits/releases?per_page=30and picks the release with the highest semver tag (drafts excluded, prereleases eligible — ties are broken byVersion.compare/2's native prerelease ordering, so e.g.v1.3.0-rc.1beatsv1.2.9).:github_token— optional bearer token for higher rate limits and private-repo access.:etag— value from a prior call's response. A matching server response returns{:ok, :not_modified}without counting against quota.:req_options— extra options forwarded toReq.new/1(used by tests to injectplug:for stubbing).
Returns {:ok, release} on a current release, {:ok, :not_modified}
on 304, {:error, :no_release} when :channel is :prerelease and
no release has a parseable semver tag, {:error, :rate_limited} on
quota exhaustion, {:error, :not_found} on 404, or {:error, term()}
on transport errors.