Skip to content

base-14/exitasana

Repository files navigation

exitasana

exitasana

A tool to migrate Asana tasks from CSV export to GitHub Projects V2.

Features

  • ✅ Migrates tasks as GitHub issues
  • ✅ Maps Asana sections to GitHub Project status field
  • ✅ Converts Asana tags to GitHub labels
  • ✅ Handles subtasks (proper GitHub sub-issue relationships)
  • ✅ Preserves completed status
  • ✅ Includes custom fields as metadata
  • ✅ Duplicate detection by Asana GID (prevents duplicate names from colliding)
  • ✅ Asana GID tracking (custom field for reliable task lookup)
  • ✅ Assignee mapping (Asana names → GitHub usernames)
  • ✅ Non-interactive mode with --yes flag
  • ✅ Dry-run mode for preview

Architecture

The tool is organized into modular components:

  • models.py - Data models (MigrationStats, ProjectFields, MigrationConfig)
  • asana_parser.py - Asana CSV parsing and data extraction
  • github_client.py - GitHub CLI wrapper for API operations
  • migrate.py - CLI entry point and migration orchestration
  • utils.py - Utility functions (diagnose, cleanup, analyze)

Prerequisites

  1. GitHub CLI (gh) - Install instructions
  2. Python 3.9+ - Uses uv for dependency management
  3. Authentication - Run gh auth login before using this tool
  4. Project scope (if creating new projects) - Run gh auth refresh -s project

Setup

  1. Export your Asana project:
    • Export to CSV format (includes all tasks, subtasks, and metadata)
    • From Asana: Project → Export/Print → CSV
  2. Create/select GitHub Project:
    • Option A: Let the tool create a new GitHub Project with status field automatically
    • Option B: Use an existing GitHub Project (V2) and ensure status field values match your Asana sections
  3. Configure assignee mapping (optional):
    • Create assignee_mapping.json in the project root to map Asana names to GitHub usernames
    • Example:
      {
        "comment": "Map Asana assignee names to GitHub usernames",
        "mappings": {
          "John Doe": "johndoe",
          "Jane Smith": "janesmith"
        }
      }

Usage

Dry Run (Preview Only)

Before running a migration, preview the Asana CSV export to verify parsing:

./migrate.py dry-run data/export.csv

This will display:

  • Summary counts (parent tasks, subtasks, sections, custom fields)
  • Sections that will become GitHub Status values
  • Custom field values and their colors
  • Sample tasks with full details
  • Subtask counts per parent

No GitHub connection required - just validates the Asana CSV export.

Full Migration

# Full migration with all arguments
./migrate.py migrate data/export.csv --repo owner/repo --project 1

# Test with limited tasks (first 5 parent tasks and their subtasks)
./migrate.py migrate data/export.csv --repo owner/repo --project 1 --limit 5

# Create new project automatically
./migrate.py migrate data/export.csv --repo owner/repo --project new

# Fully interactive (will prompt for CSV path, repo, and project)
./migrate.py migrate

Arguments:

  • csv_path - Path to Asana CSV export file (positional, optional - will prompt if not provided)
  • --repo - Target GitHub repository in format owner/repo (optional)
  • --project - GitHub Project number or new to create a new project (optional)
  • --labels - Label source: tags (Asana tags) or none (no labels). Default: tags
  • --limit - Limit migration to first N parent tasks (useful for testing). Subtasks of these parents will also be included.
  • --yes, -y - Automatically answer yes to all prompts (non-interactive mode for automation)

Any arguments not provided will be prompted interactively.

Interactive Prompts:

The tool will prompt you for:

  • Label configuration (which fields to use)
  • If --project not specified: Create new project or use existing one
    • If creating new: Project title (status field will be auto-created from Asana sections)
    • If using existing: Project number

Migration Process:

The migration runs in multiple phases:

  1. Parent tasks are created first with tracking of Asana GID → GitHub issue mapping
  2. Subtasks are created and linked as proper GitHub sub-issues to their parents
  3. Existing issues are linked (subtasks to parents) based on Asana GID field
  4. Assignees are updated based on mapping from assignee_mapping.json

