#! /usr/bin/env python3 # fmt:off import sys import os from pathlib import Path sys.path.append((Path(os.environ["EWCONFIG_ROOT"]) / "python_modules").as_posix()) # fmt:on import argparse import sys import logging import requests from pathlib import Path from dataclasses import dataclass, field from typing import List, Optional, Dict, Any from ewconfig.secret_manager import get_semi_secret_string from ewconfig.trello import TRELLO_API_KEY, get_trello_api_token from ewconfig.trello.cards import get_all_trello_cards, create_card, add_attachment from ewconfig.trello.boards import PERSONAL_TASKS_BOARD logger = logging.getLogger(__name__) GITHUB_API_VERSION = "2022-11-28" GITHUB_PAT = get_semi_secret_string("github_pat", namespace="trello-sync") TRELLO_API_TOKEN = get_trello_api_token() def get_all_issues() -> List[Dict[str, Any]]: issues = [] # Get all issues assigned to me response = requests.get( "https://api.github.com/issues", headers={ "Authorization": f"token {GITHUB_PAT}", "Accept": "application/vnd.github.raw+json", "X-GitHub-Api-Version": GITHUB_API_VERSION, }, params={"state": "open", "per_page": 100}, ) response.raise_for_status() issues.extend(response.json()) # Get all issues that mention me response = requests.get( "https://api.github.com/user/issues", headers={ "Authorization": f"token {GITHUB_PAT}", "Accept": "application/vnd.github.raw+json", "X-GitHub-Api-Version": GITHUB_API_VERSION, }, params={"state": "open", "per_page": 100, "filter": "mentioned"}, ) response.raise_for_status() issues.extend(response.json()) # Get all issues that exist in my repos response = requests.get( "https://api.github.com/user/issues", headers={ "Authorization": f"token {GITHUB_PAT}", "Accept": "application/vnd.github.raw+json", "X-GitHub-Api-Version": GITHUB_API_VERSION, }, params={"state": "open", "per_page": 100, "filter": "repos"}, ) response.raise_for_status() issues.extend(response.json()) # Get all issues that I have made in other people's repos response = requests.get( "https://api.github.com/user/issues", headers={ "Authorization": f"token {GITHUB_PAT}", "Accept": "application/vnd.github.raw+json", "X-GitHub-Api-Version": GITHUB_API_VERSION, }, params={"state": "open", "per_page": 100, "filter": "subscribed"}, ) response.raise_for_status() issues.extend(response.json()) # De-dupe issues issues = list({issue["id"]: issue for issue in issues}.values()) return issues def main() -> int: # Handle program arguments ap = argparse.ArgumentParser(prog="", description="") ap.add_argument("--dry-run", help="Don't actually do anything", action="store_true") ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) args = ap.parse_args() # Configure logging logging.basicConfig( level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s", ) # Get a list of all issues assigned to me my_issues = get_all_issues() logger.info(f"Found {len(my_issues)} issues assigned to me") # Get all cards on the personal tasks board trello_cards = get_all_trello_cards( board_id=PERSONAL_TASKS_BOARD.id, api_key=TRELLO_API_KEY, api_token=TRELLO_API_TOKEN, ) logger.info(f"Found {len(trello_cards)} cards in Trello") # Handle each GitHub issue for issue in my_issues: # Ignore archived repos if issue["repository"]["archived"]: logger.info(f"Ignoring archived repo: {issue['repository']['full_name']}") continue # Ignore anything by dependabot if issue["user"]["login"] == "dependabot[bot]": logger.debug(f"Ignoring dependabot issue: {issue['repository']['full_name']}#{issue['number']}") continue # Search each card for anything that links to the github issue for card in trello_cards: if issue["html_url"] in card["desc"]: logger.info( f"Found GitHub Issue {issue['number']} in Trello Card {card['id']}" ) break else: logger.info( f"Going to create trello card for GitHub Issue: [{issue['repository']['full_name']}] {issue['title']}" ) if not args.dry_run: # Check if this is an issue or pr is_pr = "pull_request" in issue type_label = ( PERSONAL_TASKS_BOARD.tags["Github: Pull Request"] if is_pr else PERSONAL_TASKS_BOARD.tags["Github: Issue"] ) # Create a new trello card for this issue card_id = create_card( list_id=PERSONAL_TASKS_BOARD.lists["To Do"], name=f"[{issue['repository']['full_name']}] {issue['title']}", description=( f"**GitHub Link:** [`{issue['repository']['full_name']}#{issue['number']}`]({issue['html_url']})\n\n" f"**Author:** [`{issue['user']['login']}`]({issue['user']['html_url']})\n\n" "---" ), label_ids=[type_label], api_key=TRELLO_API_KEY, api_token=TRELLO_API_TOKEN, ) add_attachment( card_id=card_id, api_key=TRELLO_API_KEY, api_token=TRELLO_API_TOKEN, url=issue["html_url"], ) logger.info( f"Created Trello Card {card_id} for GitHub Issue {issue['repository']['full_name']}#{issue['number']}" ) return 0 if __name__ == "__main__": sys.exit(main())