---
url: /guide/ci.md
description: >-
  Deploy from CI with a personal access token, wait for events with duploy
  until, and script with JSON output.
---

# CI and automation

## Access tokens

```bash
duploy token create github-actions    # printed once
duploy tokens
duploy token rm github-actions
```

A personal access token starts with `dpat_`. Pass it as `DUPLOY_TOKEN`; it
does not rotate, so parallel jobs can share it. `--expires-days` (1 to 365)
sets an expiry. Resetting your password revokes all of them.

## GitHub Actions

```yaml
- name: Install duploy
  run: curl -fsSL https://panel.duploy.dev/cli/install.sh | sh
- name: Deploy
  env:
    DUPLOY_TOKEN: ${{ secrets.DUPLOY_TOKEN }}
    DUPLOY_ORG: acme
    DUPLOY_PROJECT: shop
  run: |
    export PATH="$HOME/.local/bin:$PATH"
    duploy deploy web --timeout 15m
    duploy logs web --tail 50
```

Long operations (build, deploy, backup, restore, import, run) stream their log
and wait by default. `--no-wait` returns as soon as the job is accepted;
`--timeout` bounds the wait.

## Waiting for an event

When a push already triggers the deploy, wait for it instead of starting
another one:

```bash
duploy until build.success --sha "$GITHUB_SHA"
duploy until deploy.success,deploy.failed --service web --timeout 10m
duploy until service.running --service web
duploy until db.running --db cache
duploy until domain.tls.issued --host shop.example.com
```

`until` returns on the first matching event. A `*.failed` or `*.canceled`
match exits 1.

## Output and exit codes

| Flag | Effect |
|---|---|
| `--json` | Raw API JSON on stdout, errors on stderr |
| `-q` | Ids and status only |
| `--wide` | Do not truncate tables |
| `NO_COLOR` | No colours |

| Exit code | Meaning |
|---|---|
| `0` | Success |
| `1` | The job failed, or the API returned an error |
| `2` | Usage error or no session |
| `124` | Timeout |
