The convenience modules are thin wrappers over GhEx.REST that fill in the endpoint path. Each function returns the same {:ok, body, meta} / {:error, reason} shape as the core and passes opts through to Req (so :params, headers, and a Req.Test plug all work). They cover the common paths; for anything else, call GhEx.REST directly.

On the write wrappers (create, update, merge, and the like), the attrs argument is the sole request body: each sets :json to attrs, so a :json passed in opts is ignored.

The list_* functions return a single page. Each has a stream_* companion that auto-paginates into a lazy Stream of individual items, following Link: rel="next" (see the Pagination guide). The wrapped endpoints (Search, Actions runs/workflows/jobs, Checks) unwrap their array key for you.

# every open issue, not just the first page
client
|> GhEx.Issues.stream("elixir-lang", "elixir", params: [state: "open", per_page: 100])
|> Stream.map(& &1["number"])
|> Enum.to_list()

For a path without a stream_* wrapper, call GhEx.REST.stream/3 directly with the path and, for an object-wrapped response, the items: key.

Issues

GhEx.Issues — list, get, create, update, comment, label.

GhEx.Issues.list(client, "elixir-lang", "elixir", params: [state: "open"])
GhEx.Issues.create(client, "o", "r", %{title: "Bug", body: "..."})
GhEx.Issues.create_comment(client, "o", "r", 7, "thanks for the report")
GhEx.Issues.add_labels(client, "o", "r", 7, ["bug", "p1"])

Pull requests

GhEx.PullRequests — list, get, create, update, merge, files, reviews.

GhEx.PullRequests.create(client, "o", "r", %{title: "Fix", head: "fix", base: "main"})
GhEx.PullRequests.list_files(client, "o", "r", 42)
GhEx.PullRequests.merge(client, "o", "r", 42, %{merge_method: "squash"})
GhEx.PullRequests.create_review(client, "o", "r", 42, %{event: "APPROVE"})

Repositories and contents

GhEx.Repositories — get, list (org/user), create, update, delete, commits, branches. GhEx.Contents — read and write files.

GhEx.Repositories.get(client, "elixir-lang", "elixir")
GhEx.Repositories.list_for_org(client, "elixir-lang", params: [type: "public"])

{:ok, file, _meta} = GhEx.Contents.get(client, "o", "r", "mix.exs", params: [ref: "main"])

GhEx.Contents.create_or_update_file(client, "o", "r", "NOTES.md", %{
  message: "add notes",
  content: Base.encode64("hello"),
  sha: file["sha"]
})

content is Base64-encoded, and updating an existing file needs its blob sha.

Releases

GhEx.Releases — list, get, get_latest, get_by_tag, create, update, delete.

GhEx.Releases.get_latest(client, "o", "r")

GhEx.Releases.create(client, "o", "r", %{
  tag_name: "v1.0.0",
  name: "v1.0.0",
  generate_release_notes: true
})

Actions

GhEx.Actions — workflows, runs, dispatch. A workflow is its numeric id or its file name ("ci.yml").

GhEx.Actions.list_workflows(client, "o", "r")
GhEx.Actions.dispatch_workflow(client, "o", "r", "ci.yml", %{ref: "main", inputs: %{env: "prod"}})
GhEx.Actions.list_runs(client, "o", "r", params: [branch: "main", status: "failure"])
GhEx.Actions.rerun(client, "o", "r", run_id)

Checks and statuses

GhEx.Checks — check runs. GhEx.Statuses — commit statuses.

GhEx.Checks.create_run(client, "o", "r", %{name: "lint", head_sha: sha, status: "in_progress"})
GhEx.Checks.list_for_ref(client, "o", "r", sha)

GhEx.Statuses.create(client, "o", "r", sha, %{state: "success", context: "ci/lint"})
GhEx.Statuses.get_combined(client, "o", "r", "main")

GhEx.Search — repositories, code, issues_and_pull_requests, users, commits. The first argument is the q query; pass params: for sort and order.

GhEx.Search.repositories(client, "tetris language:elixir", params: [sort: "stars"])
GhEx.Search.issues_and_pull_requests(client, "repo:o/r is:open label:bug")

Users, organizations, and teams

GhEx.Users, GhEx.Organizations, GhEx.Teams.

GhEx.Users.get_authenticated(client)
GhEx.Users.get(client, "joshrotenberg")
GhEx.Organizations.list_members(client, "elixir-lang")
GhEx.Teams.list(client, "elixir-lang")

Gists

GhEx.Gists — list, get, create, update, delete.

GhEx.Gists.create(client, %{
  description: "example",
  public: false,
  files: %{"hello.txt" => %{content: "hi"}}
})

Webhooks

GhEx.Webhooks is the receiving side: verify a delivery signature and parse the payload. See the Testing guide for the full handler pattern.

with :ok <- GhEx.Webhooks.verify(body, signature, secret),
     {:ok, payload} <- GhEx.Webhooks.parse(body) do
  handle(event_name, payload)
end