- name
- github
- description
- Operate GitHub through the gh CLI — typed github::* functions for pull requests, issues, repos, Actions runs/workflows, releases, and search, plus github::exec / github::api escape hatches for everything else.
# PR webhook monitoring (opt-in)
For durable PR monitoring, use `github::pr::event`, NOT `github::called`.
First arm the trigger with a caller-chosen `watch_id`, then call
`github::pr::watch` with that same ID, `pr_url` OR `repo` + `number`, optional
`events: [ci,comments,reviews,pr]`, `stop_on: merged|closed` (default merged),
and mandatory future RFC3339 `expires_at`. Read `github::pr::watch-status`
once after watch to close the initial race. Never interval-poll PRs.
Inspect `status` and `health.last_error`: `preparing` is not active ingress;
`cleanup_pending` is not successful cleanup. `unwatch` and manual `recover`
are mutations requiring approval. Internal `github::webhooks::*` functions
must not be called by an agent. Event callbacks must dedupe `event_id`;
namespace and metadata are preserved, errors propagate to the durable queue.
A single passing check is NOT aggregate CI success. Closed without merge
remains watched until expiry when stop_on is merged.
Operator setup requires persistent SQLite, queue builtin file_based (current
Redis adapter is NOT durable), HTTP dedicated public listener, Quick Tunnel,
cron, and gh auth with Webhooks write plus repository reads. Default enabled
is false. See [the webhook guide](../../docs/architecture/github-webhooks.md). Quick Tunnels are not zero-loss; recovery lists
failed deliveries and requests bounded redelivery, reconciling current state.
Do not enable merely because a public repository can be read.
## Guided webhook setup
`quick-tunnel` is NOT a dependency of this worker: it is only needed for PR
webhooks. Call `github::setup::webhooks-status` (read-only) for the checklist,
in order:
1. `quick_tunnel` — the quick-tunnel worker is installed (fix: `install_worker`,
`compose::add { worker: "quick-tunnel" }`; ask the user first).
2. `cloudflared` — quick-tunnel found the cloudflared binary (fix: `open_url`,
Cloudflare's install page). Nothing downloads cloudflared; the user installs it.
3. `http_listener` — the http worker's restricted webhook listener is on (fix:
`enable_http_listener`, `github::setup::enable-http-listener`, default port 3112).
Each check is `ok`, `missing`, `blocked` (waits for an earlier one) or
`unknown` (older worker version or transient error; never blocking).
`github::setup::enable-webhooks { enabled: true }` is refused until every check
is `ok` and reports `restart_required`: webhook storage opens at startup, so
the github worker must restart. `github::pr::watch` refuses definite blockers
with the same fix list. The console's GitHub page → Webhooks runs these steps
with buttons; both enable functions keep needs_approval for agents.
# github
The github worker wraps the GitHub CLI (`gh`). Thirty typed functions cover
the high-traffic surface (pr, issue, repo, run, workflow, release, search);
`github::exec` runs any other gh command verbatim, and `github::api` reaches
any GitHub REST endpoint. Auth comes from the worker's GH_TOKEN configuration
or the host's ambient `gh auth login` state. There is no local checkout:
every repo-scoped call takes an explicit `repo: "owner/name"`.
## When to Use
- Check a PR before landing: `github::pr::view`, `github::pr::checks`
(failing/pending checks are data, not errors), `github::pr::diff`.
- Open or shepherd a PR: `github::pr::create` / `review` / `merge`.
- File and triage issues: `github::issue::create` / `list` / `comment` /
`close`.
- Watch or poke CI: `github::run::list` / `view` / `rerun` / `cancel`;
dispatch with `github::workflow::run`.
- Cut or inspect releases: `github::release::create` / `list` / `view`.
- Find things org-wide: `github::search::repos` / `issues` / `prs` / `code`
(qualifiers like `repo:o/r is:open` go in the query string).
- Anything gh does that has no typed function → `github::exec { args: [...] }`.
- Any REST endpoint → `github::api { path: "repos/o/r/…", jq? }`.
## Boundaries
- Needs the gh CLI on the worker host; a missing binary errors at call time
with code `gh_not_found` (functions still register without it).
- Mutations (create/edit/merge/comment/review/close/rerun/cancel/workflow
run/release create) and both escape hatches are approval-gated by default;
the read-only surface is allowed (see iii-permissions.yaml).
- Curated functions error on a non-zero gh exit (the message carries gh's
stderr); `github::exec` returns exit_code/stderr/timed_out as data instead.
- Output is capped per stream (default 1 MiB) with `*_truncated` flags;
per-call `timeout_ms` clamps to `max_timeout_ms` (default 120 s; 30 s when
omitted).
- `github::api` paths take concrete owner/repo values — `{owner}`/`{repo}`
placeholders need a checkout the worker does not have.
## Functions
- `github::pr::*` — list, view, create, edit, merge, comment, review, diff,
checks.
- `github::issue::*` — list, view, create, edit, comment, close.
- `github::repo::*` — view, list.
- `github::run::*` — list, view, rerun, cancel (Actions runs).
- `github::workflow::*` — list, run (workflow_dispatch).
- `github::release::*` — list, view, create.
- `github::search::*` — repos, issues, prs, code.
- `github::exec` — `{ args, stdin?, timeout_ms? }` → the full outcome as data
(`stdout`, `stderr`, `exit_code`, `timed_out`, truncation flags).
- `github::api` — `{ path, method?, fields?, body?, jq?, paginate?,
timeout_ms? }` → parsed JSON.
## Actionable PR notifications (`agent_actionable`)
The default `webhooks.notifications.profile` in `config.yaml` delivers only what
needs an agent action, as one `kind: "digest"` payload per watch:
- `ci.failed` items: `failure`, `timed_out`, `startup_failure`, `action_required`
on the current head. A failed workflow is dropped when its failed job is
already reported. Failures of a superseded head are dropped at delivery.
- New comments and reviews (created/submitted, approved, changes requested,
unresolved threads), excluding edits, deletions, the agent's own login
(`ignore_self`, discovered via `GET /user`) and known bot noise.
- `merged` / closed lifecycle, delivered immediately with anything pending.
Never delivered: CI success or progress, cancelled/skipped/neutral runs, pushes,
labels, assignments. The agent checks current CI with `github::pr::checks` when it
acts. Every item carries `event_id`; fetch the full event with
`github::pr::event-detail`.
Timing: a digest is sent after `quiet_ms` (15s) without new items, and never
later than `max_wait_ms` (2min) after its first item. `max_items` (30) bounds the
payload; extra items are counted in `omitted_items`.
## Watch lifetime follows its listeners
A watch is kept alive by the `github::pr::event` bindings that listen to it
(same `watch_id`, or a repo/number filter that matches it).
- When the last listening binding goes away (its chat was deleted, or it
unregistered), the watch is marked orphaned. If no binding listens again
within `webhooks.orphan_grace_minutes` (default 60), maintenance stops it,
releases its quick-tunnel lease and deletes the repository hook once no live
watch remains there; the tunnel stops with its last lease. One-shot wakes are
unregistered right after they fire, so re-arm before the grace period ends.
- Bindings removed while the worker was offline are reconciled against the
engine at most every five minutes.
- Calling `github::pr::watch` again with the same `watch_id` and spec resumes a
stopped watch; completed (merged/closed) and expired watches stay terminal.
- `expires_at` must be within `webhooks.max_watch_days` (1..=30, default 30):
a watch holds a quick-tunnel lease, and leases last at most 30 days.
Auf GitHub ansehen