chore: add comprehensive documentation and testing infrastructure

## 文档(全部中文)
- AGENTS.md - 完整的 AI 编码指南(中文版)
- CONTRIBUTING.md - 贡献指南
- DEVELOPMENT.md - 开发文档
- DEPLOYMENT.md - 部署文档
- TESTING.md - 测试文档
- TROUBLESHOOTING.md - 问题排查指南
- FAQ.md - 常见问题
- WORKFLOW.md - 标准开发流程文档
## AI 工作流(9个详细工作流)
- feature-development.md - 新功能开发流程
- bug-fix.md - Bug 修复流程
- code-review.md - 代码审查流程
- testing.md - 测试编写流程
- release.md - 发布流程
- refactoring.md - 代码重构流程
- documentation.md - 文档更新流程
- performance-optimization.md - 性能优化流程
- security-audit.md - 安全审计流程
## 测试基础设施
- vitest.config.ts - Vitest 单元测试配置
- playwright.config.ts - Playwright E2E 测试配置
- src/__tests__/setup.ts - 测试环境设置
- src/__tests__/unit/downloadStatus.test.ts - 示例单元测试
- e2e/basic.spec.ts - 示例 E2E 测试
## CI/CD
- .github/workflows/test.yml - 新建测试 CI 工作流
- .github/workflows/build.yml - 更新构建工作流,添加测试步骤
## Issue 模板
- 更新 bug_report.md 为标准 Bug 报告模板
- 更新 help_wanted.md 为标准功能请求模板
## 配置更新
- package.json - 添加测试依赖和 7 个新的 npm 脚本
- .gitignore - 添加测试相关忽略项
## 新增 npm 脚本
- test - 运行单元测试
- test:watch - 监听模式
- test:coverage - 生成覆盖率报告
- test:e2e - 运行 E2E 测试
- test:e2e:ui - E2E UI 模式
- test:e2e:debug - E2E 调试模式
- test:all - 运行所有测试
## 新增测试依赖
- @playwright/test ^1.40.0
- @testing-library/jest-dom ^6.1.5
- @testing-library/vue ^8.0.1
- @vitest/coverage-v8 ^1.0.0
- @vue/test-utils ^2.4.3
- jsdom ^23.0.1
- vitest ^1.0.0
This commit is contained in:
2026-03-10 00:42:56 +08:00
parent 0035b3000d
commit cef68a95d9
31 changed files with 5403 additions and 424 deletions

View File

@@ -1,6 +0,0 @@
---
description: 审查
---
审查是否符合代码规范
是否有代码缺陷

View File

@@ -0,0 +1,139 @@
---
description: Bug 修复流程
---
## 工作流说明
此工作流指导如何修复 Bug。
## 步骤
### 1. 复现 Bug
- 根据 Issue 描述复现问题
- 记录详细的复现步骤
- 收集相关日志和错误信息
- 确认环境信息
### 2. 分析问题
- 查看相关代码
- 使用调试器定位问题
- 检查日志输出
- 识别根本原因
### 3. 创建修复分支
```bash
git checkout -b fix/your-bug-fix
```
### 4. 编写回归测试
先编写测试来复现 Bug
```typescript
// src/__tests__/unit/bugFix.test.ts
import { describe, it, expect } from "vitest";
import { buggyFunction } from "@/modules/example";
describe("buggyFunction", () => {
it("should not crash with null input", () => {
expect(() => buggyFunction(null)).not.toThrow();
});
});
```
### 5. 修复代码
- 最小化修改
- 保持代码可读性
- 添加必要的注释
- 更新相关类型定义
### 6. 运行测试
```bash
# 确保新测试通过
npm run test
# 运行所有测试
npm run test:all
# 代码检查
npm run lint
npm run format
```
### 7. 本地验证
- 验证 Bug 已修复
- 测试相关功能
- 检查是否引入新问题
- 测试边界情况
### 8. 更新文档
- 更新 CHANGELOG.md如果需要
- 更新相关文档(如需要)
### 9. 提交代码
```bash
git add .
git commit -m "fix(scope): describe the bug fix" -s
git push origin fix/your-bug-fix
```
### 10. 创建 Pull Request
- 引用相关 Issue`Fixes #123`
- 描述修复方法
- 说明复现步骤
- 添加测试说明
### 11. 代码审查
- 响应审查意见
- 进行必要的修改
- 确保所有 CI 检查通过
### 12. 合并
- 等待审查批准
- Squash 合并到 main 分支
- 删除修复分支
## 注意事项
- ⚠️ 修复前先理解问题根源
- ⚠️ 最小化修改范围
- ⚠️ 添加回归测试防止复发
- ⚠️ 考虑向后兼容性
- ⚠️ 测试所有受影响的功能
## 常见 Bug 类型
### IPC 通信问题
- 检查事件名称是否匹配
- 检查数据格式是否正确
- 检查异步处理
### 状态管理问题
- 检查响应式依赖
- 检查状态更新时机
- 检查内存泄漏
### 类型错误
- 检查类型定义
- 检查类型断言
- 检查可选值处理
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [TESTING.md](../../TESTING.md) - 测试文档
- [TROUBLESHOOTING.md](../../TROUBLESHOOTING.md) - 问题排查

View File

