# ci.sarif

The `ci.sarif` function uploads a SARIF file to Code Scanning, so findings from your own tools appear as alerts on
the pull request. Locally, it prints one line that says the file was not uploaded.

## Usage

```python
ci.sarif(path, category = "")
```

## Arguments

- **`path`**
  Required. The path of the SARIF file, as a string. A relative path resolves against the script's working directory.
- **`category`**

  (Optional) A name that separates results from different tools or components, as a string. Uploads that share a
  category replace each other, and uploads in different categories coexist.

## Returns

The return value is `None`.

## Behavior

- In CI, the file is uploaded to the repository's Code Scanning. The job needs `security-events: write`. Code
  Scanning is free on public repositories and requires GitHub Advanced Security on private ones.
- Locally, the call prints one line that names the file and the reason it was not uploaded: `ci.results.enabled is off`,
  `ci.enabled is off`, the fork-gate reason, or `no CI provider detected`.
- Under `pull_request_target` and `workflow_run`, the upload is held for a pull request from a fork, like comments and
  checks. See the [fork gate](/functions/automation/ci#fork-gate).
- The file is sent exactly as written, so it is not masked. Keep secrets out of the report.
- Uploads are opt-in. In CI the call is gated by `ci.results.enabled`, which is off by default. When it is off, the call
  warns, renders locally, and the script continues. See [gating](/functions/automation/ci#gating) and the [CI configuration](/cli/configuration/ci).

## Examples

### Upload a scanner report

```python
exec.run(["trivy", "config", "--format=sarif", "--output=trivy.sarif", "."])
ci.sarif("trivy.sarif", category = "trivy")
```

### Upload one report per component

```python
for component in ["vpc", "eks"]:
    report_dir = "build/" + component
    result = exec.run(["checkov", "--directory=components/terraform/" + component, "--output=sarif", "--output-file-path=" + report_dir], check = False)
    ci.sarif(report_dir + "/results_sarif.sarif", category = "checkov-" + component)
    if result.exit_code != 0:
        fail("Checkov failed for " + component)
```

## Errors

- A missing or non-string `path`, or a file that does not exist, fails the script.
- An API error or a missing permission fails the script.
- The file must exist and be readable even when uploads are disabled; Atmos reads it before checking the upload gate.

## Related

- [`ci`](/functions/automation/ci) describes the module and the shared behavior rules.
- [`ci.annotate`](/functions/automation/ci.annotate) marks individual lines without Code Scanning.
