forked from Gitlink/gitlink-cli
210 lines
8.4 KiB
PowerShell
210 lines
8.4 KiB
PowerShell
# ----------------------------------------------------------------
|
|
# Scenario 4: Multi-Repo Collaboration
|
|
# Flow: Cross-repo issue tracking -> PR status dashboard -> Coordinated release
|
|
#
|
|
# Commands chained:
|
|
# 1. repo +list -- list all repos in org
|
|
# 2. issue +list -- fetch issues from each repo
|
|
# 3. pr +list -- fetch PRs from each repo
|
|
# 4. release +list -- check release status across repos
|
|
# 5. release +create -- coordinated release (optional)
|
|
# 6. Generate HTML dashboard
|
|
# ----------------------------------------------------------------
|
|
#Requires -Version 5.1
|
|
|
|
param(
|
|
[Parameter(Mandatory=$true)]
|
|
[string]$Org,
|
|
[string]$Repos = "",
|
|
[string]$Release = "",
|
|
[string]$Output = "dashboard.html",
|
|
[switch]$DryRun,
|
|
[switch]$Help
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
Import-Module "$PSScriptRoot/lib/common.psm1" -Force -WarningAction SilentlyContinue
|
|
|
|
if ($Help) {
|
|
Write-Host "Usage: powershell 04-multi-repo-collab.ps1 -Org ORG [-Repos 'repo1,repo2'] [-Release TAG] [-Output FILE] [-DryRun]"
|
|
exit 0
|
|
}
|
|
|
|
Check-Auth
|
|
|
|
# -- Step 1: List Repositories --
|
|
Log-Title "Multi-Repo Collaboration Dashboard"
|
|
|
|
Log-Step "Fetching repositories for org: $Org..."
|
|
$reposJson = Invoke-GLCheck "repo", "+list", "--user", $Org, "--limit", "100"
|
|
if (-not $reposJson) { Log-Err "Failed to fetch repos"; exit 1 }
|
|
|
|
$allRepos = @()
|
|
$rd = $reposJson.data
|
|
if ($rd.projects) { $allRepos = @($rd.projects) }
|
|
elseif ($rd -is [array]) { $allRepos = $rd }
|
|
|
|
Log-Ok "Found $($allRepos.Count) repositories"
|
|
|
|
$repoList = @()
|
|
if ($Repos) {
|
|
$repoList = $Repos -split ','
|
|
Log-Info "Filtering to specified repos: $($repoList -join ', ')"
|
|
} else {
|
|
foreach ($r in $allRepos) {
|
|
$rname = if ($r.name) { $r.name } elseif ($r.identifier) { $r.identifier } else { $null }
|
|
if ($rname) { $repoList += $rname }
|
|
}
|
|
}
|
|
|
|
Log-Ok "Will process $($repoList.Count) repositories"
|
|
|
|
# -- Step 2-3: Collect Issues and PRs from each repo --
|
|
Log-Title "Collecting Data Across Repos"
|
|
|
|
$totalIssues = 0; $totalOpenIssues = 0; $totalPRs = 0; $totalOpenPRs = 0
|
|
$dashboardRows = ""
|
|
|
|
foreach ($repo in $repoList) {
|
|
Divider
|
|
Log-Step "Processing $Org/$repo..."
|
|
|
|
$issuesJson = Invoke-GL "issue", "+list", "--owner", $Org, "--repo", $repo, "--state", "open", "--limit", "50"
|
|
$openIssues = if ($issuesJson) { @($issuesJson.data.issues).Count } else { 0 }
|
|
|
|
$closedJson = Invoke-GL "issue", "+list", "--owner", $Org, "--repo", $repo, "--state", "closed", "--limit", "50"
|
|
$closedIssues = if ($closedJson) { @($closedJson.data.issues).Count } else { 0 }
|
|
|
|
$prsJson = Invoke-GL "pr", "+list", "--owner", $Org, "--repo", $repo, "--state", "open", "--limit", "50"
|
|
$openPRs = 0
|
|
if ($prsJson) {
|
|
$pd = $prsJson.data
|
|
if ($pd.issues) { $openPRs = @($pd.issues).Count }
|
|
elseif ($pd.pulls) { $openPRs = @($pd.pulls).Count }
|
|
elseif ($pd -is [array]) { $openPRs = $pd.Count }
|
|
}
|
|
|
|
$mergedJson = Invoke-GL "pr", "+list", "--owner", $Org, "--repo", $repo, "--state", "merged", "--limit", "50"
|
|
$mergedPRs = 0
|
|
if ($mergedJson) {
|
|
$md = $mergedJson.data
|
|
if ($md.issues) { $mergedPRs = @($md.issues).Count }
|
|
elseif ($md.pulls) { $mergedPRs = @($md.pulls).Count }
|
|
elseif ($md -is [array]) { $mergedPRs = $md.Count }
|
|
}
|
|
|
|
$releaseJson = Invoke-GL "release", "+list", "--owner", $Org, "--repo", $repo, "--limit", "1"
|
|
$latestRelease = "none"
|
|
if ($releaseJson -and $releaseJson.data.releases) {
|
|
$releases = @($releaseJson.data.releases)
|
|
if ($releases.Count -gt 0) {
|
|
$latestRelease = if ($releases[0].tag_name) { $releases[0].tag_name } elseif ($releases[0].name) { $releases[0].name } else { "none" }
|
|
}
|
|
}
|
|
|
|
Log-Ok "$repo : Issues(open:$openIssues closed:$closedIssues) PRs(open:$openPRs merged:$mergedPRs) Release:$latestRelease"
|
|
|
|
$statusColor = "green"
|
|
$healthText = "Healthy"
|
|
if ($openIssues -gt 10) { $statusColor = "orange"; $healthText = "Moderate" }
|
|
if ($openIssues -gt 20) { $statusColor = "red"; $healthText = "Needs Attention" }
|
|
|
|
$dashboardRows += "<tr>`n"
|
|
$dashboardRows += " <td><a href=`"https://gitlink.org.cn/$Org/$repo`">$repo</a></td>`n"
|
|
$dashboardRows += " <td>$openIssues</td><td>$closedIssues</td>`n"
|
|
$dashboardRows += " <td>$openPRs</td><td>$mergedPRs</td><td>$latestRelease</td>`n"
|
|
$dashboardRows += " <td style=`"color:$statusColor;font-weight:bold;`">$healthText</td>`n"
|
|
$dashboardRows += "</tr>`n"
|
|
|
|
$totalIssues += $openIssues + $closedIssues
|
|
$totalOpenIssues += $openIssues
|
|
$totalPRs += $openPRs + $mergedPRs
|
|
$totalOpenPRs += $openPRs
|
|
}
|
|
|
|
# -- Step 4: Generate HTML Dashboard --
|
|
Log-Title "Generating Dashboard"
|
|
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
$repoCount = $repoList.Count
|
|
|
|
$html = '<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Multi-Repo Collaboration Dashboard</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #f5f5f5; padding: 20px; }
|
|
.container { max-width: 1200px; margin: 0 auto; }
|
|
h1 { color: #333; margin-bottom: 20px; }
|
|
.summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 30px; }
|
|
.card { background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
.card h3 { color: #666; font-size: 14px; margin-bottom: 8px; }
|
|
.card .value { font-size: 32px; font-weight: bold; color: #333; }
|
|
.card.blue .value { color: #2196F3; }
|
|
.card.green .value { color: #4CAF50; }
|
|
.card.orange .value { color: #FF9800; }
|
|
.card.purple .value { color: #9C27B0; }
|
|
table { width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
th { background: #2196F3; color: white; padding: 12px 16px; text-align: left; }
|
|
td { padding: 12px 16px; border-bottom: 1px solid #eee; }
|
|
tr:hover { background: #f9f9f9; }
|
|
a { color: #2196F3; text-decoration: none; }
|
|
a:hover { text-decoration: underline; }
|
|
.timestamp { color: #999; font-size: 14px; margin-bottom: 20px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>Multi-Repo Collaboration Dashboard</h1>
|
|
<p class="timestamp">Generated: ' + $timestamp + ' | Organization: ' + $Org + '</p>
|
|
<div class="summary">
|
|
<div class="card blue"><h3>Total Repos</h3><div class="value">' + $repoCount + '</div></div>
|
|
<div class="card orange"><h3>Open Issues</h3><div class="value">' + $totalOpenIssues + '</div></div>
|
|
<div class="card purple"><h3>Open PRs</h3><div class="value">' + $totalOpenPRs + '</div></div>
|
|
<div class="card green"><h3>Total Activity</h3><div class="value">' + $totalIssues + '</div></div>
|
|
</div>
|
|
<table>
|
|
<thead><tr><th>Repository</th><th>Open Issues</th><th>Closed Issues</th><th>Open PRs</th><th>Merged PRs</th><th>Latest Release</th><th>Health</th></tr></thead>
|
|
<tbody>
|
|
' + $dashboardRows + '
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</body>
|
|
</html>'
|
|
|
|
$html | Out-File -FilePath $Output -Encoding UTF8
|
|
Log-Ok "Dashboard saved to: $Output"
|
|
|
|
# -- Step 5: Coordinated Release --
|
|
if ($Release) {
|
|
Log-Title "Coordinated Release: $Release"
|
|
|
|
foreach ($repo in $repoList) {
|
|
Log-Step "Creating release for $Org/$repo..."
|
|
$relBody = "Coordinated release $Release for $Org/$repo"
|
|
$relResult = Invoke-GL "release", "+create", "--owner", $Org, "--repo", $repo, "--tag", $Release, "--name", "Release $Release", "--body", $relBody
|
|
if ($relResult -and (Get-JsonOk $relResult)) {
|
|
Log-Ok "Release $Release created for $repo"
|
|
} else {
|
|
Log-Warn "Release creation failed for $repo (tag may already exist)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# ----------------------------------------------------------------
|
|
Log-Title "Multi-Repo Dashboard Complete"
|
|
# ----------------------------------------------------------------
|
|
|
|
Write-Host " Repos processed: $repoCount" -ForegroundColor Green
|
|
Write-Host " Total issues: $totalIssues (open: $totalOpenIssues)" -ForegroundColor Green
|
|
Write-Host " Total PRs: $totalPRs (open: $totalOpenPRs)" -ForegroundColor Green
|
|
Write-Host " Dashboard: $Output" -ForegroundColor Green
|
|
if ($Release) { Write-Host " Coordinated release: $Release" -ForegroundColor Green }
|
|
Write-Host ""
|
|
Write-Host "Open dashboard:" -ForegroundColor Cyan
|
|
Write-Host " Start-Process $Output"
|