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

# CI configuration

> Supported fields, defaults, and the GitHub Actions subset for run.cloud CI

# CI configuration

run.cloud CI loads config from the commit SHA in this order:

1. **Native** `.runcloud/ci.yml` (or `.yaml` / `.json`) if present
2. **Opted-in jobs** in `.github/workflows/*.{yml,yaml}` (`runs-on: runcloud`)

Jobs from both sources are **merged**. Names must be unique.

## Native `.runcloud/ci.yml`

Use this when you want a dedicated file without GitHub Actions syntax:

```yaml theme={null}
# .runcloud/ci.yml
name: my app

jobs:
  unit:
    image: node:22
    cpu: 1
    memory: 2048
    paths:
      - src/**
      - package.json
    secrets:
      - default
    env:
      CI: "true"
    steps:
      - run: npm ci
      - run: npm test
        workdir: .
```

### Job fields (native)

| Field             | Required | Default               | Description                                            |
| ----------------- | -------- | --------------------- | ------------------------------------------------------ |
| `image`           | no       | `runcloud/agent-base` | OCI image for the sandbox                              |
| `cpu`             | no       | `1`                   | vCPU cores                                             |
| `memory`          | no       | `2048`                | Memory in MiB                                          |
| `paths`           | no       | (none — always run)   | Glob list; skip with green check if no match           |
| `secrets`         | no       | (none)                | Org [secret group](/sandboxes/secrets) names to inject |
| `secretNames`     | no       | (none)                | Individual secret names from the org store             |
| `env`             | no       | (none)                | Static environment variables (applied after secrets)   |
| `steps`           | **yes**  | —                     | Non-empty list of steps                                |
| `steps[].run`     | **yes**  | —                     | Shell command                                          |
| `steps[].workdir` | no       | repo root             | Directory relative to the repository root              |

Check Run name: `run.cloud / <job-key>`.

## GitHub Actions subset (`gha-subset`)

Opt-in jobs under `.github/workflows/` support a **documented subset** of
GitHub Actions workflow syntax. Unsupported constructs on an opted-in job fail
the check `run.cloud / config` with an explicit error (fail closed).

### Opt-in

```yaml theme={null}
runs-on: runcloud
# or: run.cloud | run-cloud | [self-hosted, runcloud]
```

### Supported

| Construct                                  | Notes                                            |
| ------------------------------------------ | ------------------------------------------------ |
| `runs-on: runcloud` (etc.)                 | Required to claim the job                        |
| `container: image` or `container.image`    | Sandbox image                                    |
| `image:`                                   | Same as native (if your linter allows it)        |
| `cpu` / `memory`                           | Native-style extensions                          |
| `env.RUNCLOUD_CPU` / `env.RUNCLOUD_MEMORY` | **Preferred** GHA-valid form for resources       |
| `paths` or `env.RUNCLOUD_PATHS`            | Path globs (`RUNCLOUD_PATHS` is comma-separated) |
| `on.pull_request.paths` / `on.push.paths`  | Applied to jobs that do not set their own paths  |
| `steps[].run`                              | Including `\|` block scalars                     |
| `working-directory`                        | Alias of `workdir`                               |
| `uses: actions/checkout@…`                 | Ignored (platform clones the SHA)                |
| `secrets: [group, …]`                      | Org secret groups                                |
| `env: NAME: ${{ secrets.NAME }}`           | Org secret by name                               |
| `env: KEY: static`                         | Static env                                       |

### Not supported (error on opted-in jobs)

| Construct                             | Notes                                   |
| ------------------------------------- | --------------------------------------- |
| `uses:` other than `actions/checkout` | No marketplace / composite actions yet  |
| `strategy` / `matrix`                 | —                                       |
| `services:`                           | —                                       |
| `needs:`                              | Jobs run independently                  |
| Expressions in `run:`                 | e.g. `${{ github.sha }}`                |
| Interpolated secret env               | Only a pure `${{ secrets.NAME }}` value |
| GitHub Actions secrets store          | Values come from the run.cloud org only |

Jobs that do **not** opt in are never validated against this list. They remain
normal GitHub Actions jobs.

### GHA-valid resource and path form

GitHub’s workflow schema (and tools like actionlint) reject unknown job keys
such as `cpu`, `memory`, and `paths`. Prefer env-based extensions:

```yaml theme={null}
jobs:
  unit:
    runs-on: runcloud
    container: node:22
    env:
      RUNCLOUD_CPU: "1"
      RUNCLOUD_MEMORY: "2048"
      RUNCLOUD_PATHS: "src/**,package.json"
      CI: "true"
    steps:
      - run: npm test
```

`RUNCLOUD_*` keys are configuration for run.cloud. They are **not** exported
into the guest environment for your steps.

## Defaults

| Setting     | Default                               |
| ----------- | ------------------------------------- |
| Image       | `runcloud/agent-base`                 |
| CPU         | `1` vCPU                              |
| Memory      | `2048` MiB                            |
| Shell       | `/bin/sh -c`                          |
| Checkout    | Shallow fetch of the exact commit SHA |
| Path filter | Off (run always) unless paths are set |

## Check Run names

| Situation           | Check name                                     |
| ------------------- | ---------------------------------------------- |
| Job `unit`          | `run.cloud / unit`                             |
| Invalid config file | `run.cloud / config` (failed)                  |
| Path filter miss    | `run.cloud / <job>` success, title **Skipped** |

## Disabling a repository

After the GitHub App is installed, you can disable CI for a single repo from
the API or dashboard controls for that installation so webhooks stop enqueueing
jobs without uninstalling the App.

## Limits and billing

Sandbox size and duration follow your org’s sandbox product limits. Usage is
metered as Firecracker sandbox time for the org bound to the installation. See
[Access Control and Metering](/billing/access-control).

## Full examples

See [GitHub workflows](/ci/github-workflows) and [Secrets in CI](/ci/secrets).
