## Depot CI

Depot CI executes GitHub Actions YAML workflows. The following tables list GitHub Actions syntax, triggers, and configuration and whether they're supported in Depot CI.

## Workflow-level configuration

| **Field** | **Purpose** | **Supported** |
| --- | --- | --- |
| `name` | Workflow display name | ✅ |
| `run-name` | Dynamic run title | ✅ |
| `on` | Workflow triggers | ✅ |
| `on.workflow_call` | Reusable workflow definition | ✅ |
| `on.workflow_call.inputs` | Reusable workflow inputs | ✅ |
| `permissions` | Token scopes | ✅ |
| `env` | Workflow environment variables | ✅ |
| `defaults` | Default settings (shell, working-directory) | ✅ |
| `concurrency` | Concurrency control | ✅ |
| `jobs` | Jobs definition | ✅ |

## Triggers (`on.*`)

| **Field** | **Event type** | **Supported** |
| --- | --- | --- |
| `on.<event_name>` | Event triggers | ✅ |
| `on.<event_name>.types` | Event trigger types | ✅ |
| `on.merge_group` | Merge queue triggers | ✅ |
| `on.push.branches` | Push branch filters | ✅ |
| `on.push.tags` | Push tag filters | ✅ |
| `on.pull_request` | Pull request triggers | ✅ |
| `on.pull_request.branches` | PR branch filters | ✅ |
| `on.pull_request_target` | Pull request triggers from the base branch context | ✅ |
| `on.pull_request_review` | Pull request review triggers | ✅ |
| `on.pull_request_review_comment` | Pull request review comment triggers | ✅ |
| `on.issue_comment` | Comments on issues and pull requests | ✅ |
| `on.deployment_status` | Deployment status triggers | ✅ |
| `on.*.paths` | Path filters | ✅ |
| `on.schedule` | Cron schedule triggers | ✅ |
| `on.workflow_call.inputs.*` | Reusable workflow inputs (type, default, required) | ✅ |
| `on.workflow_call.outputs` | Reusable workflow outputs | ✅ |
| `on.workflow_call.secrets` | Reusable workflow secrets definition | ✅ |
| `on.workflow_run` | Workflow run triggers | ✅ |
| `on.workflow_dispatch` | Manual dispatch triggers | ✅ |
| `on.workflow_dispatch.inputs` | Manual dispatch inputs | ✅ |
| `on.repository_dispatch` | Custom events sent through the GitHub API | ✅ |
| `on.repository_dispatch.types` | Custom event type filters | ✅ |

### Scheduled workflows

Use `on.schedule` to run a workflow on a cron schedule. Add the workflow to `.depot/workflows/` and merge it to your repository's default branch to activate the schedule. Scheduled workflows run from the default branch.

For example, save this workflow as `.depot/workflows/daily.yml` to run it daily at 02:00 UTC:

```
name: Daily task

on:
  schedule:
    - cron: '0 2 * * *'

jobs:
  daily:
    runs-on: depot-ubuntu-latest
    steps:
      - run: echo "Running the daily task"
```

Depot evaluates cron expressions in UTC and ignores the per-entry `timezone` setting.

Depot triggers scheduled workflows independently of GitHub's `schedule` event. We attempt to start scheduled workflows within one minute of their scheduled time, but we don't provide an official SLA for start times.

### Workflow run events

Use `workflow_run` to start a listener workflow from another workflow's events. The `on.workflow_run.workflows` filter accepts the triggering workflow's YAML `name`, Depot filename, or repository path.

Read the triggering workflow's fields from `github.event.workflow_run`:

| **Field** | **Value** |
| --- | --- |
| `name` | YAML workflow name. Defaults to `path` when no name is set, as in GitHub. Does not use `run-name`. |
| `path` | Repository-relative workflow path, such as `.depot/workflows/ci.yml`. Matches GitHub's `path`. |
| `basepath` | Depot-only field with the workflow filename, such as `ci.yml`. |

For `.depot/workflows/ci.yml` with `name: Build and test`, the payload has `name: Build and test`, `path: .depot/workflows/ci.yml`, and `basepath: ci.yml`. Without a `name`, `name` is `.depot/workflows/ci.yml`.

Use `name` to compare workflow names, `path` to compare repository paths, and `basepath` to compare filenames.

To also support older stored events, use this filename comparison:

