Files
Orchestrator/bahn/project-audit/scripts/confluence-reorganize.ps1
T
ankn a5f8fb49ab Migrate all repos into monorepo context folders
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.
2026-06-30 20:39:52 +02:00

284 lines
17 KiB
PowerShell

<#
.SYNOPSIS
Reorganisiert die Analyse-pathOS Confluence-Seiten in Kategorien mit Unterseiten
#>
$ConfluenceUrl = "https://arija-confluence.jaas.service.deutschebahn.com"
$SpaceKey = "BES"
$ParentPageId = "581013135" # Analyse pathOS Stammseite
$ApiBase = "$ConfluenceUrl/rest/api"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Write-Host "============================================================"
Write-Host " Confluence Reorganisation - Analyse pathOS"
Write-Host "============================================================"
$PAT = $null
$SecretsPath = Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Path) "..\.secrets"
if (Test-Path $SecretsPath) {
Get-Content $SecretsPath | ForEach-Object {
if ($_ -match "^CONFLUENCE_TOKEN=(.+)$") {
$val = $Matches[1].Trim()
if ($val -ne "HIER_TOKEN_EINTRAGEN") { $PAT = $val }
}
}
}
if (-not $PAT) { $PAT = Read-Host "Confluence PAT" }
$Headers = @{ "Authorization" = "Bearer $PAT"; "Content-Type" = "application/json" }
function Invoke-ConfApi($Method, $Uri, $JsonBody) {
try {
if ($JsonBody) {
$Resp = Invoke-WebRequest -Uri $Uri -Method $Method -Headers $Headers -Body ([System.Text.Encoding]::UTF8.GetBytes($JsonBody)) -UseBasicParsing -ErrorAction Stop
} else {
$Resp = Invoke-WebRequest -Uri $Uri -Method $Method -Headers $Headers -UseBasicParsing -ErrorAction Stop
}
return ($Resp.Content | ConvertFrom-Json)
} catch {
Write-Host " FEHLER: $($_.Exception.Message)" -ForegroundColor Red
return $null
}
}
function Create-CategoryPage($Title, $ParentId, $Body) {
# Pruefen ob existiert
$SearchUri = "$ApiBase/content?spaceKey=$SpaceKey&title=$([Uri]::EscapeDataString($Title))&type=page"
$Search = Invoke-ConfApi "Get" $SearchUri
if ($Search.results -and $Search.results.Count -gt 0) {
Write-Host " Existiert bereits (ID: $($Search.results[0].id))" -ForegroundColor DarkGray
return $Search.results[0].id
}
$Json = @{
type = "page"
title = $Title
space = @{ key = $SpaceKey }
ancestors = @(@{ id = $ParentId })
body = @{ storage = @{ value = $Body; representation = "storage" } }
} | ConvertTo-Json -Depth 10
$Result = Invoke-ConfApi "Post" "$ApiBase/content" $Json
if ($Result) {
Write-Host " Erstellt (ID: $($Result.id))" -ForegroundColor Green
return $Result.id
}
return $null
}
function Move-Page($PageId, $NewParentId) {
# Aktuelle Version und Parent holen
$Page = Invoke-ConfApi "Get" "$ApiBase/content/$PageId`?expand=version,ancestors"
if (-not $Page) { return $false }
# Pruefen ob schon unter richtigem Parent
if ($Page.ancestors -and $Page.ancestors.Count -gt 0) {
$CurrentParent = $Page.ancestors[-1].id
if ($CurrentParent -eq $NewParentId) {
Write-Host " Bereits korrekt" -ForegroundColor DarkGray
return $true
}
}
$Version = $Page.version.number + 1
$Title = $Page.title
$Json = @{
type = "page"
title = $Title
version = @{ number = $Version }
ancestors = @(@{ id = $NewParentId })
} | ConvertTo-Json -Depth 10
$Result = Invoke-ConfApi "Put" "$ApiBase/content/$PageId" $Json
if ($Result) { return $true }
return $false
}
# === Bekannte Seiten-IDs (aus letztem Push) ===
$Pages = @{
"summary" = "581019325" # 0. Management Summary
"uebersicht" = "581013185" # 1. Uebersicht
"probleme" = "581013186" # 2. Problemfelder
"roadmap2026" = "581013187" # 3. Technische Roadmap 2026
"gitlab" = "581013188" # 4. GitLab
"glossar" = "581013189" # 5. Abkuerzungen
"architektur" = "581013355" # 6. Architekturskizze
"fortschritt" = "581013356" # 7. Projektfortschritt
"links" = "581013548" # 8. Links
"journey" = "581013549" # 9. Customer Journey
"deepdive" = "581015678" # 10. Tech Deep Dive
"teamworkflow" = "581015844" # 11. Team Analyse
"aktionsplan" = "581016065" # 12. Roadmap Aktionsplan
"jira" = "581016316" # 13. Jira
"next" = "581019221" # 14. Naechste Schritte
"ttt" = "581019444" # 15. TTT/NEP2
"roadmapfull" = "581019652" # 16. Roadmap uebergreifend
"ttti" = "581023872" # 17. TTTI Deep Dive
"velocity" = "581024118" # 18. Velocity
}
# Dynamisch: SonarQube-Seite per Titel suchen (ID noch unbekannt)
$SonarSearch = Invoke-ConfApi "Get" "$ApiBase/content?spaceKey=$SpaceKey&title=$([Uri]::EscapeDataString('19. SonarQube Code-Qualitaet'))&type=page"
if ($SonarSearch -and $SonarSearch.results -and $SonarSearch.results.Count -gt 0) {
$Pages["sonarqube"] = $SonarSearch.results[0].id
Write-Host " SonarQube-Seite gefunden: $($Pages['sonarqube'])" -ForegroundColor DarkGray
}
# === Test Verbindung ===
Write-Host ""
Write-Host ">> Teste Verbindung..." -ForegroundColor Yellow
$Test = Invoke-ConfApi "Get" "$ApiBase/content/$ParentPageId"
if (-not $Test) { Write-Host "Verbindung fehlgeschlagen!" -ForegroundColor Red; exit 1 }
Write-Host " OK: $($Test.title)" -ForegroundColor Green
# === Schritt 1: Kategorie-Seiten erstellen ===
Write-Host ""
Write-Host ">> Erstelle Kategorie-Seiten..." -ForegroundColor Yellow
Write-Host " Systemueberblick..." -NoNewline
$CatSystem = Create-CategoryPage "Systemueberblick" $ParentPageId '<h2>Systemueberblick</h2><p>Architektur, Komponenten und Schnittstellen von pathOS.</p><h3>Unterseiten</h3><table><tr><th>Seite</th><th>Inhalt</th></tr><tr><td><strong>Uebersicht und Gesamtbild</strong></td><td>Zahlen auf einen Blick: 167 Projekte, 15 Kern-Services, Tech-Stack, Teams</td></tr><tr><td><strong>Architekturskizze</strong></td><td>Alle Komponenten und 15+ externe Schnittstellen als Tabelle mit Farbkodierung</td></tr><tr><td><strong>Customer Journey</strong></td><td>Happy Path Trassenbestellung: 7 Schritte aus Kundensicht mit Datenfluss durch alle IT-Systeme</td></tr><tr><td><strong>GitLab Projektlandschaft</strong></td><td>167 Projekte in 9 Gruppen, Sprachen-Verteilung, Aktivitaets-Status</td></tr><tr><td><strong>Abkuerzungsverzeichnis</strong></td><td>35+ Fachbegriffe und Abkuerzungen (TPN, BEP, IFP, PMW, etc.)</td></tr></table><ac:structured-macro ac:name="children"><ac:parameter ac:name="all">true</ac:parameter></ac:structured-macro>'
Write-Host " Technische Analyse..." -NoNewline
$CatTech = Create-CategoryPage "Technische Analyse" $ParentPageId '<h2>Technische Analyse</h2><p>Versionen, Dependencies, Code-Qualitaet und technische Roadmap.</p><h3>Unterseiten</h3><table><tr><th>Seite</th><th>Inhalt</th></tr><tr><td><strong>Technischer Deep Dive</strong></td><td>Gesundheits-Scorecard: Spring Boot 3.5 (Upgrade laeuft), Java 21, Camunda 8.8, CVE-Patches</td></tr><tr><td><strong>SonarQube Code-Qualitaet</strong></td><td>74 Projekte: Coverage, Bugs, Smells nach Team. Zero=Vorbild, CIB=SV-Schuld, tadef=0% Coverage</td></tr><tr><td><strong>Technische Roadmap 2026</strong></td><td>53 Items aus der internen Roadmap: 17 MUSS UKA, 24 MUSS 2026, 12 SOLL</td></tr><tr><td><strong>Nuetzliche Links</strong></td><td>GitLab, Confluence, Runbook, Portal-URLs, Kafka-UI, DefectDojo, oeffentliche Quellen</td></tr></table><ac:structured-macro ac:name="children"><ac:parameter ac:name="all">true</ac:parameter></ac:structured-macro>'
Write-Host " Teams und Velocity..." -NoNewline
$CatTeams = Create-CategoryPage "Teams und Velocity" $ParentPageId '<h2>Teams und Velocity</h2><p>Team-Struktur, Jira-Analyse, Durchsatz und Personenanalyse.</p><h3>Unterseiten</h3><table><tr><th>Seite</th><th>Inhalt</th></tr><tr><td><strong>Team und Workflow Analyse</strong></td><td>6 Teams (Zero, 404, CIB, OPs, BSSUPPORT, FbF), 5 Engpaesse, 9 Reorganisations-Empfehlungen</td></tr><tr><td><strong>Velocity und Team-Analyse</strong></td><td>12-Monats-Velocity, Go-Live-Effekt, Bug-Rate 10%&#8594;29%&#8594;20%, MVPs und Schwachstellen pro Person</td></tr><tr><td><strong>Jira-Analyse</strong></td><td>3845 Issues ueber 10 Boards, Backlog-Verteilung, Team-Auslastung</td></tr><tr><td><strong>Personal- und Bug-Analyse</strong></td><td>Rollen, Tenure, Bug-Korrelation pro Entwickler. SPOFs, Risiko-Matrix, Top 5 Massnahmen</td></tr></table><ac:structured-macro ac:name="children"><ac:parameter ac:name="all">true</ac:parameter></ac:structured-macro>'
Write-Host " TTT-Programm..." -NoNewline
$CatTTT = Create-CategoryPage "TTT-Programm" $ParentPageId '<h2>TTT-Programm</h2><p>TAF/TAP TSI Programmkontext, NEP2, TTTI-Integration und Problemfelder.</p><h3>Unterseiten</h3><table><tr><th>Seite</th><th>Inhalt</th></tr><tr><td><strong>TTT-Programm und NEP2</strong></td><td>Go-Live Dez 2025, Go/No-Go Sep 2025 positiv, NEP2 stabil, Programmrisiken TTTSOL-42 bis -52</td></tr><tr><td><strong>TTTI Deep Dive</strong></td><td>1000 Issues, aber nur 42 echte Bugs. Kritischste nach Bereich (pathOS, TPN, ujBau, Abrechnung)</td></tr><tr><td><strong>Identifizierte Problemfelder</strong></td><td>5 Hauptprobleme: Deployment-Komplexitaet, Dokumentation, Tech Debt, Altsystem, Teams</td></tr></table><ac:structured-macro ac:name="children"><ac:parameter ac:name="all">true</ac:parameter></ac:structured-macro>'
Write-Host " Roadmap und Planung..." -NoNewline
$CatRoadmap = Create-CategoryPage "Roadmap und Planung" $ParentPageId '<h2>Roadmap und Planung</h2><p>Priorisierte Aktionen, Zeitplaene und naechste Schritte.</p><h3>Unterseiten</h3><table><tr><th>Seite</th><th>Inhalt</th></tr><tr><td><strong>Roadmap uebergreifend und pathOS</strong></td><td>4 Phasen bis Mitte 2027 mit grafischem Team-Zeitstrahl: Stabilisieren, Haerten, Skalieren, Weiterentwickeln</td></tr><tr><td><strong>Roadmap und Aktionsplan</strong></td><td>24 priorisierte Aktionen (SOFORT/KURZ/MITTEL/LANG) mit Risiko-Matrix</td></tr><tr><td><strong>Produkt-Roadmap (konsolidiert)</strong></td><td>PO-Input aller 3 Teams + BO-Sicht. 18 neue Themen, 6 strategische Fragen, 4 Phasen</td></tr><tr><td><strong>Naechste Schritte</strong></td><td>Offene Punkte, Datenquellen-Status, priorisierte naechste Schritte</td></tr><tr><td><strong>Projektfortschritt</strong></td><td>Alle Iterationen mit Tasks, Zeiten und Ergebnissen</td></tr></table><ac:structured-macro ac:name="children"><ac:parameter ac:name="all">true</ac:parameter></ac:structured-macro>'
# === Schritt 2: Seiten verschieben ===
Write-Host ""
Write-Host ">> Verschiebe Seiten in Kategorien..." -ForegroundColor Yellow
# Systemueberblick
$Moves = @(
@{ id = $Pages["uebersicht"]; parent = $CatSystem; name = "Uebersicht" }
@{ id = $Pages["architektur"]; parent = $CatSystem; name = "Architektur" }
@{ id = $Pages["journey"]; parent = $CatSystem; name = "Customer Journey" }
@{ id = $Pages["gitlab"]; parent = $CatSystem; name = "GitLab" }
@{ id = $Pages["glossar"]; parent = $CatSystem; name = "Glossar" }
# Technische Analyse
@{ id = $Pages["deepdive"]; parent = $CatTech; name = "Tech Deep Dive" }
@{ id = $Pages["roadmap2026"]; parent = $CatTech; name = "Roadmap 2026" }
@{ id = $Pages["links"]; parent = $CatTech; name = "Links" }
# Teams und Velocity
@{ id = $Pages["teamworkflow"]; parent = $CatTeams; name = "Team Analyse" }
@{ id = $Pages["velocity"]; parent = $CatTeams; name = "Velocity" }
@{ id = $Pages["jira"]; parent = $CatTeams; name = "Jira" }
# TTT-Programm
@{ id = $Pages["ttt"]; parent = $CatTTT; name = "TTT/NEP2" }
@{ id = $Pages["ttti"]; parent = $CatTTT; name = "TTTI" }
@{ id = $Pages["probleme"]; parent = $CatTTT; name = "Problemfelder" }
# Roadmap und Planung
@{ id = $Pages["roadmapfull"]; parent = $CatRoadmap; name = "Roadmap gesamt" }
@{ id = $Pages["aktionsplan"]; parent = $CatRoadmap; name = "Aktionsplan" }
@{ id = $Pages["next"]; parent = $CatRoadmap; name = "Naechste Schritte" }
@{ id = $Pages["fortschritt"]; parent = $CatRoadmap; name = "Fortschritt" }
)
if ($Pages["sonarqube"]) {
$Moves += @{ id = $Pages["sonarqube"]; parent = $CatTech; name = "SonarQube" }
}
# Dynamisch: Neuere Seiten per Titel suchen und einsortieren
$DynPages = @(
@{ title = "19a. SonarQube Smells Detail"; parent = "CatTech"; name = "Smells Detail" }
@{ title = "20. Geschaeftsprozesse"; parent = "CatSystem"; name = "Geschaeftsprozesse" }
@{ title = "21. Produkt-Roadmap (konsolidiert)"; parent = "CatRoadmap"; name = "Produkt-Roadmap" }
@{ title = "22. Personal- und Bug-Analyse"; parent = "CatTeams"; name = "Personal-Analyse" }
)
foreach ($DP in $DynPages) {
$DSearch = Invoke-ConfApi "Get" "$ApiBase/content?spaceKey=$SpaceKey&title=$([Uri]::EscapeDataString($DP.title))&type=page"
if ($DSearch -and $DSearch.results -and $DSearch.results.Count -gt 0) {
$TargetParent = switch ($DP.parent) {
"CatTech" { $CatTech }
"CatSystem" { $CatSystem }
"CatRoadmap" { $CatRoadmap }
"CatTeams" { $CatTeams }
"CatTTT" { $CatTTT }
}
$Moves += @{ id = $DSearch.results[0].id; parent = $TargetParent; name = $DP.name }
Write-Host " $($DP.name) gefunden (ID: $($DSearch.results[0].id))" -ForegroundColor DarkGray
} else {
Write-Host " $($DP.name) nicht gefunden (noch nicht gepusht?)" -ForegroundColor Yellow
}
}
foreach ($M in $Moves) {
Write-Host " $($M.name) -> Kategorie..." -NoNewline
$Ok = Move-Page $M.id $M.parent
if ($Ok) { Write-Host " OK" -ForegroundColor Green }
else { Write-Host " FEHLER" -ForegroundColor Red }
}
# Management Summary umbenennen - ENTFERNT (alte Seite bereits geloescht)
Write-Host " Management Summary: Bereits korrekt" -ForegroundColor DarkGray
# === Schritt 3: Stammseite aktualisieren ===
Write-Host ""
Write-Host ">> Stammseite aktualisieren..." -ForegroundColor Yellow
$StammPage = Invoke-ConfApi "Get" "$ApiBase/content/$ParentPageId`?expand=version"
$StammVersion = $StammPage.version.number + 1
$StammHtml = @"
<h2>Analyse pathOS &#8212; Portfolio-Audit</h2>
<p><strong>Business Owner:</strong> Andre Knie | <strong>Start:</strong> 2026-04-22 | <strong>Methodik:</strong> Iterativ</p>
<ac:structured-macro ac:name="info"><ac:rich-text-body>
<p>Systematische Analyse der pathOS-Plattform (~140 GitLab-Projekte, Confluence, Jira, Runbook). pathOS ist seit Dezember 2025 produktiv (FplJ 27). Aktuell: Verlaengerte Hypercare + NEP2.</p>
</ac:rich-text-body></ac:structured-macro>
<h3>Schnelleinstieg</h3>
<table>
<tr>
<td style="width:50%;vertical-align:top;padding:10px;">
<h4><ac:link><ri:page ri:content-title="0. Management Summary"/></ac:link></h4>
<p>Kompakte Zusammenfassung mit Zeitstrahl, Top-5 Risiken und Staerken.</p>
</td>
<td style="width:50%;vertical-align:top;padding:10px;">
<h4><ac:link><ri:page ri:content-title="Roadmap und Planung"/></ac:link></h4>
<p>Priorisierte Aktionen und Zeitplaene bis Mitte 2027.</p>
</td>
</tr>
</table>
<h3>Bereiche</h3>
<table>
<tr><th>Bereich</th><th>Inhalt</th></tr>
<tr><td><ac:link><ri:page ri:content-title="Systemueberblick"/></ac:link></td><td>Architektur, Komponenten, Customer Journey, GitLab-Landschaft, Glossar</td></tr>
<tr><td><ac:link><ri:page ri:content-title="Technische Analyse"/></ac:link></td><td>Versionen, Dependencies, Gesundheits-Scorecard, Technische Roadmap 2026</td></tr>
<tr><td><ac:link><ri:page ri:content-title="Teams und Velocity"/></ac:link></td><td>Team-Struktur, 12-Monats-Velocity, Jira-Analyse, MVPs und Schwachstellen</td></tr>
<tr><td><ac:link><ri:page ri:content-title="TTT-Programm"/></ac:link></td><td>TAF/TAP TSI Kontext, NEP2, TTTI-Integration, Problemfelder</td></tr>
<tr><td><ac:link><ri:page ri:content-title="Roadmap und Planung"/></ac:link></td><td>Aktionsplan (24 Massnahmen), Roadmap bis Mitte 2027, Naechste Schritte</td></tr>
</table>
<h3>Aktueller Status</h3>
<table>
<tr><th>Phase</th><th>Status</th></tr>
<tr style="background:#d5e8d4;"><td>Phase 1: Domain Discovery</td><td>&#9989; Abgeschlossen (80 Min)</td></tr>
<tr style="background:#d5e8d4;"><td>Phase 2: Technischer Deep Dive</td><td>&#9989; Abgeschlossen (55 Min)</td></tr>
<tr style="background:#d5e8d4;"><td>Phase 3: Team &amp; Workflow</td><td>&#9989; Abgeschlossen (30 Min)</td></tr>
<tr style="background:#d5e8d4;"><td>Phase 4: Roadmap &amp; Aktionsplan</td><td>&#9989; Abgeschlossen</td></tr>
<tr style="background:#d5e8d4;"><td>Velocity-Analyse (12 Monate)</td><td>&#9989; Abgeschlossen</td></tr>
<tr style="background:#d5e8d4;"><td>TTTI + TTTSol Deep Dive</td><td>&#9989; Abgeschlossen</td></tr>
</table>
"@
$StammJson = @{
version = @{ number = $StammVersion }
title = "Analyse pathOS"
type = "page"
body = @{ storage = @{ value = $StammHtml; representation = "storage" } }
} | ConvertTo-Json -Depth 10
$StammResult = Invoke-ConfApi "Put" "$ApiBase/content/$ParentPageId" $StammJson
if ($StammResult) { Write-Host " Stammseite aktualisiert" -ForegroundColor Green }
Write-Host ""
Write-Host "============================================================" -ForegroundColor Green
Write-Host " FERTIG! Seiten reorganisiert." -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green