# Bug Fixes Summary ## Overview This document summarizes the recent bug fixes for bidirectional sync issues between Redmine and Gitea. --- ## Fix #1: Label to Field Mapping (Gitea → Redmine) ### Problem When syncing from Gitea to Redmine: - Gitea uses **labels** for tracker types ("bug", "feature") and priorities ("High Priority", etc.) - Redmine uses **fields**: `tracker_id` and `priority_id` - Previously, all Gitea issues were created in Redmine as "Bug" with "Normal" priority, regardless of labels ### Solution Added reverse mapping to parse Gitea labels and convert them to Redmine field IDs: **Tracker Mapping:** ```javascript giteaToRedmine: { "bug": 1, // Bug tracker "feature": 2, // Feature tracker "support": 3, // Support tracker } ``` **Priority Mapping:** ```javascript giteaToRedmine: { "Low Priority": 1, "Normal Priority": 2, "High Priority": 3, "Urgent": 4, "Immediate": 5, } ``` **New Utility Functions:** - `extractTrackerFromLabels(labels)` - Scans labels for tracker types - `extractPriorityFromLabels(labels)` - Scans labels for priority levels - Falls back to defaults if no matching labels found ### Testing ```bash # 1. Create issue in Gitea with labels: # - "feature" # - "High Priority" # 2. Check Redmine: # - Tracker: Feature # - Priority: High ``` --- ## Fix #2: Redmine Comments Not Syncing to Gitea ### Problem - Adding notes/journals in Redmine didn't create comments in Gitea - Gitea → Redmine comment sync worked fine - Issue was one-directional ### Root Cause The Redmine → Gitea sync only processed journals when creating NEW issues, not when updating existing ones. ### Solution Modified the webhook handler to always process journals: **Before:** ```javascript if (giteaIssue) { // Update issue await GiteaAPI.updateIssue(...); // ❌ Journals not processed here } else { // Create issue await GiteaAPI.createIssue(...); // ✅ Journals only processed for new issues } ``` **After:** ```javascript if (giteaIssue) { // Update issue await GiteaAPI.updateIssue(...); // ✅ ALWAYS process journals if (payload.journal) { await SyncUtilities.processJournals(...); } } ``` ### Improvements 1. **Better logging** for journal processing 2. **Safer author extraction** - handles both `journal.user.login` and `journal.author.login` 3. **Debug messages** to trace journal skipping decisions 4. **Change tracking** - field changes are included in Gitea comments ### Testing ```bash # 1. Create issue in Redmine # 2. Sync creates Gitea issue # 3. Add note in Redmine with text: "This is a test comment" # 4. Check Gitea issue - should see comment: [Redmine Journal #14] **admin** commented: This is a test comment **Changes:** - status_id: 1 → 2 - due_date: (none) → 2025-12-19 ``` --- ## Fix #3: Date Format Issues (422 Errors) ### Problem **Gitea → Redmine:** - Gitea sends: `2025-12-19T00:00:00Z` (ISO 8601) - Redmine expects: `2025-12-19` (date only) - Result: 422 validation error **Redmine → Gitea:** - Redmine sends: `2025-12-19` - Gitea expects: `2025-12-19T00:00:00Z` (ISO 8601) - Previously could cause issues ### Solution **For Gitea → Redmine:** ```javascript // Extract date portion only if (issue.due_date) { const dueDate = new Date(issue.due_date); if (!isNaN(dueDate.getTime())) { issueData.due_date = dueDate.toISOString().split('T')[0]; // Result: "2025-12-19" } } ``` **For Redmine → Gitea:** ```javascript // Convert to full ISO format if (issue.due_date) { const dueDate = new Date(issue.due_date); if (!isNaN(dueDate.getTime())) { issueData.due_date = dueDate.toISOString(); // Result: "2025-12-19T00:00:00.000Z" } } ``` **Safety Features:** - Date validation before sending - Try-catch blocks for invalid dates - Warning logs for malformed dates - Graceful fallback (omit field if invalid) --- ## Fix #4: Label Handling (422 Errors) ### Problem **Redmine → Gitea:** - Labels were included in issue create/update payload - Gitea expects label IDs as numbers: `[1, 2, 3]` - We were sending label objects: `[{name: "bug"}, {name: "feature"}]` - Result: 422 validation error ### Solution **Two-step process:** 1. **Create/update issue WITHOUT labels** 2. **Set labels separately using label IDs** ```javascript // Step 1: Create/update issue await GiteaAPI.updateIssue(owner, repo, number, { title: "...", body: "...", state: "open", // ❌ NO labels here }); // Step 2: Set labels separately await GiteaAPI.setIssueLabels(owner, repo, number, ["bug", "High Priority"]); ``` **Label ID Resolution:** ```javascript static async setIssueLabels(owner, repo, number, labelNames) { // Get all repository labels const allLabels = await this.getLabels(owner, repo); // Map names to IDs const labelIds = []; for (const labelName of labelNames) { const label = allLabels.find(l => l.name === labelName); if (label) { labelIds.push(label.id); } } // Send IDs to Gitea if (labelIds.length > 0) { await giteaClient.put(`/api/v1/repos/${owner}/${repo}/issues/${number}/labels`, { labels: labelIds } ); } } ``` --- ## Fix #5: Enhanced Error Logging ### Problem 422 errors showed no details about what validation failed. ### Solution Added detailed error logging for all 422 responses: ```javascript catch (err) { logger.error(`Sync failed: ${err.message}`); // ✅ NEW: Show validation details if (err.response?.status === 422) { logger.error(`Validation error details: ${JSON.stringify(err.response.data)}`); } if (CONFIG.logging.verbose) { logger.error(err.stack); } } ``` **Example Output:** ``` [ERROR] Gitea to Redmine sync failed: Request failed with status code 422 [ERROR] Validation error details: {"errors":["Due date is not a valid date"]} ``` This makes debugging much easier! --- ## Deployment ### Update Your Server ```bash # 1. Pull latest changes cd ~/redmine-gitea-sync git pull # 2. Restart PM2 pm2 restart redmine-gitea-sync # 3. Watch logs to verify pm2 logs redmine-gitea-sync ``` ### Verify Fixes **Test Label Mapping:** ```bash # Create Gitea issue with labels "feature" and "High Priority" # Check Redmine - should show Feature tracker with High priority ``` **Test Comment Sync:** ```bash # Add note in Redmine # Check Gitea - comment should appear ``` **Test Dates:** ```bash # Create issue with due date in either platform # Should sync without 422 errors ``` --- ## Configuration No configuration changes required. All fixes work automatically with existing settings. ### Optional: Enable Debug Logging To see detailed sync information: ```javascript // In ecosystem.config.cjs env: { LOG_LEVEL: 'debug', LOG_VERBOSE: 'true', } ``` Then: ```bash pm2 restart redmine-gitea-sync --update-env pm2 logs redmine-gitea-sync ``` --- ## Known Limitations ### Tracker/Priority Mapping - Only works for standard tracker IDs (1=Bug, 2=Feature, 3=Support) - Custom Redmine trackers require manual mapping in code - Custom priorities require manual mapping in code ### Comment Sync - Only text notes sync (file attachments not yet supported) - Very long comments may be truncated by platform limits - Formatting differences between Markdown (Gitea) and Textile (Redmine) ### Labels - Label colors are auto-generated (not synced) - Category labels use prefix: `category:name` - If label doesn't exist in Gitea, it's created automatically --- ## Troubleshooting ### Still Getting 422 Errors? ```bash # Enable verbose logging pm2 start ecosystem.config.cjs --env development # Watch logs for validation details pm2 logs redmine-gitea-sync # Look for: "Validation error details: {...}" ``` ### Comments Still Not Syncing? ```bash # Check if journal has content pm2 logs redmine-gitea-sync | grep "journal" # Should see: # "Synced Redmine journal #X to Gitea comment" # If you see "Skipping journal - empty notes": # - Add actual text to Redmine notes # - Empty journals (only field changes) won't sync ``` ### Labels Not Mapping? ```bash # Verify label names match exactly: # - "bug" (not "Bug" or "BUG") # - "High Priority" (not "high priority" or "HighPriority") # Check Gitea labels: curl -H "Authorization: token TOKEN" \ https://gitea.example.com/api/v1/repos/OWNER/REPO/labels ``` --- ## Version History **v2.0.1** (Current) - ✅ Fixed label to field mapping (Gitea → Redmine) - ✅ Fixed Redmine comment sync to Gitea - ✅ Fixed date format issues (both directions) - ✅ Fixed label handling (Redmine → Gitea) - ✅ Added detailed error logging - ✅ Improved journal processing with better logging **v2.0.0** - Initial comprehensive rewrite - PM2 support - Basic bidirectional sync - Label and milestone support --- ## Support If you encounter issues after applying these fixes: 1. Check [TROUBLESHOOTING.md](TROUBLESHOOTING.md) 2. Enable debug logging 3. Collect logs: `pm2 logs redmine-gitea-sync --lines 100` 4. Check server status: `curl http://localhost:3002/status` 5. Report with detailed logs and steps to reproduce