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.
128 lines
5.0 KiB
PowerShell
128 lines
5.0 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Exportiert Fachliches Board und TTTI Board aus Jira
|
|
#>
|
|
|
|
$JiraUrl = "https://arija.jaas.service.deutschebahn.com"
|
|
$ApiBase = "$JiraUrl/rest"
|
|
$OutputDir = "project-audit\data\jira-boards"
|
|
|
|
$Boards = @(
|
|
@{ id = 2791; name = "Fachliches-Board" }
|
|
@{ id = 1487; name = "TTTI-Board" }
|
|
)
|
|
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
|
|
Write-Host "============================================================"
|
|
Write-Host " pathOS Boards Export (Fachlich + TTTI)"
|
|
Write-Host "============================================================"
|
|
|
|
$Token = Read-Host "Jira PAT"
|
|
$Headers = @{ "Authorization" = "Bearer $Token"; "Content-Type" = "application/json" }
|
|
|
|
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
|
|
|
function Invoke-JiraApi($Uri) {
|
|
try {
|
|
$R = Invoke-WebRequest -Uri $Uri -Headers $Headers -UseBasicParsing -ErrorAction Stop
|
|
return ($R.Content | ConvertFrom-Json)
|
|
} catch {
|
|
Write-Host " FEHLER: $($_.Exception.Message)" -ForegroundColor Red
|
|
return $null
|
|
}
|
|
}
|
|
|
|
foreach ($Board in $Boards) {
|
|
$BId = $Board.id
|
|
$BName = $Board.name
|
|
Write-Host ""
|
|
Write-Host ">> $BName (Board ID: $BId)" -ForegroundColor Yellow
|
|
|
|
# Board-Info
|
|
$Info = Invoke-JiraApi "$ApiBase/agile/1.0/board/$BId"
|
|
if ($Info) {
|
|
Write-Host " Board: $($Info.name) (Projekt: $($Info.location.projectKey))"
|
|
$Info | ConvertTo-Json -Depth 5 | Out-File "$OutputDir\$BName-info.json" -Encoding UTF8
|
|
}
|
|
|
|
# Board-Config
|
|
$Config = Invoke-JiraApi "$ApiBase/agile/1.0/board/$BId/configuration"
|
|
if ($Config) {
|
|
$Config | ConvertTo-Json -Depth 10 | Out-File "$OutputDir\$BName-config.json" -Encoding UTF8
|
|
}
|
|
|
|
# Issues auf dem Board
|
|
Write-Host " Lade Issues..." -NoNewline
|
|
$Issues = @()
|
|
$Start = 0
|
|
do {
|
|
$Uri = "$ApiBase/agile/1.0/board/$BId/issue?startAt=$Start&maxResults=100&fields=summary,status,issuetype,assignee,labels,components,fixVersions,priority,created,updated"
|
|
$Result = Invoke-JiraApi $Uri
|
|
if ($null -eq $Result) { break }
|
|
$Issues += $Result.issues
|
|
$Start += 100
|
|
Write-Host "." -NoNewline
|
|
} while ($Issues.Count -lt $Result.total -and $Issues.Count -lt 1000)
|
|
Write-Host ""
|
|
Write-Host " $($Issues.Count) Issues geladen" -ForegroundColor Green
|
|
|
|
$Issues | ConvertTo-Json -Depth 10 | Out-File "$OutputDir\$BName-issues.json" -Encoding UTF8
|
|
|
|
# Analyse
|
|
$ByType = $Issues | Group-Object { $_.fields.issuetype.name }
|
|
$ByStatus = $Issues | Group-Object { $_.fields.status.name }
|
|
$ByLabel = @{}
|
|
foreach ($I in $Issues) {
|
|
if ($I.fields.labels) {
|
|
foreach ($L in $I.fields.labels) { $ByLabel[$L] = ($ByLabel[$L]) + 1 }
|
|
}
|
|
}
|
|
|
|
$Done = ($Issues | Where-Object { $_.fields.status.name -match "Fertig|Done|Closed|Resolved|Geloest" }).Count
|
|
$InProg = ($Issues | Where-Object { $_.fields.status.name -match "Implementation|In Bearbeitung|In Progress|Review|Validierung|Analysis" }).Count
|
|
$Open = $Issues.Count - $Done - $InProg
|
|
|
|
Write-Host " Fertig: $Done | In Arbeit: $InProg | Offen: $Open"
|
|
|
|
# CSV
|
|
$CsvData = $Issues | ForEach-Object {
|
|
$Comps = if ($_.fields.components) { ($_.fields.components | ForEach-Object { $_.name }) -join ", " } else { "" }
|
|
$Labels = if ($_.fields.labels) { $_.fields.labels -join ", " } else { "" }
|
|
[PSCustomObject]@{
|
|
Key = $_.key
|
|
Typ = $_.fields.issuetype.name
|
|
Status = $_.fields.status.name
|
|
Prioritaet = if ($_.fields.priority) { $_.fields.priority.name } else { "" }
|
|
Zusammenfassung = $_.fields.summary
|
|
Komponenten = $Comps
|
|
Labels = $Labels
|
|
Assignee = if ($_.fields.assignee) { $_.fields.assignee.displayName } else { "" }
|
|
Erstellt = $_.fields.created
|
|
Aktualisiert = $_.fields.updated
|
|
}
|
|
}
|
|
$CsvData | Export-Csv "$OutputDir\$BName-issues.csv" -Delimiter ";" -Encoding UTF8 -NoTypeInformation
|
|
|
|
# Markdown
|
|
$Md = @()
|
|
$Md += "# $BName Analyse"
|
|
$Md += ""
|
|
$Md += "> Board ID: $BId | Issues: $($Issues.Count) | Fertig: $Done | In Arbeit: $InProg | Offen: $Open"
|
|
$Md += ""
|
|
$Md += "## Nach Typ"
|
|
foreach ($G in ($ByType | Sort-Object Count -Descending)) { $Md += "- $($G.Name): $($G.Count)" }
|
|
$Md += ""
|
|
$Md += "## Nach Status"
|
|
foreach ($G in ($ByStatus | Sort-Object Count -Descending)) { $Md += "- $($G.Name): $($G.Count)" }
|
|
$Md += ""
|
|
$Md += "## Top Labels"
|
|
foreach ($E in ($ByLabel.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 20)) { $Md += "- $($E.Key): $($E.Value)" }
|
|
$Md -join "`n" | Out-File "$OutputDir\$BName-analyse.md" -Encoding UTF8
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "============================================================" -ForegroundColor Green
|
|
Write-Host " FERTIG! Ergebnisse in $OutputDir" -ForegroundColor Green
|
|
Write-Host "============================================================" -ForegroundColor Green
|