srini007

WozAgent

Aug 9th, 2025
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.33 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # /// script
  3. # requires-python = ">=3.9"
  4. # dependencies = ["requests"]
  5. # ///
  6.  
  7. import os
  8. import sys
  9. import requests
  10. from typing import Dict, List
  11. from pathlib import Path
  12. from dotenv import load_dotenv
  13.  
  14. dotenv_path = Path('.') / '.env'
  15. print(f"Loading env from {dotenv_path.resolve()}")
  16. load_dotenv(dotenv_path)
  17.  
  18. # -----------------------------
  19. # Config: Set these as environment variables before running
  20. # -----------------------------
  21. JIRA_BASE_URL = os.getenv("JIRA_BASE_URL")  # e.g. "https://yourdomain.atlassian.net"
  22. JIRA_EMAIL = os.getenv("JIRA_EMAIL")
  23. JIRA_API_TOKEN = os.getenv("JIRA_API_TOKEN")
  24. OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
  25.  
  26. if not all([JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN, OPENAI_API_KEY]):
  27.     print("Error: Missing one or more environment variables: JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN, OPENAI_API_KEY")
  28.     sys.exit(1)
  29.  
  30. # -----------------------------
  31. # Jira API Functions
  32. # -----------------------------
  33.  
  34. def get_jira_story(issue_key: str) -> Dict:
  35.     """Fetch Jira story data."""
  36.     url = f"{JIRA_BASE_URL}/rest/api/3/issue/{issue_key}"
  37.     auth = (JIRA_EMAIL, JIRA_API_TOKEN)
  38.     headers = {"Accept": "application/json"}
  39.     r = requests.get(url, headers=headers, auth=auth)
  40.     r.raise_for_status()
  41.     return r.json()
  42.  
  43. def update_jira_story_comment(issue_key: str, comment: str):
  44.     """Add a comment to the Jira story."""
  45.     url = f"{JIRA_BASE_URL}/rest/api/3/issue/{issue_key}/comment"
  46.     auth = (JIRA_EMAIL, JIRA_API_TOKEN)
  47.     headers = {"Accept": "application/json", "Content-Type": "application/json"}
  48.    
  49.     payload = {
  50.         "body": {
  51.             "type": "doc",
  52.             "version": 1,
  53.             "content": [
  54.                 {
  55.                     "type": "paragraph",
  56.                     "content": [
  57.                         {
  58.                             "text": comment,
  59.                             "type": "text"
  60.                         }
  61.                     ]
  62.                 }
  63.             ]
  64.         }
  65.     }
  66.     r = requests.post(url, headers=headers, auth=auth, json=payload)
  67.     r.raise_for_status()
  68.  
  69.  
  70. # -----------------------------
  71. # Helper to extract plain text from Jira rich text format
  72. # -----------------------------
  73.  
  74. def extract_text_from_content(content: List[Dict]) -> str:
  75.     text = ""
  76.     for block in content:
  77.         if "content" in block:
  78.             for inner in block["content"]:
  79.                 text += inner.get("text", "") + "\n"
  80.     return text
  81.  
  82. # -----------------------------
  83. # OpenAI API Function
  84. # -----------------------------
  85.  
  86. def score_description_with_openai(story: str) -> str:
  87.     """Score the story and provide improvement feedback."""
  88.  
  89.     system_prompt = (
  90.         "You are an expert in software requirements analysis with a focus on agile methodologies. "
  91.         "Evaluate the acceptance criteria for the user story below based on these patterns:\n\n"
  92.         "1. Readable\n2. Testable\n3. Implementation Agnostic\n4. Actionable When Statement\n"
  93.         "5. Strong Verb Usage\n6. Specific to the Story\n7. Tell a Story\n\n"
  94.         "Please provide:\n"
  95.         "- A numeric score from 1 to 10 for each of the seven patterns listed,\n"
  96.         "- A summary of overall score,\n"
  97.         "- Specific suggestions for improvement to make the acceptance criteria better."
  98.         "\n\nAcceptance Criteria:\n"
  99.         f"{story}"
  100.     )
  101.  
  102.     messages = [
  103.         {"role": "system", "content": system_prompt},
  104.     ]
  105.  
  106.     headers = {
  107.         "Content-Type": "application/json",
  108.         "Authorization": f"Bearer {OPENAI_API_KEY}"
  109.     }
  110.  
  111.     payload = {
  112.         "model": "gpt-4",
  113.         "messages": messages,
  114.         "temperature": 0
  115.     }
  116.  
  117.     print("Sending acceptance criteria to OpenAI...")
  118.     r = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)
  119.     r.raise_for_status()
  120.     return r.json()["choices"][0]["message"]["content"]
  121.  
  122. # -----------------------------
  123. # Main
  124. # -----------------------------
  125.  
  126. def main():
  127.     if len(sys.argv) < 2:
  128.         print("Usage: python jira_score_story.py ISSUE_KEY")
  129.         sys.exit(1)
  130.  
  131.     issue_key = sys.argv[1]
  132.  
  133.     try:
  134.         story = get_jira_story(issue_key)
  135.     except requests.HTTPError as e:
  136.         print(f"Failed to fetch Jira issue {issue_key}: {e}")
  137.         sys.exit(1)
  138.  
  139.     description_field = story["fields"].get("description", "")
  140.  
  141.     if isinstance(description_field, dict) and "content" in description_field:
  142.         description_text = extract_text_from_content(description_field["content"]).strip()
  143.     elif isinstance(description_field, str):
  144.         description_text = description_field
  145.     else:
  146.         description_text = ""
  147.  
  148.     if not description_text:
  149.         print(f"No description found for {issue_key}")
  150.         sys.exit(1)
  151.  
  152.     print(f"Scoring Jira story {issue_key}...")
  153.     score_text = score_description_with_openai(description_text)
  154.     print(f"\nScore & Feedback:\n{score_text}")
  155.  
  156.     print("\nAdding score and feedback as a comment on the Jira story...")
  157.     try:
  158.         update_jira_story_comment(issue_key, f"### AI Acceptance Criteria Review\n\n{score_text}")
  159.     except requests.HTTPError as e:
  160.         print(f"Failed to update Jira issue {issue_key} comment: {e}")
  161.         sys.exit(1)
  162.  
  163.     print("Done.")
  164.  
  165. if __name__ == "__main__":
  166.     main()
  167.  
Advertisement
Add Comment
Please, Sign In to add comment