# Gitea Deployment en Kubernetes

## Gitea StatefulSet

```yaml
# k8s/gitea/gitea-statefulset.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gitea-data
  namespace: gitea
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: gitea
  namespace: gitea
spec:
  serviceName: gitea
  replicas: 1
  selector:
    matchLabels:
      app: gitea
  template:
    metadata:
      labels:
        app: gitea
    spec:
      containers:
      - name: gitea
        image: gitea/gitea:1.22
        ports:
        - name: http
          containerPort: 3000
        - name: ssh
          containerPort: 22
        env:
        - name: USER_UID
          value: "1000"
        - name: USER_GID
          value: "1000"
        - name: GITEA__database__DB_TYPE
          value: "mysql"
        - name: GITEA__database__HOST
          value: "mysql.control-plane.svc.cluster.local:3306"
        - name: GITEA__database__NAME
          value: "gitea"
        - name: GITEA__database__USER
          value: "root"
        - name: GITEA__database__PASSWD
          valueFrom:
            secretKeyRef:
              name: aiworker-secrets
              key: db-password
        - name: GITEA__server__DOMAIN
          value: "git.aiworker.dev"
        - name: GITEA__server__SSH_DOMAIN
          value: "git.aiworker.dev"
        - name: GITEA__server__ROOT_URL
          value: "https://git.aiworker.dev"
        - name: GITEA__server__HTTP_PORT
          value: "3000"
        - name: GITEA__server__SSH_PORT
          value: "2222"
        - name: GITEA__security__INSTALL_LOCK
          value: "true"
        - name: GITEA__webhook__ALLOWED_HOST_LIST
          value: "*.svc.cluster.local"
        volumeMounts:
        - name: data
          mountPath: /data
        resources:
          requests:
            cpu: "500m"
            memory: "1Gi"
          limits:
            cpu: "2"
            memory: "4Gi"
        livenessProbe:
          httpGet:
            path: /api/healthz
            port: 3000
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /api/healthz
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 5
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: gitea-data
---
apiVersion: v1
kind: Service
metadata:
  name: gitea
  namespace: gitea
spec:
  selector:
    app: gitea
  ports:
  - name: http
    port: 3000
    targetPort: 3000
  - name: ssh
    port: 2222
    targetPort: 22
  type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
  name: gitea-ssh
  namespace: gitea
  annotations:
    service.beta.kubernetes.io/external-traffic: OnlyLocal
spec:
  selector:
    app: gitea
  ports:
  - name: ssh
    port: 2222
    targetPort: 22
    protocol: TCP
  type: LoadBalancer
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: gitea
  namespace: gitea
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/proxy-body-size: "512m"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - git.aiworker.dev
    secretName: gitea-tls
  rules:
  - host: git.aiworker.dev
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: gitea
            port:
              number: 3000
```

## Gitea Configuration

```yaml
# k8s/gitea/gitea-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: gitea-config
  namespace: gitea
data:
  app.ini: |
    [server]
    PROTOCOL = http
    DOMAIN = git.aiworker.dev
    ROOT_URL = https://git.aiworker.dev
    HTTP_PORT = 3000
    SSH_PORT = 2222
    DISABLE_SSH = false
    START_SSH_SERVER = true
    SSH_LISTEN_HOST = 0.0.0.0
    SSH_LISTEN_PORT = 22
    LFS_START_SERVER = true
    OFFLINE_MODE = false

    [database]
    DB_TYPE = mysql
    HOST = mysql.control-plane.svc.cluster.local:3306
    NAME = gitea
    USER = root
    SSL_MODE = disable

    [security]
    INSTALL_LOCK = true
    SECRET_KEY = your-secret-key-here
    INTERNAL_TOKEN = your-internal-token-here

    [service]
    DISABLE_REGISTRATION = false
    REQUIRE_SIGNIN_VIEW = false
    ENABLE_NOTIFY_MAIL = false

    [webhook]
    ALLOWED_HOST_LIST = *.svc.cluster.local,*.aiworker.dev

    [api]
    ENABLE_SWAGGER = true

    [actions]
    ENABLED = true

    [repository]
    DEFAULT_BRANCH = main
    FORCE_PRIVATE = false

    [ui]
    DEFAULT_THEME = arc-green
```

## Inicialización de Gitea

