Skip to content

g1t/apps/docs/src/content/docs/guides/checks.md

300 lines13,898 bytesCodeBlame
1---
2title: Checks
3description: Report what CI and integrations find on a commit as statuses and check runs, see them beside every commit, and require them before a merge.
4---
5
6Every commit can carry checks: what your workflows, your CI, your
7deployments and any integration say about it. g1t shows them beside the
8commit wherever it appears, so you can tell at a glance whether a change
9works and how far along it is.
10
11- A green check: every check passed.
12- A red cross: at least one failed.
13- An amber dot: at least one is still running or queued.
14
15Select the mark to see the list: a headline ("All checks have passed",
16"Some checks were not successful" or "Some checks haven't completed yet"),
17how many passed, failed and are running, and each check with how it went,
18how long it took, and a **Details** link.
19
20## Where checks show
21
22| Page | Where |
23| --- | --- |
24| **Code** | Beside the latest commit, above the files |
25| **Commits** | Beside each commit |
26| A commit's page | Beside its hash |
27| **Branches** | Beside each branch's latest commit |
28| **Tags** | Beside each tagged commit |
29| A pull request | Beside its head commit, in the sidebar; its merge box lists them too |
30| A project's overview | Beside the latest commit, and each active branch |
31
32A page reads the checks of all its commits at once, after the page itself
33has loaded: each mark shows a placeholder until they arrive.
34
35## Statuses and check runs
36
37There are two ways to report a check. Use either, or both.
38
39| | A status | A check run |
40| --- | --- | --- |
41| What it is | A state for one context on a commit, such as `ci/build` | One run of one check, with a life of its own |
42| States | `pending`, `success`, `failure`, `error` | `status`: `queued`, `in_progress`, `completed`; once completed, a `conclusion`: `success`, `failure`, `neutral`, `cancelled`, `skipped`, `timed_out` or `action_required` |
43| Report | A short `description` and a `target_url` | A `title`, a Markdown `summary` and `text`, up to 1,000 annotations on lines of files, and up to 3 buttons |
44| On g1t | Listed with a link to `target_url` | Its own page under the repository, linked from the list |
45| Set again | Replaces the context's status on that commit | Update the same run, or create a new one |
46| Use it for | A quick pass or fail from any tool | Test, lint and scan results someone needs to read |
47
48Every job of a [workflow](/guides/actions/) run is a check run, named
49`Workflow / job (event)` in the list, such as `CI / test (push)`, and its
50**Details** opens the job's log. You do not report those: g1t does.
51
52## Report a status
53
54You need a token with the `checks:write` scope (see
55[scopes](/guides/authentication/#scopes)) and the Write
56[role](/guides/access-and-roles/) on the repository.
57
58```sh
59curl -X POST https://api.g1t.sh/repos/<workspace>/<repo>/statuses/<sha> \
60 -H "Authorization: Bearer $G1T_TOKEN" \
61 -H "Content-Type: application/json" \
62 -d '{
63 "state": "success",
64 "context": "ci/build",
65 "description": "Build #4821 passed",
66 "target_url": "https://ci.example.com/builds/4821"
67 }'
68```
69
70| Field | Required | What it is |
71| --- | --- | --- |
72| `state` | Yes | `pending`, `success`, `failure` or `error`. `error` counts as a failure. |
73| `context` | No | What reports it, such as `ci/build`; `default` when left out. At most 100 characters. |
74| `description` | No | A short word on it, at most 140 characters. |
75| `target_url` | No | Where to see more: an `http` or `https` address. |
76
77[`create_commit_status`](/reference/api/checks/create-commit-status/)
78returns the status. Set a context again to replace it: report `pending`
79when a build starts, then `success` or `failure` when it ends.
80[`get_combined_status`](/reference/api/checks/get-combined-status/) gives
81a commit's statuses and what they add up to:
82`GET /repos/<workspace>/<repo>/commits/<ref>/status`, where `<ref>` is a
83commit SHA, a branch or a tag.
84
85## Report a check run
86
87A check run is reported in two steps: create it when the work starts,
88then complete it.
89
901. Create it, in progress:
91
92 ```sh
93 curl -X POST https://api.g1t.sh/repos/<workspace>/<repo>/check-runs \
94 -H "Authorization: Bearer $G1T_TOKEN" \
95 -H "Content-Type: application/json" \
96 -d '{"name": "lint", "head_sha": "<sha>", "status": "in_progress", "details_url": "https://ci.example.com/builds/4821"}'
97 ```
98
99 The answer has its `id`, such as `cr_01kq4b7c8d9e0f1g2h3j4k5m6n`.
100
1012. Complete it with a `conclusion`, a report and annotations:
102
103 ```sh
104 curl -X PATCH https://api.g1t.sh/repos/<workspace>/<repo>/check-runs/<id> \
105 -H "Authorization: Bearer $G1T_TOKEN" \
106 -H "Content-Type: application/json" \
107 -d '{
108 "conclusion": "failure",
109 "output": {
110 "title": "2 problems",
111 "summary": "**2** problems in `src/parse.rs`.",
112 "annotations": [
113 {"path": "src/parse.rs", "start_line": 42, "end_line": 42, "annotation_level": "warning", "message": "unused variable: `depth`"},
114 {"path": "src/parse.rs", "start_line": 57, "end_line": 60, "annotation_level": "failure", "message": "this match is not exhaustive"}
115 ]
116 }
117 }'
118 ```
119
120Giving a `conclusion` completes the run; `started_at` and `completed_at`
121are filled in when you leave them out. A run can also be created already
122completed, in one call.
123
124| Field | What it is |
125| --- | --- |
126| `name` | The check's name, at most 100 characters. Required to create one. |
127| `head_sha` | The commit it is about. Required to create one. |
128| `status` | `queued` (the default), `in_progress` or `completed`. |
129| `conclusion` | `success`, `failure`, `neutral`, `cancelled`, `skipped`, `timed_out` or `action_required`. |
130| `started_at`, `completed_at` | When it started and ended, in RFC 3339. |
131| `details_url` | Your own page for it. |
132| `external_id` | Your own id for it. |
133| `output` | `title`, `summary` and `text` (Markdown, at most 65,535 characters each) and `annotations`. |
134| `actions` | Up to 3 buttons: `label` (20 characters), `description` (40) and `identifier` (20). |
135| `app` | Who reports it, such as `Codecov`. By default, your token's name. |
136
137### A minimal reporter
138
139This script runs a command and reports it as a check run, from any CI that
140has `curl` and `jq`:
141
142```sh
143#!/bin/sh
144# check.sh <name> <command…>: report a command as a g1t check run.
145set -u
146name=$1; shift
147api="https://api.g1t.sh/repos/$G1T_REPO"
148auth="Authorization: Bearer $G1T_TOKEN"
149
150id=$(curl -sf -X POST "$api/check-runs" -H "$auth" -H "Content-Type: application/json" \
151 -d "$(jq -n --arg name "$name" --arg sha "$G1T_SHA" '{name: $name, head_sha: $sha, status: "in_progress"}')" | jq -r .id)
152
153if output=$("$@" 2>&1); then conclusion=success; else conclusion=failure; fi
154
155curl -sf -X PATCH "$api/check-runs/$id" -H "$auth" -H "Content-Type: application/json" \
156 -d "$(jq -n --arg c "$conclusion" --arg log "$(printf '%s' "$output" | tail -c 60000)" \
157 '{conclusion: $c, output: {title: $c, summary: ("```\n" + $log + "\n```")}}')" > /dev/null
158[ "$conclusion" = success ]
159```
160
161```sh
162G1T_REPO=acme/web G1T_SHA=$(git rev-parse HEAD) ./check.sh lint npm run lint
163```
164
165### Annotations
166
167An annotation points at lines of a file at the run's commit: `path`,
168`start_line` and `end_line` (from 1), and for one line, `start_column`
169and `end_column`. `annotation_level` is `notice`, `warning` or `failure`;
170`message` says what is wrong, `title` names it, and `raw_details` holds
171anything longer.
172
173Send at most 50 in one request; each update adds to those the run has,
174up to 1,000. On the check run's page they are grouped by file, each
175linking to its lines.
176[`list_check_run_annotations`](/reference/api/checks/list-check-run-annotations/)
177returns them in the order they were reported.
178
179### Buttons
180
181`actions` puts up to 3 buttons on the check run's page, such as **Fix
182this** or **Ignore**. When someone with the Write role presses one, g1t
183sends your webhook a `check_run.requested_action` event with the button's
184`identifier` in `data.requested_action`. What happens next is up to you.
185
186### Check suites
187
188Each reporter's check runs on a commit form one check suite, with a
189status and conclusion worked out from its latest runs: in progress while any
190is, then the worst conclusion. A workflow run is the suite of its jobs.
191[`list_check_suites_for_ref`](/reference/api/checks/list-check-suites-for-ref/)
192lists a commit's suites. A suite completing sends `check_suite.completed`.
193
194## From a workflow
195
196A workflow job reports extra check runs with its own `G1T_TOKEN`. They
197report as **g1t Actions**:
198
199```yaml
200- name: Report coverage
201 if: always()
202 env:
203 G1T_TOKEN: ${{ secrets.G1T_TOKEN }}
204 run: |
205 curl -sf -X POST "$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/check-runs" \
206 -H "Authorization: Bearer $G1T_TOKEN" -H "Content-Type: application/json" \
207 -d "{\"name\": \"coverage\", \"head_sha\": \"$GITHUB_SHA\", \"conclusion\": \"neutral\", \"output\": {\"title\": \"81% covered\", \"summary\": \"Up 2% from main.\"}}"
208```
209
210A pull request's runs from someone without the Write role get no token
211that can write, so they cannot report checks.
212
213## Required checks
214
215A [required status check](/guides/pull-requests/#required-status-checks),
216in branch protection or a [ruleset](/guides/rules/), is met by a status of
217its name or a check run of its name alike:
218
219| What reported it | Counts as |
220| --- | --- |
221| A status `success` | Passing |
222| A status `failure` or `error` | Failing |
223| A status `pending` | Running: the merge waits |
224| A check run not yet completed | Running: the merge waits |
225| A check run completed `success`, `neutral` or `skipped` | Passing |
226| A check run completed `failure`, `cancelled`, `timed_out` or `action_required` | Failing |
227| Nothing yet | Expected: the merge waits |
228
229A workflow is required by its name, such as `CI`, which all its jobs
230report under. To require only what was reported through the API, pin the
231check to the `api` integration in a ruleset:
232`{"context": "lint", "integration": "api"}`.
233
234A pull request [g1t is working on](/guides/working-with-g1t/#seeing-it-through)
235goes back to g1t when a check fails, whatever reported it.
236
237## Run again
238
239[`rerequest_check_run`](/reference/api/checks/rerequest-check-run/) and
240[`rerequest_check_suite`](/reference/api/checks/rerequest-check-suite/), or
241**Re-run** on a check run's page, ask for it to run again. A check run
242reported through the API sends its reporter `check_run.rerequested` (or
243`check_suite.rerequested`): run it again and report a new check run. A
244workflow job's run runs again, which also needs `workflows:write`.
245
246## Webhooks
247
248[Webhooks](/guides/webhooks/) can be sent:
249
250| Event | When |
251| --- | --- |
252| `status.created` | A status was set on a commit through the API. |
253| `check_run.created` | A check run was reported. |
254| `check_run.completed` | A check run completed. |
255| `check_run.rerequested` | Someone asked for a check run to run again. |
256| `check_run.requested_action` | Someone pressed one of a check run's buttons. |
257| `check_suite.completed` | Every latest check run of a suite completed. |
258| `check_suite.rerequested` | Someone asked for a check suite to run again. |
259
260These are left out of a repository's timeline.
261
262## Who can report checks
263
264| | Can |
265| --- | --- |
266| Anyone who can read the repository | See its checks, and read them through the API with `checks:read` (no token for a public repository) |
267| The Write role and up, with `checks:write` | Report statuses and check runs, and ask for them to run again |
268| A workflow job, with `G1T_TOKEN` | The same, in its repository |
269| g1t's agents | Read checks, never report them |
270
271An agent's own work is never judged by checks it reported: what a check
272says is up to your CI and integrations.
273
274## From the API and MCP
275
276| Route | Operation |
277| --- | --- |
278| `POST /repos/{owner}/{name}/statuses/{sha}` | [`create_commit_status`](/reference/api/checks/create-commit-status/) |
279| `GET /repos/{owner}/{name}/commits/{ref}/statuses` | [`list_commit_statuses`](/reference/api/checks/list-commit-statuses/) |
280| `GET /repos/{owner}/{name}/commits/{ref}/status` | [`get_combined_status`](/reference/api/checks/get-combined-status/) |
281| `POST /repos/{owner}/{name}/check-runs` | [`create_check_run`](/reference/api/checks/create-check-run/) |
282| `PATCH /repos/{owner}/{name}/check-runs/{id}` | [`update_check_run`](/reference/api/checks/update-check-run/) |
283| `GET /repos/{owner}/{name}/check-runs/{id}` | [`get_check_run`](/reference/api/checks/get-check-run/) |
284| `GET /repos/{owner}/{name}/check-runs/{id}/annotations` | [`list_check_run_annotations`](/reference/api/checks/list-check-run-annotations/) |
285| `POST /repos/{owner}/{name}/check-runs/{id}/rerequest` | [`rerequest_check_run`](/reference/api/checks/rerequest-check-run/) |
286| `GET /repos/{owner}/{name}/commits/{ref}/check-runs` | [`list_check_runs_for_ref`](/reference/api/checks/list-check-runs-for-ref/) |
287| `GET /repos/{owner}/{name}/commits/{ref}/check-suites` | [`list_check_suites_for_ref`](/reference/api/checks/list-check-suites-for-ref/) |
288| `GET /repos/{owner}/{name}/check-suites/{id}` | [`get_check_suite`](/reference/api/checks/get-check-suite/) |
289| `POST /repos/{owner}/{name}/check-suites/{id}/rerequest` | [`rerequest_check_suite`](/reference/api/checks/rerequest-check-suite/) |
290
291[`list_check_runs_for_ref`](/reference/api/checks/list-check-runs-for-ref/)
292gives each name's latest run and each workflow's latest run per event;
293`filter=all` gives every one. Narrow it with `check_name`, `status` and
294`app` (a reporter's slug; `actions` for workflow jobs).
295
296On the [MCP server](/reference/mcp/#workflow), the `workflow` tool has an
297action for each: `combined_status`, `list_statuses`, `set_status`,
298`list_check_runs`, `get_check_run`, `check_run_annotations`,
299`create_check_run`, `update_check_run`, `rerequest_check_run`,
300`list_check_suites`, `get_check_suite` and `rerequest_check_suite`.