feat. rebuild service in Go
Rebuild the Gitea Codex review bot from the product contract with a Go HTTP service, durable SQL queue, typed Gitea client, isolated runner, and deployment updates. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,99 +1,119 @@
|
||||
# Gitea Codex Review Bot
|
||||
|
||||
Webhook-driven PR review bot for Gitea.
|
||||
A self-hosted, webhook-driven pull-request review bot for Gitea, rebuilt in Go. It validates signed Gitea comment webhooks, queues durable review jobs, runs Codex in an isolated container at the exact PR head SHA, and posts structured feedback back to the pull request.
|
||||
|
||||
## Features
|
||||
|
||||
- Handles `issue_comment` and `pull_request_comment` events.
|
||||
- Verifies `X-Gitea-Signature` HMAC (`sha256`).
|
||||
- Triggers on `@codex ...`, `@<GITEA_BOT_USERNAME> ...`, plus optional custom aliases from `GITEA_BOT_MENTIONS`.
|
||||
- Ignores bot-authored comments.
|
||||
- Enforces strict repository allowlist (`ALLOWED_REPOS`).
|
||||
- Deduplicates webhook deliveries/comments in DB.
|
||||
- Enforces PR cooldown for review requests.
|
||||
- Uses MariaDB + SQLAlchemy + Alembic.
|
||||
- Runs review jobs through ephemeral runner containers (with local fallback if Docker runtime is unavailable).
|
||||
- Posts/updates one persistent PR summary comment.
|
||||
- Supports repository config via `.codex-review.yml`.
|
||||
- HMAC-SHA256 verification of `X-Gitea-Signature` over the raw webhook body.
|
||||
- `issue_comment` and `pull_request_comment` support.
|
||||
- `@codex`, bot-username, and configured mention aliases.
|
||||
- Bot-loop prevention and exact `ALLOWED_REPOS` enforcement.
|
||||
- Delivery/comment deduplication and PR review cooldowns.
|
||||
- Durable FIFO jobs with retry and stale-running-job recovery.
|
||||
- MariaDB-compatible persistence with SQLite support for local tests.
|
||||
- `.codex-review.yml` at the exact PR head SHA.
|
||||
- Fork review policy, disabled-repository acknowledgements, and non-review commands.
|
||||
- Strict structured review result validation and bounded Markdown comments.
|
||||
- Isolated Docker runner with detached exact-SHA checkout verification.
|
||||
- Health and operational endpoints with bounded error output.
|
||||
|
||||
## Endpoints
|
||||
The runner executes untrusted repository content. Secure the Docker API/socket, use least-privilege tokens, pin the runner image, restrict egress, and review the threat model before production use.
|
||||
|
||||
- `POST /webhook/gitea`
|
||||
- `GET /healthz`
|
||||
## Routes
|
||||
|
||||
## Webhook Setup Model
|
||||
- `GET /` — embedded service landing page.
|
||||
- `GET /healthz` — liveness response: `{"status":"ok"}`.
|
||||
- `GET /healthz/latest-job` — bounded latest-job metadata.
|
||||
- `GET /healthz/latest-failure` — bounded latest-failure metadata.
|
||||
- `POST /webhook/gitea` — signed Gitea webhook receiver.
|
||||
|
||||
This bot is designed for self-hosted deployment:
|
||||
## Commands
|
||||
|
||||
1. You host this service yourself.
|
||||
2. A Gitea admin points webhook events to your hosted endpoint:
|
||||
- `https://your-bot-domain/webhook/gitea`
|
||||
3. Gitea sends `issue_comment` and `pull_request_comment` events to that endpoint.
|
||||
```text
|
||||
@codex review
|
||||
@codex review security
|
||||
@codex review performance --full
|
||||
@codex review tests
|
||||
@codex rerun
|
||||
@codex explain
|
||||
@codex ignore
|
||||
@codex help
|
||||
```
|
||||
|
||||
Webhook configuration is manual by design.
|
||||
Commands must begin the comment. `@codex fix` is intentionally unsupported. Unknown prefixed commands receive an explanatory comment; ordinary comments without a command are ignored.
|
||||
|
||||
Detailed setup instructions for both global and repository-only webhooks:
|
||||
## Configuration
|
||||
|
||||
- [docs/webhook-setup.md](docs/webhook-setup.md)
|
||||
|
||||
## Environment
|
||||
|
||||
Use `.env.example` as template.
|
||||
|
||||
Required:
|
||||
Copy `.env.example` to `.env`. Required values:
|
||||
|
||||
- `GITEA_BASE_URL`
|
||||
- `GITEA_TOKEN`
|
||||
- `GITEA_BOT_USERNAME`
|
||||
- `GITEA_WEBHOOK_SECRET`
|
||||
- `ALLOWED_REPOS`
|
||||
- `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`
|
||||
- `DATABASE_URL` or `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`
|
||||
- `OPENAI_API_KEY` when `CODEX_AUTH_MODE=api_key`
|
||||
|
||||
Optional:
|
||||
Important optional values include `OPENAI_REVIEW_MODEL`, `CODEX_AUTH_MODE`, `CODEX_AUTH_JSON_PATH`, `COOLDOWN_SECONDS`, `MAX_REVIEW_MINUTES`, `CONCURRENCY`, `REVIEW_RUNNER_IMAGE`, `ALLOW_UNTRUSTED_FORKS`, and `WEBHOOK_MAX_BYTES`.
|
||||
|
||||
- `OPENAI_API_KEY` (required when `CODEX_AUTH_MODE=api_key`, optional when `CODEX_AUTH_MODE=chatgpt`)
|
||||
- `OPENAI_PROJECT_ID`
|
||||
- `OPENAI_ORG_ID`
|
||||
- `GITEA_BOT_MENTIONS` (comma-separated extra mention aliases, e.g. `@review-buddy,helper-bot`)
|
||||
- `CODEX_AUTH_MODE` (`api_key` default, or `chatgpt`)
|
||||
- `CODEX_AUTH_JSON_PATH` (custom host path to `auth.json`; defaults to `~/.codex/auth.json` in `chatgpt` mode)
|
||||
- `DATABASE_URL` (overrides composed DB URL)
|
||||
For local development, use SQLite:
|
||||
|
||||
## Local Run
|
||||
```dotenv
|
||||
DATABASE_URL=sqlite://./gitea-codex.db
|
||||
```
|
||||
|
||||
For production, use MariaDB and a scoped Gitea token. The Go service applies schema migrations on startup.
|
||||
|
||||
## Local development
|
||||
|
||||
Requirements: Go 1.25+, Docker for real review execution, and Gitea credentials for integration use.
|
||||
|
||||
```bash
|
||||
python -m pip install -e .[dev]
|
||||
alembic upgrade head
|
||||
uvicorn gitea_codex_bot.main:app --host 0.0.0.0 --port 8000
|
||||
go mod download
|
||||
go test ./...
|
||||
go vet ./...
|
||||
go build -trimpath -o gitea-codex ./cmd/gitea-codex
|
||||
|
||||
# With environment configured:
|
||||
./gitea-codex
|
||||
```
|
||||
|
||||
The default listener is `:8000`; set `PORT` to change it. The unit/integration tests use a temporary SQLite database and fake Gitea HTTP server, so they do not require a live Gitea instance or Docker.
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```bash
|
||||
# Local dev image build
|
||||
cp .env.example .env
|
||||
# Edit .env, then:
|
||||
docker compose -f docker-compose.dev.yml up --build
|
||||
|
||||
# Published image
|
||||
docker compose up
|
||||
```
|
||||
|
||||
## CI
|
||||
The bot container needs access to the host Docker API to launch isolated review containers. Mounting `/var/run/docker.sock` is a privileged deployment decision; use a dedicated runner service or hardened Docker host where possible.
|
||||
|
||||
The workflow in `.gitea/workflows/ci.yml`:
|
||||
## Repository configuration
|
||||
|
||||
1. starts MariaDB service,
|
||||
2. runs Alembic migrations + tests,
|
||||
3. builds and pushes image tags to `gitea.reversed.dev/space/gitea-codex` on push.
|
||||
A target repository may provide `.codex-review.yml`:
|
||||
|
||||
Expected secrets for publish job:
|
||||
```yaml
|
||||
enabled: true
|
||||
review:
|
||||
default_mode: full
|
||||
max_diff_bytes: 200000
|
||||
include_tests: false
|
||||
focus:
|
||||
- correctness
|
||||
- security
|
||||
- maintainability
|
||||
ignore:
|
||||
- generated/
|
||||
```
|
||||
|
||||
- `REGISTRY_USERNAME`
|
||||
- `REGISTRY_PASSWORD`
|
||||
The file is read from the PR head and is treated as untrusted data. It cannot choose commands, credentials, images, host paths, container privileges, or network policy. Tests are disabled by default; `tests` mode or `include_tests: true` explicitly permits the runner to execute project tests.
|
||||
|
||||
## AI Note
|
||||
This project is a super big experiment i made because i wanted to have codex reviews in gitea. I hate using Github and i will never willingly without good reasons use their copilot bs.
|
||||
This project was made WITH codex and is meant to be used WITH codex as a review agent.
|
||||
If you are as rich as Peter Steinberg and get a free OpenAI API Key, feel free to use it for this bot.
|
||||
## Webhooks and deployment
|
||||
|
||||
## Contributing
|
||||
Contributions are welcome! Please open issues or submit pull requests for bug fixes, improvements, or new features.
|
||||
Webhook provisioning is manual in Gitea. See [docs/webhook-setup.md](docs/webhook-setup.md) for global and repository-only configuration. CI runs Go formatting, race-enabled tests, vet, and a static build before publishing an image.
|
||||
|
||||
## Design notes
|
||||
|
||||
This project exists to provide Codex-based review workflows for self-hosted Gitea installations without requiring GitHub. The implementation is intentionally provider- and runner-bound at the outer edge, while the domain, queue, storage, and HTTP layers remain independently testable.
|
||||
|
||||
Reference in New Issue
Block a user