diff --git a/README.md b/README.md index 5c33231..8c6a8b2 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,55 @@ docker run -d -p 3000:3000 --env-file .env gitea-assistant docker-compose up -d ``` +### Kubernetes + +Kubernetes manifests are located in the `k8s/` directory. + +**1. Configure Secrets** + +Encode your credentials as base64 and update `k8s/gitea-assistant.yaml`: + +```bash +echo -n "your_gitea_token" | base64 +echo -n "your_openai_key" | base64 +echo -n "your_webhook_secret" | base64 +echo -n "your_admin_password" | base64 +``` + +**2. Configure Application** + +Edit the ConfigMap in `k8s/gitea-assistant.yaml`: + +- Set `GITEA_API_URL` to your Gitea instance API endpoint +- Adjust model and review engine settings as needed + +**3. Deploy** + +```bash +# Using Kustomize (recommended) +kubectl apply -k k8s/ + +# Or apply individually +kubectl apply -f k8s/namespace.yaml +kubectl apply -f k8s/qdrant.yaml +kubectl apply -f k8s/gitea-assistant.yaml +``` + +**4. Verify** + +```bash +kubectl -n gitea-assistant get pods +kubectl -n gitea-assistant get svc +``` + +**5. Expose the Service (optional)** + +By default, services use `ClusterIP`. To expose externally, use an Ingress or change the Service type: + +```bash +kubectl -n gitea-assistant patch svc gitea-assistant -p '{"spec":{"type":"NodePort"}}' +``` + ## License MIT License diff --git a/docs/README.zh-CN.md b/docs/README.zh-CN.md index b561482..02d5423 100644 --- a/docs/README.zh-CN.md +++ b/docs/README.zh-CN.md @@ -175,6 +175,55 @@ docker run -d -p 3000:3000 --env-file .env gitea-assistant docker-compose up -d ``` +### Kubernetes + +Kubernetes 部署清单位于 `k8s/` 目录。 + +**1. 配置密钥** + +将凭证编码为 base64 并更新 `k8s/gitea-assistant.yaml` 中的 Secret: + +```bash +echo -n "your_gitea_token" | base64 +echo -n "your_openai_key" | base64 +echo -n "your_webhook_secret" | base64 +echo -n "your_admin_password" | base64 +``` + +**2. 配置应用** + +编辑 `k8s/gitea-assistant.yaml` 中的 ConfigMap: + +- 将 `GITEA_API_URL` 设置为你的 Gitea 实例 API 地址 +- 根据需要调整模型和审查引擎配置 + +**3. 部署** + +```bash +# 使用 Kustomize(推荐) +kubectl apply -k k8s/ + +# 或逐个应用 +kubectl apply -f k8s/namespace.yaml +kubectl apply -f k8s/qdrant.yaml +kubectl apply -f k8s/gitea-assistant.yaml +``` + +**4. 验证** + +```bash +kubectl -n gitea-assistant get pods +kubectl -n gitea-assistant get svc +``` + +**5. 暴露服务(可选)** + +默认使用 `ClusterIP` 类型。如需外部访问,可使用 Ingress 或修改 Service 类型: + +```bash +kubectl -n gitea-assistant patch svc gitea-assistant -p '{"spec":{"type":"NodePort"}}' +``` + ## 许可证 MIT 许可证 diff --git a/k8s/gitea-assistant.yaml b/k8s/gitea-assistant.yaml new file mode 100644 index 0000000..cc37ff3 --- /dev/null +++ b/k8s/gitea-assistant.yaml @@ -0,0 +1,142 @@ +--- +# Secret for sensitive environment variables +# Replace base64-encoded values before applying: +# echo -n "your_value" | base64 +apiVersion: v1 +kind: Secret +metadata: + name: gitea-assistant-secret + namespace: gitea-assistant + labels: + app.kubernetes.io/name: gitea-assistant + app.kubernetes.io/part-of: gitea-assistant +type: Opaque +data: + # REQUIRED: replace with your own base64-encoded values + GITEA_ACCESS_TOKEN: eW91cl9naXRlYV90b2tlbg== + OPENAI_API_KEY: eW91cl9vcGVuYWlfa2V5 + WEBHOOK_SECRET: eW91cl93ZWJob29rX3NlY3JldA== + ADMIN_PASSWORD: cGFzc3dvcmQ= + # Optional + # FEISHU_WEBHOOK_URL: "" + # FEISHU_WEBHOOK_SECRET: "" + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitea-assistant-config + namespace: gitea-assistant + labels: + app.kubernetes.io/name: gitea-assistant + app.kubernetes.io/part-of: gitea-assistant +data: + GITEA_API_URL: "http://localhost:3000/api/v1" + OPENAI_BASE_URL: "https://api.openai.com/v1" + OPENAI_MODEL: "gpt-4o-mini" + PORT: "3000" + QDRANT_URL: "http://qdrant.gitea-assistant.svc.cluster.local:6333" + REVIEW_ENGINE: "legacy" + REVIEW_WORKDIR: "/tmp/gitea-assistant" + REVIEW_MODEL_PLANNER: "gpt-4o-mini" + REVIEW_MODEL_SPECIALIST: "gpt-4o-mini" + REVIEW_MODEL_JUDGE: "gpt-4o-mini" + REVIEW_MAX_PARALLEL_RUNS: "2" + REVIEW_MAX_FILES_PER_RUN: "200" + REVIEW_AUTO_PUBLISH_MIN_CONFIDENCE: "0.8" + REVIEW_ENABLE_HUMAN_GATE: "true" + ENABLE_MEMORY: "false" + ENABLE_REFLECTION: "false" + ENABLE_DEBATE: "false" + config-overrides.json: | + { + "version": 1, + "updatedAt": "2026-03-01T10:50:57.952Z", + "overrides": {} + } + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gitea-assistant + namespace: gitea-assistant + labels: + app.kubernetes.io/name: gitea-assistant + app.kubernetes.io/part-of: gitea-assistant +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: gitea-assistant + template: + metadata: + labels: + app.kubernetes.io/name: gitea-assistant + app.kubernetes.io/part-of: gitea-assistant + spec: + containers: + - name: gitea-assistant + image: ghcr.io/jeffusion/gitea-ai-assistant:latest + ports: + - name: http + containerPort: 3000 + protocol: TCP + envFrom: + - configMapRef: + name: gitea-assistant-config + - secretRef: + name: gitea-assistant-secret + resources: + limits: + memory: "512Mi" + requests: + memory: "256Mi" + cpu: "100m" + volumeMounts: + - name: config-overrides + mountPath: /app/config-overrides.json + subPath: config-overrides.json + readOnly: true + livenessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 10 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + volumes: + - name: config-overrides + configMap: + name: gitea-assistant-config + items: + - key: config-overrides.json + path: config-overrides.json + +--- +apiVersion: v1 +kind: Service +metadata: + name: gitea-assistant + namespace: gitea-assistant + labels: + app.kubernetes.io/name: gitea-assistant + app.kubernetes.io/part-of: gitea-assistant +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: gitea-assistant + ports: + - name: http + port: 3000 + targetPort: http + protocol: TCP diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml new file mode 100644 index 0000000..8a088a3 --- /dev/null +++ b/k8s/kustomization.yaml @@ -0,0 +1,9 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: gitea-assistant + +resources: + - namespace.yaml + - qdrant.yaml + - gitea-assistant.yaml diff --git a/k8s/namespace.yaml b/k8s/namespace.yaml new file mode 100644 index 0000000..fd69652 --- /dev/null +++ b/k8s/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: gitea-assistant + labels: + app.kubernetes.io/part-of: gitea-assistant diff --git a/k8s/qdrant.yaml b/k8s/qdrant.yaml new file mode 100644 index 0000000..4de7780 --- /dev/null +++ b/k8s/qdrant.yaml @@ -0,0 +1,99 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: qdrant-data + namespace: gitea-assistant + labels: + app.kubernetes.io/name: qdrant + app.kubernetes.io/part-of: gitea-assistant +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: qdrant + namespace: gitea-assistant + labels: + app.kubernetes.io/name: qdrant + app.kubernetes.io/part-of: gitea-assistant +spec: + serviceName: qdrant + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: qdrant + template: + metadata: + labels: + app.kubernetes.io/name: qdrant + app.kubernetes.io/part-of: gitea-assistant + spec: + containers: + - name: qdrant + image: qdrant/qdrant:latest + ports: + - name: http + containerPort: 6333 + protocol: TCP + - name: grpc + containerPort: 6334 + protocol: TCP + resources: + limits: + memory: "1Gi" + requests: + memory: "512Mi" + cpu: "250m" + volumeMounts: + - name: qdrant-storage + mountPath: /qdrant/storage + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 10 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + volumes: + - name: qdrant-storage + persistentVolumeClaim: + claimName: qdrant-data + +--- +apiVersion: v1 +kind: Service +metadata: + name: qdrant + namespace: gitea-assistant + labels: + app.kubernetes.io/name: qdrant + app.kubernetes.io/part-of: gitea-assistant +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: qdrant + ports: + - name: http + port: 6333 + targetPort: http + protocol: TCP + - name: grpc + port: 6334 + targetPort: grpc + protocol: TCP