GitHub: Report a run's status
Turns a run’s lifecycle event into a GitHub commit status: run.started posts pending, run.succeeded success, run.failed failure and run.cancelled error.
- Kind:
github.report_run_status - Palette: Integrations, under GitHub
- Credential: a credential of kind
bearer, named incredential - Other GitHub actions: Set commit status
When to use
Section titled “When to use”- A handler that reports every run of a workflow back to the commit that started it, with no expression written by hand.
- Runs the automatic status reporting doesn’t cover, such as ones you submit yourself with
repoandshain their input.
A waiting run (run.awaiting, run.wait_expired) posts pending. For a run started by a
handler or a trigger step, see which runs it reports.
Connection (with)
Section titled “Connection (with)”| Field | Required | Description |
|---|---|---|
api_base |
no | Set this for GitHub Enterprise. Omit for github.com. For example: https://api.github.com. |
context |
no | The check’s name on the commit. One context per name, so two pipelines reporting on the same commit need two. Defaults to hyperspool. For example: hyperspool/ci. |
Input (input)
Section titled “Input (input)”| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | The lifecycle event type. Bind the whole envelope instead of the individual fields: input: {“$expr”: “input”}. |
payload |
object | yes | The lifecycle payload. Needs trigger.repo and trigger.sha, so gate the handler on both: –when ‘has(event.payload.trigger.repo) && has(event.payload.trigger.sha)’. |
Settings
Section titled “Settings”Beside with and input in the node’s config.
| Field | Type | Required | Description |
|---|---|---|---|
credential |
string | yes | Name of the project credential the action authenticates with. |
fail_on_error_status |
boolean | no | Treat any 4xx/5xx as a failure. On by default: an action either did its job or did not. Default true. |
optional_when_untrusted |
boolean | no | Run without the credential when the run is untrusted (a fork pull request), instead of failing. The credential is still withheld. |
retry_on |
array | no | Status codes that fail the node instead of returning, so its retry: policy applies (e.g. [429, 503]). |
Output
Section titled “Output”The HTTP response. The reply is under body: nodes.<id>.output.body.<field>.
| Field | Type | Description |
|---|---|---|
status |
integer | The HTTP status code. |
headers |
object | The response headers. |
body |
object | The response body, parsed as JSON when it is JSON. |
body.context |
string | |
body.id |
integer | |
body.state |
string | |
body.target_url |
string | |
body.url |
string | The status on the API. |
How it runs
Section titled “How it runs”- On an agent with the
connectorcapability. The managed environments have one, so this needs no agent of your own. - One
POSTrequest to an address built fromwith. - Any 4xx or 5xx fails the step, unless
fail_on_error_statusisfalse.retry:asks again after a 5xx, a 401, 408, 409, 423, 425 or 429, or a 4xx withRetry-After, and not after any other 4xx, which would get the same answer.
Example
Section titled “Example”As a graph whose trigger takes every run lifecycle event:
version: hyperspool-graph/v1nodes: - id: on_run type: trigger config: { event: run.* } - id: report type: github.report_run_status if: "has(input.payload.trigger.repo) && has(input.payload.trigger.sha)" config: credential: forge with: { context: hyperspool/ci } input: { $expr: "input" }edges: - { from: on_run, to: report }input: { $expr: "input" } hands the action the whole event, and it reads
payload.trigger.repo, payload.trigger.sha and payload.run_url from it. The if: skips
runs with no commit behind them, such as a spool submit without repo and sha in its
input, or a delivery that names a repo without a commit (a pull request comment, an issue).
The same binding works as a handler, which needs no graph of its own:
spool credential set forge --kind bearer # a token with repo:status
spool handler set forge-status \ --on run.started,run.succeeded,run.failed,run.cancelled \ --when 'has(event.payload.trigger.repo) && has(event.payload.trigger.sha)' \ --node github.report_run_status \ --config '{"credential":"forge","with":{"context":"hyperspool/ci"},"input":{"$expr":"input"}}'Which runs it reports
Section titled “Which runs it reports”A run’s lifecycle event carries trigger.repo and trigger.sha when its input has top-level
repo and sha fields: the builds spool repo connect starts, and a run you submit with
--input '{"repo": "owner/name", "sha": "<full sha>"}'. A run started by spool spawn or a
call keeps only the fields that match what the run at the head of its chain was given, so it
can’t name another commit, and a fork’s builds post nothing, since their handlers run untrusted
with no credential. A run that a handler or a trigger step started directly never reaches
handlers; end that workflow with a set_commit_status step.
A cancelled run posts error because a check left pending never resolves, and branch protection
would then block the merge with nothing to click. run.wait_withdrawn posts the run’s ending,
which its status carries, since that delivery can land after the ending’s own. One context
is one check on the commit, so two workflows reporting on the same commit need two contexts.
See Connectors for credentials and versions, and the node reference for every other node.