Skip to main content
Glama
tasks_to_issues_cli.py6.99 kB
#!/usr/bin/env python """ Simplified task migration script using GitHub CLI (gh) to transition from TASKS.md to GitHub Issues. This script: 1. Creates necessary labels in GitHub repo 2. Parses TASKS.md to extract tasks 3. Uses 'gh issue create' to create corresponding GitHub issues 4. Provides a simple one-step migration process Requirements: - GitHub CLI (gh) must be installed and authenticated - Run from the root of the repository """ import re import os import sys import argparse import subprocess from typing import Dict, List, Optional, Tuple def run_command(cmd, capture_output=True): """Run a shell command and return the output.""" result = subprocess.run(cmd, shell=True, text=True, capture_output=capture_output) if result.returncode != 0: print(f"Error running command: {cmd}") print(f"Error: {result.stderr}") return None return result.stdout.strip() if capture_output else True def create_required_labels(): """Create all required GitHub labels for task tracking.""" print("Creating required GitHub labels...") # Define status labels status_labels = [ {"name": "status:prioritized", "color": "0075ca", "description": "Task is prioritized but not started"}, {"name": "status:in-progress", "color": "fbca04", "description": "Task is in progress"}, {"name": "status:completed", "color": "0e8a16", "description": "Task is completed"}, {"name": "status:reviewed", "color": "8250df", "description": "Task has been reviewed"}, {"name": "status:archived", "color": "6e6e6e", "description": "Task has been archived"} ] # Define priority labels (1-20) priority_labels = [ {"name": f"priority:{i}", "color": "d93f0b", "description": f"Priority level {i}"} for i in range(1, 21) ] # Combine all labels all_labels = status_labels + priority_labels # Create each label created_count = 0 for label in all_labels: cmd = f'gh label create "{label["name"]}" --color "{label["color"]}" --description "{label["description"]}" || true' if run_command(cmd, capture_output=False): created_count += 1 print(f"Created or confirmed {created_count} labels") return created_count > 0 def parse_tasks(tasks_file='TASKS.md'): """ Parse tasks from TASKS.md file. Returns: List of dictionaries with task information """ try: with open(tasks_file, 'r') as f: content = f.read() except Exception as e: print(f"Error reading tasks file: {e}") return [] # Extract the task table table_pattern = r'\|\s*Priority\s*\|\s*Task #\s*\|\s*Status\s*\|\s*Description\s*\|\s*\n\|[-\s|]*\n((?:\|[^|]*\|[^|]*\|[^|]*\|[^|]*\|\s*\n)+)' table_match = re.search(table_pattern, content) if not table_match: print("Could not find task table in TASKS.md") return [] table_content = table_match.group(1) # Extract tasks from table tasks = [] for line in table_content.strip().split('\n'): if not line.startswith('|'): continue columns = [col.strip() for col in line.split('|')[1:-1]] if len(columns) != 4: continue priority, task_number, status, description = columns # Skip tasks that are already completed if status.lower() == 'completed': continue try: task = { 'priority': int(priority), 'task_number': int(task_number.strip()), 'status': status, 'description': description, } tasks.append(task) except ValueError: # Skip entries that don't have proper number values continue # Sort tasks by priority tasks.sort(key=lambda x: x['priority']) return tasks def create_issue_with_gh(task): """Create GitHub issue using gh CLI.""" title = f"Task #{task['task_number']}: {task['description']}" # Build the body with task information body = f"## Original Task Information\n\n" body += f"- Priority: {task['priority']}\n" body += f"- Task Number: {task['task_number']}\n" body += f"- Original Status: {task['status']}\n\n" body += f"## Description\n\n{task['description']}\n\n" # Create labels - use multiple --label parameters instead of comma-separated priority_label = f"priority:{task['priority']}" status_label = f"status:{task['status'].lower()}" # Build the gh command cmd = f'gh issue create --title "{title}" --body "{body}" --label "{priority_label}" --label "{status_label}"' # Run the command print(f"Creating issue: {title}") result = run_command(cmd) if result: print(f"Created issue: {result}") return True else: print(f"Failed to create issue for task #{task['task_number']}") return False def main(): """Main function to run the migration.""" parser = argparse.ArgumentParser(description='Migrate tasks from TASKS.md to GitHub Issues using gh CLI') parser.add_argument('--tasks-file', default='TASKS.md', help='Path to TASKS.md file') parser.add_argument('--dry-run', action='store_true', help='Dry run without creating issues') parser.add_argument('--skip-labels', action='store_true', help='Skip creating labels') args = parser.parse_args() # Check if gh CLI is available if not run_command("gh --version", capture_output=True): print("GitHub CLI (gh) is not installed or not in PATH. Please install it and try again.") print("See https://cli.github.com/ for installation instructions.") return 1 # Check if gh is authenticated if not run_command("gh auth status", capture_output=False): print("You are not authenticated with GitHub CLI. Please run 'gh auth login' and try again.") return 1 # Create required labels if not args.skip_labels and not args.dry_run: create_required_labels() # Parse tasks tasks = parse_tasks(args.tasks_file) if not tasks: print("No incomplete tasks found in TASKS.md") return 0 print(f"Found {len(tasks)} tasks to migrate") # Create issues or simulate in dry run mode if args.dry_run: print("Dry run mode: Not creating GitHub issues") for task in tasks: print(f"Would create issue for Task #{task['task_number']}: {task['description']}") else: created_count = 0 for task in tasks: if create_issue_with_gh(task): created_count += 1 print(f"\nMigration complete! Created {created_count} GitHub issues.") print("You can view them by running: gh issue list") return 0 if __name__ == "__main__": sys.exit(main())

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/non-dirty/imap-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server