Skip to content

Instantly share code, notes, and snippets.

@incognitojam
Created April 12, 2025 13:48
Show Gist options
  • Save incognitojam/ec163cdaaa932bcc436c2e5e5cd88bb2 to your computer and use it in GitHub Desktop.
Save incognitojam/ec163cdaaa932bcc436c2e5e5cd88bb2 to your computer and use it in GitHub Desktop.
# /// script
# dependencies = [
# "requests",
# ]
# ///
import requests
import re
import sys
from datetime import datetime
def parse_github_issue_url(url: str) -> tuple[str, str, str]:
"""Extract owner, repo, and issue number from a GitHub issue URL."""
match = re.match(r'https://github\.com/([^/]+)/([^/]+)/issues/(\d+)', url)
if not match:
raise ValueError("Invalid GitHub issue URL.")
return match.group(1), match.group(2), match.group(3)
def get_issue_data(owner: str, repo: str, issue_number: str) -> tuple[dict, list[dict]]:
"""Fetch issue data and comments from GitHub API."""
base_url = f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}"
headers = {"Accept": "application/vnd.github+json"}
issue_response = requests.get(base_url, headers=headers)
comments_response = requests.get(base_url + "/comments", headers=headers)
if issue_response.status_code != 200:
raise Exception(f"Failed to fetch issue: {issue_response.status_code}")
if comments_response.status_code != 200:
raise Exception(f"Failed to fetch comments: {comments_response.status_code}")
return issue_response.json(), comments_response.json()
def format_markdown(issue: dict, comments: list[dict]) -> str:
"""Generate a Markdown string from issue data."""
title = issue["title"]
number = issue["number"]
user = issue["user"]["login"]
created_at = datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ").strftime("%Y-%m-%d")
body = issue["body"] or "*No description provided.*"
labels = ", ".join(label["name"] for label in issue.get("labels", [])) or "*No labels*"
md = f"# {title} (#{number})\n\n"
md += f"**opened by {user} on {created_at}**\n\n"
md += f"{body}\n\n"
md += f"**Labels:** {labels}\n\n"
md += "## Comments\n\n"
for comment in comments:
comment_user = comment["user"]["login"]
comment_date = datetime.strptime(comment["created_at"], "%Y-%m-%dT%H:%M:%SZ").strftime("%Y-%m-%d")
comment_body = comment["body"]
md += f"**{comment_user} on {comment_date}:**\n{comment_body}\n\n"
return md
def save_markdown(content: str, filename: str) -> None:
with open(filename, "w", encoding="utf-8") as f:
f.write(content)
def main() -> None:
if len(sys.argv) < 2:
print("Usage: uv run issue2md.py <github_issue_url>")
sys.exit(1)
url = sys.argv[1]
try:
owner, repo, issue_number = parse_github_issue_url(url)
issue, comments = get_issue_data(owner, repo, issue_number)
markdown = format_markdown(issue, comments)
filename = f"{repo}_issue_{issue_number}.md"
save_markdown(markdown, filename)
print(f"Issue saved to {filename}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment