Skip to content

Commit c6f6648

Browse files
wgutmannclaude
andcommitted
feat: add Sentry cron monitoring for post-deploy tests
- Add Push-SentryCheckIn helper using Sentry Monitors API - Auto-creates monitor on first check-in via monitor_config - Wraps post-deploy test block with in_progress/ok/error check-ins - Non-fatal: deploy continues if Sentry API is unreachable - Both check-in events logged to Loki (deploy_sentry_checkin) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent deea264 commit c6f6648

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

deploy.ps1

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,52 @@ function Push-SentryApi {
434434
}
435435
}
436436

437+
function Push-SentryCheckIn {
438+
param([string]$MonitorSlug, [string]$Status, [string]$CheckInId)
439+
if ([string]::IsNullOrWhiteSpace($sentryAuthToken)) { return $null }
440+
try {
441+
$headers = @{ Authorization = "Bearer $sentryAuthToken"; 'Content-Type' = 'application/json' }
442+
if ([string]::IsNullOrWhiteSpace($CheckInId)) {
443+
# Initial check-in: POST with monitor_config for auto-creation
444+
$url = "https://sentry.io/api/0/organizations/$sentryOrg/monitors/$MonitorSlug/checkins/"
445+
$body = @{
446+
status = $Status
447+
monitor_config = @{
448+
schedule = @{ type = 'interval'; value = 1; unit = 'day' }
449+
checkin_margin = 5
450+
max_runtime = 10
451+
timezone = 'UTC'
452+
}
453+
}
454+
$json = $body | ConvertTo-Json -Compress -Depth 5
455+
$resp = Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $json -ErrorAction Stop
456+
$newId = $resp.id
457+
Push-LokiEvent 'deploy_sentry_checkin' 'INFO' "Sentry cron check-in started: $MonitorSlug" @{
458+
monitor_slug = $MonitorSlug
459+
status = $Status
460+
checkin_id = $newId
461+
}
462+
return $newId
463+
} else {
464+
# Completion check-in: PUT to update existing
465+
$url = "https://sentry.io/api/0/organizations/$sentryOrg/monitors/$MonitorSlug/checkins/$CheckInId/"
466+
$body = @{ status = $Status }
467+
$json = $body | ConvertTo-Json -Compress -Depth 5
468+
Invoke-RestMethod -Uri $url -Method Put -Headers $headers -Body $json -ErrorAction Stop | Out-Null
469+
Push-LokiEvent 'deploy_sentry_checkin' 'INFO' "Sentry cron check-in completed: $MonitorSlug ($Status)" @{
470+
monitor_slug = $MonitorSlug
471+
status = $Status
472+
checkin_id = $CheckInId
473+
}
474+
return $null
475+
}
476+
} catch {
477+
# Non-fatal: deploy must not fail because Sentry API is down
478+
Write-Warning "Sentry CheckIn ($MonitorSlug/$Status): $($_.Exception.Message)"
479+
return $null
480+
}
481+
}
482+
437483
if (-not [string]::IsNullOrWhiteSpace($sentryAuthToken) -and -not [string]::IsNullOrWhiteSpace($sentryRelease)) {
438484
Write-Host "Registering Sentry release: $sentryRelease (3 projects)"
439485

@@ -509,6 +555,7 @@ if (-not $skipTests) {
509555
script_count = $testScripts.Count
510556
scripts = ($testScripts | ForEach-Object { $_.Name }) -join ','
511557
}
558+
$checkInId = Push-SentryCheckIn 'post-deploy-tests' 'in_progress'
512559
foreach ($ts in $testScripts) {
513560
Write-Host " Running: $($ts.Name)"
514561
$tsStart = Get-Date
@@ -557,6 +604,8 @@ if (-not $skipTests) {
557604
}
558605
}
559606
}
607+
$checkInStatus = if ($postDeployFailed) { 'error' } else { 'ok' }
608+
Push-SentryCheckIn 'post-deploy-tests' $checkInStatus $checkInId | Out-Null
560609
if ($postDeployFailed) {
561610
Write-Warning "Post-deploy tests failed. Deploy files are in place but integration is not fully verified."
562611
} else {

0 commit comments

Comments
 (0)