1
ewconfig/scripts/github-to-trello

136 lines
4.5 KiB
Python
Executable File

#! /usr/bin/env python3
import argparse
import sys
import logging
import subprocess
import requests
try:
import github
except ImportError:
print("Please install the 'PyGithub' package from pip", file=sys.stderr)
sys.exit(1)
TRELLO_BOARD_ID = "tw3Cn3L6"
TRELLO_LIST_ID = "6348a3ce5208f505b61d29bf" # To Do
TRELLO_TAGS = {
"waiting_to_merge": "65524315edf2d2edb0cc5d09",
"draft": "65fdd81c83e5d6e00f1b9721",
"issue": "64eb5d72fb694cd8f0ba7a8d"
}
logger = logging.getLogger(__name__)
def main() -> int:
# Handle program arguments
ap = argparse.ArgumentParser(
prog="github-to-trello", description="Syncs GitHub issues to Trello cards"
)
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",
)
# Read Trello API credentials
trello_api_key = subprocess.check_output(
"op read -n 'op://ewconfig/cbnd5vv3germmc4korkxx3nsim/api key'", shell=True
).decode()
trello_api_token = subprocess.check_output(
"op read -n 'op://ewconfig/cbnd5vv3germmc4korkxx3nsim/credential'",
shell=True,
).decode()
# Read GitHub credential
logger.info("Authenticating with GitHub")
github_pat = subprocess.check_output(
"op read -n 'op://ewconfig/obs3gaeg7lcff7v5ewbvgxvwgu/credential'", shell=True
).decode()
gh_api = github.Github(auth=github.Auth.Token(github_pat))
# Get my user object
user = gh_api.get_user()
logger.info(f"Authenticated as {user.login}")
# Get all my issues
issues = list(user.get_issues())
logger.info(f"Found {len(issues)} issues/prs")
# Filter out any issue that is in an archived repo
issues = [issue for issue in issues if not issue.repository.archived]
logger.info(f"{len(issues)} of those are actually in active repos")
# Fetch a list of all of my Trello cards
trello_cards = requests.get(
f"https://api.trello.com/1/boards/{TRELLO_BOARD_ID}/cards",
params={"key": trello_api_key, "token": trello_api_token},
).json()
for issue in issues:
repo = issue.repository
is_pr = issue.pull_request is not None
author = issue.user.login
logger.info(
f"Found {'pr' if is_pr else 'issue'} {repo.full_name}#{issue.number} by {author}"
)
# Check if any trello card already mentions this issue in the description
for card in trello_cards:
if issue.html_url in card["desc"]:
logger.info(f"Found Trello card {card['id']} for this issue")
break
else:
logger.info(f"Creating Trello card for this issue")
# Sort out the appropriate labels
card_labels = []
if is_pr:
# If this is a draft PR, add the draft label
if issue.draft:
card_labels.append(TRELLO_TAGS["draft"])
else:
# Otherwise, add the waiting to merge label
card_labels.append(TRELLO_TAGS["waiting_to_merge"])
else:
# If this is an issue, add the issue label
card_labels.append(TRELLO_TAGS["issue"])
print(card_labels)
# Create the card
card = requests.post(
f"https://api.trello.com/1/cards",
params={
"key": trello_api_key,
"token": trello_api_token,
"idList": TRELLO_LIST_ID,
"name": f"[{repo.full_name}] {issue.title}",
"desc": f"**GitHub Link:** {issue.html_url}\n\n**Author:** [{author}]({issue.user.html_url})\n\n---",
"idLabels": card_labels
},
).json()
logger.info(f"Created Trello card {card['id']} for this issue")
# Attach the issue to the card
requests.post(
f"https://api.trello.com/1/cards/{card['id']}/attachments",
params={
"key": trello_api_key,
"token": trello_api_token,
"url": issue.html_url
}
)
logger.info(f"Attached issue to Trello card {card['id']}")
return 0
if __name__ == "__main__":
sys.exit(main())