Asana GID Custom Field: The tool automatically creates and populates an "Asana GID" custom field in your GitHub Project. This field stores the unique Asana task ID and enables:

  • Reliable duplicate detection (prevents tasks with duplicate names from being skipped)
  • Accurate parent-child linking for subtasks
  • Idempotent migrations (re-running won't create duplicates)

You'll see a preview and be asked to confirm before any changes are made (unless using --yes flag).

What Gets Migrated

Migrated:

  • Task name → Issue title
  • Task notes → Issue body
  • Asana tags → GitHub labels
  • Sections → Project status field
  • Custom fields → Metadata in issue body
  • Completed status → Closed issues
  • Subtasks → Proper GitHub sub-issues with parent-child relationships
  • Asana GID → Custom "Asana GID" field (automatic)
  • Assignees → GitHub assignees (via assignee_mapping.json)

Not migrated:

  • Comments/activity history
  • File attachments (only URLs in description)

Edge Cases Handled

  • Empty task notes
  • Orphaned subtasks (parent not in export)
  • Tasks with multiple project memberships (uses first section)
  • Tags without color field
  • Various custom field types (enum, multi_enum, text, number)

Troubleshooting

Authentication Issues

gh auth login
gh auth status

# If creating new projects, you need the project scope
gh auth refresh -s project

Repository Access

Ensure you have write access to the target repository.

Project Access

The GitHub Project must exist and be accessible. Use the project number from the URL: https://github.com/users/USERNAME/projects/NUMBER or https://github.com/orgs/ORGNAME/projects/NUMBER

Status Field Mismatch

If Asana sections don't match GitHub Project status values, the migration will fail with a clear error message. Update your GitHub Project status field options to match.

Examples

# Step 1: Preview the Asana CSV export first
./migrate.py dry-run data/my-asana-export.csv

# Step 2: Test with a small subset (5 tasks) to verify everything works
./migrate.py migrate data/my-asana-export.csv --repo johndoe/my-repo --project 1 --limit 5

# Step 3: If test looks good, run full migration
./migrate.py migrate data/my-asana-export.csv --repo johndoe/my-repo --project 1

# Step 4: Non-interactive mode (useful for automation/CI)
./migrate.py migrate data/my-asana-export.csv --repo johndoe/my-repo --project 1 --yes

# Example project URLs
# User project: https://github.com/users/johndoe/projects/1 → use --project 1
# Org project: https://github.com/orgs/acme/projects/5 → use --project 5

# Or run interactively (will prompt for CSV path, repo, and project)
./migrate.py migrate

Additional Commands

The tool includes additional subcommands for project management:

diagnose - Analyze Project State

Diagnose a GitHub Project to identify duplicates and orphaned issues:

./migrate.py diagnose --repo owner/repo --project 15

Shows:

  • Duplicate issues (by title or GID)
  • Orphaned subtasks (issues without expected parent relationships)
  • Parent-child relationship statistics

cleanup - Remove Duplicates

Remove duplicate issues without Asana GID from a project:

# Interactive mode (asks for confirmation)
./migrate.py cleanup --repo owner/repo --project 15

# Non-interactive mode
./migrate.py cleanup --repo owner/repo --project 15 --yes

analyze - CSV Metadata Analysis

Analyze a CSV export to show metadata before migration:

./migrate.py analyze data/export.csv

Shows:

  • Task counts (parents, subtasks, total)
  • Sections and their distribution
  • Custom fields
  • Assignees and task counts
  • Tags

Output

The tool logs all operations and creates a migration report:

  • migration_report.log - Detailed operation log
  • Console output - Progress and summary

Limitations

  • Only first section used if task belongs to multiple projects
  • People-type custom fields are skipped
  • Tasks without sections default to "Todo" status

License

MIT

About

a Tool that helps transfer projects from asana to github projects

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors