# Gitea-Jira工单同步系统 ## 部署指南 ### 第一步:环境准备 #### 1.1 系统要求 - Node.js版本: 14.0.0或更高 - npm版本: 6.0.0或更高 - SQLite: 3.0或更高 #### 1.2 依赖安装 ```bash cd /path/to/gitea-jira-sync npm install ``` 该命令将安装以下依赖: - express (5.x): Web框架和HTTP服务器 - axios (1.13.x): HTTP客户端库 - better-sqlite3 (9.x): SQLite数据库驱动 - dotenv (17.x): 环境变量加载 - express-rate-limit (8.x): 速率限制中间件 - j2m (1.1.x): Markdown与Jira格式转换库 ### 第二步:环境变量配置 #### 2.1 创建.env文件 ```bash cp .env.example .env ``` #### 2.2 配置SQLite数据库 ``` SQLITE_PATH=./data/gitea_jira_sync.db ``` 获取方法: - SQLITE_PATH: SQLite数据库文件路径(默认./data/gitea_jira_sync.db) 注意: 数据库文件和表会自动创建,无需手动初始化 #### 2.3 配置Gitea信息 ``` GITEA_URL=https://gitea.example.com GITEA_TOKEN=your_gitea_api_token GITEA_BOT_ID=your_bot_user_id GITEA_BOT_NAME=your_bot_username ``` 获取方法: - GITEA_URL: Gitea服务器地址 - GITEA_TOKEN: 登录Gitea后,访问设置->应用->创建新令牌(api_token) - GITEA_BOT_ID: 登录机器人账号,访问API /api/v1/user 获取id字段 - GITEA_BOT_NAME: 机器人的用户名 #### 2.4 配置Jira信息 ``` JIRA_URL=https://jira.example.com JIRA_USERNAME=your_jira_username JIRA_PASSWORD=your_jira_password_or_pat JIRA_PROJECT_ID_1=10000 JIRA_PROJECT_KEY_1=TEST JIRA_BOT_ID=jira_bot_id JIRA_BOT_NAME=jira_bot_name ``` 获取方法: - JIRA_URL: Jira服务器地址 - JIRA_USERNAME: Jira用户名 - JIRA_PASSWORD: Jira密码或个人访问令牌(推荐使用PAT) - JIRA_PROJECT_ID_1: 访问/rest/api/2/project获取id - JIRA_PROJECT_KEY_1: 项目的英文标识符(如TEST、PROJ等) - JIRA_BOT_ID: 机器人账号的ID或Key - JIRA_BOT_NAME: 机器人显示名称 #### 2.5 配置Webhook签名密钥 ``` GITEA_WEBHOOK_SECRET=your_webhook_secret_key JIRA_WEBHOOK_SECRET=your_jira_webhook_secret ``` #### 2.6 配置熔断器参数(可选) ``` CIRCUIT_BREAKER_LIMIT=20 CIRCUIT_BREAKER_WINDOW=10000 DEBUG_MODE=false ``` 参数说明: - CIRCUIT_BREAKER_LIMIT: 时间窗口内允许的最大请求数(默认20) - CIRCUIT_BREAKER_WINDOW: 时间窗口大小,单位毫秒(默认10000ms=10秒) - DEBUG_MODE: 是否启用调试模式(默认false,启用后熔断器不会强制退出) ### 第三步:映射配置 #### 3.1 编辑mappings.json 配置需要同步的仓库及其字段映射 目前,已经开发了图形化配置工具,无需再手动配置,但是遇到特殊情况(比如json损坏、扫不出流转状态和sprint还是要手动,实测发生概率不大) #### 3.2 获取Jira映射ID **获取Priority ID**: ```bash curl -u username:password https://jira.example.com/rest/api/2/priority ``` 返回JSON中查看id字段 **获取Issue Type ID**: ```bash curl -u username:password https://jira.example.com/rest/api/2/issuetype ``` 返回JSON中查看id字段 **获取Sprint ID**: ```bash curl -u username:password https://jira.example.com/rest/api/2/issue/TEST-1 ``` 搜索customfield_10105字段,格式:[id=37,name=Sprint Name,...] **获取Transition ID**: ```bash curl -u username:password https://jira.example.com/rest/api/2/issue/TEST-1/transitions ``` 查看transitions数组中的id字段 ### 第四步:启动服务 #### 4.1 直接运行 ```bash node index.js ``` 输出示例: ``` Server running on http://localhost:3000 Database initialized: issue_mapping table ready Webhook endpoints ready: POST /webhook/gitea POST /webhook/jira ``` #### 4.2 后台运行(使用pm2) ```bash npm install -g pm2 pm2 start index.js --name "gitea-jira-sync" pm2 save pm2 startup ``` #### 4.3 使用systemd服务(Linux) 创建/etc/systemd/system/gitea-jira-sync.service: ```ini [Unit] Description=Gitea-Jira Sync Service After=network.target [Service] Type=simple User=your_user WorkingDirectory=/path/to/gitea-jira-sync ExecStart=/usr/bin/node index.js Restart=always RestartSec=10 [Install] WantedBy=multi-user.target ``` 启动服务: ```bash sudo systemctl start gitea-jira-sync sudo systemctl enable gitea-jira-sync ``` ### 第五步:配置Webhook #### 5.1 Gitea端配置 1. 进入仓库设置 -> 设置 -> Web Hooks -> Gitea 2. 点击"添加Webhook" 3. 填写以下信息: - 推送地址: http://your_server:3000/webhook/gitea - HTTP方法: POST - POST内容类型: application/json - 密钥: 与.env中GITEA_WEBHOOK_SECRET一致 - 触发事件: Issue和Comment(必选) 4. 测试Webhook确保连接正常 #### 5.2 Jira端配置 1. 访问Jira管理界面 -> 系统 -> Webhooks 2. 点击"创建webhook" 3. 填写以下信息: - 名称: Gitea Sync Webhook - URL: http://your_server:3000/webhook/jira - 事件类型: jira:issue_created, jira:issue_updated, jira:issue_deleted - 认证: Basic auth或Bearer token(与.env配置一致) 4. 点击"创建" ### 第六步:验证部署 #### 6.1 检查服务状态 ```bash curl http://localhost:3000/health ``` 预期输出: 200状态码,表示服务运行正常 #### 6.2 查看日志 ```bash tail -f logs/$(date +%Y-%m-%d).log ``` 观察同步操作的日志记录 #### 6.3 测试同步 **测试Gitea->Jira**: 1. 在Gitea中新建工单 2. 观察logs中出现同步日志 3. 检查Jira中是否创建了对应问题 **测试Jira->Gitea**: 1. 在Jira中新建问题 2. 观察logs中出现同步日志 3. 检查Gitea中是否创建了对应工单 ## 使用指南 ### 场景一:新建工单自动同步 **Gitea新建工单**: 1. 进入Gitea仓库 2. 点击Issues -> 新建Issue 3. 填写标题、描述、指派人、标签(优先级、类型)、里程碑 4. 点击提交 5. 系统自动在Jira创建对应问题 6. Gitea工单中添加评论,包含Jira问题链接 **Jira新建问题**: 1. 进入Jira项目 2. 点击创建按钮 3. 填写摘要、描述、经办人、优先级、问题类型、迭代 4. 点击创建 5. 系统自动在Gitea创建对应工单 6. Jira问题中添加评论,包含Gitea工单链接 ### 场景二:更新工单字段 **修改优先级**: 1. 在任何一端修改优先级 2. 系统自动更新对方平台的对应标签 3. 对应标签根据mappings.js中的优先级映射进行转换 **修改工单类型**: 1. 在任何一端修改工单类型 2. 系统自动更新对方平台的对应标签 3. 对应标签根据mappings.js中的类型映射进行转换 **修改迭代/里程碑**: 1. 在任何一端修改迭代或里程碑 2. 系统自动更新对方平台 3. 里程碑名称与Sprint ID根据mappings.js进行映射 **重开操作**: 1. 在Gitea关闭工单 -> Jira问题自动转至完成状态 2. 在Jira完成问题 -> Gitea工单自动关闭 3. 重开操作会将对方平台状态改为处理中/打开 ### 场景三:跨平台手动同步 **使用/resync命令**: 1. 在Gitea或Jira工单评论中输入`/resync` 2. 系统会强制重新同步所有字段 3. 如果对方平台不存在对应工单,会自动创建 4. 如果已存在,会更新所有字段 **#不同步标记**: 1. 在工单标题中添加`#不同步`标记 2. 该工单不会自动同步到对方平台 3. 使用`/resync`命令可以强制同步带有`#不同步`标记的工单 ### 场景四:类型过滤 **类型未配置的工单不同步**: 1. 如果工单的类型标签在mappings.json中没有配置对应关系 2. 且mappings.json中没有设置`defaultType` 3. 该工单不会被同步,日志会记录跳过原因 ### 启用DEBUG模式 用于开发和故障诊断: ```bash DEBUG_MODE=true node index.js ``` DEBUG模式下: - 打印所有webhook payload - 打印API调用详情 - 跳过熔断器强制退出 - 输出详细的转换过程 ## 性能优化 ### 1. 连接池配置 - axios客户端使用keep-alive连接 - 自动复用TCP连接减少握手开销 ### 2. 数据库优化 - SQLite支持并发访问和连接优化 - 映射表创建了repo_key、gitea_id、jira_key索引加速查询 - 支持事务和完整的ACID特性 ### 3. 异步处理 - 日志写入使用异步队列 - Webhook响应立即返回,实际处理异步进行 ### 4. 缓存策略 - 标签、优先级、工单类型信息在mappings.json中缓存 - 避免每次处理都请求Jira API ## 安全考虑 ### 1. Webhook签名验证 - 所有webhook请求都经过HMAC签名验证 - 未通过验证的请求被直接拒绝 ### 2. API认证 - Gitea使用token认证 - Jira支持Basic Auth和PAT认证 ### 3. 敏感信息保护 - 环境变量不在代码中硬编码 - 日志不记录password和token字段 - SQLite数据库文件应该在安全位置存储 ### 4. 防无限循环 - 机器人识别防止自己操作的无限循环 - 熔断机制防止恶意攻击导致的无限请求 - 内存锁防止重复处理同一工单 ## 代码结构 ``` src/ config/ - 配置文件 env.js - 环境变量加载 mappings.js - 字段映射配置 db/ - 数据库相关 connection.js - 数据库连接 issueMap.js - 映射表操作 logic/ - 业务逻辑 converter.js - 数据转换 syncManager.js - Gitea->Jira同步 jiraSyncManager.js - Jira->Gitea同步 services/ - API服务 gitea.js - Gitea API客户端 jira.js - Jira API客户端 utils/ - 工具函数 logger.js - 日志模块 circuitBreaker.js - 熔断器 index.js - 主程序 mappings.json -映射表 ```