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"