""" BSSUPPORT Bugs mit Releases in KW 18+19 (28.04 - 07.05.2026). Sucht Bugs die: - FixVersion enthalten (KTU oder Prod Release) - In den letzten 2 Kalenderwochen aktualisiert wurden - Status: Fertig/Geschlossen ODER ReTest (= im Release enthalten) """ import urllib.request, json, ssl, urllib.parse secrets = {} with open("project-audit/.secrets", "r", encoding="utf-8-sig") as f: for line in f: if "=" in line and not line.startswith("#"): k, v = line.strip().split("=", 1) secrets[k.strip()] = v.strip() TOKEN = secrets.get("JIRA_TOKEN", "") ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE JIRA_URL = "https://arija.jaas.service.deutschebahn.com" def search(jql, max_results=100): url = f"{JIRA_URL}/rest/api/2/search?jql={urllib.parse.quote(jql)}&maxResults={max_results}&fields=key,summary,status,issuetype,updated,resolved,resolution,fixVersions,labels,description" req = urllib.request.Request(url) req.add_header("Authorization", f"Bearer {TOKEN}") try: resp = urllib.request.urlopen(req, context=ctx, timeout=30) return json.loads(resp.read().decode("utf-8")) except Exception as e: print(f" API-Fehler: {e}") return {"issues": [], "total": 0} # KW18 Start: Montag 28.04.2026 START_DATE = "2026-04-28" print(f"=== BSSUPPORT: Bugs mit Release-Bezug seit {START_DATE} (KW18+19) ===") print() # Suche: Bugs mit FixVersion die in KW18/19 aktualisiert wurden jql = f'project = BSSUPPORT AND issuetype = Bug AND fixVersions is not EMPTY AND updated >= "{START_DATE}" ORDER BY fixVersions DESC, updated DESC' r = search(jql) print(f"Bugs mit FixVersion (aktualisiert seit {START_DATE}): {r.get('total', 0)}") print() # Auch Bugs im ReTest (= im Release, noch nicht abgenommen) jql2 = f'project = BSSUPPORT AND issuetype = Bug AND status = ReTest AND updated >= "{START_DATE}" ORDER BY updated DESC' r2 = search(jql2) # Auch geschlossene Bugs ohne FixVersion aber mit Release-Bezug im Label jql3 = f'project = BSSUPPORT AND issuetype = Bug AND statusCategory = Done AND updated >= "{START_DATE}" ORDER BY updated DESC' r3 = search(jql3) # Alle zusammenfuehren (deduplizieren) all_issues = {} for issue_list in [r.get("issues", []), r2.get("issues", []), r3.get("issues", [])]: for i in issue_list: all_issues[i["key"]] = i print(f"Gesamt (dedupliziert): {len(all_issues)} Bugs") print() # Ausgabe als Tabelle print(f"{'Ticket':<18} {'Titel':<55} {'Release':<20} {'Status'}") print("=" * 110) for key in sorted(all_issues.keys()): i = all_issues[key] f = i["fields"] s = f["status"]["name"] res = (f.get("resolution") or {}).get("name", "") fv = ", ".join([v["name"] for v in f.get("fixVersions", [])]) summary = f["summary"][:54] # Status-Anzeige if s == "Geschlossen" and res == "Fertig": status_display = "Fertig" elif s == "Geschlossen" and res: status_display = res elif s == "ReTest": status_display = "ReTest" else: status_display = s # Nur KTU/Prod Releases oder geschlossene Bugs if fv or status_display in ["Fertig", "ReTest"]: link = f"{JIRA_URL}/browse/{key}" print(f" {key:<16} {summary:<55} {fv:<20} {status_display}") print() print() print("=== Markdown-Tabelle ===") print() print("| Ticket | Titel | Release | Status |") print("|--------|-------|---------|--------|") for key in sorted(all_issues.keys()): i = all_issues[key] f = i["fields"] s = f["status"]["name"] res = (f.get("resolution") or {}).get("name", "") fv = ", ".join([v["name"] for v in f.get("fixVersions", [])]) summary = f["summary"][:65] if s == "Geschlossen" and res == "Fertig": status_display = "✅ Fertig" elif s == "Geschlossen" and res: status_display = f"🔒 {res}" elif s == "ReTest": status_display = "🔄 ReTest" else: status_display = s if fv or "Fertig" in status_display or "ReTest" in status_display: link = f"[{key}]({JIRA_URL}/browse/{key})" print(f"| {link} | {summary} | {fv} | {status_display} |")