JIRA_BASE_URL=https://yourdomain.atlassian.net JIRA_API_TOKEN=your_jira_api_token JIRA_EMAIL=your_email@company.com
GITHUB_TOKEN=your_github_token OPENAI_API_KEY=your_openai_key
pip install requests openai python-dotenv rich
import requests import openai import os from dotenv import load_dotenv from rich import print from rich.console import Console from rich.table import Table
load_dotenv()
JIRA_BASE = os.getenv("JIRA_BASE_URL") JIRA_EMAIL = os.getenv("JIRA_EMAIL") JIRA_TOKEN = os.getenv("JIRA_API_TOKEN") GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") openai.api_key = OPENAI_API_KEY
console = Console()
def get_board_id(board_name): url = f"{JIRA_BASE}/rest/agile/1.0/board" response = requests.get(url, auth=(JIRA_EMAIL, JIRA_TOKEN)) for board in response.json()["values"]: if board["name"] == board_name: return board["id"] raise Exception("Board not found.")
def get_active_sprint(board_id): url = f"{JIRA_BASE}/rest/agile/1.0/board/{board_id}/sprint?state=active" response = requests.get(url, auth=(JIRA_EMAIL, JIRA_TOKEN)).json() return response["values"][0]["id"]
def get_issues(sprint_id): url = f"{JIRA_BASE}/rest/agile/1.0/sprint/{sprint_id}/issue" response = requests.get(url, auth=(JIRA_EMAIL, JIRA_TOKEN)).json() return response["issues"]
def get_pr_status(issue_key): headers = {"Authorization": f"token {GITHUB_TOKEN}"} url = f"https://api.github.com/search/issues?q={issue_key}+type:pr" res = requests.get(url, headers=headers).json() pr_data = [] for item in res.get("items", []): pr_data.append({ "url": item["html_url"], "state": item["state"] }) return pr_data
def summarize_with_openai(data): prompt = f""" This is data from an active sprint. Provide a daily standup summary for each user: {data} """ res = openai.ChatCompletion.create( model="gpt-4", messages=[{"role": "user", "content": prompt}], temperature=0.7 ) return res['choices'][0]['message']['content']
def generate_standup(board_name): board_id = get_board_id(board_name) sprint_id = get_active_sprint(board_id) issues = get_issues(sprint_id)
summary_data = []
for issue in issues:
key = issue["key"]
fields = issue["fields"]
assignee = fields["assignee"]["displayName"] if fields["assignee"] else "Unassigned"
status = fields["status"]["name"]
title = fields["summary"]
pr_info = get_pr_status(key)
summary_data.append({
"key": key,
"title": title,
"assignee": assignee,
"status": status,
"pr": pr_info
})
# Display table
table = Table(title="Jira Standup Summary")
table.add_column("Assignee", style="cyan")
table.add_column("Issue", style="magenta")
table.add_column("Status")
table.add_column("PR")
for item in summary_data:
pr_state = ", ".join([f"{pr['state']} ({pr['url']})" for pr in item["pr"]]) or "No PR"
table.add_row(item["assignee"], f"{item['key']}: {item['title']}", item["status"], pr_state)
console.print(table)
# GenAI summary
ai_summary = summarize_with_openai(summary_data)
console.print("[bold green]\nGenAI Summary:[/bold green]")
console.print(ai_summary)
if name == "main": board = input("Enter Jira board name: ") generate_standup(board)