感谢您对为 DevFlow 做贡献的兴趣!本文档为贡献者提供指南和信息。
通过参与这个项目,您同意遵守我们的行为准则。请在贡献之前阅读它。
创建问题之前:
- 搜索现有问题以避免重复
- 使用清晰、描述性的标题
- 提供详细的重现步骤
- 包含系统信息(操作系统、Rust 版本等)
- 添加相关标签
我们欢迎功能建议!请:
- 检查功能是否已存在或已计划
- 使用 "enhancement" 标签打开问题
- 描述您试图解决的问题
- 解释您提议的解决方案
- 考虑实现复杂性
- Rust 1.70 或更高版本
- Git
- 对异步 Rust 的基本理解
- 熟悉 CLI 开发
- Fork 仓库
- 克隆您的 fork:
git clone https://github.com/yourusername/devflow.git cd devflow - 创建新分支:
git checkout -b feature/your-feature-name
- 安装依赖并构建:
cargo build
- 遵循 Rust 约定和习语
- 使用
cargo fmt格式化代码 - 运行
cargo clippy并修复警告 - 为公共 API 添加文档
- 为新功能编写测试
# 运行所有测试
cargo test
# 使用覆盖率运行
cargo tarpaulin --out Html
# 测试特定模块
cargo test ai::tests遵循约定式提交格式:
feat:新功能fix:错误修复docs:文档更改style:代码风格更改refactor:代码重构test:测试添加/更改chore:维护任务
示例:
feat(ai): 添加 Claude API 提供商支持
- 实现 ClaudeProvider 结构体
- 添加异步 trait 实现
- 更新配置以支持 Claude
- 为 Claude 集成添加测试
Closes #123
- 确保所有测试通过
- 如有需要更新文档
- 为您的更改添加/更新测试
- 确保代码遵循风格指南
- 创建清晰的 PR 描述
- 链接相关问题
- 请求维护者审查
devflow/
├── src/
│ ├── main.rs # 入口点
│ ├── cli/ # CLI 接口
│ │ ├── mod.rs
│ │ └── commands/ # 命令实现
│ ├── ai/ # AI 提供商集成
│ │ ├── mod.rs
│ │ ├── openai.rs
│ │ ├── claude.rs
│ │ └── ollama.rs
│ ├── templates/ # 模板系统
│ ├── generators/ # 代码生成器
│ ├── config/ # 配置管理
│ └── utils/ # 工具函数
├── templates/ # 内置模板
├── tests/ # 集成测试
├── docs/ # 文档
└── examples/ # 使用示例
- 🐛 错误修复
- 📚 文档改进
- 🧪 测试覆盖率提升
- 🔧 性能优化
- 🎨 新项目模板
- 🌐 额外语言支持
- 🔌 新 AI 提供商集成
- ⚙️ 配置增强
- 🎯 功能增强
- 🖥️ UI 改进
- 📦 包管理
- 🚀 性能监控
要添加新项目模板:
-
创建模板目录:
mkdir templates/my-template
-
创建
template.toml:[metadata] name = "my-template" description = "我的优秀模板" version = "1.0.0" author = "您的姓名" tech_stack = ["React", "Node.js"] [dependencies] runtime = { react = "^18.0.0" } development = { "@types/react" = "^18.0.0" } system = ["nodejs", "npm"] [scripts] dev = "npm run dev" build = "npm run build" test = "npm test"
-
在
files/目录中添加模板文件 -
使用
{{ project_name }}等变量进行自定义 -
在
tests/templates/中添加测试 -
更新文档
要添加新的 AI 提供商:
-
创建提供商模块:
// src/ai/myprovider.rs use super::{AIProvider, AIResponse}; pub struct MyProvider { // 提供商字段 } #[async_trait::async_trait] impl AIProvider for MyProvider { async fn generate_project_config(&self, config: &ProjectConfig) -> Result<AIResponse> { // 实现 } // ... 其他方法 }
-
更新
src/ai/mod.rs:pub mod myprovider; pub enum AIProviderEnum { // ... 现有提供商 MyProvider(myprovider::MyProvider), }
-
添加配置支持
-
添加测试
-
更新文档
- 测试单个函数和模块
- 模拟外部依赖
- 使用描述性测试名称
- 遵循 AAA 模式(安排、执行、断言)
- 测试完整工作流
- 为文件操作使用临时目录
- 测试后清理资源
- 测试错误条件
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[tokio::test]
async fn test_project_generation() {
// 安排
let temp_dir = TempDir::new().unwrap();
let config = ProjectConfig {
name: "test-project".to_string(),
// ... 其他字段
};
// 执行
let result = generate_project(&config, temp_dir.path()).await;
// 断言
assert!(result.is_ok());
assert!(temp_dir.path().join("package.json").exists());
}
}- 记录所有公共 API
- 使用 rustdoc 约定
- 在文档注释中包含示例
- 保持文档最新
- 为新功能更新 README.md
- 向
examples/目录添加示例 - 更新 CLI 帮助文本
- 为复杂功能创建教程
- 更新
Cargo.toml中的版本 - 更新 CHANGELOG.md
- 创建发布分支
- 彻底测试
- 创建 GitHub 发布
- 发布到 crates.io(仅维护者)
- 💬 加入我们的 Discord
- 📧 邮箱:dev@devflow.dev
- 🐛 为错误打开问题
- 💡 为问题开始讨论
贡献者将:
- 列在 CONTRIBUTORS.md 中
- 在发布说明中提及
- 被邀请加入维护者团队(对于重大贡献)
感谢您让 DevFlow 变得更好!🚀