# ci.check

The `ci.check` function reports a named status on the current commit and returns a handle that you update as the
work moves from pending to a final state. Locally, each state change prints on stderr.

## Usage

```python
check = ci.check(name, state = "pending", description = "", url = "")
check.update(state, description = "", url = "")
```

## Arguments

- **`name`**
  Required. The name of the status, as a string. On GitHub Actions it is the status context shown in the pull request checks list.
- **`state`**

  (Optional) The state, as a string: `"pending"` (the default), `"in_progress"`, `"success"`, `"failure"`,
  `"error"`, or `"cancelled"`.
- **`description`**
  (Optional) A short line shown next to the status. On GitHub Actions it is truncated to 140 characters.
- **`url`**
  (Optional) A link for the status. It defaults to the URL of the current run.

The `update` method takes the same `state`, `description`, and `url` arguments. Its `state` is required.

## Returns

A handle with these attributes and one method:

- **`name`**
  The name of the status, as a string.
- **`state`**
  The current state, as a string. It changes each time you call 
  `update`
  .
- **`id`**

  The identifier of the status. `update` addresses the same status by this identifier, so two checks that share a
  name stay separate.
- **`url`**

  The link attached to the status, as a string. It is the `url` you passed, or the URL of the current run when you
  passed none, and it changes when you pass a new `url` to `update`.
- **`update(state, description = "", url = "")`**
  Sets a new state on the same status and returns 
  `None`
  .

## Behavior

- On GitHub Actions, a check is a commit status, not a Checks API check run. It has a name, a state, a short
  description, and a link, and it has no body. Put details in [`ci.summary`](/functions/automation/ci.summary) or
  [`ci.comment`](/functions/automation/ci.comment). Posting needs `statuses: write`.
- GitHub commit statuses have four states. `"pending"` and `"in_progress"` both report as `pending`, `"success"` reports
  as `success`, `"failure"` reports as `failure`, and `"error"` and `"cancelled"` both report as `error`. The handle
  keeps the state you passed.
- Locally, each call prints the name, state, and description on stderr and nothing is posted.
- Checks are opt-in. In CI the call is gated by [`ci.checks.enabled`](/cli/configuration/ci/checks), which is off by
  default. When it is off, the call warns, renders locally, and the script continues.
- Under `pull_request_target` and `workflow_run`, checks are held only when the pull request comes from a fork
  (`ci.context.pr.fork`), unless `ci.allow_unsafe_fork_execution` is set. A held call warns and renders locally
  instead. See the [fork gate](/functions/automation/ci#fork-gate).
- The description is masked before it leaves the process.

## Examples

### Report progress

```python
check = ci.check("deploy / prod", state = "in_progress", description = "Applying vpc")
result = exec.run(["atmos", "terraform", "deploy", "vpc", "--stack=prod"], check = False)
if result.exit_code != 0:
    check.update("failure", description = "Deployment failed")
    fail("deployment failed")
check.update("success", description = "Applied vpc")
```

### Report a failure with a link

```python
check = ci.check("lint")
result = exec.run(["tflint"], check = False, output = "capture")
if result.exit_code != 0:
    check.update("failure", description = "tflint found issues", url = ci.context.run_url)
else:
    check.update("success")
```

## Errors

- An unknown `state` fails with an argument error that names `ci.check`.
- An API error, a missing token, or a commit that does not exist fails the script. A gated-off call never fails.

## Related

- [`ci`](/functions/automation/ci) describes the module and the shared behavior rules.
- [CI status checks](/cli/configuration/ci/checks) configures the native statuses that Atmos reports for commands.
