177 lines
6.0 KiB
Python
Executable File
177 lines
6.0 KiB
Python
Executable File
#! /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())
|