Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
65 lines
2.6 KiB
Python
65 lines
2.6 KiB
Python
"""Prueft BSSUPPORT Projekt-Struktur und sucht gefixt Bugs."""
|
|
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
|
|
|
|
def search(jql, max_results=30):
|
|
url = f"https://arija.jaas.service.deutschebahn.com/rest/api/2/search?jql={urllib.parse.quote(jql)}&maxResults={max_results}&fields=key,summary,status,issuetype,updated,resolved,resolution,fixVersions,labels"
|
|
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}
|
|
|
|
# 1. Alle kuerzlich aktualisierten Tickets
|
|
print("=== BSSUPPORT: Letzte 30 aktualisierte Tickets ===")
|
|
r = search("project = BSSUPPORT ORDER BY updated DESC")
|
|
print(f"Total im Projekt: {r.get('total', 0)}")
|
|
print()
|
|
|
|
types_seen = set()
|
|
for i in r.get("issues", []):
|
|
f = i["fields"]
|
|
itype = f.get("issuetype", {}).get("name", "?")
|
|
types_seen.add(itype)
|
|
s = f["status"]["name"]
|
|
res = (f.get("resolution") or {}).get("name", "")
|
|
fv = ", ".join([v["name"] for v in f.get("fixVersions", [])])
|
|
updated = f.get("updated", "")[:10]
|
|
print(f" {i['key']:<18} [{itype:<15}] [{s:<14}] Res={res:<12} Upd={updated} {f['summary'][:50]}")
|
|
if fv:
|
|
print(f" {'':18} FixVersion: {fv}")
|
|
|
|
print(f"\nGesehene Issue-Typen: {sorted(types_seen)}")
|
|
|
|
# 2. Nur geschlossene/geloeste in letzten 2 Wochen
|
|
print("\n\n=== BSSUPPORT: Geschlossen in letzten 14 Tagen ===")
|
|
r2 = search("project = BSSUPPORT AND statusCategory = Done AND updated >= -14d ORDER BY updated DESC")
|
|
print(f"Treffer: {r2.get('total', 0)}")
|
|
for i in r2.get("issues", []):
|
|
f = i["fields"]
|
|
itype = f.get("issuetype", {}).get("name", "?")
|
|
s = f["status"]["name"]
|
|
res = (f.get("resolution") or {}).get("name", "")
|
|
resolved = (f.get("resolved") or "")[:10]
|
|
fv = ", ".join([v["name"] for v in f.get("fixVersions", [])])
|
|
labels = ", ".join(f.get("labels", []))
|
|
print(f" {i['key']:<18} [{itype:<15}] Res={res:<12} Resolved={resolved} {f['summary'][:55]}")
|
|
if fv:
|
|
print(f" {'':18} FixVersion: {fv}")
|
|
if labels:
|
|
print(f" {'':18} Labels: {labels}")
|