diff --git a/gitea-build-monitor.ps1 b/gitea-build-monitor.ps1 index 38101a6..2933d39 100755 --- a/gitea-build-monitor.ps1 +++ b/gitea-build-monitor.ps1 @@ -52,6 +52,8 @@ $Config = @{ SlowBuildThresholdMins = 20 CacheFile = Join-Path $PSScriptRoot 'gitea-build-monitor-cache.json' LogFile = Join-Path $PSScriptRoot 'gitea-build-monitor.log' + BuildLogFile = Join-Path $PSScriptRoot 'org-web-build.log' + BuildSuccessPattern = 'JSON saved to output/test.json' MaxJobsPerRepository = 50 MaxLogBytesToAnalyze = 250000 MaxDiscordEmbeds = 10 @@ -76,6 +78,7 @@ $Config = @{ # When true, completed successful runs are reported too. NotifySuccessfulBuilds = $true MaxPreviousFailures = 5 + AlwaysNotifyBuildStatus = $true # When true, successful but slow/warned jobs are reported too. # Keep this false if Discord should only receive notifications for failed/cancelled/timed-out jobs. @@ -309,6 +312,120 @@ function Get-CommitMessage { return '' } +function Get-FirstNonEmptyValue { + param([object[]]$Values) + + foreach ($value in $Values) { + if (-not [string]::IsNullOrWhiteSpace([string]$value)) { + return [string]$value + } + } + + return '' +} + +function Get-CurrentBuildStatus { + $explicitStatus = Get-FirstNonEmptyValue -Values @( + $env:BUILD_STATUS, + $env:GITEA_BUILD_STATUS, + $env:CI_JOB_STATUS, + $env:JOB_STATUS + ) + if ($explicitStatus) { + return $explicitStatus + } + + $exitCode = Get-FirstNonEmptyValue -Values @( + $env:BUILD_EXIT_CODE, + $env:GITEA_BUILD_EXIT_CODE, + $env:CI_BUILD_EXIT_CODE + ) + if ($exitCode) { + if ($exitCode -eq '0') { + return 'success' + } + return 'failure' + } + + if ((Test-Path -Path $Config.BuildLogFile) -and -not [string]::IsNullOrWhiteSpace($Config.BuildSuccessPattern)) { + try { + $tail = Get-Content -Path $Config.BuildLogFile -Tail 25 -ErrorAction Stop + if (($tail -join "`n") -match [regex]::Escape($Config.BuildSuccessPattern)) { + return 'success' + } + } + catch { + Write-Log -Level 'WARN' -Message "Could not inspect build log $($Config.BuildLogFile): $($_.Exception.Message)" + } + } + + return 'success' +} + +function New-CurrentBuildAnalysis { + param([Parameter(Mandatory)][hashtable]$Repository) + + $repositorySlug = Get-RepositorySlug -Repository $Repository + $status = Get-CurrentBuildStatus + $severity = if (Test-IsSuccessfulStatus -Status $status) { 'Info' } else { 'Critical' } + $runId = Get-FirstNonEmptyValue -Values @( + $env:GITEA_RUN_ID, + $env:ACTIONS_RUN_ID, + $env:GITHUB_RUN_ID, + $env:CI_PIPELINE_ID, + $env:CI_RUN_ID + ) + if (-not $runId) { + $runId = (Get-Date).ToUniversalTime().ToString('yyyyMMddHHmmss') + } + + $branch = Get-FirstNonEmptyValue -Values @( + $env:GITEA_REF_NAME, + $env:GITHUB_REF_NAME, + $env:CI_COMMIT_BRANCH, + $env:BRANCH_NAME + ) + if (-not $branch) { + $branch = 'unknown' + } + + $sha = Get-FirstNonEmptyValue -Values @( + $env:GITEA_SHA, + $env:GITHUB_SHA, + $env:CI_COMMIT_SHA + ) + $buildUrl = Get-FirstNonEmptyValue -Values @( + $env:GITEA_RUN_URL, + $env:GITHUB_SERVER_URL + ) + if (-not $buildUrl) { + $buildUrl = Join-Url -Base $Config.GiteaBaseUrl -Path "$repositorySlug/actions/runs/$runId" + } + + return [pscustomobject]@{ + Repository = $repositorySlug + Owner = Get-RepositoryOwner -Repository $Repository + Repo = Get-RepositoryName -Repository $Repository + JobId = 'current' + RunId = $runId + Branch = $branch + CommitSha = $sha + CommitMessage = '' + Status = $status + Duration = [timespan]::Zero + DurationText = 'current run' + BuildUrl = $buildUrl + ErrorSummary = if (Test-IsSuccessfulStatus -Status $status) { "Build completed successfully. Success marker: $($Config.BuildSuccessPattern)" } else { 'Build status reported as failed by the monitor environment.' } + HasErrors = -not (Test-IsSuccessfulStatus -Status $status) + HasWarnings = $false + IsSlow = $false + Severity = $severity + ShouldAlert = $true + StartedAt = Get-Date + IsCurrent = $true + } +} + function Get-JobLogText { param( [Parameter(Mandatory)][hashtable]$Repository, @@ -848,18 +965,20 @@ function Send-BuildStatusNotification { }) } + $content = if ($failedLatestCount -gt 0) { + "❌ Latest Gitea build status: $failedLatestCount failed, $successfulLatestCount successful. Previous failures in window: $previousFailureCount." + } + elseif ($successfulLatestCount -gt 0) { + "✅ Latest Gitea build status: $successfulLatestCount successful. Previous failures in window: $previousFailureCount." + } + else { + "ℹ️ Latest Gitea build status reported. Previous failures in window: $previousFailureCount." + } + $payload = @{ username = 'Gitea Build Monitor' - content = if ($failedLatestCount -gt 0) { - "❌ Latest Gitea build status: $failedLatestCount failed, $successfulLatestCount successful. Previous failures in window: $previousFailureCount." - } - elseif ($successfulLatestCount -gt 0) { - "✅ Latest Gitea build status: $successfulLatestCount successful. Previous failures in window: $previousFailureCount." - } - else { - "ℹ️ Latest Gitea build status reported. Previous failures in window: $previousFailureCount." - } - embeds = @($embeds) + content = $content + embeds = @($embeds.ToArray()) } Invoke-DiscordWebhook -Payload $payload @@ -1096,15 +1215,14 @@ function Start-BuildMonitor { return } - $authoringTestResult = Invoke-AuthoringServerTests - if ($null -ne $authoringTestResult) { - Send-AuthoringTestNotification -Result $authoringTestResult - } - $cache = if ($DryRun) { @{} } else { Read-ProcessedCache } $analyses = New-Object System.Collections.Generic.List[object] foreach ($repository in $Config.Repositories) { + $currentAnalysis = New-CurrentBuildAnalysis -Repository $repository + $analyses.Add($currentAnalysis) + Write-Log -Message ("Prepared current build status for {0}: severity={1}, status={2}" -f $currentAnalysis.Repository, $currentAnalysis.Severity, $currentAnalysis.Status) + Write-Log -Message "Fetching recent Gitea Actions runs for $(Get-RepositorySlug -Repository $repository)." try { @@ -1136,12 +1254,12 @@ function Start-BuildMonitor { if ($analyses.Count -gt 0) { $summaryCacheKey = Get-BuildSummaryCacheKey -Analyses $analyses.ToArray() - if ($cache.ContainsKey($summaryCacheKey)) { + if (-not $Config.AlwaysNotifyBuildStatus -and $cache.ContainsKey($summaryCacheKey)) { Write-Log -Message 'Build status summary has already been sent.' } else { Send-BuildStatusNotification -Analyses $analyses.ToArray() - if (-not $DryRun) { + if (-not $DryRun -and -not $Config.AlwaysNotifyBuildStatus) { $cache[$summaryCacheKey] = Get-Date } } @@ -1150,6 +1268,11 @@ function Start-BuildMonitor { Write-Log -Message "No completed builds found in the last $($Config.LookbackMinutes) minute(s)." } + $authoringTestResult = Invoke-AuthoringServerTests + if ($null -ne $authoringTestResult) { + Send-AuthoringTestNotification -Result $authoringTestResult + } + if (-not $DryRun) { Save-ProcessedCache -Cache $cache } diff --git a/posts/posts-list.org b/posts/posts-list.org index e10fe37..3996627 100755 --- a/posts/posts-list.org +++ b/posts/posts-list.org @@ -4,7 +4,7 @@ See the categories: @@html:Categories@@ * Posts: -- [[file:career/career-list.org][Career List]] @@html:08-05-2026 16:04@@ +- [[file:career/career-list.org][Career List]] @@html:08-05-2026 16:10@@ - [[file:posts-list.sync-conflict-20260417-233432-VT6366A.org][Posts List]] @@html:14-04-2026 16:36@@ - [[file:career/ha-dr.org][High Availability, Disaster Recovery and Business Continuity]] @@html:11-03-2026 17:18@@ @@html:learning@@ @@html:notes@@ - [[file:career/javascript.org][Understands the Javascript language]] @@html:11-03-2026 16:52@@ @@html:learning@@ @@html:notes@@ diff --git a/sitemap.org b/sitemap.org index 130ecb8..ddd18a4 100755 --- a/sitemap.org +++ b/sitemap.org @@ -11,8 +11,8 @@ - [[file:tags/notes.org][Tag: notes]] - [[file:tags/review.org][Tag: review]] - [[file:tags/website.org][Tag: website]] - - [[file:tags/life.org][Tag: life]] - [[file:tags/update.org][Tag: update]] + - [[file:tags/life.org][Tag: life]] - [[file:tags/education.org][Tag: education]] - [[file:tags/insights.org][Tag: insights]] - [[file:tags/reading.org][Tag: reading]]