---
name: iamfourh2e/deployment
source: https://app.decimal.ai/s/iamfourh2e-deployment@1/SKILL.md
source_sha256: 3ca26d5ed959
---

# Deployment Skill

Covers the full CI/CD pipeline from local build to production deployment.

## CI Pipeline (GitHub Actions)

File: `.github/workflows/ci.yml`

### Jobs

| Job | Trigger | Purpose |
|---|---|---|
| **check** | push/PR to main | `cargo fmt --check` → `clippy` → `build --release` → `test` |
| **test** | after check | Start PostgreSQL service → build server → run Ruby integration tests |
| **docker** | after check | Build Docker image → push to GHCR (on push to main) |

### Check Job
```
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo build --release
cargo test --release
```

### Integration Test Job
- Spins up `postgres:16-alpine` service container
- Creates `.env` with CI secrets
- Starts the compiled server binary
- Waits for gRPC health check (30s timeout)
- Runs `ruby scripts/test_all.rb`

### Docker Job
- Multi-stage build
- Pushes to `ghcr.io/<repo>` with tags: `latest`, `main`, `<sha>`
- BuildKit cache (GHA)

## Dockerfile

```dockerfile
# Stage 1: Builder
FROM rust:1.88-slim AS builder
# Install protobuf + SSL + pkg-config
# Copy manifests for dep caching
# Copy source + build --release

# Stage 2: Runtime
FROM debian:bookworm-slim
# Install ca-certificates + curl
# Non-root user (app)
# Copy binary from builder
# EXPOSE 50050 9090 9091
# CMD ["server"]
```

### Build Optimizations
- Dep caching: copy `Cargo.toml`/`Cargo.lock` first, dummy `main.rs`
- BuildKit cache mounts for cargo registry/git/target
- Slim runtime image (~80MB)

## Environment Variables

### Required (Backend)
```
DATABASE_URL, JWT_SECRET, JWT_ACCESS_EXPIRY_SECS, JWT_REFRESH_EXPIRY_SECS,
GRPC_HOST, GRPC_PORT, RESEND_API_KEY, EMAIL_FROM, EMAIL_FROM_NAME,
FRONTEND_URL, CORS_ORIGINS, METRICS_PORT, WS_PORT,
BAKONG_EMAIL, BAKONG_TOKEN, BAKONG_ACCOUNT_ID, BAKONG_MERCHANT_NAME,
BAKONG_MERCHANT_CITY, KHR_EXCHANGE_RATE, SUPER_ADMIN_EMAIL,
SUPER_ADMIN_USERNAME, SUPER_ADMIN_PASSWORD
```

### Optional
```
PLASGATE_PRIVATE_KEY, PLASGATE_SECRET_KEY, TELEGRAM_BOT_TOKEN,
TELEGRAM_GATEWAY_TOKEN, GOOGLE_CLIENT_ID, ALERT_CHAT_ID, REDIS_URL
```

### Frontend (.env)
```
VITE_API_URL=http://localhost:50050
VITE_GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
```

## Cloud Run Deployment

```bash
gcloud run deploy anachak \
  --image ghcr.io/khemapos/anachak_rust:latest \
  --region asia-southeast1 \
  --platform managed \
  --port 50050 \
  --allow-unauthenticated \
  --set-secrets "DATABASE_URL=DATABASE_URL:latest,JWT_SECRET=JWT_SECRET:latest,..."
```

## K8s (Self-Hosted)

Kustomize manifests in `k8s/` for self-hosted Kubernetes deployments.

## Quick Deploy Workflow

```fish
cc                    # cargo check
ct                    # cargo test
ship "feat: X"        # git add + commit + push → triggers CI
```