feat. rebuild service in Go
ci / test (pull_request) Successful in 1m54s
ci / publish (pull_request) Has been skipped

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:
Space-Banane
2026-07-12 21:51:01 +02:00
parent fdd3819ff8
commit f19b271642
74 changed files with 2623 additions and 4819 deletions
+16 -155
View File
@@ -24,74 +24,22 @@ jobs:
--health-interval 5s
--health-timeout 5s
--health-retries 20
env:
GITEA_BASE_URL: https://gitea.reversed.dev
GITEA_TOKEN: test
GITEA_BOT_USERNAME: codex-bot
GITEA_WEBHOOK_SECRET: testsecret
OPENAI_API_KEY: test-openai
ALLOWED_REPOS: org/repo
COOLDOWN_SECONDS: 60
WEBHOOK_MODE: repo
DB_HOST: mariadb
DB_PORT: 3306
DB_NAME: gitea_codex
DB_USER: gitea_codex
DB_PASSWORD: gitea_codex
TEST_DATABASE_URL: mysql+pymysql://gitea_codex:gitea_codex@mariadb:3306/gitea_codex?charset=utf8mb4
WORKDIR: /tmp/work
MAX_DIFF_BYTES: 200000
MAX_REVIEW_MINUTES: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/setup-go@v5
with:
python-version: '3.12'
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
- name: Wait for MariaDB
run: |
python - <<'PY'
import os
import time
import pymysql
host = os.environ["DB_HOST"]
port = int(os.environ["DB_PORT"])
user = os.environ["DB_USER"]
password = os.environ["DB_PASSWORD"]
database = os.environ["DB_NAME"]
for _ in range(60):
try:
conn = pymysql.connect(
host=host,
port=port,
user=user,
password=password,
database=database,
connect_timeout=2,
read_timeout=2,
write_timeout=2,
)
conn.close()
print("MariaDB is ready")
raise SystemExit(0)
except Exception as exc:
print(f"Waiting for MariaDB: {exc}")
time.sleep(2)
print("MariaDB did not become ready in time")
raise SystemExit(1)
PY
- name: Run Alembic migrations
run: alembic upgrade head
- name: Run tests
run: pytest
go-version: '1.25.x'
- name: Check formatting
shell: bash
run: test -z "$(gofmt -l cmd internal)"
- name: Test
env:
DATABASE_URL: sqlite://./ci.db
run: go test -race ./...
- name: Vet
run: go vet ./...
- name: Build
run: CGO_ENABLED=0 go build -trimpath -o gitea-codex ./cmd/gitea-codex
publish:
runs-on: ubuntu-latest
@@ -103,19 +51,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Derive package metadata
id: meta
shell: bash
run: |
set -euo pipefail
owner="${IMAGE_NAME%%/*}"
repo="${IMAGE_NAME##*/}"
if [ -z "${owner}" ] || [ -z "${repo}" ]; then
echo "::error::Failed to derive owner/repo from IMAGE_NAME=${IMAGE_NAME}"
exit 1
fi
echo "owner=${owner}" >> "${GITHUB_OUTPUT}"
echo "repo=${repo}" >> "${GITHUB_OUTPUT}"
- name: Login to Gitea container registry
uses: docker/login-action@v3
with:
@@ -129,80 +64,6 @@ jobs:
CI_REF_NAME: ${{ gitea.ref_name }}
run: |
set -euo pipefail
IMAGE="${REGISTRY}/${IMAGE_NAME}"
SHA_TAG="sha-${CI_SHA::12}"
REF_TAG="${CI_REF_NAME}"
docker buildx build --push \
-t "${IMAGE}:${SHA_TAG}" \
-t "${IMAGE}:${REF_TAG}" \
.
if [ "${CI_REF_NAME}" = "main" ]; then
docker buildx build --push -t "${IMAGE}:latest" .
fi
- name: Publish image summary
shell: bash
env:
CI_SHA: ${{ gitea.sha }}
CI_REF_NAME: ${{ gitea.ref_name }}
run: |
set -euo pipefail
IMAGE="${REGISTRY}/${IMAGE_NAME}"
echo "Published image tags:" >> "${GITHUB_STEP_SUMMARY}"
echo "- ${IMAGE}:${CI_REF_NAME}" >> "${GITHUB_STEP_SUMMARY}"
echo "- ${IMAGE}:sha-${CI_SHA::12}" >> "${GITHUB_STEP_SUMMARY}"
if [ "${CI_REF_NAME}" = "main" ]; then
echo "- ${IMAGE}:latest" >> "${GITHUB_STEP_SUMMARY}"
fi
- name: Link package to repository
shell: bash
env:
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
PACKAGE_OWNER: ${{ steps.meta.outputs.owner }}
PACKAGE_NAME: ${{ steps.meta.outputs.repo }}
REPO_NAME: ${{ steps.meta.outputs.repo }}
run: |
set -euo pipefail
token="${REGISTRY_PASSWORD:-${REGISTRY_TOKEN:-}}"
if [ -z "$token" ]; then
echo "::error::Registry token/password is empty. Set REGISTRY_PASSWORD or REGISTRY_TOKEN."
exit 1
fi
python3 - <<'PY'
import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request
owner = os.environ["PACKAGE_OWNER"]
package = os.environ["PACKAGE_NAME"]
repo = os.environ["REPO_NAME"]
token = os.environ["REGISTRY_PASSWORD"] or os.environ["REGISTRY_TOKEN"]
base = "https://gitea.reversed.dev/api/v1"
headers = {
"Authorization": f"token {token}",
"Accept": "application/json",
}
latest_url = f"{base}/packages/{urllib.parse.quote(owner)}/container/{urllib.parse.quote(package)}/-/latest"
req = urllib.request.Request(latest_url, headers=headers)
with urllib.request.urlopen(req) as resp:
current = json.load(resp)
linked_repo = (current.get("repository") or {}).get("name")
if linked_repo == repo:
print(f"package already linked to {owner}/{repo}")
sys.exit(0)
link_url = f"{base}/packages/{urllib.parse.quote(owner)}/container/{urllib.parse.quote(package)}/-/link/{urllib.parse.quote(repo)}"
link_req = urllib.request.Request(link_url, data=b"", method="POST", headers=headers)
try:
with urllib.request.urlopen(link_req) as resp:
print(f"linked package to {owner}/{repo}, status={resp.status}")
except urllib.error.HTTPError as exc:
body = exc.read().decode(errors="replace")
print(f"link failed: status={exc.code} body={body}")
raise
PY
image="${REGISTRY}/${IMAGE_NAME}"
docker buildx build --push -t "${image}:sha-${CI_SHA::12}" -t "${image}:${CI_REF_NAME}" .
if [ "${CI_REF_NAME}" = "main" ]; then docker buildx build --push -t "${image}:latest" .; fi