Redmine-Gitea-Sync/FIX_SUMMARY.md

8.9 KiB

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:

giteaToRedmine: {
  "bug": 1,        // Bug tracker
  "feature": 2,    // Feature tracker
  "support": 3,    // Support tracker
}

Priority Mapping:

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

# 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:

if (giteaIssue) {
  // Update issue
  await GiteaAPI.updateIssue(...);
  // ❌ Journals not processed here
} else {
  // Create issue
  await GiteaAPI.createIssue(...);
  // ✅ Journals only processed for new issues
}

After:

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

# 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: 12
- 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:

// 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:

// 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
// 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:

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:

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

# 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:

# Create Gitea issue with labels "feature" and "High Priority"
# Check Redmine - should show Feature tracker with High priority

Test Comment Sync:

# Add note in Redmine
# Check Gitea - comment should appear

Test Dates:

# 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:

// In ecosystem.config.cjs
env: {
  LOG_LEVEL: 'debug',
  LOG_VERBOSE: 'true',
}

Then:

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?

# 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?

# 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?

# 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
  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