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

# CI and deploys

> What CI checks, how each app reaches production, and how to roll back.

## CI

`.github/workflows/ci.yml` runs on every pull request and every push to main. A pull request that fails a check does not merge.

| Job | Checks |
| - | - |
| **Types, lint, tests, build** | Build, typecheck, lint and tests against a real Postgres 17 |
| **Accessibility on the public pages** | axe on the main pages, and Lighthouse targets: performance 90, accessibility 95, SEO 100 |
| **Secret scan** | gitleaks over the full history |
| **Terraform** | `fmt` and `validate` |
| **API image builds** | The Docker build |
| **Deploy the API** | Only on main, after every other job passes |

The tenant isolation tests need the real database. They try to read another organization's requests and must fail.

## The web app

Vercel deploys the web app from GitHub automatically.

* **Push to main.** Production at [www.oncoeverything.com](http://www.oncoeverything.com).
* **Pull request.** A preview deploy with its own address.

Vercel's environment variables are in Terraform (`vercel.tf`): `API_URL` for production and preview, and `NEXT_PUBLIC_SITE_URL` for production. A changed variable reaches the site only with the next deploy.

## The API

The **Deploy the API** job:

**1. Signs in to AWS**

Through GitHub's OIDC provider, as the `oncoeverything-deploy` role. There is no access key anywhere.

**2. Builds and pushes the image**

The tag is the first seven characters of the commit. The ECR repository does not let a push overwrite a tag, so a tag always means the same image.

**3. Registers a task definition and rolls the service**

The new task runs migrations, then opens its port. The old task serves until the new one passes the health check.

**4. Waits for the service to be stable**

If the new task never becomes healthy, the service's circuit breaker rolls back to the previous one.

Check a deploy:

```bash theme={null}
AWS_PROFILE=onco aws ecs describe-services --cluster oncoeverything \
  --services oncoeverything-api \
  --query "services[0].deployments[].[status,taskDefinition,rolloutState]" \
  --output text
```

## The handbook

Mintlify deploys the handbook from the `handbook/` folder on each push to main.

## Roll back

**The web app.** In the Vercel dashboard, open Deployments. Find the last good deployment. Promote it.

**The API.** Point the service at the previous task definition revision:

```bash theme={null}
AWS_PROFILE=onco aws ecs update-service --cluster oncoeverything \
  --service oncoeverything-api \
  --task-definition oncoeverything-api:<previous revision>
```

ECR keeps the last ten images.

> [!WARNING]
>
> Neither rollback undoes a database migration. Write a new migration that fixes it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.