Standard production layout: the OKR app (was nested under AINative_OKR_CASAN5/) is now
the repository root. No more wrapper directory.
- Promote AINative_OKR_CASAN5/* -> repo root (backend/ frontend/ packages/ apps/
.specify/ docs/ infra/ nginx/ scripts/ + configs). Merge tool dirs: .gitea (kept the
active deploy ci.yml, added harness-ci.yml + runbooks), .claude (agents/commands +
launch.json), .github moved up.
- Remove redundant: 00_SUBMISSION_PACKAGE, scattered root notes (FPT_CASAN_Full.md,
tu-tuong-casan.md, casan-tu-sinh..., casan_harness_assessment.md, source-review...,
README_CASAN5_REFINED.md), casan-next-plans/ and optimize-docs/ (competition/planning
artifacts — roadmap + design history preserved in git log / commit messages).
- Update all references to the old layout:
- .gitea/workflows/{ci,harness-ci}.yml, .github/workflows/{ci,deploy}.yml:
working-directory .; drop AINative_OKR_CASAN5/ prefix; .specify/{tests,scripts}
-> packages/casan-harness/... (.specify/logs state kept)
- .claude/launch.json, .gitea/*-runbook.md: path prefixes
- CLAUDE.md, README.md: docs/input -> apps/okr/domain/input
- policy-bundle.yaml: 8 policy paths -> packages/casan-harness/...; manifest re-signed
- secrets-scan.sh: fixture excludes -> new package/domain paths.
Full gate from the new root: PASS=64 FAIL=0 SKIP=3.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.4 KiB
VPS CI/CD Setup Runbook
Oracle Cloud Tokyo — 161.33.139.73
Architecture
VPS (Ubuntu 24.04, 1 GB RAM)
├── /opt/gitea/
│ ├── docker-compose.yml ← add act-runner service here
│ ├── .env ← add RUNNER_REGISTRATION_TOKEN here
│ ├── act-runner-config.yaml ← copy from .gitea/act-runner-config.yaml
│ └── gitea-data/
Step 1 — Enable Gitea Actions
SSH into the VPS:
ssh ubuntu@161.33.139.73
Add the Actions env variable to the Gitea service in docker-compose.yml:
# In the gitea service environment section, add:
- GITEA__actions__ENABLED=true
Restart Gitea:
cd /opt/gitea
docker compose restart gitea
Verify: Open http://161.33.139.73:3000 → Site Administration → Runners You should see "Runners" menu item (confirming Actions is enabled).
Step 2 — Get the Runner Registration Token
- Log into Gitea as admin: http://161.33.139.73:3000
- Go to: Site Administration (⚙) → Runners → "Create new runner"
- Copy the Registration Token shown (looks like:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
Step 3 — Copy act_runner config to VPS
From your local machine:
scp .gitea/act-runner-config.yaml \
ubuntu@161.33.139.73:/opt/gitea/act-runner-config.yaml
Step 4 — Add RUNNER_REGISTRATION_TOKEN to /opt/gitea/.env
On the VPS:
# Replace <TOKEN> with the token copied in Step 2
echo "RUNNER_REGISTRATION_TOKEN=<TOKEN>" >> /opt/gitea/.env
Step 5 — Add act_runner service to docker-compose.yml
Edit /opt/gitea/docker-compose.yml and add the act-runner service.
Typical Gitea docker-compose.yml after changes:
version: "3"
networks:
gitea:
external: false
volumes:
gitea-data:
act-runner-data:
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: always
networks:
- gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__actions__ENABLED=true # ← ADD THIS LINE
ports:
- "3000:3000"
- "2222:22"
volumes:
- ./gitea-data:/data
act-runner:
image: gitea/act_runner:latest
container_name: act-runner
restart: unless-stopped
networks:
- gitea # same network as gitea
depends_on:
- gitea
environment:
- GITEA_INSTANCE_URL=http://gitea:3000 # internal Docker hostname
- GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_REGISTRATION_TOKEN}
- GITEA_RUNNER_NAME=casan-runner-oracle
- CONFIG_FILE=/config/act-runner-config.yaml
volumes:
- /var/run/docker.sock:/var/run/docker.sock # DinD for job containers
- ./act-runner-config.yaml:/config/act-runner-config.yaml:ro
- act-runner-data:/data
If your current docker-compose.yml already has a
networks:orvolumes:section, merge them — don't add duplicate top-level keys.
Step 6 — Start act_runner
cd /opt/gitea
docker compose pull act-runner
docker compose up -d act-runner
Check registration:
docker compose logs -f act-runner
# Look for: "runner registered" or "connected to Gitea"
In Gitea Web UI: Site Administration → Runners → you should see "casan-runner-oracle" with status Online.
Step 7 — Pull the catthehacker runner image (one-time)
The first CI run will pull catthehacker/ubuntu:act-22.04 (~2 GB). Pre-pull to avoid timeout:
docker pull catthehacker/ubuntu:act-22.04
This takes ~2-5 minutes depending on internet speed.
Step 8 — Create repo in Gitea and push the project
On the VPS (or via Gitea web UI), create a new repository:
- URL: http://161.33.139.73:3000
- Name:
casan5(or any name) - Make it public or private (your choice)
On your local machine:
cd Output_CASAN5_REFINED # repo root (app promoted from AINative_OKR_CASAN5/)
# Add Gitea as remote
git remote add gitea ssh://git@161.33.139.73:2222/<YOUR_USER>/casan5.git
# Push
git push gitea main
Step 9 — Verify CI triggered
After push, go to: http://161.33.139.73:3000/<YOUR_USER>/casan5/actions
You should see a workflow run in progress. Click it to see live logs.
Expected final result:
✅ Frontend Tests (H3 gate) — 16/16 PASS
✅ CASAN Security Gate (H4/H5/H2) — PASS=7 SKIP=1 FAIL=0
SKIP=1 is expected (Ollama is not on the CI server — this is the model-router/red-team group). The gate exits 0 because FAIL=0.
Memory Monitoring
# Watch RAM usage while CI runs
watch -n 2 'free -h && docker stats --no-stream'
If OOM occurs, reduce the job container memory limit in act-runner-config.yaml or add swap:
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Troubleshooting
| Symptom | Fix |
|---|---|
| Runner shows "Offline" | Check docker compose logs act-runner; verify token is correct |
GITEA_INSTANCE_URL unreachable |
Ensure gitea and act-runner are on the same Docker network |
| Job stuck "Waiting for runner" | Runner is busy (capacity=1); wait or increase capacity |
python: command not found |
The workflow's "Install test tools" step installs python-is-python3 |
| OOM during npm ci | Switch to npm ci -w frontend (already done in workflow) or add swap |
catthehacker/ubuntu:act-22.04 pull fails |
Run docker pull manually on VPS first |