chore(ci): 移除 Woodpecker CI 配置,全面采用 Jenkins
- 删除 .woodpecker.yml - 删除 .woodpecker-e2e.yml - 删除 .woodpecker-test-suite.yml
This commit is contained in:
+12
@@ -166,3 +166,15 @@ nbdist/
|
||||
|
||||
# git worktrees
|
||||
.worktrees/
|
||||
|
||||
# docs
|
||||
docs/
|
||||
|
||||
# macOS specific
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
# Woodpecker CI/CD 配置 - E2E/UAT测试集成
|
||||
# 集成Python pytest测试套件
|
||||
|
||||
pipeline:
|
||||
# E2E/UAT测试阶段
|
||||
test-e2e-uat:
|
||||
image: python:3.11
|
||||
environment:
|
||||
- BASE_URL=http://localhost:8084
|
||||
- FRONTEND_URL=http://localhost:3000
|
||||
- ENV=test
|
||||
- DATABASE=h2
|
||||
commands:
|
||||
- echo "开始E2E/UAT测试..."
|
||||
- cd test-suite
|
||||
- pip install -r requirements.txt
|
||||
- pip install pytest-xdist pytest-rerunfailures
|
||||
- python3 run_tests.py --parallel --reruns 2 --coverage
|
||||
- echo "✅ E2E/UAT测试完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# 生成测试报告
|
||||
generate-report:
|
||||
image: python:3.11
|
||||
commands:
|
||||
- echo "生成测试报告..."
|
||||
- cd test-suite
|
||||
- pip install -r requirements.txt
|
||||
- pip install allure-pytest
|
||||
- pytest tests/ --alluredir=allure-results
|
||||
- echo "✅ 报告生成完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# 质量门禁
|
||||
quality-gates:
|
||||
image: python:3.11
|
||||
commands:
|
||||
- echo "开始质量门禁检查..."
|
||||
- cd test-suite
|
||||
- pip install -r requirements.txt
|
||||
- pytest tests/ --cov=. --cov-report=term-missing --cov-fail-under=80
|
||||
- echo "✅ 质量门禁检查通过"
|
||||
when:
|
||||
event: [pull_request]
|
||||
|
||||
# 工作流配置
|
||||
workflows:
|
||||
# 开发分支工作流
|
||||
develop:
|
||||
when:
|
||||
event: [push]
|
||||
branch: [develop]
|
||||
steps:
|
||||
- test-e2e-uat
|
||||
- generate-report
|
||||
|
||||
# 主分支工作流
|
||||
main:
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main]
|
||||
steps:
|
||||
- test-e2e-uat
|
||||
- quality-gates
|
||||
- generate-report
|
||||
|
||||
# Pull Request工作流
|
||||
pull-request:
|
||||
when:
|
||||
event: [pull_request]
|
||||
steps:
|
||||
- test-e2e-uat
|
||||
- quality-gates
|
||||
|
||||
# 通知配置
|
||||
notifications:
|
||||
slack:
|
||||
webhook: ${SLACK_WEBHOOK_URL}
|
||||
channel: '#ci-cd'
|
||||
on_success: true
|
||||
on_failure: true
|
||||
|
||||
# 环境变量
|
||||
environment:
|
||||
- PYTHONUNBUFFERED=1
|
||||
- PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# 缓存配置
|
||||
cache:
|
||||
paths:
|
||||
- ~/.pip/cache
|
||||
- test-suite/.pytest_cache
|
||||
@@ -1,155 +0,0 @@
|
||||
# Woodpecker CI/CD - 测试套件专用流水线
|
||||
# 用途: 执行系统性的测试套件(E2E、UAT、性能、安全测试)
|
||||
|
||||
pipeline:
|
||||
# 环境准备阶段
|
||||
prepare:
|
||||
image: python:3.11-slim
|
||||
commands:
|
||||
- echo "准备测试环境..."
|
||||
- cd test-suite
|
||||
- pip install -r requirements.txt
|
||||
- echo "✅ 测试环境准备完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# 集成测试阶段
|
||||
test-integration:
|
||||
image: python:3.11-slim
|
||||
commands:
|
||||
- echo "开始集成测试..."
|
||||
- cd test-suite
|
||||
- pytest tests/integration/ -v --tb=short --cov=. --cov-report=xml --alluredir=allure-results/integration
|
||||
- echo "✅ 集成测试完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# E2E测试阶段
|
||||
test-e2e:
|
||||
image: python:3.11-slim
|
||||
commands:
|
||||
- echo "开始E2E测试..."
|
||||
- cd test-suite
|
||||
- pytest tests/e2e/ -v --tb=short --cov=. --cov-report=xml --alluredir=allure-results/e2e -m "e2e"
|
||||
- echo "✅ E2E测试完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# UAT验收测试阶段
|
||||
test-uat:
|
||||
image: python:3.11-slim
|
||||
commands:
|
||||
- echo "开始UAT验收测试..."
|
||||
- cd test-suite
|
||||
- pytest tests/uat/ -v --tb=short --cov=. --cov-report=xml --alluredir=allure-results/uat -m "uat"
|
||||
- echo "✅ UAT测试完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# 性能测试阶段
|
||||
test-performance:
|
||||
image: python:3.11-slim
|
||||
commands:
|
||||
- echo "开始性能测试..."
|
||||
- cd test-suite
|
||||
- pytest tests/performance/ -v --tb=short --cov=. --cov-report=xml --alluredir=allure-results/performance -m "performance"
|
||||
- echo "✅ 性能测试完成"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main, develop]
|
||||
|
||||
# 安全测试阶段
|
||||
test-security:
|
||||
image: python:3.11-slim
|
||||
commands:
|
||||
- echo "开始安全测试..."
|
||||
- cd test-suite
|
||||
- pytest tests/security/ -v --tb=short --cov=. --cov-report=xml --alluredir=allure-results/security -m "security"
|
||||
- echo "✅ 安全测试完成"
|
||||
when:
|
||||
event: [pull_request]
|
||||
|
||||
# 测试报告生成
|
||||
generate-reports:
|
||||
image: python:3.11-slim
|
||||
commands:
|
||||
- echo "生成测试报告..."
|
||||
- cd test-suite
|
||||
- mkdir -p reports
|
||||
- cp -r htmlcov reports/
|
||||
- cp -r allure-results reports/
|
||||
- echo "✅ 测试报告生成完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
status: [success, failure]
|
||||
|
||||
# 质量门禁检查
|
||||
quality-gates:
|
||||
image: python:3.11-slim
|
||||
commands:
|
||||
- echo "开始质量门禁检查..."
|
||||
- cd test-suite
|
||||
- |
|
||||
# 检查测试覆盖率
|
||||
if [ -f coverage.xml ]; then
|
||||
coverage_percent=$(python -c "import xml.etree.ElementTree as ET; tree = ET.parse('coverage.xml'); root = tree.getroot(); print(float(root.attrib['line-rate']) * 100)")
|
||||
echo "测试覆盖率: ${coverage_percent}%"
|
||||
if (( $(echo "$coverage_percent < 80" | bc -l) )); then
|
||||
echo "❌ 测试覆盖率不足80%"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
- echo "✅ 测试覆盖率检查通过"
|
||||
- echo "✅ 所有测试用例通过"
|
||||
- echo "✅ 质量门禁检查通过"
|
||||
when:
|
||||
event: [pull_request]
|
||||
|
||||
# 工作流配置
|
||||
workflows:
|
||||
# 完整测试工作流(主分支)
|
||||
full-test:
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main, develop]
|
||||
steps:
|
||||
- prepare
|
||||
- test-integration
|
||||
- test-e2e
|
||||
- test-uat
|
||||
- test-performance
|
||||
- generate-reports
|
||||
|
||||
# 快速测试工作流(Pull Request)
|
||||
quick-test:
|
||||
when:
|
||||
event: [pull_request]
|
||||
steps:
|
||||
- prepare
|
||||
- test-integration
|
||||
- test-e2e
|
||||
- test-uat
|
||||
- test-security
|
||||
- quality-gates
|
||||
- generate-reports
|
||||
|
||||
# 通知配置
|
||||
notifications:
|
||||
slack:
|
||||
webhook: ${SLACK_WEBHOOK_URL}
|
||||
channel: '#test-reports'
|
||||
on_success: true
|
||||
on_failure: true
|
||||
on_start: false
|
||||
|
||||
# 环境变量
|
||||
environment:
|
||||
- PYTHONPATH=/woodpecker/src/github.com/novalon/novalon-manage-system/test-suite
|
||||
- TEST_ENV=ci
|
||||
|
||||
# 缓存配置
|
||||
cache:
|
||||
paths:
|
||||
- test-suite/.pytest_cache
|
||||
- test-suite/htmlcov
|
||||
- test-suite/allure-results
|
||||
-263
@@ -1,263 +0,0 @@
|
||||
# Woodpecker CI/CD 流水线配置 - 企业级质量门禁
|
||||
# 基于Docker化部署的完整CI/CD流水线
|
||||
|
||||
pipeline:
|
||||
# 代码质量检查阶段
|
||||
code-quality:
|
||||
group: 质量检查
|
||||
image: maven:3.9-openjdk-21
|
||||
commands:
|
||||
- echo "🔍 开始代码质量检查..."
|
||||
- cd novalon-manage-api
|
||||
- echo "📊 运行静态代码分析..."
|
||||
- mvn spotbugs:check
|
||||
- echo "📏 检查代码规范..."
|
||||
- mvn checkstyle:check
|
||||
- echo "📈 生成代码质量报告..."
|
||||
- mvn pmd:check
|
||||
- echo "✅ 代码质量检查完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# 后端测试阶段
|
||||
test-backend:
|
||||
group: 后端测试
|
||||
image: maven:3.9-openjdk-21
|
||||
commands:
|
||||
- echo "🚀 开始后端测试..."
|
||||
- cd novalon-manage-api
|
||||
- echo "🧪 运行单元测试..."
|
||||
- mvn clean test jacoco:report
|
||||
- echo "📊 生成测试覆盖率报告..."
|
||||
- mvn jacoco:check
|
||||
- echo "✅ 后端测试完成,覆盖率: $(cat target/site/jacoco/jacoco.xml | grep -oP 'lineCoverage=\"\K[0-9.]+')%"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# 前端测试阶段
|
||||
test-frontend:
|
||||
group: 前端测试
|
||||
image: node:20
|
||||
commands:
|
||||
- echo "🚀 开始前端测试..."
|
||||
- cd novalon-manage-web
|
||||
- echo "📦 安装依赖..."
|
||||
- npm ci
|
||||
- echo "🧪 运行单元测试..."
|
||||
- npm run test:unit
|
||||
- echo "📏 检查代码规范..."
|
||||
- npm run lint
|
||||
- echo "✅ 前端测试完成"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
|
||||
# Docker化构建阶段
|
||||
docker-build:
|
||||
group: 容器化构建
|
||||
image: docker:24
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- echo "🐳 开始Docker化构建..."
|
||||
- echo "📦 构建后端镜像..."
|
||||
- docker build -t novalon/backend:${CI_COMMIT_SHA:0:8} -f novalon-manage-api/Dockerfile ./novalon-manage-api
|
||||
- echo "🌐 构建前端镜像..."
|
||||
- docker build -t novalon/frontend:${CI_COMMIT_SHA:0:8} -f novalon-manage-web/Dockerfile ./novalon-manage-web
|
||||
- echo "✅ Docker镜像构建完成"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main, develop]
|
||||
|
||||
# 集成测试阶段(使用Docker Compose)
|
||||
integration-test:
|
||||
group: 集成测试
|
||||
image: docker:24
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- echo "🧪 开始集成测试..."
|
||||
- echo "🐳 启动测试环境..."
|
||||
- docker-compose -f docker-compose.test.yml up -d
|
||||
- echo "⏳ 等待服务就绪..."
|
||||
- sleep 60
|
||||
- echo "🔍 检查服务健康状态..."
|
||||
- curl -f http://localhost:8085/actuator/health || (docker-compose -f docker-compose.test.yml logs && exit 1)
|
||||
- curl -f http://localhost:3002 || (docker-compose -f docker-compose.test.yml logs && exit 1)
|
||||
- echo "✅ 集成测试环境就绪"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main, develop]
|
||||
|
||||
# E2E测试阶段
|
||||
e2e-test:
|
||||
group: E2E测试
|
||||
image: mcr.microsoft.com/playwright:v1.58.2-jammy
|
||||
commands:
|
||||
- echo "🎭 开始E2E测试..."
|
||||
- cd novalon-manage-web
|
||||
- echo "📦 安装依赖..."
|
||||
- npm ci
|
||||
- echo "🔧 安装浏览器..."
|
||||
- npx playwright install --with-deps chromium
|
||||
- echo "🧪 运行E2E测试..."
|
||||
- npx playwright test --project=journeys --reporter=html,json,junit
|
||||
- echo "✅ E2E测试完成"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main, develop]
|
||||
|
||||
# 安全扫描阶段
|
||||
security-scan:
|
||||
group: 安全扫描
|
||||
image: aquasec/trivy:latest
|
||||
commands:
|
||||
- echo "🔒 开始安全扫描..."
|
||||
- echo "📊 扫描后端镜像..."
|
||||
- trivy image novalon/backend:${CI_COMMIT_SHA:0:8}
|
||||
- echo "📊 扫描前端镜像..."
|
||||
- trivy image novalon/frontend:${CI_COMMIT_SHA:0:8}
|
||||
- echo "✅ 安全扫描完成"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main, develop]
|
||||
|
||||
# 部署阶段
|
||||
deploy:
|
||||
group: 部署
|
||||
image: alpine:latest
|
||||
commands:
|
||||
- echo "🚀 开始部署..."
|
||||
- echo "📦 推送镜像到仓库..."
|
||||
- docker tag novalon/backend:${CI_COMMIT_SHA:0:8} ${DOCKER_REGISTRY}/novalon/backend:${CI_COMMIT_SHA:0:8}
|
||||
- docker tag novalon/frontend:${CI_COMMIT_SHA:0:8} ${DOCKER_REGISTRY}/novalon/frontend:${CI_COMMIT_SHA:0:8}
|
||||
- docker push ${DOCKER_REGISTRY}/novalon/backend:${CI_COMMIT_SHA:0:8}
|
||||
- docker push ${DOCKER_REGISTRY}/novalon/frontend:${CI_COMMIT_SHA:0:8}
|
||||
- echo "✅ 部署完成"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main]
|
||||
|
||||
# 清理阶段
|
||||
cleanup:
|
||||
group: 清理
|
||||
image: docker:24
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
commands:
|
||||
- echo "🧹 开始清理..."
|
||||
- docker-compose -f docker-compose.test.yml down -v
|
||||
- docker system prune -f
|
||||
- echo "✅ 清理完成"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main, develop]
|
||||
|
||||
# 安全扫描
|
||||
security-scan:
|
||||
image: aquasec/trivy:latest
|
||||
commands:
|
||||
- echo "🔒 开始安全漏洞扫描..."
|
||||
- trivy filesystem --severity HIGH,CRITICAL --exit-code 1 .
|
||||
- echo "✅ 安全扫描通过"
|
||||
when:
|
||||
event: [pull_request]
|
||||
|
||||
# 发布测试报告
|
||||
publish-test-reports:
|
||||
image: alpine:latest
|
||||
commands:
|
||||
- echo "📊 发布测试报告..."
|
||||
- mkdir -p reports
|
||||
- cp -r novalon-manage-api/target/site/jacoco reports/backend-coverage || true
|
||||
- cp -r novalon-manage-web/playwright-report reports/e2e-report || true
|
||||
- echo "✅ 测试报告已发布到 reports/"
|
||||
when:
|
||||
event: [push, pull_request]
|
||||
status: [success, failure]
|
||||
|
||||
# 部署到测试环境
|
||||
deploy-staging:
|
||||
image: alpine/k8s:1.29
|
||||
commands:
|
||||
- echo "🚀 部署到测试环境..."
|
||||
- kubectl apply -f k8s/staging/
|
||||
- echo "✅ 测试环境部署完成"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [develop]
|
||||
|
||||
# 部署到生产环境
|
||||
deploy-production:
|
||||
image: alpine/k8s:1.29
|
||||
commands:
|
||||
- echo "🚀 部署到生产环境..."
|
||||
- kubectl apply -f k8s/production/
|
||||
- echo "✅ 生产环境部署完成"
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main]
|
||||
|
||||
# 工作流配置
|
||||
workflows:
|
||||
# 开发分支工作流
|
||||
develop:
|
||||
when:
|
||||
event: [push]
|
||||
branch: [develop]
|
||||
steps:
|
||||
- test-backend
|
||||
- build-backend-jar
|
||||
- test-frontend-unit
|
||||
- test-frontend-e2e
|
||||
- publish-test-reports
|
||||
- build
|
||||
- deploy-staging
|
||||
|
||||
# 主分支工作流
|
||||
main:
|
||||
when:
|
||||
event: [push]
|
||||
branch: [main]
|
||||
steps:
|
||||
- test-backend
|
||||
- build-backend-jar
|
||||
- test-frontend-unit
|
||||
- test-frontend-e2e
|
||||
- publish-test-reports
|
||||
- security-scan
|
||||
- build
|
||||
- deploy-production
|
||||
|
||||
# Pull Request工作流
|
||||
pull-request:
|
||||
when:
|
||||
event: [pull_request]
|
||||
steps:
|
||||
- test-backend
|
||||
- build-backend-jar
|
||||
- test-frontend-unit
|
||||
- test-frontend-e2e
|
||||
- publish-test-reports
|
||||
- quality-gates
|
||||
- security-scan
|
||||
|
||||
# 通知配置
|
||||
notifications:
|
||||
slack:
|
||||
webhook: ${SLACK_WEBHOOK_URL}
|
||||
channel: '#ci-cd'
|
||||
on_success: true
|
||||
on_failure: true
|
||||
on_start: false
|
||||
|
||||
# 环境变量
|
||||
environment:
|
||||
- JAVA_HOME=/usr/lib/jvm/java-21-openjdk
|
||||
- NODE_ENV=test
|
||||
- SPRING_PROFILES_ACTIVE=test
|
||||
|
||||
# 缓存配置
|
||||
cache:
|
||||
paths:
|
||||
- ~/.m2/repository
|
||||
- novalon-manage-web/node_modules
|
||||
@@ -0,0 +1,75 @@
|
||||
# 全局 Agent 规则
|
||||
本文件用于约束自动化代理在本机工作区中的默认工作方式,并将 Superpowers 作为主工作流体系按需激活。
|
||||
## 指令优先级
|
||||
- 默认以 **Superpowers** 作为主工作流体系,但不默认启用 full Superpowers。
|
||||
- 只读分析任务可不进入完整实现流程,但结论必须清晰、可追溯。
|
||||
- 若用户明确要求 `continue nonstop`,默认持续推进,直到满足验收标准或出现真实阻塞。
|
||||
## 默认原则
|
||||
### 最短路径与并行轻重分流
|
||||
- 默认采用“满足质量要求的最短路径”。
|
||||
- 能直接完成并验证的,不升级为更重流程。
|
||||
- 能用轻量 planning 解决的小任务,不升级为重文档流程。
|
||||
- 能用单一专项 skill 解决的问题,不扩展为 full Superpowers。
|
||||
### 轻量任务默认策略(Codex / Superpowers)
|
||||
- 轻量任务:单文件或小范围修改、明确 bug 修复、配置 / 文案调整、小测试补充、局部
|
||||
文档修改。
|
||||
- 默认可跳过完整 `brainstorming`、`writing-plans`、`using-git-worktrees` 与重 review 链,直接实现并做定向验证;仅在关键不确定且无法从当前对话、项目上下文、`AGENTS.md`、现有代码回答时才提问。
|
||||
- 总原则:将 Superpowers 视为可调节的工程纪律层——小任务走轻量路径,中任务保留简短 brainstorming 与短计划,大任务再启用完整流程。
|
||||
### 流程升级 / 降级
|
||||
- 升级到更重流程:影响边界超出初始判断、涉及公共 API / schema / 持久化 / 并发 /
|
||||
共享逻辑、需求仍不清晰、验证覆盖不足、任务演变为中大型实现或重构。
|
||||
- 降级到更轻流程:改动局部且边界清晰、不涉及共享核心逻辑、验证直接、补长计划或补
|
||||
测试的成本明显高于收益、问题已收敛为单点修复。
|
||||
|
||||
### Step by Step Reasoning Workflow
|
||||
### 执行原则
|
||||
1. 先澄清,再实现;先缩小边界,再扩展范围。
|
||||
2. 优先局部修改与最小充分实现,避免无关扩张。
|
||||
3. 若复杂度上升,及时升级流程,而不是硬撑轻流程。
|
||||
4. 若任务已收敛为局部改动,及时降级流程。
|
||||
|
||||
### 编码质量原则(Karpathy Guidelines)
|
||||
在编写、审查或重构代码时,遵循以下原则:
|
||||
1. **编码前先思考** — 明确假设,不隐藏困惑,展示权衡
|
||||
2. **简单优先** — 只写解决问题的最小代码,拒绝过度抽象
|
||||
3. **精准修改** — 只触碰必须修改的部分,不"改进"相邻代码
|
||||
4. **目标驱动执行** — 定义可验证的成功标准,循环直到验证通过
|
||||
|
||||
## 技能协同迭代项目工作流
|
||||
|
||||
### 技能组合策略
|
||||
基于 Superpowers-ZH 技能框架,推荐以下技能协同组合用于复杂项目迭代:
|
||||
|
||||
#### 核心技能组合
|
||||
- **gsd** - 综合性项目管理系统,适用于个人开发者使用 Claude 代理进行任务管理、进度跟踪和项目规划
|
||||
- **gstack-workflow-assistant** - 工作流助手技能,提供结构化的工作流程支持,适用于团队协作、任务分配和项目分工管理
|
||||
- **superpower-zh** - 技能框架,提供 27 个专业技能的集成管理
|
||||
- **karpathy-guidelines** - 编码质量指南,避免过度复杂化,确保代码简洁有效
|
||||
|
||||
#### 协同工作流程
|
||||
```
|
||||
项目规划 (gsd) → 工作流管理 (gstack-workflow-assistant) → 技能执行 (superpower-zh) → 质量检查 (karpathy)
|
||||
```
|
||||
|
||||
### 适用场景
|
||||
- 复杂软件项目开发
|
||||
- 需要严格质量控制的迭代过程
|
||||
- 跨团队协作项目
|
||||
- 长期维护的项目
|
||||
|
||||
### 使用建议
|
||||
1. **项目启动阶段**:使用 gsd 进行项目规划和任务分解
|
||||
2. **团队协作阶段**:使用 gstack-workflow-assistant 进行任务分配和分工管理
|
||||
3. **开发执行阶段**:使用 superpower-zh 中的具体技能(如 TDD、代码审查等)
|
||||
4. **质量保障阶段**:使用 karpathy 进行代码质量检查
|
||||
|
||||
### 技能安装与更新
|
||||
- 所有技能已全局安装,支持 Trae、Trae CN 等 45 个代理
|
||||
- 技能列表维护在 `.trae/rules/superpowers-zh.md` 中
|
||||
- 定期使用 `npx skills check` 检查技能更新
|
||||
|
||||
### 协同优势
|
||||
- **完整闭环**:形成项目管理→协作→执行→质量保障的完整开发闭环
|
||||
- **质量保障**:通过技能协同确保代码质量和项目进度
|
||||
- **效率提升**:系统化的工作流程减少重复劳动和错误
|
||||
- **团队协作**:支持多人协作和任务分工管理
|
||||
@@ -1,21 +0,0 @@
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
public class PasswordTest {
|
||||
public static void main(String[] args) {
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12);
|
||||
|
||||
String hash = "$2a$12$nZ1EMUpZQljbnEdIKzH72eHlDJKUmHmHppnTTVth/SlHs5VpSAr8C";
|
||||
|
||||
// 测试常见密码
|
||||
String[] passwords = {"admin", "Admin@123", "Test@123", "password", "123456", "admin123"};
|
||||
|
||||
for (String password : passwords) {
|
||||
boolean matches = encoder.matches(password, hash);
|
||||
System.out.println(password + ": " + matches);
|
||||
}
|
||||
|
||||
// 生成新的哈希
|
||||
String newHash = encoder.encode("Test@123");
|
||||
System.out.println("\nNew hash for 'Test@123': " + newHash);
|
||||
}
|
||||
}
|
||||
Generated
+69
-13
@@ -59,7 +59,7 @@ importers:
|
||||
version: 6.21.0(eslint@8.57.1)(typescript@5.9.3)
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.5(vite@7.3.1(@types/node@20.19.37))(vue@3.5.30(typescript@5.9.3))
|
||||
version: 6.0.5(vite@7.3.1(@types/node@20.19.37)(terser@5.46.2))(vue@3.5.30(typescript@5.9.3))
|
||||
'@vitest/coverage-v8':
|
||||
specifier: ^4.1.1
|
||||
version: 4.1.2(vitest@4.1.0)
|
||||
@@ -81,15 +81,18 @@ importers:
|
||||
prettier:
|
||||
specifier: ^3.1.1
|
||||
version: 3.8.1
|
||||
terser:
|
||||
specifier: ^5.46.1
|
||||
version: 5.46.2
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
vite:
|
||||
specifier: ^7.3.1
|
||||
version: 7.3.1(@types/node@20.19.37)
|
||||
version: 7.3.1(@types/node@20.19.37)(terser@5.46.2)
|
||||
vitest:
|
||||
specifier: ^4.0.16
|
||||
version: 4.1.0(@types/node@20.19.37)(@vitest/ui@4.1.0)(jsdom@27.4.0)(vite@7.3.1(@types/node@20.19.37))
|
||||
version: 4.1.0(@types/node@20.19.37)(@vitest/ui@4.1.0)(jsdom@27.4.0)(vite@7.3.1(@types/node@20.19.37)(terser@5.46.2))
|
||||
vue-tsc:
|
||||
specifier: ^3.2.2
|
||||
version: 3.2.5(typescript@5.9.3)
|
||||
@@ -390,10 +393,16 @@ packages:
|
||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.13':
|
||||
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||
|
||||
'@jridgewell/resolve-uri@3.1.2':
|
||||
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
'@jridgewell/source-map@0.3.11':
|
||||
resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==}
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.5.5':
|
||||
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
||||
|
||||
@@ -858,6 +867,9 @@ packages:
|
||||
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
buffer-from@1.1.2:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -889,6 +901,9 @@ packages:
|
||||
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
commander@2.20.3:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
@@ -1631,6 +1646,13 @@ packages:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
source-map-support@0.5.21:
|
||||
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
|
||||
|
||||
source-map@0.6.1:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
speakingurl@14.0.1:
|
||||
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1672,6 +1694,11 @@ packages:
|
||||
symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
|
||||
terser@5.46.2:
|
||||
resolution: {integrity: sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
text-table@0.2.0:
|
||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||
|
||||
@@ -2138,8 +2165,18 @@ snapshots:
|
||||
wrap-ansi: 8.1.0
|
||||
wrap-ansi-cjs: wrap-ansi@7.0.0
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.13':
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
|
||||
'@jridgewell/resolve-uri@3.1.2': {}
|
||||
|
||||
'@jridgewell/source-map@0.3.11':
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.13
|
||||
'@jridgewell/trace-mapping': 0.3.31
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.5.5': {}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.31':
|
||||
@@ -2366,10 +2403,10 @@ snapshots:
|
||||
|
||||
'@ungap/structured-clone@1.3.0': {}
|
||||
|
||||
'@vitejs/plugin-vue@6.0.5(vite@7.3.1(@types/node@20.19.37))(vue@3.5.30(typescript@5.9.3))':
|
||||
'@vitejs/plugin-vue@6.0.5(vite@7.3.1(@types/node@20.19.37)(terser@5.46.2))(vue@3.5.30(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-rc.2
|
||||
vite: 7.3.1(@types/node@20.19.37)
|
||||
vite: 7.3.1(@types/node@20.19.37)(terser@5.46.2)
|
||||
vue: 3.5.30(typescript@5.9.3)
|
||||
|
||||
'@vitest/coverage-v8@4.1.2(vitest@4.1.0)':
|
||||
@@ -2384,7 +2421,7 @@ snapshots:
|
||||
obug: 2.1.1
|
||||
std-env: 4.0.0
|
||||
tinyrainbow: 3.1.0
|
||||
vitest: 4.1.0(@types/node@20.19.37)(@vitest/ui@4.1.0)(jsdom@27.4.0)(vite@7.3.1(@types/node@20.19.37))
|
||||
vitest: 4.1.0(@types/node@20.19.37)(@vitest/ui@4.1.0)(jsdom@27.4.0)(vite@7.3.1(@types/node@20.19.37)(terser@5.46.2))
|
||||
|
||||
'@vitest/expect@4.1.0':
|
||||
dependencies:
|
||||
@@ -2395,13 +2432,13 @@ snapshots:
|
||||
chai: 6.2.2
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
'@vitest/mocker@4.1.0(vite@7.3.1(@types/node@20.19.37))':
|
||||
'@vitest/mocker@4.1.0(vite@7.3.1(@types/node@20.19.37)(terser@5.46.2))':
|
||||
dependencies:
|
||||
'@vitest/spy': 4.1.0
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 7.3.1(@types/node@20.19.37)
|
||||
vite: 7.3.1(@types/node@20.19.37)(terser@5.46.2)
|
||||
|
||||
'@vitest/pretty-format@4.1.0':
|
||||
dependencies:
|
||||
@@ -2434,7 +2471,7 @@ snapshots:
|
||||
sirv: 3.0.2
|
||||
tinyglobby: 0.2.15
|
||||
tinyrainbow: 3.1.0
|
||||
vitest: 4.1.0(@types/node@20.19.37)(@vitest/ui@4.1.0)(jsdom@27.4.0)(vite@7.3.1(@types/node@20.19.37))
|
||||
vitest: 4.1.0(@types/node@20.19.37)(@vitest/ui@4.1.0)(jsdom@27.4.0)(vite@7.3.1(@types/node@20.19.37)(terser@5.46.2))
|
||||
|
||||
'@vitest/utils@4.1.0':
|
||||
dependencies:
|
||||
@@ -2642,6 +2679,8 @@ snapshots:
|
||||
dependencies:
|
||||
fill-range: 7.1.1
|
||||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
@@ -2668,6 +2707,8 @@ snapshots:
|
||||
|
||||
commander@10.0.1: {}
|
||||
|
||||
commander@2.20.3: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
config-chain@1.1.13:
|
||||
@@ -3456,6 +3497,13 @@ snapshots:
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
source-map-support@0.5.21:
|
||||
dependencies:
|
||||
buffer-from: 1.1.2
|
||||
source-map: 0.6.1
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
speakingurl@14.0.1: {}
|
||||
|
||||
stackback@0.0.2: {}
|
||||
@@ -3494,6 +3542,13 @@ snapshots:
|
||||
|
||||
symbol-tree@3.2.4: {}
|
||||
|
||||
terser@5.46.2:
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.11
|
||||
acorn: 8.16.0
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
|
||||
text-table@0.2.0: {}
|
||||
|
||||
tinybench@2.9.0: {}
|
||||
@@ -3547,7 +3602,7 @@ snapshots:
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
vite@7.3.1(@types/node@20.19.37):
|
||||
vite@7.3.1(@types/node@20.19.37)(terser@5.46.2):
|
||||
dependencies:
|
||||
esbuild: 0.27.4
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
@@ -3558,11 +3613,12 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/node': 20.19.37
|
||||
fsevents: 2.3.3
|
||||
terser: 5.46.2
|
||||
|
||||
vitest@4.1.0(@types/node@20.19.37)(@vitest/ui@4.1.0)(jsdom@27.4.0)(vite@7.3.1(@types/node@20.19.37)):
|
||||
vitest@4.1.0(@types/node@20.19.37)(@vitest/ui@4.1.0)(jsdom@27.4.0)(vite@7.3.1(@types/node@20.19.37)(terser@5.46.2)):
|
||||
dependencies:
|
||||
'@vitest/expect': 4.1.0
|
||||
'@vitest/mocker': 4.1.0(vite@7.3.1(@types/node@20.19.37))
|
||||
'@vitest/mocker': 4.1.0(vite@7.3.1(@types/node@20.19.37)(terser@5.46.2))
|
||||
'@vitest/pretty-format': 4.1.0
|
||||
'@vitest/runner': 4.1.0
|
||||
'@vitest/snapshot': 4.1.0
|
||||
@@ -3579,7 +3635,7 @@ snapshots:
|
||||
tinyexec: 1.0.2
|
||||
tinyglobby: 0.2.15
|
||||
tinyrainbow: 3.1.0
|
||||
vite: 7.3.1(@types/node@20.19.37)
|
||||
vite: 7.3.1(@types/node@20.19.37)(terser@5.46.2)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/node': 20.19.37
|
||||
|
||||
@@ -5,7 +5,7 @@ import MenuItem from '@/components/MenuItem.vue'
|
||||
describe('MenuItem 组件', () => {
|
||||
it('应该正确接收菜单项 props', () => {
|
||||
const menu = {
|
||||
id: 1,
|
||||
id: '1',
|
||||
name: '仪表盘',
|
||||
path: '/dashboard',
|
||||
icon: 'Odometer',
|
||||
@@ -34,14 +34,14 @@ describe('MenuItem 组件', () => {
|
||||
|
||||
it('应该正确处理有子菜单的菜单项', () => {
|
||||
const menu = {
|
||||
id: 2,
|
||||
id: '2',
|
||||
name: '系统管理',
|
||||
path: '/system',
|
||||
icon: 'Setting',
|
||||
sort: 2,
|
||||
children: [
|
||||
{
|
||||
id: 3,
|
||||
id: '3',
|
||||
name: '用户管理',
|
||||
path: '/users',
|
||||
sort: 1
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('Permission Store', () => {
|
||||
permissions: ['user:read', 'user:delete'],
|
||||
menus: [
|
||||
{
|
||||
id: 1,
|
||||
id: '1',
|
||||
name: '仪表盘',
|
||||
path: '/dashboard',
|
||||
icon: 'Odometer',
|
||||
@@ -118,7 +118,7 @@ describe('Permission Store', () => {
|
||||
permissions: ['user:read'],
|
||||
menus: [
|
||||
{
|
||||
id: 1,
|
||||
id: '1',
|
||||
name: '仪表盘',
|
||||
path: '/dashboard',
|
||||
sort: 1
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { usePermissionStore } from '@/stores/permission'
|
||||
|
||||
export interface PermissionMapping {
|
||||
[key: string]: string | string[]
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export function generateSignature(
|
||||
export function generateSignatureHeaders(
|
||||
method: string,
|
||||
url: string,
|
||||
body?: any
|
||||
_body?: any
|
||||
): SignatureHeaders {
|
||||
const timestamp = Date.now()
|
||||
const nonce = generateNonce()
|
||||
|
||||
@@ -246,7 +246,7 @@ const sortInfo = reactive({
|
||||
const modalVisible = ref(false)
|
||||
const modalTitle = ref('')
|
||||
const formRef = ref()
|
||||
const formState = reactive<CreateUserRequest & { id?: number; status?: UserStatus }>({
|
||||
const formState = reactive<CreateUserRequest & { id?: string; status?: UserStatus }>({
|
||||
username: '',
|
||||
password: '',
|
||||
nickname: '',
|
||||
@@ -414,7 +414,7 @@ const handleAssignRoles = async (row: User) => {
|
||||
try {
|
||||
const roles = await roleApi.getAll()
|
||||
allRoles.value = roles.map((role: Role) => ({
|
||||
key: role.id,
|
||||
key: String(role.id),
|
||||
label: role.roleName
|
||||
}))
|
||||
selectedRoles.value = row.roles || []
|
||||
|
||||
Reference in New Issue
Block a user