```bash
#!/bin/bash
# scripts/init-gitea.sh

set -e

echo "🚀 Initializing Gitea..."

# Wait for Gitea to be ready
echo "⏳ Waiting for Gitea pod..."
kubectl wait --for=condition=ready pod -l app=gitea -n gitea --timeout=300s

# Port-forward temporalmente
echo "🔌 Port-forwarding Gitea..."
kubectl port-forward -n gitea svc/gitea 3001:3000 &
PF_PID=$!
sleep 5

# Create admin user
echo "👤 Creating admin user..."
kubectl exec -n gitea gitea-0 -- gitea admin user create \
  --username aiworker \
  --password admin123 \
  --email admin@aiworker.dev \
  --admin \
  --must-change-password=false

# Create organization
echo "🏢 Creating organization..."
kubectl exec -n gitea gitea-0 -- gitea admin user create \
  --username aiworker-bot \
  --password bot123 \
  --email bot@aiworker.dev

# Generate access token
echo "🔑 Generating access token..."
TOKEN=$(kubectl exec -n gitea gitea-0 -- gitea admin user generate-access-token \
  --username aiworker-bot \
  --scopes write:repository,write:issue,write:user \
  --raw)

echo "✅ Gitea initialized!"
echo "📍 URL: https://git.aiworker.dev"
echo "👤 User: aiworker / admin123"
echo "🔑 Bot Token: $TOKEN"
echo ""
echo "⚠️  Save this token and update the secret:"
echo "kubectl create secret generic aiworker-secrets -n control-plane \\"
echo "  --from-literal=gitea-token='$TOKEN' --dry-run=client -o yaml | kubectl apply -f -"

# Stop port-forward
kill $PF_PID
```

## Gitea Webhook Configuration

```typescript
// services/gitea/setup.ts
import { giteaClient } from './client'
import { logger } from '../../utils/logger'

export async function setupGiteaWebhooks(owner: string, repo: string) {
  const backendUrl = process.env.BACKEND_URL || 'https://api.aiworker.dev'

  try {
    // Create webhook for push events
    await giteaClient.createWebhook(owner, repo, {
      url: `${backendUrl}/api/webhooks/gitea`,
      contentType: 'json',
      secret: process.env.GITEA_WEBHOOK_SECRET || '',
      events: ['push', 'pull_request', 'pull_request_closed'],
    })

    logger.info(`Webhooks configured for ${owner}/${repo}`)
  } catch (error) {
    logger.error('Failed to setup webhooks:', error)
    throw error
  }
}

export async function initializeGiteaForProject(projectName: string) {
  const owner = process.env.GITEA_OWNER || 'aiworker'

  // Create repository
  const repo = await giteaClient.createRepo(projectName, {
    description: `AiWorker project: ${projectName}`,
    private: true,
    autoInit: true,
    defaultBranch: 'main',
  })

  // Setup webhooks
  await setupGiteaWebhooks(owner, projectName)

  // Create initial branches
  await giteaClient.createBranch(owner, projectName, 'develop', 'main')
  await giteaClient.createBranch(owner, projectName, 'staging', 'main')

  logger.info(`Gitea initialized for project: ${projectName}`)

  return {
    repoUrl: repo.html_url,
    cloneUrl: repo.clone_url,
    sshUrl: repo.ssh_url,
  }
}
```

## Backup de Gitea

```yaml
# k8s/gitea/gitea-backup-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: gitea-backup
  namespace: gitea
spec:
  schedule: "0 2 * * *"  # Daily at 2 AM
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: gitea/gitea:1.22
            command:
            - /bin/sh
            - -c
            - |
              echo "Starting backup..."
              gitea dump -c /data/gitea/conf/app.ini -f /backups/gitea-backup-$(date +%Y%m%d).zip
              echo "Backup complete!"
              # Upload to S3 or other storage
            volumeMounts:
            - name: data
              mountPath: /data
            - name: backups
              mountPath: /backups
          volumes:
          - name: data
            persistentVolumeClaim:
              claimName: gitea-data
          - name: backups
            persistentVolumeClaim:
              claimName: gitea-backups
          restartPolicy: OnFailure
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gitea-backups
  namespace: gitea
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Gi
```

## Monitoreo de Gitea

```yaml
# k8s/gitea/gitea-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: gitea
  namespace: gitea
spec:
  selector:
    matchLabels:
      app: gitea
  endpoints:
  - port: http
    path: /metrics
    interval: 30s
```

## Troubleshooting

```bash
# Ver logs
kubectl logs -n gitea gitea-0 --tail=100 -f

# Entrar al pod
kubectl exec -it -n gitea gitea-0 -- /bin/sh

# Verificar config
kubectl exec -n gitea gitea-0 -- cat /data/gitea/conf/app.ini

# Regenerar admin user
kubectl exec -n gitea gitea-0 -- gitea admin user change-password \
  --username aiworker --password newpassword

# Limpiar cache
kubectl exec -n gitea gitea-0 -- rm -rf /data/gitea/queues/*
```

## SSH Keys Setup

```bash
# Generar SSH key para agentes
ssh-keygen -t ed25519 -C "aiworker-agent" -f agent-key -N ""

# Crear secret
kubectl create secret generic git-ssh-keys -n agents \
  --from-file=private-key=agent-key \
  --from-file=public-key=agent-key.pub

# Añadir public key a Gitea
# (via API o manualmente en UI)
```

## Git Config para Agentes

```yaml
# k8s/agents/git-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: git-config
  namespace: agents
data:
  .gitconfig: |
    [user]
      name = AiWorker Agent
      email = agent@aiworker.dev
    [core]
      sshCommand = ssh -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=no
    [credential]
      helper = store
```
