# 13. CI/CD & Environments

## Environments

| Environment | Purpose | URL | Database |
|------------|---------|-----|----------|
| **Local dev** | Development and debugging | `http://localhost:3007` (dev.sh) | `../data/sasha.db` |
| **Docker local** | Production-like testing | `http://localhost:3006` (docker-local.sh) | Volume-mounted |
| **Sliplane** | Customer deployments | Per-customer domain | Volume-persisted |
| **AWS ECS** | sasha1 deployment | `sasha1.hirebest.ai` | EFS-persisted |

## Local Development

### Setup

```bash
# Install dependencies
cd claudecodeui && npm install

# Create local data directories
mkdir -p data/logs data/projects data/config

# Configure environment
# Edit claudecodeui/.env.local with absolute paths
```

### Running

```bash
./dev.sh          # UI + server with hot reload → http://localhost:3007
./docker-local.sh # Production-like Docker → http://localhost:3006
```

### Key Environment File: `.env.local`

| Variable | Purpose | Example |
|----------|---------|---------|
| `SHARED_ROOT` | Base for all paths | `/path/to/sasha` |
| `DOCS_PATH` | Knowledge docs | `$SHARED_ROOT/deployed-md-files/docs` |
| `DB_PATH` | SQLite database | `../data/sasha.db` |
| `PROJECTS_PATH` | Project directories | `$SHARED_ROOT/data/projects` |
| `EXECUTION_LOG_FILE` | Execution logs | `../data/logs/executions.jsonl` |
| `SCHEDULER_LOG_FILE` | Scheduler logs | `../data/logs/scheduler.jsonl` |

### Local Login
- Username: `lindsay` / Password: `password`

### Validating Paths

```bash
cd claudecodeui
node --env-file=.env.local -e "import('./server/utils/paths.js').then(m => { 
  console.log('SHARED_ROOT:', m.SHARED_ROOT); 
  console.log('DOCS_ROOT:', m.DOCS_ROOT); 
})"
```

## Docker Build

### Build Scripts

| Script | Purpose |
|--------|---------|
| `./dev.sh` | Local dev (UI + server, hot reload) |
| `./docker-local.sh` | Local Docker build and run |
| `./docker-build-ghcr.sh` | Release image to GHCR (bumps VERSION, commits, pushes) |

### Dockerfile: `claudecodeui/Dockerfile.sliplane`

Multi-stage build:

```
Stage 1: base         → Node 20 + build tools
Stage 2: deps         → npm install (cached)
Stage 3: assets       → Static files and docs
Stage 4: mcp-*        → 14 parallel MCP package builds
Stage 5: builder      → Vite production build
Stage 6: runner        → Final image (Alpine)
```

**Key inclusions:**
- Claude CLI v2.1.81 (installed globally)
- Vercel CLI
- Playwright Chromium (shared with Puppeteer)
- rclone
- All MCP packages
- Documentation from `deployed-md-files/`

### Build Trigger Rules

```
claudecodeui/ changes  → Triggers Docker build
deployed-md-files/     → Does NOT trigger builds (included in image)
.github/workflows/     → Triggers builds
VERSION                → Triggers builds
docs/ changes          → Does NOT trigger builds
```

## GitHub Actions

### Workflows

| Workflow | File | Trigger | Purpose |
|----------|------|---------|---------|
| Docker Build | `docker-build.yml` | Tags `v*`, path changes | Build and push to GHCR |
| Docker Base | `docker-base.yml` | Manual | Build base image layer |
| CI | `ci.yml` | PRs | Lint, test, build validation |
| MCP Packages | `mcp-packages.yml` | MCP path changes | Build MCP npm packages |
| DocSidecar | `docsidecar-docker-build.yml` | Sidecar changes | Build sidecar image |
| CodeQL | `codeql.yml` | PRs, schedule | Security analysis |
| Semgrep | `semgrep.yml` | PRs | SAST scanning |
| OSV | `osv.yml` | PRs | Dependency vulnerability scan |
| Container Scan | `container-scan.yml` | Builds | Docker image vulnerability scan |
| Control Panel CI | `control-panel-ci.yml` | Control panel changes | Separate CI |

### Container Registry

| Property | Value |
|----------|-------|
| Registry | GitHub Container Registry (ghcr.io) |
| Image | `ghcr.io/context-is-everything/sasha-ai-knowledge-management` |
| Tags | `latest`, semantic versions, commit SHAs |
| Platforms | linux/amd64, linux/arm64 |

## Build Commands

```bash
# Frontend lint (server only — ESLint)
cd claudecodeui && npm run lint

# Frontend build validation
cd claudecodeui && npx vite build

# Run tests
cd claudecodeui && npm run test:integration

# Docker build (local)
docker build -f claudecodeui/Dockerfile.sliplane -t sasha-studio .

# Release build
./docker-build-ghcr.sh patch  # bumps VERSION, commits, pushes, triggers GH Actions
```

## Version Management

- **VERSION file:** Contains semver (e.g., `1.0.1363`)
- **Bump:** `./docker-build-ghcr.sh patch|minor|major`
- **Process:** Bump → git commit → git tag → git push → GitHub Actions builds

## Migration Process

### Database Migrations

Migrations run automatically on server startup in `db.js`:
- `ALTER TABLE ADD COLUMN` for new columns
- `CREATE TABLE IF NOT EXISTS` for new tables
- No down-migration support
- No migration versioning table (uses try/catch on ALTER)

### Deployment Process

**Sliplane:**
1. Push to main → GitHub Actions builds image
2. Sliplane auto-deploys on image update (or manual trigger)
3. Container starts, runs migrations, serves on port 3005

**AWS ECS:**
1. Image built and pushed to GHCR
2. Copy to ECR: `crane copy ghcr.io/.../:latest <ecr>:latest --platform linux/amd64`
3. Force new deployment: `aws ecs update-service --force-new-deployment`
4. ECS rolls out new task, health check validates

## Release Gates

| Gate | Tool | Blocking? |
|------|------|-----------|
| ESLint (server) | `npm run lint` | Yes (CI blocks) |
| Vite build | `npx vite build` | Yes |
| Integration tests | `npm run test:integration` | TBD |
| CodeQL | GitHub CodeQL | Advisory |
| Semgrep | Semgrep | Advisory |
| OSV scan | OSV Scanner | Advisory |
| Container scan | Trivy/Grype | Advisory |

## Environment Variables

See [17-iam-and-secrets.md](./17-iam-and-secrets.md) for the complete environment variable inventory.
