Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
403c6cfb2c | ||
|
|
8d0ca11c94 | ||
|
|
f1ff798f46 | ||
|
|
8548ce50e6 | ||
|
|
852a7eef34 |
@@ -0,0 +1,29 @@
|
||||
name: 简单测试工作流
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ test-workflow-trigger ]
|
||||
pull_request:
|
||||
branches: [ test-workflow-trigger ]
|
||||
|
||||
jobs:
|
||||
hello-world:
|
||||
name: 👋 Hello World 测试
|
||||
runs-on: macos
|
||||
|
||||
steps:
|
||||
- name: 🎯 输出 Hello World
|
||||
run: |
|
||||
echo "🎉 Hello from Gitea Actions!"
|
||||
echo "🏃 Runner: ${{ runner.name }}"
|
||||
echo "🖥️ 系统: $(uname -s)"
|
||||
echo "📅 时间: $(date)"
|
||||
|
||||
- name: 🔍 检查环境
|
||||
run: |
|
||||
echo "Node.js 版本: $(node --version 2>/dev/null || echo '未安装')"
|
||||
echo "Python 版本: $(python --version 2>/dev/null || echo '未安装')"
|
||||
echo "Docker 版本: $(docker --version 2>/dev/null || echo '未安装')"
|
||||
|
||||
- name: ✅ 成功标记
|
||||
run: echo "🎯 简单测试工作流执行成功!"
|
||||
@@ -0,0 +1,322 @@
|
||||
# 🚀 Gitea Actions 工作流演示指南
|
||||
|
||||
> **目标**: 演示如何通过创建 Pull Request 自动触发质量门禁检查
|
||||
> **Runner 状态**: ✅ 运行中 (PID: 91128)
|
||||
> **测试分支**: `test-workflow-trigger`
|
||||
|
||||
---
|
||||
|
||||
## 🎯 演示概览
|
||||
|
||||
### 📋 工作流配置
|
||||
|
||||
我们已经配置了完整的质量门禁工作流,位于 `.gitea/workflows/quality-gate.yml`:
|
||||
|
||||
```yaml
|
||||
name: 质量门禁 CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
frontend-quality: # 🎨 前端质量检查 (runs-on: [macos, docker])
|
||||
backend-quality: # 🐍 后端质量检查 (runs-on: macos)
|
||||
contract-quality: # 📋 API契约检查 (runs-on: macos)
|
||||
data-quality: # 📊 数据质量检查 (runs-on: macos)
|
||||
prompt-security: # 🔐 提示词安全检查 (runs-on: macos)
|
||||
quality-gate: # 🚪 最终质量门禁 (runs-on: macos)
|
||||
performance-benchmark: # ⚡ 性能基准测试 (runs-on: [macos, docker])
|
||||
```
|
||||
|
||||
### 🏷️ Runner 标签匹配
|
||||
|
||||
我们的本地 Runner 标签:`macos, amd64, docker, local`
|
||||
|
||||
```yaml
|
||||
# 匹配的工作流配置
|
||||
runs-on: macos ✅ 匹配
|
||||
runs-on: [macos, docker] ✅ 匹配
|
||||
runs-on: docker ✅ 匹配
|
||||
runs-on: local ✅ 匹配
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 演示步骤
|
||||
|
||||
### 第一步:创建测试分支 ✅
|
||||
|
||||
```bash
|
||||
# 我们已经创建了测试分支
|
||||
git checkout -b test-workflow-trigger
|
||||
git push origin test-workflow-trigger
|
||||
```
|
||||
|
||||
### 第二步:在 Gitea 中创建 Pull Request
|
||||
|
||||
1. **访问 Gitea**: http://192.168.1.83:33000
|
||||
2. **进入仓库**: gao/ai-stock
|
||||
3. **创建 PR**:
|
||||
- 点击 "Pull Requests" → "New Pull Request"
|
||||
- 选择源分支: `test-workflow-trigger`
|
||||
- 选择目标分支: `master`
|
||||
- 填写标题: "测试 Gitea Actions 工作流触发"
|
||||
- 填写描述: 参考 `TEST_WORKFLOW.md` 内容
|
||||
|
||||
### 第三步:观察工作流自动触发
|
||||
|
||||
创建 PR 后,工作流会自动触发,执行以下检查:
|
||||
|
||||
#### 🎨 前端质量检查 (frontend-quality)
|
||||
```bash
|
||||
- TypeScript 类型检查
|
||||
- ESLint 代码规范检查
|
||||
- 单元测试执行
|
||||
- 构建验证
|
||||
- 开发标准合规检查
|
||||
```
|
||||
|
||||
#### 🐍 后端质量检查 (backend-quality)
|
||||
```bash
|
||||
- Python 单元测试
|
||||
- 代码质量检查
|
||||
- 安全漏洞扫描
|
||||
- 数据库迁移验证
|
||||
```
|
||||
|
||||
#### 📋 API契约检查 (contract-quality)
|
||||
```bash
|
||||
- OpenAPI 规范验证
|
||||
- API 合同测试
|
||||
- 接口兼容性检查
|
||||
```
|
||||
|
||||
#### 📊 数据质量检查 (data-quality)
|
||||
```bash
|
||||
- 数据完整性验证
|
||||
- 数据格式规范检查
|
||||
- 数据质量指标验证
|
||||
```
|
||||
|
||||
#### 🔐 提示词安全检查 (prompt-security)
|
||||
```bash
|
||||
- 提示词内容安全验证
|
||||
- 注入攻击防护检查
|
||||
- 敏感信息泄露检查
|
||||
```
|
||||
|
||||
#### 🚪 最终质量门禁 (quality-gate)
|
||||
```bash
|
||||
- 汇总所有检查结果
|
||||
- 如果任何检查失败,阻止合并
|
||||
- 生成质量检查报告
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 监控工作流执行
|
||||
|
||||
### 查看 Runner 状态
|
||||
|
||||
```bash
|
||||
# 进入 Runner 目录
|
||||
cd /Users/brunogao/work/codes/tools/macos/gitea/runners
|
||||
|
||||
# 查看实时日志
|
||||
tail -f runner.log
|
||||
|
||||
# 查看运行状态
|
||||
./manage-runner.sh status
|
||||
|
||||
# 健康检查
|
||||
./manage-runner.sh health
|
||||
```
|
||||
|
||||
### 在 Gitea 界面查看
|
||||
|
||||
1. **Actions 页面**: 仓库 → Actions
|
||||
2. **工作流详情**: 点击具体的工作流执行
|
||||
3. **日志查看**: 点击每个 job 查看详细执行日志
|
||||
4. **结果状态**: 查看每个检查项的通过/失败状态
|
||||
|
||||
---
|
||||
|
||||
## 📊 预期结果
|
||||
|
||||
### ✅ 成功场景
|
||||
|
||||
如果所有检查都通过,你将看到:
|
||||
|
||||
```yaml
|
||||
工作流状态: ✅ Success
|
||||
检查项目:
|
||||
🎨 frontend-quality: ✅ 通过
|
||||
🐍 backend-quality: ✅ 通过
|
||||
📋 contract-quality: ✅ 通过
|
||||
📊 data-quality: ✅ 通过
|
||||
🔐 prompt-security: ✅ 通过
|
||||
🚪 quality-gate: ✅ 通过
|
||||
|
||||
PR 状态: 可以合并
|
||||
合并按钮: ✅ 可用
|
||||
```
|
||||
|
||||
### ❌ 失败场景
|
||||
|
||||
如果任何检查失败,你将看到:
|
||||
|
||||
```yaml
|
||||
工作流状态: ❌ Failed
|
||||
失败的检查项: 🔴 显示具体哪个检查失败
|
||||
详细错误: 在日志中查看错误信息
|
||||
|
||||
PR 状态: 阻止合并
|
||||
合并按钮: ❌ 禁用
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 故障排除
|
||||
|
||||
### 工作流未触发
|
||||
|
||||
**可能原因**:
|
||||
- Gitea Actions 未启用
|
||||
- 分支保护规则未配置
|
||||
- Runner 标签不匹配
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 Gitea Actions 设置
|
||||
管理后台 → Actions → Enable Actions ✅
|
||||
|
||||
# 2. 检查分支保护
|
||||
仓库设置 → 分支保护 → 启用质量门禁 ✅
|
||||
|
||||
# 3. 检查 Runner 状态
|
||||
./manage-runner.sh status
|
||||
```
|
||||
|
||||
### 工作流执行失败
|
||||
|
||||
**可能原因**:
|
||||
- Docker 未运行
|
||||
- 依赖包未安装
|
||||
- 配置文件错误
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 Docker
|
||||
docker info
|
||||
|
||||
# 2. 查看详细日志
|
||||
./manage-runner.sh logs
|
||||
|
||||
# 3. 检查工作流语法
|
||||
cat .gitea/workflows/quality-gate.yml
|
||||
```
|
||||
|
||||
### Runner 连接问题
|
||||
|
||||
**可能原因**:
|
||||
- Gitea 服务未运行
|
||||
- 网络连接问题
|
||||
- Token 过期
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 Gitea 服务
|
||||
curl -s http://localhost:33000/api/v1/version
|
||||
|
||||
# 2. 重启 Runner
|
||||
./manage-runner.sh restart
|
||||
|
||||
# 3. 重新注册 Runner
|
||||
echo -e "http://localhost:33000\ne9udfPmR6PsKbTXNRY61fMiGpmVBXv1PRKhbTfPD\nmacos-local-runner\nmacos,amd64,docker,local" | /Users/brunogao/bin/act_runner register
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 最佳实践
|
||||
|
||||
### 📝 PR 创建规范
|
||||
|
||||
1. **清晰的标题**: 描述变更内容
|
||||
2. **详细的描述**: 说明变更原因和影响
|
||||
3. **关联 Issue**: 引用相关的 Issue 编号
|
||||
4. **测试计划**: 说明如何测试变更
|
||||
|
||||
### 🔄 分支管理
|
||||
|
||||
```bash
|
||||
# 功能开发流程
|
||||
git checkout -b feature/新功能名称
|
||||
# 开发代码...
|
||||
git add .
|
||||
git commit -m "feat: 添加新功能"
|
||||
git push origin feature/新功能名称
|
||||
# 在 Gitea 创建 PR
|
||||
|
||||
# 修复 Bug 流程
|
||||
git checkout -b fix/问题描述
|
||||
# 修复代码...
|
||||
git add .
|
||||
git commit -m "fix: 修复具体问题"
|
||||
git push origin fix/问题描述
|
||||
# 在 Gitea 创建 PR
|
||||
```
|
||||
|
||||
### 📊 质量标准
|
||||
|
||||
- **前端**: TypeScript 0 错误,ESLint ≤ 10 警告,测试覆盖率 ≥ 90%
|
||||
- **后端**: Python 测试覆盖率 ≥ 80%,无高危安全漏洞
|
||||
- **API**: OpenAPI 规范有效,无 Breaking Changes
|
||||
- **文档**: 及时更新相关文档
|
||||
|
||||
---
|
||||
|
||||
## 📞 获取帮助
|
||||
|
||||
### 🛠️ 管理命令
|
||||
|
||||
```bash
|
||||
# Runner 管理
|
||||
cd /Users/brunogao/work/codes/tools/macos/gitea/runners
|
||||
|
||||
# 查看帮助
|
||||
./manage-runner.sh help
|
||||
|
||||
# 查看状态
|
||||
./manage-runner.sh status
|
||||
|
||||
# 查看日志
|
||||
./manage-runner.sh logs
|
||||
|
||||
# 健康检查
|
||||
./manage-runner.sh health
|
||||
```
|
||||
|
||||
### 📚 相关文档
|
||||
|
||||
- **Gitea Actions 文档**: https://docs.gitea.com/next/usage/actions/overview
|
||||
- **工作流语法**: https://docs.gitea.com/next/usage/actions/workflow-syntax
|
||||
- **Runner 配置**: `/Users/brunogao/work/codes/tools/macos/gitea/GITEA_RUNNER_DEPLOYMENT.md`
|
||||
|
||||
---
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
✅ **工作流配置完成**: 已适配本地 Runner 标签
|
||||
✅ **自动触发机制**: PR 创建时自动执行 CI 检查
|
||||
✅ **质量门禁体系**: 5 维度全面质量检查
|
||||
✅ **本地 Runner**: macOS 优化的高性能执行环境
|
||||
✅ **监控工具**: 完整的管理和诊断工具
|
||||
|
||||
**🚀 现在你可以在 Gitea 中创建 PR,自动触发完整的质量门禁检查!**
|
||||
|
||||
---
|
||||
|
||||
**下一步**: 在 Gitea 中访问 http://192.168.1.83:33000/gao/ai-stock 创建 Pull Request,观察 CI 自动执行!
|
||||
@@ -0,0 +1,223 @@
|
||||
# 顶层Makefile - 统一命令入口(Claude Code优化版)
|
||||
.PHONY: help dev-up dev-down web api bigscreen test lint build clean claude-auto claude-monitor claude-quality claude-assign dev-claude
|
||||
|
||||
# 默认目标
|
||||
help:
|
||||
@echo "🚀 LJWX-Stock开发命令汇总 (Claude Code增强版)"
|
||||
@echo ""
|
||||
@echo "环境管理:"
|
||||
@echo " dev-up 启动开发环境"
|
||||
@echo " dev-down 停止开发环境"
|
||||
@echo ""
|
||||
@echo "服务启动:"
|
||||
@echo " web 启动前端开发服务器"
|
||||
@echo " api 启动后端API服务"
|
||||
@echo " bigscreen 启动大屏服务"
|
||||
@echo ""
|
||||
@echo "Claude Code智能功能:"
|
||||
@echo " claude-auto 启动Claude自动化任务执行"
|
||||
@echo " claude-monitor 启动Claude任务监控面板"
|
||||
@echo " claude-quality 执行Claude质量检查"
|
||||
@echo " claude-assign 智能分配Claude任务"
|
||||
@echo " dev-claude 智能开发模式(推荐)"
|
||||
@echo ""
|
||||
@echo "代码质量:"
|
||||
@echo " lint 代码检查和格式化"
|
||||
@echo " test 运行测试"
|
||||
@echo ""
|
||||
@echo "构建部署:"
|
||||
@echo " build 构建所有服务"
|
||||
@echo " clean 清理临时文件"
|
||||
@echo ""
|
||||
@echo "AI训练:"
|
||||
@echo " ai-train 训练AI模型"
|
||||
@echo " ai-eval 评估模型性能"
|
||||
|
||||
# 环境管理
|
||||
dev-up:
|
||||
@echo "🚀 启动开发环境..."
|
||||
@if [ -f "infra/scripts/dev-up.sh" ]; then \
|
||||
bash infra/scripts/dev-up.sh; \
|
||||
else \
|
||||
echo "⚠️ 开发环境脚本不存在,请先创建 infra/scripts/dev-up.sh"; \
|
||||
fi
|
||||
|
||||
dev-down:
|
||||
@echo "🛑 停止开发环境..."
|
||||
@if [ -f "infra/scripts/dev-down.sh" ]; then \
|
||||
bash infra/scripts/dev-down.sh; \
|
||||
else \
|
||||
echo "⚠️ 开发环境脚本不存在,请先创建 infra/scripts/dev-down.sh"; \
|
||||
fi
|
||||
|
||||
# 服务启动
|
||||
web:
|
||||
@echo "🌐 启动前端开发服务器..."
|
||||
@if [ -d "apps/web" ]; then \
|
||||
cd apps/web && npm run dev; \
|
||||
else \
|
||||
echo "⚠️ 前端应用目录不存在,请先初始化 apps/web"; \
|
||||
fi
|
||||
|
||||
api:
|
||||
@echo "🔧 启动后端API服务..."
|
||||
@if [ -d "apps/api" ]; then \
|
||||
cd apps/api && uv run uvicorn ljwx_api.main:app --reload --host 0.0.0.0 --port 8000; \
|
||||
else \
|
||||
echo "⚠️ API应用目录不存在,请先初始化 apps/api"; \
|
||||
fi
|
||||
|
||||
bigscreen:
|
||||
@echo "📊 启动大屏服务..."
|
||||
@if [ -d "apps/bigscreen" ]; then \
|
||||
cd apps/bigscreen && uv run python -m flask --app bigscreen.app run --host=0.0.0.0 --port=5001; \
|
||||
else \
|
||||
echo "⚠️ 大屏应用目录不存在,请先初始化 apps/bigscreen"; \
|
||||
fi
|
||||
|
||||
# Claude Code智能功能
|
||||
claude-auto:
|
||||
@echo "🤖 启动Claude自动化任务执行..."
|
||||
@if [ -f "claude/task_manager/claude_task_manager.py" ]; then \
|
||||
python claude/task_manager/claude_task_manager.py; \
|
||||
else \
|
||||
echo "⚠️ Claude任务管理器不存在,请先初始化 claude/task_manager/"; \
|
||||
fi
|
||||
|
||||
claude-monitor:
|
||||
@echo "📊 启动Claude任务监控面板..."
|
||||
@if [ -f "claude/task_manager/monitor_dashboard.py" ]; then \
|
||||
python claude/task_manager/monitor_dashboard.py; \
|
||||
else \
|
||||
echo "⚠️ Claude监控面板不存在,请先初始化 claude/task_manager/"; \
|
||||
fi
|
||||
|
||||
claude-quality:
|
||||
@echo "🔍 执行Claude质量检查..."
|
||||
@if [ -f "claude/automation/quality_checker.py" ]; then \
|
||||
python claude/automation/quality_checker.py; \
|
||||
else \
|
||||
echo "⚠️ Claude质量检查器不存在,请先初始化 claude/automation/"; \
|
||||
fi
|
||||
|
||||
claude-assign:
|
||||
@echo "🎯 智能分配Claude任务..."
|
||||
@if [ -f "claude/automation/task_executor.py" ]; then \
|
||||
python claude/automation/task_executor.py --mode=assign; \
|
||||
else \
|
||||
echo "⚠️ Claude任务执行器不存在,请先初始化 claude/automation/"; \
|
||||
fi
|
||||
|
||||
# 智能开发模式
|
||||
dev-claude:
|
||||
@echo "🚀 启动Claude智能开发模式..."
|
||||
@echo "这将依次启动:开发环境 + Claude任务管理 + Claude监控面板"
|
||||
@read -p "是否继续?(y/N): " confirm && [ "$$confirm" = "y" ] || exit 1
|
||||
@make dev-up
|
||||
@echo "等待5秒后启动Claude服务..."
|
||||
@sleep 5
|
||||
@make claude-auto &
|
||||
@sleep 2
|
||||
@make claude-monitor
|
||||
|
||||
# 代码质量
|
||||
lint:
|
||||
@echo "🔍 代码检查和格式化..."
|
||||
@if [ -d "apps/web" ]; then \
|
||||
echo "检查前端代码..." && cd apps/web && npm run lint && npm run format; \
|
||||
fi
|
||||
@if [ -d "apps/api" ]; then \
|
||||
echo "检查后端代码..." && cd apps/api && uv run ruff check . && uv run ruff format .; \
|
||||
fi
|
||||
|
||||
test:
|
||||
@echo "🧪 运行测试..."
|
||||
@if [ -d "apps/api" ]; then \
|
||||
echo "运行后端测试..." && cd apps/api && uv run pytest -q; \
|
||||
fi
|
||||
@if [ -d "apps/web" ]; then \
|
||||
echo "运行前端测试..." && cd apps/web && npm run test; \
|
||||
fi
|
||||
|
||||
# 构建部署
|
||||
build:
|
||||
@echo "🏗️ 构建所有服务..."
|
||||
@if [ -d "apps/web" ]; then \
|
||||
echo "构建前端..." && cd apps/web && npm run build; \
|
||||
fi
|
||||
@if [ -f "infra/docker/api.Dockerfile" ]; then \
|
||||
echo "构建API Docker镜像..." && docker build -f infra/docker/api.Dockerfile -t ljwx/api:latest .; \
|
||||
fi
|
||||
@if [ -f "infra/docker/web.Dockerfile" ]; then \
|
||||
echo "构建Web Docker镜像..." && docker build -f infra/docker/web.Dockerfile -t ljwx/web:latest .; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
@echo "🧹 清理临时文件..."
|
||||
@find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||
@find . -type f -name "*.pyc" -delete 2>/dev/null || true
|
||||
@find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
|
||||
@if [ -d "apps/web" ]; then \
|
||||
cd apps/web && rm -rf dist 2>/dev/null || true; \
|
||||
fi
|
||||
|
||||
# AI训练
|
||||
ai-train:
|
||||
@echo "🤖 训练AI模型..."
|
||||
@if [ -f "ai/pipelines/Makefile" ]; then \
|
||||
cd ai/pipelines && make train-xgb; \
|
||||
else \
|
||||
echo "⚠️ AI训练流水线不存在,请先初始化 ai/pipelines/"; \
|
||||
fi
|
||||
|
||||
ai-eval:
|
||||
@echo "📊 评估模型性能..."
|
||||
@if [ -f "ai/pipelines/Makefile" ]; then \
|
||||
cd ai/pipelines && make eval; \
|
||||
else \
|
||||
echo "⚠️ AI评估流水线不存在,请先初始化 ai/pipelines/"; \
|
||||
fi
|
||||
|
||||
# 数据库操作
|
||||
db-migrate:
|
||||
@echo "🗄️ 运行数据库迁移..."
|
||||
@if [ -d "apps/api" ]; then \
|
||||
cd apps/api && uv run alembic upgrade head; \
|
||||
else \
|
||||
echo "⚠️ API应用不存在,无法执行数据库迁移"; \
|
||||
fi
|
||||
|
||||
db-seed:
|
||||
@echo "🌱 初始化基础数据..."
|
||||
@if [ -f "infra/db/seed/seed.sh" ]; then \
|
||||
bash infra/db/seed/seed.sh; \
|
||||
else \
|
||||
echo "⚠️ 数据初始化脚本不存在,请先创建 infra/db/seed/seed.sh"; \
|
||||
fi
|
||||
|
||||
# 快速启动命令(开发时常用)
|
||||
dev: dev-up
|
||||
@echo "✅ 开发环境已启动"
|
||||
@echo "在新的终端中运行:"
|
||||
@echo " make api # 启动后端"
|
||||
@echo " make web # 启动前端"
|
||||
@echo " make claude-auto # 启动Claude自动化"
|
||||
|
||||
# Claude报告生成
|
||||
claude-report:
|
||||
@echo "📋 生成Claude执行报告..."
|
||||
@if [ -f "claude_execution_report.json" ]; then \
|
||||
echo "Claude执行报告已存在:claude_execution_report.json"; \
|
||||
cat claude_execution_report.json | python -m json.tool | head -50; \
|
||||
else \
|
||||
echo "⚠️ Claude执行报告不存在,请先运行 make claude-auto"; \
|
||||
fi
|
||||
|
||||
# 生产环境部署
|
||||
deploy-staging:
|
||||
@echo "🚀 部署到预发布环境..."
|
||||
@echo "⚠️ 生产部署功能待实现"
|
||||
|
||||
deploy-prod:
|
||||
@echo "🚀 部署到生产环境..."
|
||||
@echo "⚠️ 生产部署功能待实现"
|
||||
@@ -0,0 +1,28 @@
|
||||
# 测试 Gitea Actions 工作流触发
|
||||
|
||||
这个 PR 用于验证 Gitea Actions 工作流是否能正确触发和执行。
|
||||
|
||||
## 测试内容
|
||||
|
||||
- [ ] 前端质量检查 (TypeScript + ESLint + 测试)
|
||||
- [ ] 后端质量检查 (Python 测试 + 安全检查)
|
||||
- [ ] API 契约检查
|
||||
- [ ] 数据质量检查
|
||||
- [ ] 提示词安全检查
|
||||
- [ ] 最终质量门禁
|
||||
|
||||
## 预期结果
|
||||
|
||||
所有检查项都应该通过,因为我们的代码符合质量标准。
|
||||
|
||||
|
||||
|
||||
|
||||
## Actions 启用后测试更新
|
||||
|
||||
更新时间: Tue Oct 28 15:44:19 CST 2025
|
||||
- Actions 功能已启用: ✅ confirmed
|
||||
- 准备触发工作流执行
|
||||
- 测试质量门禁检查
|
||||
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
claude_roles:
|
||||
primary_developer:
|
||||
id: "claude-dev-01"
|
||||
display_name: "主要开发者"
|
||||
capabilities:
|
||||
- "核心功能开发"
|
||||
- "代码质量保证"
|
||||
- "单元测试编写"
|
||||
- "技术文档编写"
|
||||
- "API设计"
|
||||
- "前端组件开发"
|
||||
max_concurrent_tasks: 3
|
||||
priority_areas:
|
||||
- "apps/api"
|
||||
- "apps/web"
|
||||
- "packages"
|
||||
- "services/rec-service"
|
||||
expertise_level: "senior"
|
||||
daily_capacity_hours: 8
|
||||
|
||||
ai_specialist:
|
||||
id: "claude-ai-01"
|
||||
display_name: "AI算法专家"
|
||||
capabilities:
|
||||
- "AI模型开发"
|
||||
- "特征工程"
|
||||
- "模型评估"
|
||||
- "算法优化"
|
||||
- "推荐算法设计"
|
||||
- "深度学习模型"
|
||||
max_concurrent_tasks: 2
|
||||
priority_areas:
|
||||
- "ai/"
|
||||
- "services/rec-service"
|
||||
- "services/model-service"
|
||||
- "ai/features"
|
||||
expertise_level: "expert"
|
||||
daily_capacity_hours: 8
|
||||
|
||||
data_engineer:
|
||||
id: "claude-data-01"
|
||||
display_name: "数据工程师"
|
||||
capabilities:
|
||||
- "数据管道开发"
|
||||
- "数据质量保证"
|
||||
- "ETL流程"
|
||||
- "数据架构"
|
||||
- "数据清洗"
|
||||
- "实时数据处理"
|
||||
max_concurrent_tasks: 2
|
||||
priority_areas:
|
||||
- "services/data-service"
|
||||
- "ai/data"
|
||||
- "ai/features"
|
||||
- "infra/db"
|
||||
expertise_level: "senior"
|
||||
daily_capacity_hours: 8
|
||||
|
||||
quality_assurance:
|
||||
id: "claude-qa-01"
|
||||
display_name: "质量保证工程师"
|
||||
capabilities:
|
||||
- "代码审查"
|
||||
- "测试策略"
|
||||
- "性能优化"
|
||||
- "安全检查"
|
||||
- "自动化测试"
|
||||
- "质量门禁"
|
||||
max_concurrent_tasks: 4
|
||||
priority_areas:
|
||||
- "tests/"
|
||||
- "docs/standards/"
|
||||
- "ci/"
|
||||
- ".gitea/workflows/"
|
||||
expertise_level: "senior"
|
||||
daily_capacity_hours: 8
|
||||
|
||||
devops_engineer:
|
||||
id: "claude-devops-01"
|
||||
display_name: "DevOps工程师"
|
||||
capabilities:
|
||||
- "基础设施配置"
|
||||
- "CI/CD流水线"
|
||||
- "监控告警"
|
||||
- "部署自动化"
|
||||
- "容器化配置"
|
||||
- "系统优化"
|
||||
max_concurrent_tasks: 2
|
||||
priority_areas:
|
||||
- "infra/"
|
||||
- ".gitea/"
|
||||
- "docker/"
|
||||
- "k8s/"
|
||||
expertise_level: "senior"
|
||||
daily_capacity_hours: 8
|
||||
|
||||
# 工作流规则
|
||||
workflow_rules:
|
||||
task_assignment:
|
||||
algorithm: "skill_based_load_balancing"
|
||||
considerations:
|
||||
- "技能匹配度"
|
||||
- "当前工作负载"
|
||||
- "任务优先级"
|
||||
- "历史表现"
|
||||
|
||||
conflict_resolution:
|
||||
auto_resolve_types:
|
||||
- "duplicate_tasks"
|
||||
- "dependency_conflicts"
|
||||
- "resource_conflicts"
|
||||
escalation_threshold: 3
|
||||
escalation_roles: ["claude-qa-01", "claude-dev-01"]
|
||||
|
||||
quality_gates:
|
||||
mandatory_checks:
|
||||
- "code_quality_score >= 8.0"
|
||||
- "test_coverage >= 80%"
|
||||
- "security_scan_passed"
|
||||
- "documentation_complete"
|
||||
reviewers_required: 1
|
||||
auto_approval_threshold: 9.0
|
||||
|
||||
# 协作协议
|
||||
collaboration_protocol:
|
||||
communication:
|
||||
preferred_channels: ["structured_logs", "json_reports"]
|
||||
update_frequency: "real_time"
|
||||
escalation_path: ["claude-dev-01", "claude-qa-01"]
|
||||
|
||||
knowledge_sharing:
|
||||
shared_memory: "docs/development/CLAUDE_COLLABORATION.md"
|
||||
code_patterns: "packages/shared-utils/"
|
||||
best_practices: "docs/standards/"
|
||||
|
||||
conflict_prevention:
|
||||
code_ownership: "file_level"
|
||||
concurrent_editing: "branch_based"
|
||||
merge_strategy: "squash_with_review"
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"execution_summary": {
|
||||
"start_time": "2025-10-28T06:45:11.531083",
|
||||
"end_time": "2025-10-28T06:46:27.696644",
|
||||
"start_time": "2025-10-28T16:17:35.829594",
|
||||
"end_time": "2025-10-28T16:18:51.986343",
|
||||
"total_duration": "计算中...",
|
||||
"total_tasks": 20,
|
||||
"completed_tasks": 20,
|
||||
@@ -10,7 +10,7 @@
|
||||
"overall_progress": 100.0
|
||||
},
|
||||
"quality_metrics": {
|
||||
"average_quality_score": 8.985,
|
||||
"average_quality_score": 9.01,
|
||||
"high_quality_tasks": 11,
|
||||
"medium_quality_tasks": 9,
|
||||
"low_quality_tasks": 0
|
||||
@@ -89,11 +89,11 @@
|
||||
"module": "权限系统",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.9,
|
||||
"quality_score": 9.4,
|
||||
"assigned_claude": "claude_architect_001",
|
||||
"start_time": "2025-10-28T06:45:11.531083",
|
||||
"end_time": "2025-10-28T06:45:17.546830",
|
||||
"duration": "0:00:06.015747"
|
||||
"start_time": "2025-10-28T16:17:35.829594",
|
||||
"end_time": "2025-10-28T16:17:41.840282",
|
||||
"duration": "0:00:06.010688"
|
||||
},
|
||||
{
|
||||
"id": "T-AUTH-002",
|
||||
@@ -101,11 +101,11 @@
|
||||
"module": "权限系统",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.5,
|
||||
"quality_score": 8.9,
|
||||
"assigned_claude": "claude_architect_001",
|
||||
"start_time": "2025-10-28T06:45:18.549667",
|
||||
"end_time": "2025-10-28T06:45:26.565738",
|
||||
"duration": "0:00:08.016071"
|
||||
"start_time": "2025-10-28T16:17:42.842874",
|
||||
"end_time": "2025-10-28T16:17:50.862700",
|
||||
"duration": "0:00:08.019826"
|
||||
},
|
||||
{
|
||||
"id": "T-AUTH-003",
|
||||
@@ -113,11 +113,11 @@
|
||||
"module": "权限系统",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.3,
|
||||
"quality_score": 8.6,
|
||||
"assigned_claude": "claude_architect_001",
|
||||
"start_time": "2025-10-28T06:45:18.549913",
|
||||
"end_time": "2025-10-28T06:45:26.566234",
|
||||
"duration": "0:00:08.016321"
|
||||
"start_time": "2025-10-28T16:17:42.843152",
|
||||
"end_time": "2025-10-28T16:17:50.863091",
|
||||
"duration": "0:00:08.019939"
|
||||
},
|
||||
{
|
||||
"id": "T-AUTH-004",
|
||||
@@ -125,11 +125,11 @@
|
||||
"module": "权限系统",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.4,
|
||||
"quality_score": 8.7,
|
||||
"assigned_claude": "claude_architect_001",
|
||||
"start_time": "2025-10-28T06:45:27.568915",
|
||||
"end_time": "2025-10-28T06:45:33.585818",
|
||||
"duration": "0:00:06.016903"
|
||||
"start_time": "2025-10-28T16:17:51.866127",
|
||||
"end_time": "2025-10-28T16:17:57.885006",
|
||||
"duration": "0:00:06.018879"
|
||||
},
|
||||
{
|
||||
"id": "T-AUTH-005",
|
||||
@@ -137,11 +137,11 @@
|
||||
"module": "权限系统",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.2,
|
||||
"quality_score": 9.1,
|
||||
"assigned_claude": "claude_architect_001",
|
||||
"start_time": "2025-10-28T06:45:36.593755",
|
||||
"end_time": "2025-10-28T06:45:46.610697",
|
||||
"duration": "0:00:10.016942"
|
||||
"start_time": "2025-10-28T16:18:00.891784",
|
||||
"end_time": "2025-10-28T16:18:10.908277",
|
||||
"duration": "0:00:10.016493"
|
||||
},
|
||||
{
|
||||
"id": "T-AUTH-006",
|
||||
@@ -149,11 +149,11 @@
|
||||
"module": "权限系统",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.5,
|
||||
"quality_score": 8.8,
|
||||
"assigned_claude": "claude_architect_001",
|
||||
"start_time": "2025-10-28T06:45:27.569180",
|
||||
"end_time": "2025-10-28T06:45:33.586235",
|
||||
"duration": "0:00:06.017055"
|
||||
"start_time": "2025-10-28T16:17:51.866601",
|
||||
"end_time": "2025-10-28T16:17:57.885372",
|
||||
"duration": "0:00:06.018771"
|
||||
},
|
||||
{
|
||||
"id": "T-AUTH-007",
|
||||
@@ -161,11 +161,11 @@
|
||||
"module": "权限系统",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.2,
|
||||
"quality_score": 8.6,
|
||||
"assigned_claude": "claude_architect_001",
|
||||
"start_time": "2025-10-28T06:45:47.613908",
|
||||
"end_time": "2025-10-28T06:45:51.631040",
|
||||
"duration": "0:00:04.017132"
|
||||
"start_time": "2025-10-28T16:18:11.910285",
|
||||
"end_time": "2025-10-28T16:18:15.928848",
|
||||
"duration": "0:00:04.018563"
|
||||
},
|
||||
{
|
||||
"id": "T-DATA-001",
|
||||
@@ -173,11 +173,11 @@
|
||||
"module": "数据层",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.3,
|
||||
"quality_score": 9.0,
|
||||
"assigned_claude": "claude_data_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:11.531109",
|
||||
"end_time": "2025-10-28T06:45:17.547289",
|
||||
"duration": "0:00:06.016180"
|
||||
"start_time": "2025-10-28T16:17:35.829620",
|
||||
"end_time": "2025-10-28T16:17:41.840559",
|
||||
"duration": "0:00:06.010939"
|
||||
},
|
||||
{
|
||||
"id": "T-DATA-002",
|
||||
@@ -185,11 +185,11 @@
|
||||
"module": "数据层",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.0,
|
||||
"quality_score": 8.6,
|
||||
"assigned_claude": "claude_data_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:18.549990",
|
||||
"end_time": "2025-10-28T06:45:22.563568",
|
||||
"duration": "0:00:04.013578"
|
||||
"start_time": "2025-10-28T16:17:42.843239",
|
||||
"end_time": "2025-10-28T16:17:46.855845",
|
||||
"duration": "0:00:04.012606"
|
||||
},
|
||||
{
|
||||
"id": "T-DATA-003",
|
||||
@@ -197,11 +197,11 @@
|
||||
"module": "数据层",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.5,
|
||||
"quality_score": 8.6,
|
||||
"assigned_claude": "claude_data_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:18.550051",
|
||||
"end_time": "2025-10-28T06:45:26.566366",
|
||||
"duration": "0:00:08.016315"
|
||||
"start_time": "2025-10-28T16:17:42.843288",
|
||||
"end_time": "2025-10-28T16:17:50.863293",
|
||||
"duration": "0:00:08.020005"
|
||||
},
|
||||
{
|
||||
"id": "T-DATA-004",
|
||||
@@ -209,11 +209,11 @@
|
||||
"module": "数据层",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.3,
|
||||
"quality_score": 9.4,
|
||||
"assigned_claude": "claude_data_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:27.569271",
|
||||
"end_time": "2025-10-28T06:45:33.586336",
|
||||
"duration": "0:00:06.017065"
|
||||
"start_time": "2025-10-28T16:17:51.866885",
|
||||
"end_time": "2025-10-28T16:17:57.885554",
|
||||
"duration": "0:00:06.018669"
|
||||
},
|
||||
{
|
||||
"id": "T-DATA-005",
|
||||
@@ -221,11 +221,11 @@
|
||||
"module": "数据层",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.7,
|
||||
"quality_score": 9.3,
|
||||
"assigned_claude": "claude_data_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:36.594117",
|
||||
"end_time": "2025-10-28T06:45:42.605252",
|
||||
"duration": "0:00:06.011135"
|
||||
"start_time": "2025-10-28T16:18:00.892013",
|
||||
"end_time": "2025-10-28T16:18:06.909996",
|
||||
"duration": "0:00:06.017983"
|
||||
},
|
||||
{
|
||||
"id": "T-DATA-006",
|
||||
@@ -233,11 +233,11 @@
|
||||
"module": "数据层",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.8,
|
||||
"quality_score": 9.1,
|
||||
"assigned_claude": "claude_data_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:27.569361",
|
||||
"end_time": "2025-10-28T06:45:35.590328",
|
||||
"duration": "0:00:08.020967"
|
||||
"start_time": "2025-10-28T16:17:51.867071",
|
||||
"end_time": "2025-10-28T16:17:59.889125",
|
||||
"duration": "0:00:08.022054"
|
||||
},
|
||||
{
|
||||
"id": "T-DATA-007",
|
||||
@@ -245,11 +245,11 @@
|
||||
"module": "数据层",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.2,
|
||||
"quality_score": 9.0,
|
||||
"assigned_claude": "claude_data_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:47.614391",
|
||||
"end_time": "2025-10-28T06:45:57.631257",
|
||||
"duration": "0:00:10.016866"
|
||||
"start_time": "2025-10-28T16:18:11.910682",
|
||||
"end_time": "2025-10-28T16:18:21.925999",
|
||||
"duration": "0:00:10.015317"
|
||||
},
|
||||
{
|
||||
"id": "T-DATA-008",
|
||||
@@ -257,11 +257,11 @@
|
||||
"module": "数据层",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.3,
|
||||
"quality_score": 8.8,
|
||||
"assigned_claude": "claude_data_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:58.633287",
|
||||
"end_time": "2025-10-28T06:46:04.651964",
|
||||
"duration": "0:00:06.018677"
|
||||
"start_time": "2025-10-28T16:18:22.928240",
|
||||
"end_time": "2025-10-28T16:18:28.942078",
|
||||
"duration": "0:00:06.013838"
|
||||
},
|
||||
{
|
||||
"id": "T-AI-001",
|
||||
@@ -269,11 +269,11 @@
|
||||
"module": "AI模型",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.0,
|
||||
"quality_score": 8.9,
|
||||
"assigned_claude": "claude_ai_engineer_001",
|
||||
"start_time": "2025-10-28T06:45:58.633799",
|
||||
"end_time": "2025-10-28T06:46:06.652990",
|
||||
"duration": "0:00:08.019191"
|
||||
"start_time": "2025-10-28T16:18:22.928392",
|
||||
"end_time": "2025-10-28T16:18:30.942281",
|
||||
"duration": "0:00:08.013889"
|
||||
},
|
||||
{
|
||||
"id": "T-AI-002",
|
||||
@@ -281,11 +281,11 @@
|
||||
"module": "AI模型",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.8,
|
||||
"quality_score": 9.3,
|
||||
"assigned_claude": "claude_ai_engineer_001",
|
||||
"start_time": "2025-10-28T06:46:07.655585",
|
||||
"end_time": "2025-10-28T06:46:17.670943",
|
||||
"duration": "0:00:10.015358"
|
||||
"start_time": "2025-10-28T16:18:31.944622",
|
||||
"end_time": "2025-10-28T16:18:41.961292",
|
||||
"duration": "0:00:10.016670"
|
||||
},
|
||||
{
|
||||
"id": "T-AI-003",
|
||||
@@ -293,11 +293,11 @@
|
||||
"module": "AI模型",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.9,
|
||||
"quality_score": 9.3,
|
||||
"assigned_claude": "claude_ai_engineer_001",
|
||||
"start_time": "2025-10-28T06:46:07.655803",
|
||||
"end_time": "2025-10-28T06:46:17.671473",
|
||||
"duration": "0:00:10.015670"
|
||||
"start_time": "2025-10-28T16:18:31.944940",
|
||||
"end_time": "2025-10-28T16:18:41.961530",
|
||||
"duration": "0:00:10.016590"
|
||||
},
|
||||
{
|
||||
"id": "T-AI-004",
|
||||
@@ -305,11 +305,11 @@
|
||||
"module": "AI模型",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 8.7,
|
||||
"quality_score": 9.4,
|
||||
"assigned_claude": "claude_ai_engineer_001",
|
||||
"start_time": "2025-10-28T06:46:18.674712",
|
||||
"end_time": "2025-10-28T06:46:26.693577",
|
||||
"duration": "0:00:08.018865"
|
||||
"start_time": "2025-10-28T16:18:42.963977",
|
||||
"end_time": "2025-10-28T16:18:50.983000",
|
||||
"duration": "0:00:08.019023"
|
||||
},
|
||||
{
|
||||
"id": "T-AI-005",
|
||||
@@ -317,11 +317,11 @@
|
||||
"module": "AI模型",
|
||||
"status": "completed",
|
||||
"progress": 100.0,
|
||||
"quality_score": 9.2,
|
||||
"quality_score": 9.4,
|
||||
"assigned_claude": "claude_ai_engineer_001",
|
||||
"start_time": "2025-10-28T06:46:18.675198",
|
||||
"end_time": "2025-10-28T06:46:26.694117",
|
||||
"duration": "0:00:08.018919"
|
||||
"start_time": "2025-10-28T16:18:42.964200",
|
||||
"end_time": "2025-10-28T16:18:50.983481",
|
||||
"duration": "0:00:08.019281"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"project_name": "LJWX-Stock AI股票推荐平台",
|
||||
"project_type": "monorepo",
|
||||
"claude_version": "sonnet-4.5",
|
||||
"features": {
|
||||
"auto_task_execution": true,
|
||||
"multi_claude_collaboration": true,
|
||||
"intelligent_code_generation": true,
|
||||
"automated_quality_control": true,
|
||||
"real_time_monitoring": true
|
||||
},
|
||||
"directory_structure": {
|
||||
"apps": ["web", "api", "bigscreen", "mobile"],
|
||||
"services": ["data-service", "rec-service", "model-service", "alert-service"],
|
||||
"ai": ["data", "features", "trainers", "models", "evals"],
|
||||
"packages": ["shared-schemas", "shared-utils", "shared-prompts"],
|
||||
"claude": ["task_manager", "collaboration", "automation"]
|
||||
},
|
||||
"automation_settings": {
|
||||
"task_parallel_execution": true,
|
||||
"conflict_auto_resolution": true,
|
||||
"quality_gates_enforcement": true,
|
||||
"progress_monitoring": true
|
||||
},
|
||||
"development_workflow": {
|
||||
"code_generation_prompts": "docs/prompts/ai_model_development_prompts.md",
|
||||
"task_management": "claude/task_manager/claude_task_manager.py",
|
||||
"quality_standards": "docs/standards/",
|
||||
"collaboration_rules": "docs/development/CLAUDE_COLLABORATION.md"
|
||||
},
|
||||
"claude_roles": {
|
||||
"primary_developer": {
|
||||
"id": "claude-dev-01",
|
||||
"capabilities": ["核心功能开发", "代码质量保证", "单元测试编写", "技术文档编写"],
|
||||
"max_concurrent_tasks": 3,
|
||||
"priority_areas": ["apps/api", "apps/web", "packages"]
|
||||
},
|
||||
"ai_specialist": {
|
||||
"id": "claude-ai-01",
|
||||
"capabilities": ["AI模型开发", "特征工程", "模型评估", "算法优化"],
|
||||
"max_concurrent_tasks": 2,
|
||||
"priority_areas": ["ai/", "services/rec-service", "services/model-service"]
|
||||
},
|
||||
"data_engineer": {
|
||||
"id": "claude-data-01",
|
||||
"capabilities": ["数据管道开发", "数据质量保证", "ETL流程", "数据架构"],
|
||||
"max_concurrent_tasks": 2,
|
||||
"priority_areas": ["services/data-service", "ai/data", "ai/features"]
|
||||
},
|
||||
"quality_assurance": {
|
||||
"id": "claude-qa-01",
|
||||
"capabilities": ["代码审查", "测试策略", "性能优化", "安全检查"],
|
||||
"max_concurrent_tasks": 4,
|
||||
"priority_areas": ["tests/", "docs/standards/", "ci/"]
|
||||
},
|
||||
"devops_engineer": {
|
||||
"id": "claude-devops-01",
|
||||
"capabilities": ["基础设施配置", "CI/CD流水线", "监控告警", "部署自动化"],
|
||||
"max_concurrent_tasks": 2,
|
||||
"priority_areas": ["infra/", ".gitea/", "docker/"]
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,706 @@
|
||||
# 🏗️ Gitea 企业级 CI/CD 实施指南
|
||||
|
||||
> **目标**: 基于 ChatGPT5 专家建议,为 LJWX-Stock 项目构建完整的"测试-编译-打镜像-上 K8s"流水线
|
||||
> **适用环境**: Mac Studio (Apple Silicon) + 本地 Gitea + Orbstack Docker
|
||||
> **文档版本**: v1.0
|
||||
> **更新时间**: 2025-10-28
|
||||
|
||||
---
|
||||
|
||||
## 📋 环境信息
|
||||
|
||||
### 🖥️ **本地开发环境**
|
||||
- **系统**: macOS (Apple Silicon M1/M2)
|
||||
- **内存**: 32GB RAM
|
||||
- **存储**: 1TB SSD
|
||||
- **Docker**: Orbstack (替代 Docker Desktop)
|
||||
- **Gitea**: 本地实例 http://localhost:33000
|
||||
- **Runner**: act_runner v0.2.11 (macos, amd64, docker, local)
|
||||
|
||||
### 🐳 **容器化环境**
|
||||
- **私有镜像仓库**: Harbor (计划部署)
|
||||
- **Kubernetes**: 本地 K3s 或 minikube
|
||||
- **基础镜像**: 多架构支持 (arm64 + amd64)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Runner 硬性要求配置
|
||||
|
||||
### ✅ **执行器与隔离配置**
|
||||
|
||||
#### Mac Studio 优化配置
|
||||
```yaml
|
||||
# 推荐配置:Docker Socket + Buildx
|
||||
act_runner_config:
|
||||
runner:
|
||||
capacity: 2 # 并发任务数
|
||||
timeout: 3600s # 超时时间
|
||||
envs:
|
||||
- DOCKER_BUILDKIT=1 # 启用 BuildKit
|
||||
- BUILDKIT_PROGRESS=plain # 构建进度显示
|
||||
labels:
|
||||
- "macos:docker" # Mac 专用标签
|
||||
- "linux:docker" # Linux 兼容标签
|
||||
- "multi-arch:builder" # 多架构构建标签
|
||||
|
||||
container:
|
||||
network: bridge
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock # Docker Socket 挂载
|
||||
- /var/tmp/buildx:/tmp/buildx # Buildx 缓存目录
|
||||
- /Users/brunogao/.docker:/root/.docker # Docker 配置缓存
|
||||
```
|
||||
|
||||
#### 为什么选择 Docker Socket 而非 DinD
|
||||
```yaml
|
||||
macos_optimization:
|
||||
docker_socket:
|
||||
advantages:
|
||||
- "性能更优:避免 DinD 在 Mac 上的网络和磁盘性能问题"
|
||||
- "缓存共享:直接使用宿主机的镜像层缓存"
|
||||
- "资源效率:减少容器层级,降低内存和 CPU 开销"
|
||||
|
||||
security_considerations:
|
||||
- "信任 Runner Job:拥有宿主机 root 权限"
|
||||
- "网络隔离:通过 Docker 网络进行隔离"
|
||||
- "文件系统隔离:通过工作目录进行隔离"
|
||||
```
|
||||
|
||||
### 🏗️ **多架构镜像构建配置**
|
||||
|
||||
#### QEMU 设置 (arm64 → amd64)
|
||||
```bash
|
||||
# 安装 QEMU 模拟器
|
||||
brew install qemu
|
||||
|
||||
# 在 Docker 中启用多架构支持
|
||||
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
|
||||
# 验证多架构支持
|
||||
docker buildx ls
|
||||
# 应该显示: docker-buildx (default) 支持 linux/amd64, linux/arm64
|
||||
```
|
||||
|
||||
#### Buildx 配置
|
||||
```yaml
|
||||
# buildx_config.yaml
|
||||
buildx:
|
||||
driver: docker-container
|
||||
platforms:
|
||||
- "linux/amd64"
|
||||
- "linux/arm64"
|
||||
cache:
|
||||
type: registry
|
||||
ref: harbor.local/ljwx/buildkit-cache:latest
|
||||
max_parallelism: 4
|
||||
```
|
||||
|
||||
### 🐙 **Kubernetes 部署配置**
|
||||
|
||||
#### 最小权限 RBAC
|
||||
```yaml
|
||||
# k8s/rbac.yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: ljwx-prod
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: gitea-deployer
|
||||
namespace: ljwx-prod
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: deployer-role
|
||||
namespace: ljwx-prod
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "services", "configmaps", "secrets"]
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["deployments", "statefulsets"]
|
||||
verbs: ["get", "list", "watch", "update", "patch"]
|
||||
- apiGroups: ["batch"]
|
||||
resources: ["jobs"]
|
||||
verbs: ["get", "list", "watch", "create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: deployer-binding
|
||||
namespace: ljwx-prod
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: gitea-deployer
|
||||
namespace: ljwx-prod
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: deployer-role
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
```
|
||||
|
||||
#### Kubeconfig 配置
|
||||
```bash
|
||||
# 生成受限的 kubeconfig
|
||||
kubectl config view --raw > /tmp/kubeconfig-full
|
||||
kubectl config use-context k3s-default --kubeconfig=/tmp/kubeconfig-full
|
||||
|
||||
# 提取特定命名空间的配置
|
||||
kubectl config set-context gitea-deployer \
|
||||
--cluster=k3s-default \
|
||||
--user=gitea-deployer \
|
||||
--namespace=ljwx-prod \
|
||||
--kubeconfig=/tmp/kubeconfig-restricted
|
||||
|
||||
# Base64 编码用于 Gitea Secrets
|
||||
base64 -i /tmp/kubeconfig-restricted
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 完整 CI/CD 流水线
|
||||
|
||||
### 📋 **工作流设计**
|
||||
```yaml
|
||||
# .gitea/workflows/enterprise-ci-cd.yml
|
||||
name: 🏗️ Enterprise CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
env:
|
||||
REGISTRY: harbor.local:3000/ljwx
|
||||
IMAGE_NAME: ai-stock-service
|
||||
K8S_NAMESPACE: ljwx-prod
|
||||
RELEASE_NAME: ai-stock
|
||||
|
||||
jobs:
|
||||
# 🔍 代码质量检查
|
||||
quality-gates:
|
||||
name: 🔍 质量门禁
|
||||
runs-on: macos
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: 🎨 前端质量检查
|
||||
uses: ./.gitea/actions/frontend-verify
|
||||
|
||||
- name: 🐍 后端质量检查
|
||||
uses: ./.gitea/actions/backend-verify
|
||||
|
||||
- name: 📋 API 契约检查
|
||||
uses: ./.gitea/actions/contract-verify
|
||||
|
||||
- name: 🔐 安全扫描
|
||||
run: |
|
||||
npm audit --audit-level=high
|
||||
safety check -r requirements.txt
|
||||
trivy fs --security-checks vuln,config .
|
||||
|
||||
# 🧪 测试阶段
|
||||
test:
|
||||
name: 🧪 测试执行
|
||||
runs-on: [macos, docker]
|
||||
needs: quality-gates
|
||||
strategy:
|
||||
matrix:
|
||||
component: [frontend, backend, integration]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: 🔧 设置环境
|
||||
run: |
|
||||
case "${{ matrix.component }}" in
|
||||
"frontend")
|
||||
npm ci
|
||||
;;
|
||||
"backend")
|
||||
python -m pip install -r requirements-dev.txt
|
||||
;;
|
||||
"integration")
|
||||
docker-compose -f docker-compose.test.yml up -d
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: 🧪 执行测试
|
||||
run: |
|
||||
case "${{ matrix.component }}" in
|
||||
"frontend")
|
||||
npm run test:coverage
|
||||
npm run e2e
|
||||
;;
|
||||
"backend")
|
||||
pytest --cov=src --cov-report=xml
|
||||
;;
|
||||
"integration")
|
||||
pytest tests/integration/
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: 📊 上传测试报告
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-reports-${{ matrix.component }}
|
||||
path: |
|
||||
coverage/
|
||||
test-results/
|
||||
reports/
|
||||
|
||||
# 🏗️ 构建和打包
|
||||
build:
|
||||
name: 🏗️ 构建打包
|
||||
runs-on: [macos, docker]
|
||||
needs: test
|
||||
outputs:
|
||||
image-digest: ${{ steps.build.outputs.digest }}
|
||||
image-tag: ${{ steps.meta.outputs.tags }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: 🐳 设置 Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver-opts: |
|
||||
image=moby/buildkit:buildx-stable-1
|
||||
|
||||
- name: 🔧 设置 QEMU (多架构)
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
- name: 📝 生成镜像元数据
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=sha,prefix={{branch}}-
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: 🐙 登录私有镜像仓库
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.HARBOR_USER }}
|
||||
password: ${{ secrets.HARBOR_PASS }}
|
||||
|
||||
- name: 🏗️ 构建并推送镜像
|
||||
id: build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
|
||||
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
|
||||
|
||||
- name: 🏷️ 生成 SBOM
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.IMAGE_TAG }} --format '{{.Manifest}}' > sbom.json
|
||||
|
||||
- name: 📦 上传构建产物
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
path: |
|
||||
sbom.json
|
||||
build-info.json
|
||||
|
||||
# 🚀 部署到 Kubernetes
|
||||
deploy:
|
||||
name: 🚀 部署到 K8s
|
||||
runs-on: macos
|
||||
needs: build
|
||||
if: github.ref == 'refs/heads/main'
|
||||
environment: production
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: 🔧 设置 kubectl
|
||||
uses: azure/setup-kubectl@v4
|
||||
with:
|
||||
version: 'v1.28.0'
|
||||
|
||||
- name: 🔐 配置 Kubeconfig
|
||||
run: |
|
||||
mkdir -p $HOME/.kube
|
||||
echo "${{ secrets.KUBECONFIG_B64 }}" | base64 -d > $HOME/.kube/config
|
||||
chmod 600 $HOME/.kube/config
|
||||
|
||||
- name: 📝 更新 Helm Chart
|
||||
run: |
|
||||
helm repo add bitnami https://charts.bitnami.com/bitnami
|
||||
helm repo update
|
||||
|
||||
# 更新 values.yaml
|
||||
cat > helm/values.yaml << EOF
|
||||
image:
|
||||
repository: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tag: ${{ needs.build.outputs.image-tag }}
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 80
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
hostname: ai-stock.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
EOF
|
||||
|
||||
- name: 🚀 Helm 部署
|
||||
run: |
|
||||
helm upgrade --install ${{ env.RELEASE_NAME }} ./helm \
|
||||
--namespace ${{ env.K8S_NAMESPACE }} \
|
||||
--create-namespace \
|
||||
--values helm/values.yaml \
|
||||
--wait \
|
||||
--timeout 10m
|
||||
|
||||
- name: ✅ 部署验证
|
||||
run: |
|
||||
# 检查部署状态
|
||||
kubectl -n ${{ env.K8S_NAMESPACE }} rollout status deployment/${{ env.RELEASE_NAME }} --timeout=300s
|
||||
|
||||
# 健康检查
|
||||
kubectl -n ${{ env.K8S_NAMESPACE }} get pods -l app.kubernetes.io/name=${{ env.RELEASE_NAME }}
|
||||
|
||||
# 服务检查
|
||||
kubectl -n ${{ env.K8S_NAMESPACE }} get service ${{ env.RELEASE_NAME }}
|
||||
|
||||
- name: 📊 性能测试
|
||||
run: |
|
||||
# 等待服务就绪
|
||||
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=${{ env.RELEASE_NAME }} -n ${{ env.K8S_NAMESPACE }} --timeout=300s
|
||||
|
||||
# 执行性能测试
|
||||
npm install -g artillery
|
||||
artillery run tests/performance/load-test.yml
|
||||
|
||||
- name: 📧 通知部署结果
|
||||
if: always()
|
||||
run: |
|
||||
if [ "${{ job.status }}" = "success" ]; then
|
||||
echo "✅ 部署成功!"
|
||||
# 发送成功通知到 Slack/Teams
|
||||
else
|
||||
echo "❌ 部署失败!"
|
||||
# 发送失败通知
|
||||
fi
|
||||
|
||||
# 🧹 清理和报告
|
||||
cleanup:
|
||||
name: 🧹 清理和报告
|
||||
runs-on: macos
|
||||
needs: [deploy]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: 📊 生成部署报告
|
||||
run: |
|
||||
cat > deployment-report.md << EOF
|
||||
# 🚀 部署报告
|
||||
|
||||
## 📋 部署信息
|
||||
- **镜像**: ${{ needs.build.outputs.image-tag }}
|
||||
- **命名空间**: ${{ env.K8S_NAMESPACE }}
|
||||
- **部署时间**: $(date)
|
||||
- **部署状态**: ${{ needs.deploy.result }}
|
||||
|
||||
## 🎯 性能指标
|
||||
- **构建时间**: ${{ needs.build.outputs.build-time }}
|
||||
- **部署时间**: ${{ needs.deploy.outputs.deploy-time }}
|
||||
- **测试覆盖率**: ${{ needs.test.outputs.coverage }}
|
||||
|
||||
EOF
|
||||
|
||||
- name: 📦 上传部署报告
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: deployment-report
|
||||
path: deployment-report.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 安全和密钥管理
|
||||
|
||||
### 📋 **必需的 Gitea Secrets**
|
||||
|
||||
#### 镜像仓库认证
|
||||
```yaml
|
||||
harbor_secrets:
|
||||
HARBOR_USER: "harbor 用户名"
|
||||
HARBOR_PASS: "harbor 密码"
|
||||
HARBOR_REGISTRY: "harbor.local:3000"
|
||||
```
|
||||
|
||||
#### Kubernetes 认证
|
||||
```yaml
|
||||
k8s_secrets:
|
||||
KUBECONFIG_B64: "base64 编码的 kubeconfig"
|
||||
K8S_API_SERVER: "K8s API 服务器地址"
|
||||
K8S_CA_CRT: "K8s CA 证书"
|
||||
K8S_TOKEN: "ServiceAccount Token"
|
||||
```
|
||||
|
||||
#### 第三方服务
|
||||
```yaml
|
||||
external_services:
|
||||
SLACK_WEBHOOK: "Slack 通知 Webhook"
|
||||
EMAIL_SMTP_PASS: "SMTP 密码"
|
||||
SONARQUBE_TOKEN: "SonarQube 访问令牌"
|
||||
```
|
||||
|
||||
### 🛡️ **安全最佳实践**
|
||||
|
||||
#### Runner 安全配置
|
||||
```yaml
|
||||
runner_security:
|
||||
network_isolation:
|
||||
- "仅允许访问内网资源"
|
||||
- "限制外网访问,使用代理"
|
||||
|
||||
resource_limits:
|
||||
cpu_limit: "2000m"
|
||||
memory_limit: "4Gi"
|
||||
disk_limit: "50Gi"
|
||||
|
||||
job_restrictions:
|
||||
- "仅运行来自可信仓库的工作流"
|
||||
- "限制敏感操作的执行权限"
|
||||
- "禁止使用 privileged 容器(除构建外)"
|
||||
```
|
||||
|
||||
#### 镜像安全扫描
|
||||
```yaml
|
||||
security_scanning:
|
||||
sast:
|
||||
- "使用 Semgrep 进行代码静态分析"
|
||||
- "使用 Bandit 进行 Python 安全扫描"
|
||||
- "使用 ESLint Security 插件"
|
||||
|
||||
sca:
|
||||
- "使用 Trivy 进行依赖漏洞扫描"
|
||||
- "使用 Safety 检查 Python 依赖"
|
||||
- "使用 npm audit 检查 Node.js 依赖"
|
||||
|
||||
container_security:
|
||||
- "使用 Trivy 扫描镜像漏洞"
|
||||
- "使用 Docker Scout 进行安全分析"
|
||||
- "生成 SBOM (Software Bill of Materials)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 性能优化和监控
|
||||
|
||||
### ⚡ **缓存策略**
|
||||
|
||||
#### 依赖缓存
|
||||
```yaml
|
||||
dependency_cache:
|
||||
nodejs:
|
||||
path: "~/.npm"
|
||||
strategy: "cache-from + cache-to"
|
||||
retention: "7天"
|
||||
|
||||
python:
|
||||
path: "~/.cache/pip"
|
||||
strategy: "pip cache"
|
||||
retention: "7天"
|
||||
|
||||
docker:
|
||||
type: "registry"
|
||||
ref: "harbor.local/ljwx/buildkit-cache"
|
||||
mode: "max"
|
||||
retention: "30天"
|
||||
```
|
||||
|
||||
#### 构建优化
|
||||
```yaml
|
||||
build_optimization:
|
||||
multi_stage_builds:
|
||||
- "使用多阶段构建减少镜像大小"
|
||||
- "分离构建和运行环境"
|
||||
|
||||
layer_caching:
|
||||
- "优化 Dockerfile 层顺序"
|
||||
- "使用 .dockerignore 排除不必要文件"
|
||||
|
||||
parallel_builds:
|
||||
- "多架构并行构建"
|
||||
- "测试和构建并行执行"
|
||||
```
|
||||
|
||||
### 📈 **监控和可观测性**
|
||||
|
||||
#### 指标收集
|
||||
```yaml
|
||||
metrics:
|
||||
build_metrics:
|
||||
- "构建时长"
|
||||
- "镜像大小"
|
||||
- "缓存命中率"
|
||||
- "构建成功率"
|
||||
|
||||
deploy_metrics:
|
||||
- "部署时长"
|
||||
- "回滚次数"
|
||||
- "服务可用性"
|
||||
- "错误率"
|
||||
|
||||
resource_metrics:
|
||||
- "CPU 使用率"
|
||||
- "内存使用率"
|
||||
- "磁盘使用率"
|
||||
- "网络流量"
|
||||
```
|
||||
|
||||
#### 日志管理
|
||||
```yaml
|
||||
logging:
|
||||
runner_logs:
|
||||
level: "info"
|
||||
format: "json"
|
||||
retention: "30天"
|
||||
destination: "elasticsearch"
|
||||
|
||||
application_logs:
|
||||
level: "warn"
|
||||
format: "structured"
|
||||
retention: "7天"
|
||||
destination: "loki"
|
||||
|
||||
audit_logs:
|
||||
level: "info"
|
||||
format: "json"
|
||||
retention: "90天"
|
||||
destination: "secure_storage"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 实施检查清单
|
||||
|
||||
### ✅ **前期准备**
|
||||
- [ ] Harbor 私有镜像仓库部署完成
|
||||
- [ ] Kubernetes 集群 (K3s/minikube) 就绪
|
||||
- [ ] 网络连通性测试通过
|
||||
- [ ] RBAC 权限配置完成
|
||||
- [ ] 基础监控体系建立
|
||||
|
||||
### ✅ **Runner 配置**
|
||||
- [ ] Gitea Runner 部署并运行
|
||||
- [ ] Docker Buildx 配置完成
|
||||
- [ ] QEMU 多架构支持启用
|
||||
- [ ] 缓存目录挂载配置
|
||||
- [ ] 资源限制设置
|
||||
|
||||
### ✅ **工作流配置**
|
||||
- [ ] 质量门禁工作流测试通过
|
||||
- [ ] 测试工作流执行正常
|
||||
- [ ] 构建工作流多架构支持
|
||||
- [ ] 部署工作流权限验证
|
||||
- [ ] 通知机制配置完成
|
||||
|
||||
### ✅ **安全配置**
|
||||
- [ ] 所有敏感信息配置到 Secrets
|
||||
- [ ] 镜像安全扫描集成
|
||||
- [ ] 网络访问控制配置
|
||||
- [ ] 审计日志启用
|
||||
- [ ] 定期安全扫描计划
|
||||
|
||||
### ✅ **监控配置**
|
||||
- [ ] 性能指标收集
|
||||
- [ ] 日志聚合系统
|
||||
- [ ] 告警规则配置
|
||||
- [ ] 可视化仪表板
|
||||
- [ ] 定期报告生成
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 故障排除
|
||||
|
||||
### ❌ **常见问题**
|
||||
|
||||
#### Runner 连接问题
|
||||
```bash
|
||||
# 检查 Runner 状态
|
||||
./manage-runner.sh health
|
||||
|
||||
# 检查网络连接
|
||||
curl -f http://localhost:33000/api/v1/version
|
||||
|
||||
# 重新注册 Runner
|
||||
echo -e "http://localhost:33000\nTOKEN\nmacos-runner\nmacos,docker" | act_runner register
|
||||
```
|
||||
|
||||
#### 构建失败问题
|
||||
```bash
|
||||
# 检查 Docker 状态
|
||||
docker info
|
||||
docker buildx ls
|
||||
|
||||
# 清理构建缓存
|
||||
docker buildx prune -f
|
||||
docker system prune -f
|
||||
```
|
||||
|
||||
#### 部署失败问题
|
||||
```bash
|
||||
# 检查 K8s 连接
|
||||
kubectl cluster-info
|
||||
kubectl get nodes
|
||||
|
||||
# 检查权限
|
||||
kubectl auth can-i create deployments --namespace=ljwx-prod
|
||||
kubectl auth can-i get pods --namespace=ljwx-prod
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- **Gitea Actions 官方文档**: https://docs.gitea.com/next/usage/actions/overview
|
||||
- **Docker Buildx 文档**: https://docs.docker.com/buildx/
|
||||
- **Kubernetes 部署指南**: ./k8s/
|
||||
- **Helm Chart 配置**: ./helm/
|
||||
- **监控和告警**: ./monitoring/
|
||||
|
||||
---
|
||||
|
||||
**🎯 本文档将根据实际使用情况持续更新和完善!**
|
||||
|
||||
---
|
||||
|
||||
**文档维护**: DevOps 团队
|
||||
**最后更新**: 2025-10-28
|
||||
**版本**: v1.0
|
||||
@@ -0,0 +1,305 @@
|
||||
# 🏗️ 企业级 CI/CD 实施方案
|
||||
|
||||
> 基于 ChatGPT5 专家建议,为 LJWX-Stock 项目构建完整的"测试-编译-打镜像-上 K8s"流水线
|
||||
|
||||
---
|
||||
|
||||
## 📋 文档结构
|
||||
|
||||
```
|
||||
docs/cicd/
|
||||
├── README.md # 📖 总览和导航
|
||||
├── GITEA_ENTERPRISE_CICD_GUIDE.md # 🎯 企业级 CI/CD 完整指南
|
||||
├── runner-config.yaml # ⚙️ Runner 配置文件
|
||||
├── k8s-setup.sh # 🚀 K8s 环境配置脚本
|
||||
├── harbor-setup.md # 🐳 Harbor 私有镜像仓库配置
|
||||
├── monitoring-setup.md # 📊 监控和可观测性配置
|
||||
└── best-practices.md # 💡 最佳实践和故障排除
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 核心特性
|
||||
|
||||
### ✅ **完整流水线支持**
|
||||
- 🔍 **代码质量检查**: TypeScript、Python、安全扫描
|
||||
- 🧪 **自动化测试**: 单元测试、集成测试、E2E 测试
|
||||
- 🏗️ **多架构构建**: ARM64 + AMD64 镜像构建
|
||||
- 🚀 **Kubernetes 部署**: Helm Chart 自动化部署
|
||||
- 📊 **性能监控**: 构建性能、服务可用性监控
|
||||
|
||||
### 🖥️ **Mac Studio 优化**
|
||||
- **Docker Socket + Buildx**: 针对 Apple Silicon 优化的构建方案
|
||||
- **QEMU 多架构支持**: ARM64 主机构建 AMD64 镜像
|
||||
- **Orbstack 集成**: 轻量级 Docker 环境支持
|
||||
- **本地缓存策略**: 构建缓存和依赖缓存优化
|
||||
|
||||
### 🛡️ **企业级安全**
|
||||
- **最小权限原则**: K8s RBAC 精细化权限控制
|
||||
- **密钥管理**: Gitea Secrets 统一管理敏感信息
|
||||
- **镜像安全扫描**: Trivy 漏洞扫描集成
|
||||
- **网络隔离**: K8s NetworkPolicy 安全策略
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 前置条件
|
||||
```bash
|
||||
# 系统要求
|
||||
- macOS (Apple Silicon)
|
||||
- Orbstack 或 Docker Desktop
|
||||
- kubectl
|
||||
- helm (可选)
|
||||
|
||||
# 检查依赖
|
||||
./docs/cicd/k8s-setup.sh --check-deps
|
||||
```
|
||||
|
||||
### 1️⃣ Kubernetes 环境配置
|
||||
```bash
|
||||
# 自动化配置 K8s 环境
|
||||
./docs/cicd/k8s-setup.sh
|
||||
|
||||
# 手动配置(可选)
|
||||
kubectl apply -f docs/cicd/k8s/
|
||||
```
|
||||
|
||||
### 2️⃣ Runner 配置升级
|
||||
```bash
|
||||
# 应用优化的 Runner 配置
|
||||
cd /Users/brunogao/work/codes/tools/macos/gitea/runners
|
||||
cp /Users/brunogao/work/codes/stock/ai_stock/docs/cicd/runner-config.yaml .
|
||||
./manage-runner.sh restart
|
||||
```
|
||||
|
||||
### 3️⃣ 配置 Gitea Secrets
|
||||
```yaml
|
||||
# 必需的 Secrets
|
||||
HARBOR_USER: "harbor 用户名"
|
||||
HARBOR_PASS: "harbor 密码"
|
||||
KUBECONFIG_B64: "base64 编码的 kubeconfig"
|
||||
SLACK_WEBHOOK: "通知 Webhook (可选)"
|
||||
```
|
||||
|
||||
### 4️⃣ 测试流水线
|
||||
```bash
|
||||
# 创建测试分支
|
||||
git checkout -b test-enterprise-cicd
|
||||
git push origin test-enterprise-cicd
|
||||
|
||||
# 在 Gitea 中创建 PR 触发流水线
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 性能优化
|
||||
|
||||
### ⚡ **构建性能**
|
||||
```yaml
|
||||
build_optimization:
|
||||
parallel_builds:
|
||||
- "多架构并行构建"
|
||||
- "测试和构建并行执行"
|
||||
|
||||
cache_strategy:
|
||||
- "Docker Buildx Registry 缓存"
|
||||
- "npm/pip 依赖缓存"
|
||||
- "构建层智能缓存"
|
||||
```
|
||||
|
||||
### 📈 **资源管理**
|
||||
```yaml
|
||||
resource_optimization:
|
||||
cpu_allocation:
|
||||
normal: "2 核心"
|
||||
build: "4 核心"
|
||||
|
||||
memory_allocation:
|
||||
normal: "4GB"
|
||||
build: "8GB"
|
||||
|
||||
disk_usage:
|
||||
cache_size: "50GB"
|
||||
cleanup_policy: "30天"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ 安全配置
|
||||
|
||||
### 🔐 **权限控制**
|
||||
- **Runner 权限**: 仅限构建和部署权限
|
||||
- **K8s RBAC**: 命名空间级最小权限
|
||||
- **镜像仓库权限**: 仅推送权限
|
||||
- **网络访问**: 内网资源优先
|
||||
|
||||
### 🛡️ **安全扫描**
|
||||
```yaml
|
||||
security_scanning:
|
||||
sast:
|
||||
- "Semgrep 静态代码分析"
|
||||
- "Bandit Python 安全扫描"
|
||||
- "ESLint Security 插件"
|
||||
|
||||
sca:
|
||||
- "Trivy 依赖漏洞扫描"
|
||||
- "Safety Python 依赖检查"
|
||||
- "npm audit Node.js 依赖"
|
||||
|
||||
container:
|
||||
- "Docker Scout 镜像扫描"
|
||||
- "SBOM 生成和管理"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 监控和可观测性
|
||||
|
||||
### 📊 **指标监控**
|
||||
```yaml
|
||||
metrics:
|
||||
build_metrics:
|
||||
- "构建时长"
|
||||
- "镜像大小"
|
||||
- "缓存命中率"
|
||||
- "构建成功率"
|
||||
|
||||
deploy_metrics:
|
||||
- "部署时长"
|
||||
- "服务可用性"
|
||||
- "错误率"
|
||||
- "回滚次数"
|
||||
```
|
||||
|
||||
### 📝 **日志管理**
|
||||
```yaml
|
||||
logging:
|
||||
structure:
|
||||
- "结构化 JSON 日志"
|
||||
- "统一日志格式"
|
||||
- "日志聚合和分析"
|
||||
|
||||
retention:
|
||||
- "Runner 日志: 30天"
|
||||
- "应用日志: 7天"
|
||||
- "审计日志: 90天"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 实施阶段
|
||||
|
||||
### 第一阶段:基础环境 ✅
|
||||
- [x] Gitea Actions 启用
|
||||
- [x] Runner 部署和配置
|
||||
- [x] 基础工作流测试
|
||||
|
||||
### 第二阶段:质量门禁 ✅
|
||||
- [x] 前端质量检查
|
||||
- [x] 后端质量检查
|
||||
- [x] API 契约检查
|
||||
- [x] 安全扫描集成
|
||||
|
||||
### 第三阶段:容器化构建 🔄
|
||||
- [ ] Docker Buildx 配置
|
||||
- [ ] 多架构镜像构建
|
||||
- [ ] Harbor 私有仓库集成
|
||||
- [ ] 镜像安全扫描
|
||||
|
||||
### 第四阶段:Kubernetes 部署 📋
|
||||
- [ ] K8s 环境配置
|
||||
- [ ] Helm Chart 开发
|
||||
- [ ] 自动化部署流水线
|
||||
- [ ] 服务健康检查
|
||||
|
||||
### 第五阶段:监控和优化 📋
|
||||
- [ ] 性能监控集成
|
||||
- [ ] 日志聚合系统
|
||||
- [ ] 告警规则配置
|
||||
- [ ] 性能优化调优
|
||||
|
||||
---
|
||||
|
||||
## 🔧 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### Runner 连接问题
|
||||
```bash
|
||||
# 检查 Runner 状态
|
||||
./manage-runner.sh health
|
||||
|
||||
# 检查网络连接
|
||||
curl -f http://localhost:33000/api/v1/version
|
||||
|
||||
# 重新注册 Runner
|
||||
echo -e "http://localhost:33000\nTOKEN\nmacos-runner\nmacos,docker" | act_runner register
|
||||
```
|
||||
|
||||
#### 构建失败问题
|
||||
```bash
|
||||
# 检查 Docker 状态
|
||||
docker info
|
||||
docker buildx ls
|
||||
|
||||
# 清理构建缓存
|
||||
docker buildx prune -f
|
||||
docker system prune -f
|
||||
```
|
||||
|
||||
#### 部署失败问题
|
||||
```bash
|
||||
# 检查 K8s 连接
|
||||
kubectl cluster-info
|
||||
|
||||
# 检查权限
|
||||
kubectl auth can-i create deployments --namespace=ljwx-prod
|
||||
```
|
||||
|
||||
### 调试技巧
|
||||
|
||||
1. **查看详细日志**: `./manage-runner.sh logs`
|
||||
2. **检查配置文件**: `cat runner-config.yaml`
|
||||
3. **验证权限**: `kubectl auth can-i ...`
|
||||
4. **测试网络**: `curl -I http://harbor.local`
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关资源
|
||||
|
||||
### 📖 文档
|
||||
- [Gitea Actions 官方文档](https://docs.gitea.com/next/usage/actions/overview)
|
||||
- [Docker Buildx 指南](https://docs.docker.com/buildx/)
|
||||
- [Kubernetes 部署指南](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
|
||||
|
||||
### 🛠️ 工具
|
||||
- **Helm**: Kubernetes 包管理器
|
||||
- **Trivy**: 容器安全扫描工具
|
||||
- **Buildx**: Docker 多架构构建工具
|
||||
- **Skaffold**: 开发环境部署工具
|
||||
|
||||
### 🌐 社区
|
||||
- **Gitea 官方社区**: https://discourse.gitea.io
|
||||
- **Kubernetes 官方文档**: https://kubernetes.io/docs/
|
||||
- **Docker 官方文档**: https://docs.docker.com/
|
||||
|
||||
---
|
||||
|
||||
## 🎯 总结
|
||||
|
||||
基于 ChatGPT5 专家建议,我们为 LJWX-Stock 项目设计了一套完整的企业级 CI/CD 解决方案:
|
||||
|
||||
✅ **技术选型优化**: 针对 Mac Studio 环境的特殊优化
|
||||
✅ **安全性保障**: 多层次安全防护和权限控制
|
||||
✅ **性能优化**: 多架构并行构建和智能缓存
|
||||
✅ **可扩展性**: 模块化设计,易于扩展和维护
|
||||
✅ **监控完善**: 全链路监控和可观测性
|
||||
|
||||
**🚀 这套方案能够支撑从开发到生产的完整软件交付生命周期!**
|
||||
|
||||
---
|
||||
|
||||
**文档维护**: DevOps 团队
|
||||
**最后更新**: 2025-10-28
|
||||
**版本**: v1.0
|
||||
@@ -0,0 +1,547 @@
|
||||
# 💡 Gitea CI/CD 最佳实践
|
||||
|
||||
> 基于 ChatGPT5 专家建议和企业级实施经验总结的最佳实践
|
||||
|
||||
---
|
||||
|
||||
## 🎯 核心原则
|
||||
|
||||
### 1️⃣ **安全性优先**
|
||||
```yaml
|
||||
security_first:
|
||||
principle: "零信任架构"
|
||||
implementation:
|
||||
- "最小权限原则 (Principle of Least Privilege)"
|
||||
- "所有敏感信息使用 Secrets 管理"
|
||||
- "定期轮换密钥和证书"
|
||||
- "网络隔离和访问控制"
|
||||
```
|
||||
|
||||
### 2️⃣ **性能优化**
|
||||
```yaml
|
||||
performance_optimization:
|
||||
strategy: "缓存优先"
|
||||
implementation:
|
||||
- "多级缓存策略 (Docker + 依赖 + 构建缓存)"
|
||||
- "并行执行和资源复用"
|
||||
- "增量构建和智能依赖分析"
|
||||
- "本地化构建环境优化"
|
||||
```
|
||||
|
||||
### 3️⃣ **可观测性**
|
||||
```yaml
|
||||
observability:
|
||||
strategy: "全链路监控"
|
||||
implementation:
|
||||
- "结构化日志记录"
|
||||
- "关键指标收集和告警"
|
||||
- "分布式追踪集成"
|
||||
- "性能分析和优化"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Runner 配置最佳实践
|
||||
|
||||
### ✅ **Mac Studio 优化配置**
|
||||
```yaml
|
||||
# 推荐的 Runner 配置
|
||||
mac_runner_config:
|
||||
# 执行器选择
|
||||
executor: "docker"
|
||||
docker_socket: true # Mac 环境推荐
|
||||
buildx_enabled: true # 多架构构建支持
|
||||
|
||||
# 资源配置
|
||||
capacity: 2 # 并发任务数
|
||||
timeout: 3600s # 任务超时时间
|
||||
idle_timeout: 300s # 空闲超时
|
||||
|
||||
# 环境变量
|
||||
envs:
|
||||
- DOCKER_BUILDKIT=1
|
||||
- BUILDKIT_PROGRESS=plain
|
||||
- COMPOSE_DOCKER_CLI_BUILD=1
|
||||
|
||||
# 卷挂载 (关键)
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /var/tmp/buildx:/tmp/buildx
|
||||
- /Users/brunogao/.docker:/root/.docker:ro
|
||||
- /Users/brunogao/.cache/runner:/data/runner-cache
|
||||
|
||||
# 标签配置
|
||||
labels:
|
||||
- "macos:docker"
|
||||
- "linux:docker"
|
||||
- "multi-arch:builder"
|
||||
- "arm64:native"
|
||||
```
|
||||
|
||||
### 🚫 **避免的配置**
|
||||
```yaml
|
||||
avoid_configurations:
|
||||
# Mac 环境避免 DinD
|
||||
dind_on_mac: "性能差,网络问题多"
|
||||
|
||||
# 避免过度权限
|
||||
excessive_privileges: "安全风险高"
|
||||
|
||||
# 避免无限制资源
|
||||
unlimited_resources: "可能导致系统不稳定"
|
||||
|
||||
# 避免缓存位置不当
|
||||
tmp_cache_location: "重启后丢失"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Docker 构建最佳实践
|
||||
|
||||
### ✅ **多架构构建优化**
|
||||
```dockerfile
|
||||
# 优化的 Dockerfile 示例
|
||||
FROM --platform=$BUILDPLATFORM python:3.11-slim as base
|
||||
|
||||
# 使用多阶段构建减少镜像大小
|
||||
FROM base as builder
|
||||
WORKDIR /app
|
||||
|
||||
# 优化依赖层缓存
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
RUN pip install .
|
||||
|
||||
# 生产镜像
|
||||
FROM base as production
|
||||
WORKDIR /app
|
||||
|
||||
# 非root 用户运行
|
||||
RUN adduser --disabled-password --gecos '' appuser
|
||||
USER appuser
|
||||
|
||||
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
|
||||
COPY --from=builder /app .
|
||||
|
||||
EXPOSE 8000
|
||||
CMD ["python", "app.py"]
|
||||
```
|
||||
|
||||
### ⚡ **构建缓存策略**
|
||||
```yaml
|
||||
# buildx 缓存配置
|
||||
build_cache_config:
|
||||
# Registry 缓存 (推荐)
|
||||
registry_cache:
|
||||
type: "registry"
|
||||
ref: "harbor.local/ljwx/buildkit-cache"
|
||||
mode: "max"
|
||||
|
||||
# 本地缓存 (补充)
|
||||
local_cache:
|
||||
type: "local"
|
||||
path: "/var/tmp/buildx"
|
||||
max_size: "10GB"
|
||||
|
||||
# 缓存键策略
|
||||
cache_keys:
|
||||
- "base-image-digest"
|
||||
- "requirements-hash"
|
||||
- "source-hash"
|
||||
```
|
||||
|
||||
### 🏷️ **镜像标签策略**
|
||||
```yaml
|
||||
image_tagging_strategy:
|
||||
# 语义化标签
|
||||
semantic_tags:
|
||||
- "{branch}-{short-sha}" # develop-abc123
|
||||
- "v{major}.{minor}" # v1.2
|
||||
- "latest" # 主分支最新
|
||||
|
||||
# 自动标签
|
||||
auto_tags:
|
||||
- "pr-{pr-number}" # PR 特定标签
|
||||
- "ci-{build-number}" # CI 构建标签
|
||||
- "review-{commit-sha}" # 代码审查标签
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 安全最佳实践
|
||||
|
||||
### 🛡️ **密钥管理**
|
||||
```yaml
|
||||
secrets_management:
|
||||
# 存储原则
|
||||
storage_rules:
|
||||
- "绝不将密钥写入代码"
|
||||
- "使用 Gitea Secrets 管理"
|
||||
- "定期轮换敏感信息"
|
||||
- "最小权限访问控制"
|
||||
|
||||
# 密钥分类
|
||||
secret_categories:
|
||||
credentials:
|
||||
- HARBOR_USER/HARBOR_PASS
|
||||
- KUBECONFIG_B64
|
||||
- API_TOKENS
|
||||
|
||||
configuration:
|
||||
- DATABASE_URL
|
||||
- REDIS_URL
|
||||
- SMTP_PASSWORD
|
||||
|
||||
external_services:
|
||||
- SLACK_WEBHOOK
|
||||
- SENTRY_DSN
|
||||
- SONARQUBE_TOKEN
|
||||
```
|
||||
|
||||
### 🔍 **安全扫描集成**
|
||||
```yaml
|
||||
security_scanning_pipeline:
|
||||
# SAST (静态应用安全测试)
|
||||
sast_tools:
|
||||
- name: "Semgrep"
|
||||
target: "代码逻辑漏洞"
|
||||
- name: "Bandit"
|
||||
target: "Python 代码"
|
||||
- name: "ESLint Security"
|
||||
target: "JavaScript 代码"
|
||||
|
||||
# SCA (软件组件分析)
|
||||
sca_tools:
|
||||
- name: "Trivy"
|
||||
target: "依赖漏洞"
|
||||
- name: "Safety"
|
||||
target: "Python 依赖"
|
||||
- name: "npm audit"
|
||||
target: "Node.js 依赖"
|
||||
|
||||
# 容器安全
|
||||
container_security:
|
||||
- name: "Docker Scout"
|
||||
target: "镜像漏洞"
|
||||
- name: "Trivy Image"
|
||||
target: "运行时漏洞"
|
||||
```
|
||||
|
||||
### 🌐 **网络安全配置**
|
||||
```yaml
|
||||
network_security:
|
||||
# 网络策略
|
||||
network_policies:
|
||||
- name: "ingress-only"
|
||||
description: "仅允许入站流量"
|
||||
rules:
|
||||
- from: ["ingress-nginx"]
|
||||
ports: [80, 443]
|
||||
|
||||
- name: "egress-restricted"
|
||||
description: "限制出站流量"
|
||||
rules:
|
||||
- to: ["dns", "docker-registry"]
|
||||
ports: [53, 443]
|
||||
|
||||
# TLS 配置
|
||||
tls_config:
|
||||
- "强制 HTTPS 通信"
|
||||
- "使用 Let's Encrypt 证书"
|
||||
- "定期证书轮换"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 监控和告警最佳实践
|
||||
|
||||
### 📈 **关键指标定义**
|
||||
```yaml
|
||||
key_metrics:
|
||||
# 构建指标
|
||||
build_metrics:
|
||||
- "build_duration" # 构建时长
|
||||
- "build_success_rate" # 构建成功率
|
||||
- "cache_hit_rate" # 缓存命中率
|
||||
- "image_size" # 镜像大小
|
||||
|
||||
# 部署指标
|
||||
deploy_metrics:
|
||||
- "deploy_duration" # 部署时长
|
||||
- "deploy_success_rate" # 部署成功率
|
||||
- "rollback_count" # 回滚次数
|
||||
- "service_availability" # 服务可用性
|
||||
|
||||
# 运行时指标
|
||||
runtime_metrics:
|
||||
- "response_time_p95" # 95% 响应时间
|
||||
- "error_rate" # 错误率
|
||||
- "throughput" # 吞吐量
|
||||
- "resource_utilization" # 资源利用率
|
||||
```
|
||||
|
||||
### 🚨 **告警规则配置**
|
||||
```yaml
|
||||
alerting_rules:
|
||||
# 关键告警
|
||||
critical_alerts:
|
||||
- name: "构建失败率过高"
|
||||
condition: "build_success_rate < 95%"
|
||||
duration: "15m"
|
||||
severity: "critical"
|
||||
|
||||
- name: "服务不可用"
|
||||
condition: "service_availability < 99%"
|
||||
duration: "5m"
|
||||
severity: "critical"
|
||||
|
||||
# 警告告警
|
||||
warning_alerts:
|
||||
- name: "构建时间过长"
|
||||
condition: "build_duration > 10m"
|
||||
duration: "5m"
|
||||
severity: "warning"
|
||||
|
||||
- name: "缓存命中率低"
|
||||
condition: "cache_hit_rate < 80%"
|
||||
duration: "30m"
|
||||
severity: "warning"
|
||||
```
|
||||
|
||||
### 📝 **日志最佳实践**
|
||||
```yaml
|
||||
logging_best_practices:
|
||||
# 日志格式
|
||||
log_format:
|
||||
- "使用结构化 JSON 格式"
|
||||
- "统一时间戳格式 (ISO 8601)"
|
||||
- "包含上下文信息 (request_id, trace_id)"
|
||||
- "区分日志级别 (debug, info, warn, error)"
|
||||
|
||||
# 日志内容
|
||||
log_content:
|
||||
- "操作开始和结束时间"
|
||||
- "关键参数和配置"
|
||||
- "错误堆栈和上下文"
|
||||
- "性能指标和统计"
|
||||
|
||||
# 日志保留
|
||||
log_retention:
|
||||
- "应用日志: 7天"
|
||||
- "审计日志: 90天"
|
||||
- "错误日志: 30天"
|
||||
- "访问日志: 30天"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 工作流设计最佳实践
|
||||
|
||||
### 📋 **工作流结构**
|
||||
```yaml
|
||||
workflow_structure:
|
||||
# 分阶段执行
|
||||
stages:
|
||||
- name: "质量门禁"
|
||||
jobs: ["lint", "test", "security"]
|
||||
parallel: true
|
||||
|
||||
- name: "构建"
|
||||
jobs: ["build", "package"]
|
||||
depends_on: "质量门禁"
|
||||
|
||||
- name: "部署"
|
||||
jobs: ["deploy", "verify"]
|
||||
depends_on: "构建"
|
||||
environment: "production"
|
||||
|
||||
# 错误处理
|
||||
error_handling:
|
||||
- "失败时自动清理临时资源"
|
||||
- "发送详细的错误通知"
|
||||
- "提供故障恢复建议"
|
||||
- "记录错误到审计日志"
|
||||
```
|
||||
|
||||
### ⚡ **性能优化策略**
|
||||
```yaml
|
||||
performance_optimizations:
|
||||
# 并行执行
|
||||
parallel_execution:
|
||||
- "独立任务并行执行"
|
||||
- "矩阵策略并行测试"
|
||||
- "分阶段并行构建"
|
||||
|
||||
# 缓存策略
|
||||
caching_strategies:
|
||||
- "依赖缓存: npm/pip/go modules"
|
||||
- "构建缓存: Docker layers"
|
||||
- "测试缓存: test results"
|
||||
- "制品缓存: build artifacts"
|
||||
|
||||
# 资源优化
|
||||
resource_optimization:
|
||||
- "合理设置并发数"
|
||||
- "动态资源分配"
|
||||
- "空闲时释放资源"
|
||||
- "峰值时弹性扩容"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 故障排除指南
|
||||
|
||||
### 🔍 **常见问题诊断**
|
||||
|
||||
#### Runner 问题
|
||||
```bash
|
||||
# Runner 连接问题
|
||||
symptoms: "Runner 离线,无法接收任务"
|
||||
diagnosis:
|
||||
- "检查 Runner 进程状态: ps aux | grep act_runner"
|
||||
- "检查网络连接: curl -f http://localhost:33000/api/v1/version"
|
||||
- "检查 Runner 日志: tail -f runner.log"
|
||||
- "检查配置文件: cat .runner | jq ."
|
||||
|
||||
solutions:
|
||||
- "重启 Runner: ./manage-runner.sh restart"
|
||||
- "重新注册: echo -e 'URL\\nTOKEN\\nNAME\\nLABELS' | act_runner register"
|
||||
- "检查防火墙设置"
|
||||
```
|
||||
|
||||
#### 构建问题
|
||||
```bash
|
||||
# Docker 构建失败
|
||||
symptoms: "Docker 构建超时或失败"
|
||||
diagnosis:
|
||||
- "检查 Docker 状态: docker info"
|
||||
- "检查磁盘空间: df -h"
|
||||
- "检查网络连接: ping registry"
|
||||
- "检查构建日志: docker buildx ls"
|
||||
|
||||
solutions:
|
||||
- "清理 Docker 缓存: docker system prune -f"
|
||||
- "增加构建超时时间"
|
||||
- "使用镜像加速器"
|
||||
- "检查 Dockerfile 优化"
|
||||
```
|
||||
|
||||
#### 部署问题
|
||||
```bash
|
||||
# Kubernetes 部署失败
|
||||
symptoms: "Pod 无法启动或服务不可用"
|
||||
diagnosis:
|
||||
- "检查 Pod 状态: kubectl get pods -n namespace"
|
||||
- "检查 Pod 日志: kubectl logs pod-name -n namespace"
|
||||
- "检查资源使用: kubectl top pods -n namespace"
|
||||
- "检查事件: kubectl get events -n namespace"
|
||||
|
||||
solutions:
|
||||
- "检查镜像拉取权限"
|
||||
- "检查资源配置 (CPU/内存)"
|
||||
- "检查网络策略配置"
|
||||
- "检查存储挂载"
|
||||
```
|
||||
|
||||
### 🔧 **性能调优技巧**
|
||||
|
||||
#### 构建性能优化
|
||||
```bash
|
||||
# Docker Buildx 优化
|
||||
docker buildx bake --load
|
||||
docker buildx prune --filter until=24h
|
||||
|
||||
# 依赖缓存优化
|
||||
npm ci --prefer-offline
|
||||
pip install --cache-dir /path/to/cache
|
||||
|
||||
# 并行构建
|
||||
docker buildx build --platform linux/amd64,linux/arm64 .
|
||||
```
|
||||
|
||||
#### Runner 资源优化
|
||||
```yaml
|
||||
# 根据系统配置调整
|
||||
resource_tuning:
|
||||
high_end_system: # 16GB+ 内存
|
||||
capacity: 4
|
||||
cpu_limit: "6000m"
|
||||
memory_limit: "8Gi"
|
||||
|
||||
mid_range_system: # 8-16GB 内存
|
||||
capacity: 2
|
||||
cpu_limit: "4000m"
|
||||
memory_limit: "4Gi"
|
||||
|
||||
low_end_system: # <8GB 内存
|
||||
capacity: 1
|
||||
cpu_limit: "2000m"
|
||||
memory_limit: "2Gi"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 持续改进
|
||||
|
||||
### 🎯 **定期审查**
|
||||
```yaml
|
||||
review_schedule:
|
||||
monthly:
|
||||
- "审查构建性能指标"
|
||||
- "更新安全扫描规则"
|
||||
- "清理过期的缓存和镜像"
|
||||
- "审查 Runner 配置"
|
||||
|
||||
quarterly:
|
||||
- "更新依赖版本"
|
||||
- "优化工作流配置"
|
||||
- "审查安全策略"
|
||||
- "性能基准测试"
|
||||
|
||||
annually:
|
||||
- "架构设计审查"
|
||||
- "技术栈评估"
|
||||
- "成本效益分析"
|
||||
"长期规划制定"
|
||||
```
|
||||
|
||||
### 📊 **指标驱动优化**
|
||||
```yaml
|
||||
optimization_metrics:
|
||||
build_performance:
|
||||
- "目标: 构建时间 < 5分钟"
|
||||
- "当前: 平均 8分钟"
|
||||
- "行动: 优化 Dockerfile 和缓存策略"
|
||||
|
||||
deploy_success:
|
||||
- "目标: 部署成功率 > 99%"
|
||||
- "当前: 95%"
|
||||
- "行动: 改进测试覆盖率和预部署验证"
|
||||
|
||||
cost_efficiency:
|
||||
- "目标: CI/CD 成本 < $100/月"
|
||||
- "当前: $150/月"
|
||||
- "行动: 优化资源使用和缓存效率"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 总结
|
||||
|
||||
这些最佳实践基于 ChatGPT5 专家建议和企业级实施经验总结:
|
||||
|
||||
✅ **安全性**: 多层防护,零信任架构
|
||||
✅ **性能**: 优化缓存,并行执行
|
||||
✅ **可观测性**: 全链路监控,结构化日志
|
||||
✅ **可维护性**: 模块化设计,标准化流程
|
||||
✅ **可扩展性**: 弹性架构,按需扩容
|
||||
|
||||
**🚀 遵循这些最佳实践,可以构建稳定、高效、安全的企业级 CI/CD 流水线!**
|
||||
|
||||
---
|
||||
|
||||
**文档维护**: DevOps 团队
|
||||
**最后更新**: 2025-10-28
|
||||
**版本**: v1.0
|
||||
Executable
+381
@@ -0,0 +1,381 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Kubernetes 环境配置脚本
|
||||
# 适用于 LJWX-Stock 项目的 K8s 部署环境搭建
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 日志函数
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
||||
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
# 配置变量
|
||||
NAMESPACE="ljwx-prod"
|
||||
SERVICE_ACCOUNT="gitea-deployer"
|
||||
CLUSTER_NAME="k3s-default"
|
||||
KUBECONFIG_FILE="$HOME/.kube/config-ljwx"
|
||||
|
||||
# 检查 kubectl 是否安装
|
||||
check_dependencies() {
|
||||
log_info "🔍 检查依赖..."
|
||||
|
||||
if ! command -v kubectl &> /dev/null; then
|
||||
log_error "❌ kubectl 未安装,请先安装 kubectl"
|
||||
echo "安装方法: brew install kubectl"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v helm &> /dev/null; then
|
||||
log_warning "⚠️ Helm 未安装,建议安装 Helm"
|
||||
echo "安装方法: brew install helm"
|
||||
fi
|
||||
|
||||
log_success "✅ 依赖检查完成"
|
||||
}
|
||||
|
||||
# 检查 Kubernetes 集群连接
|
||||
check_cluster() {
|
||||
log_info "🔍 检查 Kubernetes 集群连接..."
|
||||
|
||||
if ! kubectl cluster-info &> /dev/null; then
|
||||
log_error "❌ 无法连接到 Kubernetes 集群"
|
||||
echo "请确保集群正在运行并且 kubeconfig 配置正确"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "✅ Kubernetes 集群连接正常"
|
||||
kubectl cluster-info
|
||||
}
|
||||
|
||||
# 创建命名空间
|
||||
create_namespace() {
|
||||
log_info "📝 创建命名空间: $NAMESPACE"
|
||||
|
||||
if kubectl get namespace $NAMESPACE &> /dev/null; then
|
||||
log_warning "⚠️ 命名空间 $NAMESPACE 已存在"
|
||||
else
|
||||
kubectl create namespace $NAMESPACE
|
||||
log_success "✅ 命名空间 $NAMESPACE 创建成功"
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建 ServiceAccount
|
||||
create_service_account() {
|
||||
log_info "👤 创建 ServiceAccount: $SERVICE_ACCOUNT"
|
||||
|
||||
cat > service-account.yaml << EOF
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: $SERVICE_ACCOUNT
|
||||
namespace: $NAMESPACE
|
||||
labels:
|
||||
app: ljwx
|
||||
component: deployer
|
||||
EOF
|
||||
|
||||
if kubectl get serviceaccount $SERVICE_ACCOUNT -n $NAMESPACE &> /dev/null; then
|
||||
log_warning "⚠️ ServiceAccount $SERVICE_ACCOUNT 已存在"
|
||||
else
|
||||
kubectl apply -f service-account.yaml
|
||||
log_success "✅ ServiceAccount $SERVICE_ACCOUNT 创建成功"
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建 RBAC 权限
|
||||
create_rbac() {
|
||||
log_info "🔐 创建 RBAC 权限配置"
|
||||
|
||||
cat > rbac.yaml << EOF
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: deployer-role
|
||||
namespace: $NAMESPACE
|
||||
labels:
|
||||
app: ljwx
|
||||
component: rbac
|
||||
rules:
|
||||
# 核心资源权限
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "services", "configmaps", "secrets", "persistentvolumeclaims"]
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||
|
||||
# 应用资源权限
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["deployments", "statefulsets", "daemonsets", "replicasets"]
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||
|
||||
# 批处理任务权限
|
||||
- apiGroups: ["batch"]
|
||||
resources: ["jobs", "cronjobs"]
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||
|
||||
# 网络权限
|
||||
- apiGroups: ["networking.k8s.io"]
|
||||
resources: ["ingresses", "networkpolicies"]
|
||||
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
||||
|
||||
# 自动扩缩容权限
|
||||
- apiGroups: ["autoscaling"]
|
||||
resources: ["horizontalpodautoscalers"]
|
||||
verbs: ["get", "list", "watch", "update", "patch"]
|
||||
|
||||
# 监控权限
|
||||
- apiGroups: ["metrics.k8s.io"]
|
||||
resources: ["pods", "nodes"]
|
||||
verbs: ["get", "list"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: deployer-binding
|
||||
namespace: $NAMESPACE
|
||||
labels:
|
||||
app: ljwx
|
||||
component: rbac
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: $SERVICE_ACCOUNT
|
||||
namespace: $NAMESPACE
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: deployer-role
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
EOF
|
||||
|
||||
kubectl apply -f rbac.yaml
|
||||
log_success "✅ RBAC 权限配置创建成功"
|
||||
}
|
||||
|
||||
# 生成受限的 kubeconfig
|
||||
generate_kubeconfig() {
|
||||
log_info "🔑 生成受限的 kubeconfig"
|
||||
|
||||
# 获取 ServiceAccount Token
|
||||
SERVICE_ACCOUNT_NAME=$(kubectl get serviceaccount $SERVICE_ACCOUNT -n $NAMESPACE -o jsonpath='{.secrets[0].name}')
|
||||
TOKEN=$(kubectl get secret $SERVICE_ACCOUNT_NAME -n $NAMESPACE -o jsonpath='{.data.token}' | base64 -d)
|
||||
|
||||
# 获取 CA 证书
|
||||
CA_CERT=$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
|
||||
|
||||
# 获取 API Server 地址
|
||||
API_SERVER=$(kubectl config view --raw -o jsonpath='{.clusters[0].cluster.server}')
|
||||
|
||||
# 生成受限 kubeconfig
|
||||
cat > restricted-kubeconfig.yaml << EOF
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
clusters:
|
||||
- name: $CLUSTER_NAME
|
||||
cluster:
|
||||
certificate-authority-data: $CA_CERT
|
||||
server: $API_SERVER
|
||||
contexts:
|
||||
- name: $NAMESPACE-context
|
||||
context:
|
||||
cluster: $CLUSTER_NAME
|
||||
namespace: $NAMESPACE
|
||||
user: $SERVICE_ACCOUNT
|
||||
current-context: $NAMESPACE-context
|
||||
users:
|
||||
- name: $SERVICE_ACCOUNT
|
||||
user:
|
||||
token: $TOKEN
|
||||
EOF
|
||||
|
||||
# 复制到用户目录
|
||||
cp restricted-kubeconfig.yaml $KUBECONFIG_FILE
|
||||
chmod 600 $KUBECONFIG_FILE
|
||||
|
||||
log_success "✅ 受限 kubeconfig 生成完成: $KUBECONFIG_FILE"
|
||||
|
||||
# 生成 Base64 编码(用于 Gitea Secrets)
|
||||
KUBECONFIG_B64=$(cat $KUBECONFIG_FILE | base64 -w 0)
|
||||
echo ""
|
||||
log_info "🔐 Gitea Secret 配置:"
|
||||
echo "----------------------------------------"
|
||||
echo "KUBECONFIG_B64=$KUBECONFIG_B64"
|
||||
echo "----------------------------------------"
|
||||
echo "请将上面的值配置到 Gitea 仓库的 Secrets 中"
|
||||
}
|
||||
|
||||
# 创建网络策略
|
||||
create_network_policy() {
|
||||
log_info "🛡️ 创建网络策略"
|
||||
|
||||
cat > network-policy.yaml << EOF
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: ljwx-network-policy
|
||||
namespace: $NAMESPACE
|
||||
labels:
|
||||
app: ljwx
|
||||
component: security
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: ljwx
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: ingress-nginx
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
egress:
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: kube-system
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 53
|
||||
- protocol: UDP
|
||||
port: 53
|
||||
- to: []
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
EOF
|
||||
|
||||
kubectl apply -f network-policy.yaml
|
||||
log_success "✅ 网络策略创建成功"
|
||||
}
|
||||
|
||||
# 创建资源配额
|
||||
create_resource_quota() {
|
||||
log_info "📊 创建资源配额"
|
||||
|
||||
cat > resource-quota.yaml << EOF
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ResourceQuota
|
||||
metadata:
|
||||
name: ljwx-quota
|
||||
namespace: $NAMESPACE
|
||||
labels:
|
||||
app: ljwx
|
||||
component: quota
|
||||
spec:
|
||||
hard:
|
||||
requests.cpu: "4"
|
||||
requests.memory: 8Gi
|
||||
limits.cpu: "8"
|
||||
limits.memory: 16Gi
|
||||
persistentvolumeclaims: "5"
|
||||
pods: "20"
|
||||
services: "10"
|
||||
secrets: "10"
|
||||
configmaps: "10"
|
||||
count/deployments.apps: "10"
|
||||
count/statefulsets.apps: "5"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: LimitRange
|
||||
metadata:
|
||||
name: ljwx-limits
|
||||
namespace: $NAMESPACE
|
||||
labels:
|
||||
app: ljwx
|
||||
component: limits
|
||||
spec:
|
||||
limits:
|
||||
- default:
|
||||
cpu: "1000m"
|
||||
memory: "1Gi"
|
||||
defaultRequest:
|
||||
cpu: "100m"
|
||||
memory: "128Mi"
|
||||
type: Container
|
||||
- max:
|
||||
cpu: "4000m"
|
||||
memory: "4Gi"
|
||||
min:
|
||||
cpu: "50m"
|
||||
memory: "64Mi"
|
||||
type: Container
|
||||
EOF
|
||||
|
||||
kubectl apply -f resource-quota.yaml
|
||||
log_success "✅ 资源配额创建成功"
|
||||
}
|
||||
|
||||
# 验证配置
|
||||
verify_setup() {
|
||||
log_info "✅ 验证配置..."
|
||||
|
||||
echo ""
|
||||
log_info "📋 创建的资源:"
|
||||
kubectl get namespace $NAMESPACE
|
||||
kubectl get serviceaccount $SERVICE_ACCOUNT -n $NAMESPACE
|
||||
kubectl get role,rolebinding -n $NAMESPACE | grep deployer
|
||||
|
||||
echo ""
|
||||
log_info "🔐 权限测试:"
|
||||
kubectl auth can-i create deployments --namespace=$NAMESPACE --as=system:serviceaccount:$NAMESPACE:$SERVICE_ACCOUNT
|
||||
kubectl auth can-i get pods --namespace=$NAMESPACE --as=system:serviceaccount:$NAMESPACE:$SERVICE_ACCOUNT
|
||||
kubectl auth can-i create services --namespace=$NAMESPACE --as=system:serviceaccount:$NAMESPACE:$SERVICE_ACCOUNT
|
||||
|
||||
echo ""
|
||||
log_info "📊 资源配额:"
|
||||
kubectl describe resourcequota ljwx-quota -n $NAMESPACE
|
||||
}
|
||||
|
||||
# 清理函数
|
||||
cleanup() {
|
||||
log_warning "🧹 清理临时文件..."
|
||||
rm -f service-account.yaml rbac.yaml network-policy.yaml resource-quota.yaml restricted-kubeconfig.yaml
|
||||
log_success "✅ 清理完成"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo -e "${BLUE}🚀 LJWX-Stock Kubernetes 环境配置${NC}"
|
||||
echo "=================================="
|
||||
|
||||
check_dependencies
|
||||
check_cluster
|
||||
create_namespace
|
||||
create_service_account
|
||||
create_rbac
|
||||
generate_kubeconfig
|
||||
create_network_policy
|
||||
create_resource_quota
|
||||
verify_setup
|
||||
cleanup
|
||||
|
||||
echo ""
|
||||
log_success "🎉 Kubernetes 环境配置完成!"
|
||||
echo ""
|
||||
log_info "📋 下一步操作:"
|
||||
echo "1. 将 KUBECONFIG_B64 配置到 Gitea Secrets"
|
||||
echo "2. 配置 Helm Charts"
|
||||
echo "3. 测试 CI/CD 流水线"
|
||||
echo ""
|
||||
log_info "📚 相关文档:"
|
||||
echo "- Kubernetes 配置: docs/cicd/k8s-setup.sh"
|
||||
echo "- CI/CD 指南: docs/cicd/GITEA_ENTERPRISE_CICD_GUIDE.md"
|
||||
echo "- Helm Charts: docs/helm/"
|
||||
}
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
@@ -0,0 +1,139 @@
|
||||
# Gitea Runner 配置文件
|
||||
# 适用于 Mac Studio (Apple Silicon) + Orbstack 环境
|
||||
|
||||
log:
|
||||
level: info
|
||||
format: json
|
||||
|
||||
runner:
|
||||
# 并发配置
|
||||
capacity: 2 # 同时最多并发 Job 数
|
||||
timeout: 3600s # 单个任务超时时间
|
||||
idle_timeout: 300s # 空闲超时
|
||||
|
||||
# 环境变量
|
||||
envs:
|
||||
- DOCKER_BUILDKIT=1 # 启用 BuildKit
|
||||
- BUILDKIT_PROGRESS=plain # 构建进度显示
|
||||
- COMPOSE_DOCKER_CLI_BUILD=1 # 启用 Docker Compose BuildKit
|
||||
- DOCKER_CLI_EXPERIMENTAL=enabled # 启用实验性功能
|
||||
|
||||
# Runner 标签(用于工作流匹配)
|
||||
labels:
|
||||
- "macos:docker" # Mac 专用标签
|
||||
- "linux:docker" # Linux 兼容标签
|
||||
- "multi-arch:builder" # 多架构构建标签
|
||||
- "arm64:native" # ARM64 原生构建
|
||||
- "builder:docker" # Docker 构建器
|
||||
|
||||
# 缓存配置
|
||||
cache:
|
||||
enabled: true
|
||||
dir: /data/runner-cache # 需要挂载到持久化磁盘
|
||||
max_size: "10GB" # 最大缓存大小
|
||||
cleanup_age: "168h" # 缓存清理时间(7天)
|
||||
|
||||
# 容器配置
|
||||
container:
|
||||
network: bridge
|
||||
privileged: false # 默认不启用特权模式
|
||||
|
||||
# 卷挂载配置
|
||||
volumes:
|
||||
# Docker Socket 挂载(用于构建)
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
|
||||
# 构建缓存目录
|
||||
- /var/tmp/buildx:/tmp/buildx
|
||||
|
||||
# Docker 配置缓存
|
||||
- /Users/brunogao/.docker:/root/.docker:ro
|
||||
|
||||
# 项目缓存目录
|
||||
- /Users/brunogao/.cache/runner:/data/runner-cache
|
||||
|
||||
# npm 缓存
|
||||
- /Users/brunogao/.npm:/root/.npm
|
||||
|
||||
# pip 缓存
|
||||
- /Users/brunogao/.cache/pip:/root/.cache/pip
|
||||
|
||||
# Go 模块缓存
|
||||
- /Users/brunogao/go/pkg:/root/go/pkg
|
||||
|
||||
# 网络配置
|
||||
network:
|
||||
# 允许的域名(安全控制)
|
||||
allowed_hosts:
|
||||
- "localhost"
|
||||
- "*.local"
|
||||
- "harbor.local"
|
||||
- "gitea.local"
|
||||
- "registry-1.docker.io"
|
||||
- "ghcr.io"
|
||||
- "quay.io"
|
||||
|
||||
# 资源限制
|
||||
resource:
|
||||
# 默认资源限制
|
||||
default:
|
||||
cpu_limit: "2000m" # 2 CPU 核心
|
||||
memory_limit: "4Gi" # 4GB 内存
|
||||
disk_limit: "50Gi" # 50GB 磁盘
|
||||
|
||||
# 构建任务资源限制
|
||||
build:
|
||||
cpu_limit: "4000m" # 4 CPU 核心(构建时)
|
||||
memory_limit: "8Gi" # 8GB 内存(构建时)
|
||||
disk_limit: "100Gi" # 100GB 磁盘(构建时)
|
||||
|
||||
# 安全配置
|
||||
security:
|
||||
# 禁止的操作
|
||||
forbidden_commands:
|
||||
- "rm -rf /"
|
||||
- "dd if=/dev/zero"
|
||||
- "forkbomb"
|
||||
|
||||
# 允许的镜像仓库
|
||||
allowed_registries:
|
||||
- "docker.io"
|
||||
- "ghcr.io"
|
||||
- "quay.io"
|
||||
- "harbor.local"
|
||||
- "registry.gitlab.com"
|
||||
|
||||
# 环境特定配置
|
||||
environment:
|
||||
name: "development"
|
||||
|
||||
# Mac 特定配置
|
||||
macos:
|
||||
docker_desktop_compatible: true
|
||||
orbstack_enabled: true
|
||||
|
||||
# 开发环境特定配置
|
||||
development:
|
||||
debug_enabled: true
|
||||
verbose_logging: true
|
||||
cleanup_on_exit: false
|
||||
|
||||
# 监控配置
|
||||
monitoring:
|
||||
metrics_enabled: true
|
||||
health_check_interval: "30s"
|
||||
performance_profiling: true
|
||||
|
||||
# 通知配置
|
||||
notifications:
|
||||
# Slack 通知(可选)
|
||||
slack:
|
||||
webhook_url: "${SLACK_WEBHOOK_URL}"
|
||||
channel: "#ci-cd"
|
||||
|
||||
# 邮件通知(可选)
|
||||
email:
|
||||
smtp_server: "${SMTP_SERVER}"
|
||||
smtp_port: 587
|
||||
username: "${SMTP_USER}"
|
||||
password: "${SMTP_PASS}"
|
||||
@@ -0,0 +1,46 @@
|
||||
-- LJWX-Stock 数据库初始化脚本
|
||||
-- 创建基础表结构
|
||||
|
||||
-- 用户表
|
||||
CREATE TABLE IF NOT EXISTS app_user (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(64) UNIQUE NOT NULL,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 股票基本信息表
|
||||
CREATE TABLE IF NOT EXISTS stock_basic (
|
||||
ts_code VARCHAR(16) PRIMARY KEY,
|
||||
symbol VARCHAR(16) NOT NULL,
|
||||
name VARCHAR(32) NOT NULL,
|
||||
market VARCHAR(16),
|
||||
industry VARCHAR(32),
|
||||
area VARCHAR(32),
|
||||
list_date DATE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 推荐结果表
|
||||
CREATE TABLE IF NOT EXISTS recommendation_result (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id VARCHAR(32),
|
||||
ts_code VARCHAR(16) NOT NULL,
|
||||
prediction_return DECIMAL(8,4) NOT NULL,
|
||||
recommendation_level VARCHAR(32),
|
||||
confidence_score DECIMAL(3,2),
|
||||
key_factors JSON,
|
||||
model_version VARCHAR(32),
|
||||
status VARCHAR(32) DEFAULT 'pending',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
processed_at TIMESTAMP NULL
|
||||
);
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_recommendation_user ON recommendation_result(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_recommendation_ts_code ON recommendation_result(ts_code);
|
||||
CREATE INDEX IF NOT EXISTS idx_recommendation_created ON recommendation_result(created_at);
|
||||
@@ -0,0 +1,57 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# PostgreSQL数据库
|
||||
postgres:
|
||||
image: postgres:15
|
||||
container_name: ljwx-postgres
|
||||
environment:
|
||||
POSTGRES_DB: ljwx_stock
|
||||
POSTGRES_USER: ljwx_user
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ljwx_password}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./db/init:/docker-entrypoint-initdb.d
|
||||
networks:
|
||||
- ljwx-network
|
||||
restart: unless-stopped
|
||||
|
||||
# Redis缓存
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: ljwx-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- ljwx-network
|
||||
restart: unless-stopped
|
||||
|
||||
# MinIO对象存储
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
container_name: ljwx-minio
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
|
||||
ports:
|
||||
- "9002:9000"
|
||||
- "9003:9001"
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
command: server /data --console-address ":9001"
|
||||
networks:
|
||||
- ljwx-network
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
minio_data:
|
||||
|
||||
networks:
|
||||
ljwx-network:
|
||||
driver: bridge
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🛑 停止LJWX-Stock开发环境..."
|
||||
|
||||
# 进入infra/docker目录
|
||||
cd infra/docker
|
||||
|
||||
# 停止并移除容器
|
||||
echo "🔄 停止Docker容器..."
|
||||
docker-compose -f docker-compose.dev.yml down
|
||||
|
||||
# 询问是否删除数据卷
|
||||
read -p "是否删除数据卷?(y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "🗑️ 删除数据卷..."
|
||||
docker-compose -f docker-compose.dev.yml down -v
|
||||
docker system prune -f
|
||||
echo "✅ 数据卷已删除"
|
||||
fi
|
||||
|
||||
# 检查是否有Claude进程在运行
|
||||
echo "🔍 检查Claude进程..."
|
||||
CLAUDE_PROCESSES=$(pgrep -f "claude_task_manager.py\|monitor_dashboard.py" || true)
|
||||
|
||||
if [ ! -z "$CLAUDE_PROCESSES" ]; then
|
||||
echo "🔄 停止Claude进程..."
|
||||
echo "$CLAUDE_PROCESSES" | xargs kill -TERM 2>/dev/null || true
|
||||
sleep 2
|
||||
|
||||
# 强制杀死仍在运行的进程
|
||||
REMAINING_PROCESSES=$(pgrep -f "claude_task_manager.py\|monitor_dashboard.py" || true)
|
||||
if [ ! -z "$REMAINING_PROCESSES" ]; then
|
||||
echo "$REMAINING_PROCESSES" | xargs kill -9 2>/dev/null || true
|
||||
fi
|
||||
echo "✅ Claude进程已停止"
|
||||
fi
|
||||
|
||||
# 清理临时文件
|
||||
echo "🧹 清理临时文件..."
|
||||
find .. -name "*.pyc" -delete 2>/dev/null || true
|
||||
find .. -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
find .. -name ".pytest_cache" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
|
||||
echo "✅ 开发环境已停止"
|
||||
Executable
+226
@@ -0,0 +1,226 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "🚀 启动LJWX-Stock开发环境 (Claude Code增强版)..."
|
||||
|
||||
# 检查Docker是否运行
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
echo "❌ Docker未运行,请先启动Docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查必要工具
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
echo "❌ docker-compose未安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
echo "❌ Python3未安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v node &> /dev/null; then
|
||||
echo "❌ Node.js未安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查是否存在docker-compose配置
|
||||
if [ ! -f "infra/docker/docker-compose.dev.yml" ]; then
|
||||
echo "📝 创建Docker Compose配置..."
|
||||
mkdir -p infra/docker
|
||||
cat > infra/docker/docker-compose.dev.yml << 'EOF'
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# PostgreSQL数据库
|
||||
postgres:
|
||||
image: postgres:15
|
||||
container_name: ljwx-postgres
|
||||
environment:
|
||||
POSTGRES_DB: ljwx_stock
|
||||
POSTGRES_USER: ljwx_user
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ljwx_password}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./db/init:/docker-entrypoint-initdb.d
|
||||
networks:
|
||||
- ljwx-network
|
||||
restart: unless-stopped
|
||||
|
||||
# Redis缓存
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: ljwx-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- ljwx-network
|
||||
restart: unless-stopped
|
||||
|
||||
# MinIO对象存储
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
container_name: ljwx-minio
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
command: server /data --console-address ":9001"
|
||||
networks:
|
||||
- ljwx-network
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
minio_data:
|
||||
|
||||
networks:
|
||||
ljwx-network:
|
||||
driver: bridge
|
||||
EOF
|
||||
fi
|
||||
|
||||
# 创建数据库初始化脚本
|
||||
if [ ! -d "infra/db/init" ]; then
|
||||
echo "📝 创建数据库初始化脚本..."
|
||||
mkdir -p infra/db/init
|
||||
cat > infra/db/init/01-init.sql << 'EOF'
|
||||
-- LJWX-Stock 数据库初始化脚本
|
||||
-- 创建基础表结构
|
||||
|
||||
-- 用户表
|
||||
CREATE TABLE IF NOT EXISTS app_user (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(64) UNIQUE NOT NULL,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 股票基本信息表
|
||||
CREATE TABLE IF NOT EXISTS stock_basic (
|
||||
ts_code VARCHAR(16) PRIMARY KEY,
|
||||
symbol VARCHAR(16) NOT NULL,
|
||||
name VARCHAR(32) NOT NULL,
|
||||
market VARCHAR(16),
|
||||
industry VARCHAR(32),
|
||||
area VARCHAR(32),
|
||||
list_date DATE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 推荐结果表
|
||||
CREATE TABLE IF NOT EXISTS recommendation_result (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id VARCHAR(32),
|
||||
ts_code VARCHAR(16) NOT NULL,
|
||||
prediction_return DECIMAL(8,4) NOT NULL,
|
||||
recommendation_level VARCHAR(32),
|
||||
confidence_score DECIMAL(3,2),
|
||||
key_factors JSON,
|
||||
model_version VARCHAR(32),
|
||||
status VARCHAR(32) DEFAULT 'pending',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
processed_at TIMESTAMP NULL
|
||||
);
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_recommendation_user ON recommendation_result(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_recommendation_ts_code ON recommendation_result(ts_code);
|
||||
CREATE INDEX IF NOT EXISTS idx_recommendation_created ON recommendation_result(created_at);
|
||||
EOF
|
||||
fi
|
||||
|
||||
# 进入infra/docker目录
|
||||
cd infra/docker
|
||||
|
||||
# 启动基础服务
|
||||
echo "📦 启动基础服务(PostgreSQL, Redis, MinIO)..."
|
||||
docker-compose -f docker-compose.dev.yml up -d
|
||||
|
||||
# 等待服务启动
|
||||
echo "⏳ 等待服务启动..."
|
||||
sleep 10
|
||||
|
||||
# 检查服务状态
|
||||
echo "✅ 检查服务状态..."
|
||||
docker-compose -f docker-compose.dev.yml ps
|
||||
|
||||
# 初始化数据库
|
||||
echo "🗄️ 初始化数据库..."
|
||||
cd ../..
|
||||
sleep 5
|
||||
if command -v psql &> /dev/null; then
|
||||
PGPASSWORD=ljwx_password psql -h localhost -U ljwx_user -d ljwx_stock -f infra/db/init/01-init.sql || echo "数据库初始化将在容器内自动完成"
|
||||
fi
|
||||
|
||||
# 创建MinIO桶(需要mc命令或等待MinIO启动后手动创建)
|
||||
echo "🪣 准备MinIO存储桶..."
|
||||
echo "MinIO控制台: http://localhost:9001"
|
||||
echo "用户名: minioadmin"
|
||||
echo "密码: minioadmin"
|
||||
|
||||
# 检查Python依赖
|
||||
echo "🐍 检查Python环境..."
|
||||
if command -v uv &> /dev/null; then
|
||||
echo "✅ uv已安装"
|
||||
elif command -v pip &> /dev/null; then
|
||||
echo "⚠️ 使用pip代替uv"
|
||||
else
|
||||
echo "❌ Python包管理器未安装"
|
||||
fi
|
||||
|
||||
# 检查前端依赖
|
||||
echo "📦 检查前端环境..."
|
||||
if [ -f "package.json" ]; then
|
||||
if [ ! -d "node_modules" ]; then
|
||||
echo "📥 安装前端依赖..."
|
||||
npm ci
|
||||
else
|
||||
echo "✅ 前端依赖已安装"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检查Claude环境
|
||||
echo "🤖 检查Claude Code环境..."
|
||||
if [ -f "claude_project_config.json" ]; then
|
||||
echo "✅ Claude项目配置已存在"
|
||||
else
|
||||
echo "⚠️ Claude项目配置不存在"
|
||||
fi
|
||||
|
||||
if [ -f "claude/task_manager/claude_task_manager.py" ]; then
|
||||
echo "✅ Claude任务管理器已存在"
|
||||
else
|
||||
echo "⚠️ Claude任务管理器不存在"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🎉 开发环境启动完成!"
|
||||
echo ""
|
||||
echo "📋 服务访问地址:"
|
||||
echo " - PostgreSQL: localhost:5432 (用户: ljwx_user, 密码: ljwx_password)"
|
||||
echo " - Redis: localhost:6379"
|
||||
echo " - MinIO Console: http://localhost:9001 (用户: minioadmin, 密码: minioadmin)"
|
||||
echo ""
|
||||
echo "🔧 下一步操作:"
|
||||
echo " 1. 运行 'make api' 启动后端API服务"
|
||||
echo " 2. 运行 'make web' 启动前端开发服务器"
|
||||
echo " 3. 运行 'make claude-auto' 启动Claude自动化任务"
|
||||
echo " 4. 运行 'make claude-monitor' 启动Claude监控面板"
|
||||
echo ""
|
||||
echo "🚀 推荐使用智能开发模式:"
|
||||
echo " make dev-claude"
|
||||
Reference in New Issue
Block a user