> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twinbay.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub

> Repositories, issues, pull requests and Projects v2, over REST and GraphQL

An account and its organization, the repositories in them, the issues and pull requests in those, the conversation on top, and the Projects v2 boards they sit on. Both surfaces answer: the REST API and `POST /graphql`, which is the only place Projects v2 exists. The conformance suite drives the twin through `octokit` `5.0.5`, the SDK GitHub publishes, against REST API version `2022-11-28`. GitHub publishes no Python client, so there is no Python target.

**Slug:** `github`

## What it models

| Area                | Modelled                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Account             | `GET /user`, `GET /users/{login}` and `GET /rate_limit`, with the full set of hypertext fields GitHub sends on a user                                                                                                                                                                                                                                                                                                                                                                    |
| Repositories        | Create, read, list, rename, archive and delete; the nine labels GitHub creates a repository with; a rename that moves every route and URL; `archived`, which makes writes `403` and leaves reads alone; `has_issues`, which makes the tracker `410 Gone`; listing sorted by `full_name` unless you ask for `created`, `updated` or `pushed`                                                                                                                                              |
| Issues              | File, read, edit, close, reopen and lock; numbering per repository and identifiers per account; `state`, `state_reason`, `closed_at` and `closed_by` settled server-side with GitHub's own refusals; a missing label created and a non-collaborator assignee dropped, as GitHub does both; filters on `state`, `labels`, `assignee`, `creator`, `since`, `sort` and `direction`                                                                                                          |
| Pull requests       | Create, list, read, update and merge, plus the one git-data route that creates a ref; numbering from the same sequence as issues; `mergeable` and `mergeable_state` settled on [advance](/concepts#time-and-advancing); `405` for merging anything not `clean`; the single-read-only fields absent from the list route, as they are at GitHub; the issue routes answering for a pull request with the `pull_request` object attached                                                     |
| Organizations       | `GET /orgs/{org}`, its members, its repositories and repositories created inside it, `GET /user/orgs`, and the pages GitHub links by organization id; classic `GET /orgs/{org}/projects` answers `404`, as the live API does                                                                                                                                                                                                                                                             |
| Comments and labels | Comments on an issue, the issue's own `comments` count, a repository's labels with GitHub's case-insensitive uniqueness, the labels an issue carries, and a deleted label coming off every issue that carried it                                                                                                                                                                                                                                                                         |
| GraphQL             | Queries, mutations, variables, aliases, fragments, inline fragments, `@skip` and `@include`, and Relay connections read as `nodes` or `edges { cursor node }` in both directions; `viewer`, `repository`, `organization`, `rateLimit`, a repository's `issues` and `pullRequests`, an issue's or pull request's `comments`; `createIssue`, `addComment` and `updateIssue`, which write the same records REST reads; refusals in graphql-ruby's own vocabulary, which is what GitHub runs |
| Projects v2         | A board created over GraphQL with GitHub's Status field, its fields and items, adding an issue to one, and reading it back through `projectV2` or `projectsV2`. Adding content already on a board answers the item that is there                                                                                                                                                                                                                                                         |
| Authentication      | A fine-grained `github_pat_` token sent as `token` or `Bearer`; `401 Requires authentication` with no header and `401 Bad credentials` for an unknown, revoked or wrongly-schemed one; the `403` and line of HTML GitHub answers a request with no `User-Agent`, before it reads the credential; and the `x-github-*` and `x-ratelimit-*` headers on every response                                                                                                                      |
| Rate limits         | Both windows. REST spends its hour's 5,000 requests one call at a time and `GET /rate_limit` costs nothing, and an empty window refuses every call `403`. GraphQL is a separate budget in points, priced by GitHub's own formula, reported through `rateLimit { limit cost remaining resetAt }`, so a spent REST hour leaves GraphQL answering                                                                                                                                           |

The account, one collaborator, the organization and one repository are the same in every container, so a seed plan can name them before any container exists: `twinbay` owns everything, `hubot` is the one assignable collaborator, `twinbay-labs` is the organization both belong to, and `twinbay/sandbox` is a repository with GitHub's nine default labels and a `main` branch. The sandbox numbers whatever you create afterwards.

Advancing opens whichever rate-limit window had anything spent in it, and settles the mergeability of every open pull request, which GitHub computes in the background.

## Scenarios

`busy-repository`, `pull-request-in-review`, `merge-conflict`, `organization-workspace`, `project-board`, `archived-repository`, `issues-disabled`, `locked-issue`, `rate-limited-token`.

## Not modelled

Actions, releases, webhooks, gists, search, teams, reviews and review comments, and git data beyond the one route that creates a branch. Four refusals are worth naming, because each one is a route or field GitHub has and the twin declines on purpose: `GET /graphql`, which is a full schema introspection on the live API; a pull request's files and commits, because there is no git here to diff; editing or labelling a pull request through the issue routes; and setting a project field value, or a board owned by anything but the organization.

An unmodelled route answers `501` in GitHub's own envelope, and an unmodelled GraphQL field answers `501` with `extensions.code: "notModelled"` rather than `null`.
