Migrate Github Issues to Kanboard

I am working on shifting everything, or as much as I reasonably can, related to dev for myself to on-prem, including git and CI/CD. So for Quadtask I had a bunch of Github issues that I wanted to migrate to my kanboard instance, gpt-5 did a bang-up job on this script

It gets each issue, creates a tag for each label, creates the kanboard ticket, then closes the github issue


#!/bin/bash

# GitHub to Kanboard Issue Migration Script
# Uses GitHub CLI (gh) and curl to migrate issues

# Exit on error
set -e

# Check required environment variables
for var in KANBOARD_URL KANBOARD_TOKEN GH_TOKEN QUADTASK_KANBOARD_PROJECT_ID; do
    if [ -z "${!var}" ]; then
        echo "Error: $var is not set"
        exit 1
    fi
done

# GitHub repository (default: pypeaday/quadtask)
GITHUB_REPO=${GITHUB_REPO:-"pypeaday/quadtask"}

# Kanboard API endpoint
KANBOARD_API="$KANBOARD_URL/jsonrpc.php"

# Get all open issues from GitHub
echo "Fetching open issues from $GITHUB_REPO..."
ISSUES_JSON=$(gh issue list --repo "$GITHUB_REPO" --state open --limit 1000 --json number,title,body,labels)

# Count issues
ISSUE_COUNT=$(echo "$ISSUES_JSON" | jq '. | length')
echo "Found $ISSUE_COUNT open issues"

# Process each issue
echo "$ISSUES_JSON" | jq -c '.[]' | while read -r issue; do
    # Extract issue details
    NUMBER=$(echo "$issue" | jq -r '.number')
    TITLE=$(echo "$issue" | jq -r '.title')
    BODY=$(echo "$issue" | jq -r '.body // ""')
    # Extract label names as a JSON array
    LABELS_JSON=$(echo "$issue" | jq -c '[.labels[]?.name] // []')
    
    # Prepare Kanboard task data
    REQUEST_DATA=$(jq -n \
        --arg method "createTask" \
        --argjson id 1 \
        --arg jsonrpc "2.0" \
        --arg title "$TITLE" \
        --arg description "$BODY" \
        --arg project_id "$QUADTASK_KANBOARD_PROJECT_ID" \
        '{
            "jsonrpc": $jsonrpc,
            "method": $method,
            "id": $id,
            "params": {
                "title": $title,
                "description": $description,
                "project_id": $project_id
            }
        }')
    
    # Create task in Kanboard
    echo "Creating task: $TITLE"
    RESPONSE=$(curl -s -X POST \
        -H "Content-Type: application/json" \
        -u "jsonrpc:$KANBOARD_TOKEN" \
        -d "$REQUEST_DATA" \
        "$KANBOARD_API")
    
    # Check for errors
    if echo "$RESPONSE" | jq -e '.error' > /dev/null; then
        echo "Error creating task: $(echo "$RESPONSE" | jq -r '.error.message')"
    else
        TASK_ID=$(echo "$RESPONSE" | jq -r '.result')
        echo "Created task ID: $TASK_ID"

        # If there are labels, set them as Kanboard tags on the task
        if [ "$(echo "$LABELS_JSON" | jq 'length')" -gt 0 ]; then
            echo "Setting tags on task $TASK_ID: $(echo "$LABELS_JSON" | jq -r 'join(", ")')"
            TAGS_REQUEST=$(jq -n \
                --arg jsonrpc "2.0" \
                --arg method "setTaskTags" \
                --argjson id 2 \
                --arg project_id "$QUADTASK_KANBOARD_PROJECT_ID" \
                --arg task_id "$TASK_ID" \
                --argjson tags "$LABELS_JSON" \
                '{
                    jsonrpc: $jsonrpc,
                    method: $method,
                    id: $id,
                    params: {
                        project_id: $project_id,
                        task_id: $task_id,
                        tags: $tags
                    }
                }')

            TAGS_RESPONSE=$(curl -s -X POST \
                -H "Content-Type: application/json" \
                -u "jsonrpc:$KANBOARD_TOKEN" \
                -d "$TAGS_REQUEST" \
                "$KANBOARD_API")

            if echo "$TAGS_RESPONSE" | jq -e '.error' > /dev/null; then
                echo "Warning: Failed to set tags: $(echo "$TAGS_RESPONSE" | jq -r '.error.message')"
            else
                echo "Tags set successfully"
            fi
        fi

        # Close the corresponding GitHub issue to avoid duplicates
        TASK_URL="${KANBOARD_URL}/?controller=TaskViewController&action=show&task_id=${TASK_ID}"
        echo "Closing GitHub issue #$NUMBER with comment linking to Kanboard task..."
        if gh issue close "$NUMBER" --repo "$GITHUB_REPO" --comment "Migrated to Kanboard task $TASK_ID: $TASK_URL" >/dev/null; then
            echo "Closed GitHub issue #$NUMBER"
        else
            echo "Warning: Failed to close GitHub issue #$NUMBER"
        fi
    fi
    
    echo "----------------------------------------"
done

echo "Migration completed"