@@ -0,0 +1,245 @@
---
description: 代码审查流程
---
## 工作流说明
此工作流指导如何进行代码审查。
## 审查清单
### 代码质量
- [ ] 代码遵循项目规范
- [ ] TypeScript 类型正确
- [ ] 没有 `any` 类型(除非必要)
- [ ] ESLint 和 Prettier 通过
- [ ] 代码可读性良好
### 功能实现
- [ ] 实现符合需求
- [ ] 边界情况处理
- [ ] 错误处理完善
- [ ] 没有引入新 Bug
### 测试
- [ ] 包含足够的测试
- [ ] 测试覆盖率合理
- [ ] 所有测试通过
- [ ] E2E 测试(如需要)
### 文档
- [ ] 更新了相关文档
- [ ] 代码注释充分
- [ ] API 文档(如需要)
- [ ] CHANGELOG.md如需要
### 安全性
- [ ] 没有安全漏洞
- [ ] 输入验证完善
- [ ] 权限检查正确
- [ ] 敏感信息保护
### 性能
- [ ] 没有明显的性能问题
- [ ] 内存使用合理
- [ ] 没有不必要的渲染
- [ ] 资源加载优化
## 审查流程
### 1. 理解变更
- 阅读 PR 描述
- 查看 Issue 链接
- 理解变更目的
- 检查变更范围
### 2. 代码审查
**主进程代码:**
```bash
# 检查类型安全
npx tsc --noEmit
# 检查代码质量
npm run lint
```
**渲染进程代码:**
- 组件结构
- 状态管理
- 事件处理
- 样式实现
### 3. 测试验证
```bash
# 运行单元测试
npm run test
# 运行 E2E 测试
npm run test:e2e
# 检查覆盖率
npm run test:coverage
```
### 4. 提供反馈
**正面反馈:**
- 好的实现
- 优秀的代码
- 有价值的贡献
**建设性反馈:**
- 指出问题
- 提出建议
- 解释原因
**反馈格式:**
````markdown
### 问题
**位置:** `src/components/AppCard.vue:45`
**描述:** 这里缺少错误处理,可能导致应用崩溃。
**建议:**
```typescript
try {
await installPackage();
} catch (error) {
console.error("Install failed:", error);
showError(error.message);
}
```
````
````
### 5. 批准或要求修改
**批准条件:**
- 所有审查项目通过
- 所有测试通过
- CI 检查通过
- 没有阻塞问题
**要求修改:**
- 指出必须修复的问题
- 给出明确的修改建议
- 等待作者响应
## 审查原则
### 及时性
- 尽快响应 PR
- 设定响应时间预期
- 优先处理紧急 PR
### 建设性
- 提供具体的反馈
- 给出改进建议
- 解释审查理由
### 尊重
- 尊重作者的贡献
- 使用礼貌的语言
- 认可好的实现
### 一致性
- 遵循项目规范
- 保持审查标准一致
- 参考之前类似 PR
## 常见问题
### 类型安全问题
**问题:** 使用了 `any` 类型
**建议:**
```typescript
// ❌ 避免
const data: any = response;
// ✅ 推荐
interface ResponseData {
id: string;
name: string;
}
const data: ResponseData = response;
````
### 代码重复
**问题:** 代码重复
**建议:**
```typescript
// 提取公共函数
function formatSize(size: number): string {
return size > 1024 ? `${size / 1024} MB` : `${size} KB`;
}
```
### 错误处理
**问题:** 缺少错误处理
**建议:**
```typescript
async function loadApps() {
try {
const response = await axios.get("/api/apps");
return response.data;
} catch (error) {
logger.error({ err: error }, "Failed to load apps");
throw error;
}
}
```
## 审查后操作
### 批准
- 点击 "Approve review"
- 添加评论(可选)
- 等待合并
### 要求修改
- 选择 "Request changes"
- 提供详细反馈
- 等待作者更新
### 评论
- 选择 "Comment"
- 提供建议或问题
- 不阻止合并
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [AGENTS.md](../../AGENTS.md) - AI 编码指南

View File

@@ -0,0 +1,264 @@
---
description: 文档更新流程
---
## 工作流说明
此工作流指导如何更新项目文档。
## 步骤
### 1. 确定需要更新的文档
根据变更内容确定需要更新的文档:
- README.md - 主要说明
- DEVELOPMENT.md - 开发指南
- CONTRIBUTING.md - 贡献指南
- TESTING.md - 测试文档
- DEPLOYMENT.md - 部署文档
- TROUBLESHOOTING.md - 问题排查
- FAQ.md - 常见问题
- AGENTS.md - AI 编码指南
- CHANGELOG.md - 变更日志
### 2. 创建文档分支
```bash
git checkout -b docs/update-documentation
```
### 3. 更新文档
#### README.md
添加新功能说明:
```markdown
## 新功能
### 应用更新
现在支持一键更新所有可更新的应用。
### 下载管理
改进了下载队列管理,支持暂停和继续。
```
#### DEVELOPMENT.md
添加开发指南:
```markdown
## 新功能开发
### 添加新功能步骤
1. 理解需求
2. 设计方案
3. 实现功能
4. 编写测试
5. 提交 PR
```
#### CONTRIBUTING.md
更新贡献指南:
```markdown
### 新功能贡献
- 遵循现有代码风格
- 编写充分的测试
- 更新相关文档
```
#### TESTING.md
添加测试示例:
```typescript
describe("New Feature", () => {
it("should work correctly", () => {
// 测试代码
});
});
```
#### CHANGELOG.md
添加变更记录:
```markdown
## [4.10.0](https://github.com/elysia-best/apm-app-store/compare/v4.9.9...v4.10.0) (2026-03-10)
### Features
- feat(download): add pause and resume for downloads
- feat(update): add batch update for apps
### Bug Fixes
- fix(ui): correct dark mode toggle persistence
```
### 4. 检查文档质量
- [ ] 语法正确
- [ ] 格式统一
- [ ] 链接有效
- [ ] 内容准确
- [ ] 示例可运行
### 5. 运行文档测试
```bash
# 如果有文档测试
npm run test:docs
# 检查链接
npm run check-links
```
### 6. 本地预览
使用 Markdown 预览工具查看效果。
### 7. 提交文档
```bash
git add .
git commit -m "docs: update documentation for new features" -s
git push origin docs/update-documentation
```
### 8. 创建 Pull Request
- 说明更新的内容
- 提供预览截图(如需要)
- 引用相关 Issue
### 9. 代码审查
- 响应审查意见
- 确保文档质量
- 合并到 main 分支
## 文档编写规范
### 格式规范
- 使用 Markdown
- 保持一致的标题层级
- 使用代码块展示示例
- 使用表格对比选项
### 语言规范
- 使用简洁清晰的语言
- 避免技术术语(或解释)
- 保持中英文术语一致
- 使用被动语态
### 示例规范
```typescript
// 好的示例
import { ref } from "vue";
const count = ref(0);
function increment() {
count.value++;
}
```
### 链接规范
```markdown
- 内部链接: [文档名](./document.md)
- 外部链接: [Vue 文档](https://vuejs.org/)
- 锚点链接: [章节](#section-name)
```
## 文档模板
### 新功能文档
````markdown
## 功能名称
### 描述
简要描述功能
### 使用方法
```typescript
// 示例代码
```
````
### 配置选项
| 选项 | 类型 | 默认值 | 说明 |
| ------ | ------ | --------- | -------- |
| option | string | 'default' | 选项说明 |
### 注意事项
- 注意事项 1
- 注意事项 2
````
### API 文档
```markdown
## API 函数名
### 签名
```typescript
function functionName(param1: Type1, param2: Type2): ReturnType
````
### 参数
| 参数 | 类型 | 必填 | 说明 |
| ------ | ----- | ---- | -------- |
| param1 | Type1 | 是 | 参数说明 |
| param2 | Type2 | 否 | 参数说明 |
### 返回值
| 类型 | 说明 |
| ---------- | ---------- |
| ReturnType | 返回值说明 |
### 示例
```typescript
const result = functionName(arg1, arg2);
```
### 错误
抛出 `Error` 异常的情况说明。
```
## 注意事项
- ⚠️ 保持文档与代码同步
- ⚠️ 更新示例代码
- ⚠️ 检查链接有效性
- ⚠️ 使用统一的格式
- ⚠️ 提供清晰的说明
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [AGENTS.md](../../AGENTS.md) - AI 编码指南
```

View File

@@ -0,0 +1,135 @@
---
description: 新功能开发流程
---
## 工作流说明
此工作流指导如何开发新功能。
## 步骤
### 1. 理解需求
- 阅读 Issue 描述
- 确认功能范围
- 识别依赖关系
- 设计 API 和数据结构
### 2. 设计方案
- 设计 UI/UX如需要
- 设计数据流
- 确定 IPC 通信(如需要)
- 编写技术方案文档(可选)
### 3. 创建功能分支
```bash
git checkout -b feature/your-feature-name
```
### 4. 更新类型定义
`src/global/typedefinition.ts` 中添加新的类型定义:
```typescript
export interface NewFeatureData {
id: string;
name: string;
// ...其他字段
}
```
### 5. 编写测试
先编写测试,遵循 TDD 原则:
```typescript
// src/__tests__/unit/newFeature.test.ts
import { describe, it, expect } from "vitest";
import { newFunction } from "@/modules/newFeature";
describe("newFunction", () => {
it("should work correctly", () => {
const result = newFunction(input);
expect(result).toBe(expected);
});
});
```
### 6. 实现功能
按照以下顺序实现:
- 后端逻辑Electron 主进程)
- 前端逻辑Vue 组件)
- IPC 通信(如需要)
- 样式和布局
### 7. 运行测试
```bash
# 单元测试
npm run test
# E2E 测试
npm run test:e2e
# 代码检查
npm run lint
npm run format
```
### 8. 本地测试
- 测试所有功能场景
- 测试边界情况
- 测试错误处理
- 检查性能影响
### 9. 更新文档
- 更新 API 文档(如需要)
- 更新用户文档(如需要)
- 更新 CHANGELOG.md
### 10. 提交代码
```bash
git add .
git commit -m "feat(scope): add new feature" -s
git push origin feature/your-feature-name
```
### 11. 创建 Pull Request
- 使用 PR 模板
- 引用相关 Issue
- 添加测试说明
- 添加截图/录屏UI 变更)
### 12. 代码审查
- 响应审查意见
- 进行必要的修改
- 确保所有 CI 检查通过
### 13. 合并
- 等待审查批准
- Squash 合并到 main 分支
- 删除功能分支
## 注意事项
- ⚠️ 保持 PR 小而聚焦(建议 < 500 行)
- ⚠️ 确保 TypeScript 严格模式通过
- ⚠️ 不引入 `any` 类型(必要时使用 `eslint-disable`
- ⚠️ 所有新功能必须有测试
- ⚠️ 遵循代码规范
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [TESTING.md](../../TESTING.md) - 测试文档

View File

@@ -0,0 +1,333 @@
---
description: 性能优化流程
---
## 工作流说明
此工作流指导如何优化应用性能。
## 步骤
### 1. 识别性能问题
使用工具分析性能:
- Chrome DevTools Performance
- Vue DevTools
- Vite Build Analysis
- 内存分析工具
### 2. 分析瓶颈
确定性能瓶颈:
- 渲染性能
- 网络请求
- 内存使用
- CPU 使用
- 磁盘 I/O
### 3. 创建优化分支
```bash
git checkout -b perf/optimize-performance
```
### 4. 添加性能测试
```typescript
// src/__tests__/perf/performance.test.ts
import { describe, it, expect } from "vitest";
import { heavyFunction } from "@/modules/example";
describe("heavyFunction", () => {
it("should complete within 100ms", () => {
const start = performance.now();
heavyFunction();
const duration = performance.now() - start;
expect(duration).toBeLessThan(100);
});
});
```
### 5. 实施优化
#### 渲染性能优化
```typescript
// 使用 computed 缓存计算结果
const filteredApps = computed(() => {
return apps.value.filter(app => app.category === selectedCategory);
});
// 使用 v-memo 优化列表渲染
<template>
<div v-for="app in apps" :key="app.pkgname" v-memo="[app.id]">
{{ app.name }}
</div>
</template>
// 防抖和节流
import { debounce } from 'lodash-es';
const debouncedSearch = debounce((query: string) => {
searchApps(query);
}, 300);
```
#### 网络请求优化
```typescript
// 使用缓存
const appCache = new Map<string, App[]>();
async function fetchApps(category: string): Promise<App[]> {
if (appCache.has(category)) {
return appCache.get(category)!;
}
const apps = await axios.get(`/api/apps/${category}`);
appCache.set(category, apps.data);
return apps.data;
}
// 并发请求
const [apps1, apps2] = await Promise.all([
fetchApps("category1"),
fetchApps("category2"),
]);
```
#### 内存优化
```typescript
// 及时清理事件监听
onMounted(() => {
window.addEventListener("resize", handleResize);
});
onUnmounted(() => {
window.removeEventListener("resize", handleResize);
});
// 避免内存泄漏
let timer: number;
function startTimer() {
clearInterval(timer);
timer = setInterval(() => {
// 定时任务
}, 1000);
}
onUnmounted(() => {
clearInterval(timer);
});
```
#### 代码分割
```typescript
// 动态导入组件
const AppDetailModal = defineAsyncComponent(
() => import("@/components/AppDetailModal.vue"),
);
// 路由懒加载
const routes = [
{
path: "/app/:id",
component: () => import("@/views/AppDetail.vue"),
},
];
```
### 6. 测试性能
```bash
# 运行性能测试
npm run test:perf
# 使用 DevTools 分析
# 1. 打开 DevTools
# 2. 切换到 Performance 标签
# 3. 点击 Record
# 4. 执行操作
# 5. 停止录制并分析
```
### 7. 对比优化效果
记录优化前后的数据:
- 渲染时间
- 内存使用
- 网络请求数
- 应用启动时间
### 8. 验证功能
```bash
# 确保功能正常
npm run test
# 手动测试主要流程
```
### 9. 代码审查
检查优化是否:
- 提升了性能
- 没有破坏功能
- 代码可读
- 易于维护
### 10. 更新文档
- 记录优化内容
- 更新性能指标
- 添加优化说明
### 11. 提交代码
```bash
git add .
git commit -m "perf(scope): optimize performance" -s
git push origin perf/optimize-performance
```
### 12. 创建 Pull Request
- 说明优化内容
- 提供性能对比
- 展示优化效果
## 性能优化清单
### 渲染性能
- [ ] 使用 computed 缓存
- [ ] 使用 v-memo 优化
- [ ] 避免不必要的重新渲染
- [ ] 使用虚拟滚动(大数据集)
- [ ] 图片懒加载
### 网络性能
- [ ] 减少请求数量
- [ ] 使用缓存
- [ ] 压缩资源
- [ ] 使用 CDN
- [ ] 并发请求
### 内存性能
- [ ] 清理事件监听
- [ ] 避免内存泄漏
- [ ] 释放不再使用的资源
- [ ] 使用对象池(如需要)
- [ ] 优化数据结构
### 构建性能
- [ ] 代码分割
- [ ] Tree shaking
- [ ] 压缩代码
- [ ] 优化依赖
- [ ] 使用缓存
## 性能监控
### 关键指标
- **FCP (First Contentful Paint):** < 1.5s
- **LCP (Largest Contentful Paint):** < 2.5s
- **TTI (Time to Interactive):** < 3.5s
- **CLS (Cumulative Layout Shift):** < 0.1
- **FID (First Input Delay):** < 100ms
### 监控工具
```typescript
// 使用 Performance API
const perfData = performance.getEntriesByType("navigation")[0];
console.log("Page Load Time:", perfData.loadEventEnd - perfData.fetchStart);
// 使用 Vue DevTools
// 监控组件渲染时间
```
## 常见性能问题
### 1. 大列表渲染
**问题:** 渲染大量数据导致卡顿
**解决方案:**
```vue
<template>
<RecycleScroller :items="largeList" :item-size="50" key-field="id">
<template #default="{ item }">
<div>{{ item.name }}</div>
</template>
</RecycleScroller>
</template>
```
### 2. 频繁的 DOM 更新
**问题:** 频繁更新 DOM 导致性能下降
**解决方案:**
```typescript
// 使用 requestAnimationFrame
function animate() {
updatePosition();
requestAnimationFrame(animate);
}
```
### 3. 内存泄漏
**问题:** 内存持续增长
**解决方案:**
```typescript
// 及时清理
onUnmounted(() => {
clearInterval(timer);
removeEventListener("resize", handleResize);
clearTimeout(timeout);
});
```
### 4. 不必要的计算
**问题:** 重复计算相同结果
**解决方案:**
```typescript
// 使用 computed
const expensiveValue = computed(() => {
return heavyCalculation(data.value);
});
```
## 注意事项
- ⚠️ 不要过早优化
- ⚠️ 先测量再优化
- ⚠️ 保持代码可读
- ⚠️ 避免过度优化
- ⚠️ 持续监控性能
## 相关文档
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [TESTING.md](../../TESTING.md) - 测试文档
- [TROUBLESHOOTING.md](../../TROUBLESHOOTING.md) - 问题排查

View File

@@ -0,0 +1,284 @@
---
description: 代码重构流程
---
## 工作流说明
此工作流指导如何安全地重构代码。
## 步骤
### 1. 识别重构需求
分析代码中的问题:
- 代码重复
- 复杂度过高
- 性能问题
- 可读性差
- 难以维护
### 2. 制定重构计划
- 确定重构范围
- 列出具体改进点
- 评估影响范围
- 制定测试策略
### 3. 创建重构分支
```bash
git checkout -b refactor/your-refactor
```
### 4. 编写测试
如果代码缺少测试,先添加测试:
```typescript
// src/__tests__/unit/refactorTarget.test.ts
import { describe, it, expect } from "vitest";
import { functionToRefactor } from "@/modules/example";
describe("functionToRefactor", () => {
it("should maintain existing behavior", () => {
const result = functionToRefactor(input);
expect(result).toBe(expected);
});
});
```
### 5. 逐步重构
**原则:**
- 小步迭代
- 保持测试通过
- 不改变外部行为
**示例:**
```typescript
// 重构前
function processApp(app: any) {
if (app) {
return {
name: app.name,
pkgname: app.pkgname,
version: app.version,
};
}
return null;
}
// 重构后 - 添加类型
interface App {
name: string;
pkgname: string;
version: string;
}
function processApp(app: App | null): App | null {
if (!app) return null;
return {
name: app.name,
pkgname: app.pkgname,
version: app.version,
};
}
```
### 6. 运行测试
```bash
# 每次重构后运行测试
npm run test
# 确保所有测试通过
npm run test:all
```
### 7. 性能验证
如果重构涉及性能:
```bash
# 运行性能测试
npm run test:perf
# 对比重构前后性能
```
### 8. 代码审查
自我检查:
- 代码更清晰
- 性能未下降
- 测试全部通过
- 没有引入新问题
### 9. 更新文档
- 更新相关文档
- 添加注释说明
- 更新 CHANGELOG.md
### 10. 提交代码
```bash
git add .
git commit -m "refactor(scope): describe the refactoring" -s
git push origin refactor/your-refactor
```
### 11. 创建 Pull Request
- 说明重构原因
- 展示改进效果
- 提供性能对比(如需要)
### 12. 代码审查
- 响应审查意见
- 确保所有测试通过
- 合并到 main 分支
## 重构原则
### 不改变外部行为
- 保持 API 兼容
- 保持输出一致
- 保持错误处理
### 小步迭代
- 每次只改一处
- 频繁运行测试
- 及时提交代码
### 测试驱动
- 先写测试
- 重构代码
- 确保通过
### 保持简单
- 减少复杂度
- 提高可读性
- 增强可维护性
## 常见重构模式
### 提取函数
```typescript
// 重构前
function processApps(apps: App[]) {
for (const app of apps) {
if (app.installed) {
console.log(app.name + " is installed");
}
}
}
// 重构后
function logInstalledApp(app: App) {
if (app.installed) {
console.log(`${app.name} is installed`);
}
}
function processApps(apps: App[]) {
apps.forEach(logInstalledApp);
}
```
### 提取类型
```typescript
// 重构前
function createDownload(data: any) {
return {
id: data.id,
name: data.name,
pkgname: data.pkgname,
};
}
// 重构后
interface DownloadData {
id: number;
name: string;
pkgname: string;
}
function createDownload(data: DownloadData): DownloadItem {
return {
id: data.id,
name: data.name,
pkgname: data.pkgname,
status: "queued",
progress: 0,
downloadedSize: 0,
totalSize: 0,
speed: 0,
timeRemaining: 0,
startTime: Date.now(),
logs: [],
source: "APM Store",
retry: false,
};
}
```
### 简化条件
```typescript
// 重构前
function getStatus(status: string): string {
if (status === "queued") {
return "Queued";
} else if (status === "downloading") {
return "Downloading";
} else if (status === "installing") {
return "Installing";
} else if (status === "completed") {
return "Completed";
} else if (status === "failed") {
return "Failed";
} else {
return "Unknown";
}
}
// 重构后
const statusMap: Record<string, string> = {
queued: "Queued",
downloading: "Downloading",
installing: "Installing",
completed: "Completed",
failed: "Failed",
};
function getStatus(status: string): string {
return statusMap[status] || "Unknown";
}
```
## 注意事项
- ⚠️ 不要在重构中引入新功能
- ⚠️ 不要同时重构多处
- ⚠️ 确保测试覆盖充分
- ⚠️ 保持提交历史清晰
- ⚠️ 及时回退有问题的重构
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [TESTING.md](../../TESTING.md) - 测试文档

View File

@@ -0,0 +1,211 @@
---
description: 发布流程
---
## 工作流说明
此工作流指导如何发布新版本。
## 步骤
### 1. 更新版本号
```bash
# 更新版本
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.0 → 1.1.0
npm version major # 1.0.0 → 2.0.0
# 或手动编辑 package.json
```
### 2. 更新 CHANGELOG.md
```bash
# 生成变更日志
npm run changelog
```
或手动更新:
```markdown
## [1.0.1](https://github.com/elysia-best/apm-app-store/compare/v1.0.0...v1.0.1) (2026-03-10)
### Bug Fixes
- fix(ui): correct dark mode toggle persistence (#123)
### Features
- feat(install): add retry mechanism for failed installations (#124)
```
### 3. 运行完整测试
```bash
# 运行所有测试
npm run test:all
# 运行代码检查
npm run lint
npm run format
# 构建项目
npm run build:vite
```
### 4. 提交变更
```bash
git add .
git commit -m "chore(release): bump version to x.x.x" -s
git push origin main
```
### 5. 创建 Git 标签
```bash
# 创建标签
git tag v{version}
# 推送标签
git push origin v{version}
```
### 6. 触发 CI 构建
推送标签后会自动触发 GitHub Actions 构建。
### 7. 验证构建
在 GitHub Actions 页面查看:
- 所有测试通过
- 构建成功
- 构建产物生成
### 8. 检查 Release
GitHub Actions 会自动创建 Release
- 访问 Releases 页面
- 检查版本信息
- 确认构建产物
### 9. 发布说明
如果需要,更新 Release 说明:
- 添加主要变更
- 添加已知问题
- 添加升级说明
### 10. 通知用户
- 更新 README
- 发布公告
- 通知用户
## 发布检查清单
### 代码质量
- [ ] 所有测试通过
- [ ] 代码检查通过
- [ ] 没有已知严重 Bug
- [ ] 性能测试通过
### 文档
- [ ] CHANGELOG.md 更新
- [ ] README.md 更新(如需要)
- [ ] API 文档更新(如需要)
### 构建
- [ ] 本地构建成功
- [ ] CI 构建成功
- [ ] 构建产物正确
### 发布
- [ ] 版本号正确
- [ ] 标签已推送
- [ ] Release 已创建
- [ ] 构建产物已上传
## 版本号规范
遵循 [Semantic Versioning](https://semver.org/)
- **MAJOR:** 不兼容的 API 变更
- **MINOR:** 向后兼容的功能新增
- **PATCH:** 向后兼容的 Bug 修复
### 示例
```
4.9.9 → 4.9.10 (PATCH: Bug 修复)
4.9.9 → 4.10.0 (MINOR: 新功能)
4.9.9 → 5.0.0 (MAJOR: 重大变更)
```
## 发布后
### 更新开发分支
```bash
git checkout develop
git merge main
git push origin develop
```
### 监控反馈
- 收集用户反馈
- 监控 Bug 报告
- 记录性能数据
### 准备下一个版本
- 创建新的 Issue
- 规划新功能
- 评估技术债务
## 回滚流程
如果发现严重问题:
### 1. 立即停止推广
- 通知用户暂停升级
- 更新下载页面
### 2. 修复问题
```bash
git checkout main
git checkout -b fix/critical-issue
# 修复问题
git push origin fix/critical-issue
```
### 3. 紧急发布
```bash
npm version patch
git tag -a v{x.x.x} -m "Hotfix: description"
git push origin v{x.x.x}
```
### 4. 通知用户
- 发布新版本
- 说明问题和修复
- 提供升级说明
## 相关文档
- [DEPLOYMENT.md](../../DEPLOYMENT.md) - 部署文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [CHANGELOG.md](../../CHANGELOG.md) - 变更日志

View File

@@ -0,0 +1,435 @@
---
description: 安全审计流程
---
## 工作流说明
此工作流指导如何进行安全审计。
## 步骤
### 1. 确定审计范围
确定需要审计的方面:
- 代码安全
- 依赖安全
- 数据安全
- 网络安全
- 权限管理
### 2. 创建审计分支
```bash
git checkout -b security/security-audit
```
### 3. 代码安全审计
#### 检查 SQL 注入
```typescript
// ❌ 不安全
const query = `SELECT * FROM apps WHERE name = '${appName}'`;
// ✅ 安全
const query = "SELECT * FROM apps WHERE name = ?";
db.query(query, [appName]);
```
#### 检查 XSS 攻击
```typescript
// ❌ 不安全
element.innerHTML = userInput;
// ✅ 安全
element.textContent = userInput;
// 或使用 DOMPurify
import DOMPurify from "dompurify";
element.innerHTML = DOMPurify.sanitize(userInput);
```
#### 检查命令注入
```typescript
// ❌ 不安全
const cmd = `apm install ${packageName}`;
exec(cmd);
// ✅ 安全
const args = ["apm", "install", packageName];
spawn("apm", args);
```
#### 检查路径遍历
```typescript
// ❌ 不安全
const filePath = path.join(basePath, userInput);
// ✅ 安全
const safePath = path.normalize(userInput).replace(/^(\.\.(\/|\\|$))+/, "");
const filePath = path.join(basePath, safePath);
```
### 4. 依赖安全审计
```bash
# 检查依赖漏洞
npm audit
# 自动修复
npm audit fix
# 手动修复
npm audit fix --force
```
#### 检查 package.json
```json
{
"dependencies": {
"axios": "^1.13.2",
"pino": "^10.3.0"
},
"devDependencies": {
"@playwright/test": "^1.40.0"
}
}
```
### 5. 数据安全审计
#### 检查敏感信息
```typescript
// ❌ 不安全 - 硬编码密钥
const apiKey = "sk-1234567890";
// ✅ 安全 - 使用环境变量
const apiKey = process.env.API_KEY;
// ❌ 不安全 - 记录敏感信息
logger.info({ password: user.password }, "User logged in");
// ✅ 安全 - 不记录敏感信息
logger.info({ userId: user.id }, "User logged in");
```
#### 检查数据加密
```typescript
// 加密敏感数据
import crypto from "crypto";
function encrypt(text: string, key: string): string {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
let encrypted = cipher.update(text, "utf8", "hex");
encrypted += cipher.final("hex");
return iv.toString("hex") + ":" + encrypted;
}
```
### 6. 网络安全审计
#### 检查 HTTPS
```typescript
// ❌ 不安全 - HTTP
const baseURL = "http://api.example.com";
// ✅ 安全 - HTTPS
const baseURL = "https://api.example.com";
```
#### 检查证书验证
```typescript
// 配置 Axios 验证证书
const axiosInstance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: true,
}),
});
```
#### 检查 CORS
```typescript
// 配置 CORS
app.use(
cors({
origin: "https://yourdomain.com",
credentials: true,
}),
);
```
### 7. 权限管理审计
#### 检查权限提升
```typescript
// 检查 pkexec 可用性
const checkSuperUserCommand = async (): Promise<string> => {
if (process.getuid && process.getuid() !== 0) {
const { stdout } = await execAsync("which /usr/bin/pkexec");
return stdout.trim().length > 0 ? "/usr/bin/pkexec" : "";
}
return "";
};
```
#### 检查上下文隔离
```typescript
// electron/preload/index.ts
// ✅ 安全 - 启用上下文隔离
contextBridge.exposeInMainWorld("ipcRenderer", {
send: (...args) => ipcRenderer.send(...args),
on: (...args) => ipcRenderer.on(...args),
invoke: (...args) => ipcRenderer.invoke(...args),
});
// ❌ 不安全 - 禁用上下文隔离
contextIsolation: false;
```
### 8. 运行安全工具
```bash
# 使用 Snyk 扫描
npx snyk test
# 使用 npm audit
npm audit
# 使用 ESLint 安全规则
npm run lint
```
### 9. 修复安全问题
根据审计结果修复发现的问题:
```typescript
// 修复示例
function validateInput(input: string): boolean {
// 验证输入
const regex = /^[a-zA-Z0-9-_]+$/;
return regex.test(input);
}
function sanitizeInput(input: string): string {
// 清理输入
return input.trim().replace(/[<>]/g, "");
}
```
### 10. 安全测试
```typescript
// src/__tests__/security/security.test.ts
import { describe, it, expect } from "vitest";
import { validateInput, sanitizeInput } from "@/modules/security";
describe("Security", () => {
describe("validateInput", () => {
it("should reject malicious input", () => {
expect(validateInput('<script>alert("xss")</script>')).toBe(false);
});
it("should accept valid input", () => {
expect(validateInput("valid-app-name")).toBe(true);
});
});
describe("sanitizeInput", () => {
it("should remove dangerous characters", () => {
expect(sanitizeInput("<script>app</script>")).toBe("scriptapp/script");
});
});
});
```
### 11. 更新文档
- 记录安全问题
- 说明修复方法
- 更新安全指南
### 12. 提交代码
```bash
git add .
git commit -m "security: fix security vulnerabilities" -s
git push origin security/security-audit
```
### 13. 创建 Pull Request
- 说明安全问题
- 展示修复方法
- 提供安全测试结果
## 安全检查清单
### 代码安全
- [ ] 输入验证
- [ ] 输出编码
- [ ] 参数化查询
- [ ] 错误处理
- [ ] 日志安全
### 依赖安全
- [ ] 定期更新依赖
- [ ] 使用 `npm audit`
- [ ] 检查已知漏洞
- [ ] 使用可信源
### 数据安全
- [ ] 敏感数据加密
- [ ] 不记录敏感信息
- [ ] 使用环境变量
- [ ] 安全存储
### 网络安全
- [ ] 使用 HTTPS
- [ ] 验证证书
- [ ] 配置 CORS
- [ ] 防止 CSRF
### 权限管理
- [ ] 最小权限原则
- [ ] 上下文隔离
- [ ] 权限检查
- [ ] 审计日志
## 常见安全问题
### 1. XSS 攻击
**问题:** 用户输入包含恶意脚本
**解决方案:**
```typescript
import DOMPurify from "dompurify";
function sanitizeHTML(html: string): string {
return DOMPurify.sanitize(html);
}
```
### 2. SQL 注入
**问题:** 恶意 SQL 代码注入
**解决方案:**
```typescript
// 使用参数化查询
db.query("SELECT * FROM apps WHERE name = ?", [appName]);
```
### 3. 命令注入
**问题:** 恶意命令注入
**解决方案:**
```typescript
// 使用 spawn 而非 exec
const args = ["apm", "install", packageName];
spawn("apm", args);
```
### 4. 路径遍历
**问题:** 访问未授权文件
**解决方案:**
```typescript
// 验证路径
const safePath = path.normalize(userPath).replace(/^(\.\.(\/|\\|$))+/, "");
```
### 5. 敏感信息泄露
**问题:** 日志中包含敏感信息
**解决方案:**
```typescript
// 不记录敏感信息
logger.info({ userId: user.id }, "User logged in");
```
## 安全最佳实践
### 1. 最小权限原则
只授予必要的权限,避免过度授权。
### 2. 深度防御
多层安全防护,不依赖单一安全措施。
### 3. 输入验证
验证所有输入,包括用户输入和 API 响应。
### 4. 输出编码
对输出进行编码,防止 XSS 攻击。
### 5. 定期审计
定期进行安全审计,及时发现和修复问题。
### 6. 安全更新
及时更新依赖和系统,修复已知漏洞。
## 安全工具
### 静态分析
- ESLint
- TypeScript
- SonarQube
### 动态分析
- OWASP ZAP
- Burp Suite
- Snyk
### 依赖扫描
- npm audit
- Snyk
- Dependabot
## 注意事项
- ⚠️ 不要忽视安全问题
- ⚠️ 及时修复漏洞
- ⚠️ 定期更新依赖
- ⚠️ 保持安全意识
- ⚠️ 遵循安全最佳实践
## 相关文档
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - 贡献指南
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档
- [SECURITY.md](../../SECURITY.md) - 安全政策

View File

@@ -0,0 +1,108 @@
---
description: 测试编写流程
---
## 工作流说明
此工作流指导如何为新功能或 Bug 修复编写测试。
## 步骤
### 1. 确定测试范围
分析需要测试的功能点:
- 单元测试:测试独立函数/组件
- 集成测试:测试模块间交互
- E2E 测试:测试完整用户流程
### 2. 编写单元测试Vitest
`src/__tests__/unit/` 目录下创建测试文件:
```typescript
import { describe, it, expect } from "vitest";
import { someFunction } from "@/modules/example";
describe("someFunction", () => {
it("should return expected result", () => {
const result = someFunction(input);
expect(result).toBe(expected);
});
});
```
### 3. 编写组件测试
```typescript
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import AppCard from "@/components/AppCard.vue";
describe("AppCard", () => {
it("should render app name", () => {
const wrapper = mount(AppCard, {
props: {
app: {
name: "Test App",
pkgname: "test-app",
},
},
});
expect(wrapper.text()).toContain("Test App");
});
});
```
### 4. 编写 E2E 测试Playwright
`e2e/` 目录下创建测试文件:
```typescript
import { test, expect } from "@playwright/test";
test("install app from store", async ({ page }) => {
await page.goto("http://localhost:3344");
await page.click("text=Test App");
await page.click('button:has-text("安装")');
await expect(page.locator(".install-progress")).toBeVisible();
});
```
### 5. 运行测试
```bash
# 运行单元测试
npm run test
# 运行测试并监听
npm run test:watch
# 运行 E2E 测试
npm run test:e2e
# 生成覆盖率报告
npm run test:coverage
```
### 6. 确保测试通过
- 所有单元测试必须通过
- E2E 测试覆盖主要用户流程
- 测试覆盖率不低于 70%
### 7. 提交代码
测试通过后,提交代码并创建 PR。
## 注意事项
- ⚠️ 不要测试第三方库的功能
- ⚠️ 保持测试独立性和可重复性
- ⚠️ 使用有意义的测试名称
- ⚠️ Mock 外部依赖APM 命令、API 调用)
## 相关文档
- [TESTING.md](../../TESTING.md) - 测试框架和规范
- [DEVELOPMENT.md](../../DEVELOPMENT.md) - 开发文档

View File

@@ -1,6 +0,0 @@
---
description: 审查
---
审查是否符合代码规范
是否有代码缺陷