```
if: ${{ (github.event.workflow_run.basepath || github.event.workflow_run.path || github.event.workflow_run.name) == 'ci.yml' }}
```

### Native GitHub stacked pull requests

Depot CI supports [native GitHub stacked pull requests](https://docs.github.com/en/pull-requests/tutorials/roll-out-stacked-prs) for `pull_request` workflows. Depot CI evaluates a stack's `branches` filter against its ultimate base branch, then runs the matching workflow for each pull request in the stack using that pull request's own merge ref.

For pull requests in a stack, `github.event.pull_request.stack` exposes the stack's `number`, `size`, `position`, `base.ref`, and `base.sha`. The value is `null` for a pull request that is not in a stack.

For ordinary pull requests without stack metadata, Depot CI continues to match `pull_request.branches` against the pull request's direct base branch.

### Pull request review events

`pull_request_review` starts a workflow when someone submits, edits, or dismisses a review. `pull_request_review_comment` starts a workflow when someone creates, edits, or deletes a comment on a pull request's diff. For comments in the pull request's conversation, use `issue_comment`.

Filter by activity with `types`:

```
on:
  pull_request_review_comment:
    types: [created, edited]
```

Without `types`, the workflow runs for every activity: `submitted`, `edited`, and `dismissed` for reviews, and `created`, `edited`, and `deleted` for review comments.

A review event starts a run only when the listening workflow is on your repository's default branch. The run uses the pull request's merge ref. Read the review or comment from `github.event`, for example `github.event.comment.body` and `github.event.pull_request.number`. As in GitHub Actions, `github.base_ref` and `github.head_ref` are empty for these events. Runs for pull requests from forks get a read-only `GITHUB_TOKEN` and no secrets. Review and review comment runs triggered by Dependabot get the same treatment.

### Repository dispatch events

`repository_dispatch` lets you trigger Depot CI workflows from outside GitHub by sending a custom event to the GitHub API — useful for kicking off a run from another system (for example, a deployment provider) without polling or running your own relay.

Subscribe to every dispatch, or filter by event type with `types`:

```
on:
  repository_dispatch:
    types: [deploy-succeeded]
```

GitHub only delivers `repository_dispatch` events against your repository's default branch, so the workflow that runs is the one on the default branch. The custom event type and any `client_payload` you send are available through the `github.event` context (`github.event.action` and `github.event.client_payload`), matching GitHub Actions.

## Job-level configuration (`jobs.<job_id>.*`)

| **Field** | **Purpose** | **Supported** | **Notes** |
| --- | --- | --- | --- |
| `jobs.<job_id>` | Job definition | ✅ |  |
| `jobs.<job_id>.name` | Job display name | ✅ |  |
| `jobs.<job_id>.needs` | Job dependencies / DAG | ✅ |  |
| `jobs.<job_id>.if` | Conditional job execution | ✅ |  |
| `jobs.<job_id>.runs-on` | Runner selection | ❌ | We respect Depot runner labels and treat non-Depot labels as `depot-ubuntu-latest`. |
| `jobs.<job_id>.permissions` | Job-scoped permissions | ✅ |  |
| `jobs.<job_id>.environment` | Deployment environments | ❌ |  |
| `jobs.<job_id>.concurrency` | Job-level concurrency | ✅ |  |
| `jobs.<job_id>.outputs` | Job outputs / cross-job data | ✅ |  |
| `jobs.<job_id>.env` | Job environment variables | ✅ |  |
| `jobs.<job_id>.defaults` | Job default settings | ✅ |  |
| `jobs.<job_id>.timeout-minutes` | Job timeout | ✅ |  |
| `jobs.<job_id>.strategy` | Matrix strategy | ✅ |  |
| `jobs.<job_id>.[strategy.fail]` | Matrix fail-fast | ✅ |  |
| `jobs.<job_id>.strategy.max-parallel` | Matrix parallel limit | ✅ |  |
| `jobs.<job_id>.continue-on-error` | Allow job failure | ✅ |  |
| `jobs.<job_id>.container` | Job container | ✅ |  |
| `jobs.<job_id>.services` | Service containers | ✅ |  |
| `jobs.<job_id>.uses` | Reusable workflow call | ✅ |  |
| `jobs.<job_id>.with` | Reusable workflow inputs | ✅ |  |
| `jobs.<job_id>.secrets` | Reusable workflow secrets | ✅ |  |
| `jobs.<job_id>.secrets.inherit` | Inherit all secrets | ✅ |  |
| `jobs.<job_id>.steps` | Step definitions | ✅ |  |
| `jobs.<job_id>.snapshot` | Custom images from sandbox snapshots | ✅ | See [Build and use custom images with Depot CI](/content/docs/ci/how-to-guides/custom-images/index.html) |

## Step-level configuration

| **Field** | **Purpose** | **Supported** |
| --- | --- | --- |
| `steps[*].id` | Step identifier | ✅ |
| `steps[*].name` | Step display name | ✅ |
| `steps[*].if` | Conditional step execution | ✅ |
| `steps[*].uses` | Action reference | ✅ |
| `steps[*].run` | Shell command execution | ✅ |
| `steps[*].shell` | Shell type (bash, pwsh, python) | ✅ |
| `steps[*].with` | Action inputs | ✅ |
| `steps[*].env` | Step environment variables | ✅ |
| `steps[*].working-directory` | Step working directory | ✅ |
| `steps[*].continue-on-error` | Allow step failure | ✅ |
| `steps[*].timeout-minutes` | Step timeout | ✅ |

## Expressions

### Contexts

| **Context** | **Purpose** | **Supported** |
| --- | --- | --- |
| `github` | Event payload, repo, actor | ✅ |
| `env` | Environment variables | ✅ |
| `vars` | Repository/org variables | ✅ |
| `secrets` | Secret values | ✅ |
| `needs` | Dependent job outputs | ✅ |
| `strategy` | Matrix strategy info | ✅ |
| `matrix` | Current matrix values | ✅ |
| `steps` | Prior step outputs | ✅ |
| `job` | Current job info | ✅ |
| `runner` | Runner info | ✅ |
| `inputs` | Workflow inputs | ✅ |
| `depot` | Depot dispatch identity | ✅ |

### Functions

| **Function** | **Purpose** | **Supported** |
| --- | --- | --- |
| `always()` | Run regardless of status | ✅ |
| `success()` | Run if no failures | ✅ |
| `failure()` | Run if any failure | ✅ |
| `cancelled()` | Run if cancelled | ✅ |
| `case()` | Conditional value select | ✅ |
| `hashFiles()` | File hashing for caching | ✅ |
| `contains()` | String/array contains | ✅ |
| `startsWith()` | String prefix check | ✅ |
| `endsWith()` | String suffix check | ✅ |
| `format()` | String formatting | ✅ |
| `join()` | Array to string | ✅ |
| `toJSON()` | Object to JSON | ✅ |
| `fromJSON()` | JSON to object | ✅ |

## Action types

| **Type** | **Description** | **Supported** |
| --- | --- | --- |
| JavaScript | Node 12/16/20/24 actions | ✅ |
| Composite | Composite actions | ✅ |
| Docker | Container actions | ✅ |

JavaScript actions that declare `runs.using: node20`, `node16`, or `node12` run on Node.js 24, matching GitHub-hosted runners. Actions that declare `runs.using: node24` are unchanged. To run those actions on Node.js 20 temporarily, set `ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION` to `'true'` in the workflow, job, or step `env`. Depot will remove this opt-out to match GitHub and will announce the date in the [changelog](/content/changelog/index.html).

This example applies the opt-out to one job:

```
jobs:
  build:
    runs-on: depot-ubuntu-24.04
    env:
      ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: 'true'
    steps:
      - uses: actions/checkout@v4
```

This runtime is separate from the `node` on `PATH` that `run:` steps use.

## GitHub checks

Depot CI automatically reports GitHub checks for each job in a workflow run. For more information, see [GitHub checks](/content/docs/ci/observability/github-checks/index.html).

## Reusable workflows from other repositories

You can call a reusable workflow from another repository using a job-level `uses` reference, such as `owner/repo/.github/workflows/build.yml@v1`. Depot CI supports nested calls, matrix jobs, inputs, and outputs.

Use a full 40-character commit SHA or a version tag such as `v1`, `v1.2`, or `v1.2.3`. Branch references such as `main` and abbreviated commit SHAs aren't supported. A version-looking reference must resolve to a tag, not a branch.

For private or internal source repositories, the caller must be a trusted private repository in the same GitHub organization. Grant the Depot Code Access GitHub App access to the source repository.

Depot resolves authored `.github/workflows/` paths to files in `.depot/workflows/` in the source repository. You can also reference `.depot/workflows/` directly.

## Limitations

### GitHub-only event triggers

The following events are GitHub-specific concepts that aren't applicable to Depot CI workflows, such as Discussions, Pages, and issue events other than comments.

| **Field** | **Event type** | **Supported** |
| --- | --- | --- |
| `on.branch_protection_rule` | GitHub specific event trigger | ❌ |
| `on.check_run` | GitHub specific event trigger | ❌ |
| `on.check_suite` | GitHub specific event trigger | ❌ |
| `on.create` | GitHub specific event trigger | ❌ |
| `on.delete` | GitHub specific event trigger | ❌ |
| `on.deployment` | GitHub specific event trigger | ❌ |
| `on.discussion` | GitHub specific event trigger | ❌ |
| `on.discussion_comment` | GitHub specific event trigger | ❌ |
| `on.fork` | GitHub specific event trigger | ❌ |
| `on.gollum` | GitHub specific event trigger | ❌ |
| `on.image_version` | GitHub specific event trigger | ❌ |
| `on.issues` | GitHub specific event trigger | ❌ |
| `on.label` | GitHub specific event trigger | ❌ |
| `on.milestone` | GitHub specific event trigger | ❌ |
| `on.page_build` | GitHub specific event trigger | ❌ |
| `on.public` | GitHub specific event trigger | ❌ |
| `on.pull_request_comment` | GitHub specific event trigger | ❌ |
| `on.registry_package` | GitHub specific event trigger | ❌ |
| `on.release` | GitHub specific event trigger | ❌ |
| `on.status` | GitHub specific event trigger | ❌ |
| `on.watch` | GitHub specific event trigger | ❌ |

### Pull request workflows triggered from forks

GitHub allows `pull_request` and `pull_request_target` workflows to run when triggered from forked repositories. Support for this is planned.

### Runner labels

Only Depot `runs-on` labels are supported. Nonstandard labels become `depot-ubuntu-latest` and expressions are preserved as-is. For Depot CI sandbox sizes and labels, see [Depot CI sandboxes](/content/docs/ci/overview#depot-ci-sandboxes/index.html).

### Permissions

The following workflow permission keys are supported: `actions`, `checks`, `code-quality`, `contents`, `id-token`, `issues`, `packages`, `pull-requests`, `security-events`, `statuses`.

Depot ignores unsupported permission keys when configuring `GITHUB_TOKEN`; they don't cause workflow validation to fail. Operations that require those permissions can fail at runtime. Use `pull-requests`, with a hyphen, to request pull request access.

To use `issues: read` or `issues: write`, your Depot Code Access GitHub App installation must have the corresponding Issues permission. If the installation hasn't granted the requested level, Depot can create the job token without `issues`; operations that require that permission won't work until you approve it in the GitHub App installation settings.

The `code-quality` permission must be requested explicitly. It isn't included in `read-all` or `write-all`, which retain the existing permission set so older Depot Code Access GitHub App installations don't fail token creation before the new permission is approved.

#### GitHub Packages authentication

Pushing and pulling from GitHub Packages registries using `secrets.GITHUB_TOKEN` doesn't work in Depot CI. GitHub's package registry servers only accept personal access tokens for authentication, not GitHub App tokens. This is a known GitHub limitation (see discussions: [Read GitHub Packages permission for GitHub App](https://github.com/orgs/community/discussions/24636) and [Using GitHub Packages with GitHub Apps](https://github.com/orgs/community/discussions/26920)).

For container images, you can use another registry instead, such as [Depot Registry](/content/docs/registry/overview/index.html). When using `depot/build-push-action`, replace the GHCR login and push steps with the `save` input:

```
- uses: depot/build-push-action@v1
  with:
    context: .
    project: <your-depot-project-id>
    save: true
    save-tags: |
      latest
      ${{ github.sha }}
```

See the [Depot Registry quickstart](/content/docs/registry/quickstart/index.html) for pulling images and other usage.

This limitation applies to all GitHub Packages registries, not just the container registry. If you need to keep using a GitHub Packages registry, you can authenticate with a GitHub [personal access token](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#authenticating-with-a-personal-access-token-classic) with `write:packages` scope, [stored as a Depot CI secret](/content/docs/ci/how-to-guides/manage-secrets-and-variables/index.html).

Note that a PAT is a long-lived credential scoped to a user account, so consider the security implications of storing and rotating it.
