import gradio as gr from datetime import datetime, timedelta import google.generativeai as genai from github import Github, GithubException import gitlab import docx import tempfile import requests def generate_release_notes(git_provider, repo_url, personal_access_token, gemini_api_key, start_date, end_date): try: start_date = datetime.strptime(start_date, "%Y-%m-%d") end_date = datetime.strptime(end_date, "%Y-%m-%d") if git_provider == "GitHub": g = Github(personal_access_token) repo = g.get_repo(repo_url) commits = list(repo.get_commits(since=start_date, until=end_date)) commit_messages = [commit.commit.message for commit in commits] elif git_provider == "GitLab": gl = gitlab.Gitlab(url='https://gitlab.com', private_token=personal_access_token) project = gl.projects.get(repo_url) commits = project.commits.list(since=start_date.isoformat(), until=end_date.isoformat()) commit_messages = [commit.message for commit in commits] elif git_provider == "Gitea": base_url = "https://gitea.com/api/v1" headers = {"Authorization": f"token {personal_access_token}"} response = requests.get(f"{base_url}/repos/{repo_url}/commits", headers=headers, params={ "since": start_date.isoformat(), "until": end_date.isoformat() }) response.raise_for_status() commits = response.json() commit_messages = [commit['commit']['message'] for commit in commits] else: return "Unsupported Git provider", None, None commit_text = "\n".join(commit_messages) if not commit_text: return "No commits found in the specified date range.", None, None genai.configure(api_key=gemini_api_key) model = genai.GenerativeModel('gemini-2.0-flash-lite') prompt = f"""Based on the following commit messages, generate comprehensive release notes: {commit_text} Please organize the release notes into sections such as: 1. New Features 2. Bug Fixes 3. Improvements 4. Breaking Changes (if any) Provide a concise summary for each item. Do not include any links, but keep issue numbers if present. Important formatting instructions: - The output should be plain text without any markdown or "-" for post processing - Use section titles followed by a colon (e.g., "New Features:") - Start each item on a new line - Be sure to briefly explain the why and benefits of the change for average users that are non-technical """ response = model.generate_content(prompt) release_notes = response.text # Create DOCX file doc = docx.Document() doc.add_heading('Release Notes', 0) current_section = None for line in release_notes.split('\n'): line = line.strip() if line.endswith(':'): doc.add_heading(line, level=1) current_section = None elif line: if current_section is None: current_section = doc.add_paragraph().style current_section.name = 'List Bullet' doc.add_paragraph(line, style=current_section) with tempfile.NamedTemporaryFile(delete=False, suffix='.docx') as temp_docx: doc.save(temp_docx.name) docx_path = temp_docx.name # Create Markdown file markdown_content = "# Release Notes\n\n" for line in release_notes.split('\n'): line = line.strip() if line.endswith(':'): markdown_content += f"\n## {line}\n\n" elif line: markdown_content += f"- {line}\n" with tempfile.NamedTemporaryFile(delete=False, suffix='.md', mode='w', encoding='utf-8') as temp_md: temp_md.write(markdown_content) md_path = temp_md.name return release_notes, docx_path, md_path except Exception as e: return f"An error occurred: {str(e)}", None, None default_end_date = datetime.now() default_start_date = default_end_date - timedelta(days=30) iface = gr.Interface( fn=generate_release_notes, inputs=[ gr.Dropdown( choices=["GitHub", "GitLab", "Gitea"], label="Git Provider" ), gr.Textbox(label="Repository URL", placeholder="owner/repo"), gr.Textbox(label="Personal Access Token", type="password"), gr.Textbox(label="Gemini API Key", type="password"), gr.Textbox( label="Start Date", placeholder="YYYY-MM-DD", value=default_start_date.strftime("%Y-%m-%d"), ), gr.Textbox( label="End Date", placeholder="YYYY-MM-DD", value=default_end_date.strftime("%Y-%m-%d"), ) ], outputs=[ gr.Textbox(label="Generated Release Notes"), gr.File(label="Download Release Notes (DOCX)"), gr.File(label="Download Release Notes (Markdown)") ], title="Automated Release Notes Generator", description="Generate release notes based on Git commits using Gemini AI. Select a Git provider, enter repository details, and specify the date range for commits.", allow_flagging="never", theme="default", analytics_enabled=False, ) iface.launch()