Replaces scripts/release/publish.sh — uploads built tarballs to a
GitHub release tagged otp-<hash>. The release is created if it
doesn't exist; existing assets with matching names are deleted before
upload (gh release upload won't replace by default).
Why this module carries the most error categories
Of the five MobDev.Release.* orchestrators this is the one most
likely to fail through no fault of ours — GitHub goes down, gh
auth expires, the local network drops. The shell version of this
step blobs all of those together as exit 1; the user can't tell
whether it's their problem or ours. This module classifies every
gh failure into one of:
:auth_required— gh CLI isn't authenticated, or token lacksreposcope. Hint suggestsgh auth login --scopes "repo,write:packages".:infra_unreachable— GitHub returned 5xx or the network's down. Detail carries the first line ofgh's stderr so it's obvious what to check on status.github.com.:precondition_failed— no tarballs inout_dirmatchinghash. Hint points the user atmix mob.release.tarball all.:cmd_failed— fallback for unexpectedghfailures (e.g. malformed tag, write permission denied on a non-our repo).
This is exactly the "is GitHub down or am I broken?" distinction the
build-system migration plan called for. Test coverage exercises each
category against a representative gh stderr snippet.
Public API
MobDev.Release.Publish.publish() # defaults
MobDev.Release.Publish.publish(repo: "fork/mob") # publish to fork
MobDev.Release.Publish.publish(assets: ["otp-android"]) # subsetReturns {:ok, %{tag, repo, assets}} on success or a tagged error.
What it does end-to-end
- Resolve
repo,hash,out_dir(env or opts). - Discover which of the four canonical tarball basenames are
present in
out_dirfor this hash. At least one must exist. gh release view otp-<hash>— exists?- If not (
release not found),gh release create. - If 401/403,
:auth_required. - If 5xx/network,
:infra_unreachable.
- If not (
- List the release's existing assets. For each one that overlaps
with what we're about to upload,
gh release delete-asset. - Single
gh release upload otp-<hash> <paths…>. - Verify by re-listing assets — returned in
info.assets.
Summary
Functions
Canonical tarball basenames the publisher knows how to upload.
Classify a gh stderr/stdout line into one of :not_found, :auth,
:infra, or :other. Public for testing — the regexes are the
contract.
Default GitHub repo (mirrors publish.sh's ${REPO:=GenericJam/mob}).
Asset basenames that exist in out_dir for the given hash. Returns
an ordered list (matching candidate_basenames/0 order).
Run the publish pipeline. See module doc for options.
Build the release tag for a hash (otp-<hash>).
Types
Functions
@spec candidate_basenames() :: [String.t()]
Canonical tarball basenames the publisher knows how to upload.
@spec classify(String.t()) :: :not_found | :auth | :infra | :other
Classify a gh stderr/stdout line into one of :not_found, :auth,
:infra, or :other. Public for testing — the regexes are the
contract.
@spec default_repo() :: String.t()
Default GitHub repo (mirrors publish.sh's ${REPO:=GenericJam/mob}).
Asset basenames that exist in out_dir for the given hash. Returns
an ordered list (matching candidate_basenames/0 order).
@spec publish(keyword()) :: {:ok, info()} | MobDev.Release.Errors.t()
Run the publish pipeline. See module doc for options.
Recognized opts:
:repo—owner/name(default:GenericJam/mob):hash— release hash. Default: detected fromOTP_SRCgit or$HASH.:otp_src— OTP checkout for hash detection. Default perHelpers.:out_dir— directory containing the built tarballs. Default perHelpers.:assets— list of tarball basenames to upload. Each may be either the bare base ("otp-android") — in which case-<hash>.tar.gzis appended — or the full filename. Default: auto-discover any of the four canonical names that exist.
Build the release tag for a hash (otp-<hash>).