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]]