Skip to content

Commit 2217770

Browse files
refactor: simplify daily support check script
1 parent 8d1e9d1 commit 2217770

3 files changed

Lines changed: 111 additions & 45 deletions

File tree

‎ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1‎

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,23 @@ function Merge-SupportConfiguration {
146146
$Base
147147
}
148148

149+
function Assert-HttpEndpointConfiguration {
150+
[CmdletBinding()]
151+
param(
152+
[Parameter(Mandatory)] [string] $SectionName,
153+
[Parameter(Mandatory)] [object] $Settings
154+
)
155+
156+
$endpointUri = $null
157+
if (-not [uri]::TryCreate([string] $Settings.BaseUrl, [UriKind]::Absolute, [ref] $endpointUri)) {
158+
throw "$SectionName.BaseUrl must be an absolute URI."
159+
}
160+
161+
if ([int] $Settings.TimeoutSeconds -le 0) {
162+
throw "$SectionName.TimeoutSeconds must be greater than zero."
163+
}
164+
}
165+
149166
function Get-SupportConfiguration {
150167
[CmdletBinding()]
151168
param([Parameter(Mandatory)] [string] $Path)
@@ -187,44 +204,23 @@ function Get-SupportConfiguration {
187204
return $configuration
188205
}
189206

190-
$healthMonitoringUri = $null
191-
if (-not [uri]::TryCreate([string] $configuration.HealthMonitoring.BaseUrl, [UriKind]::Absolute, [ref] $healthMonitoringUri)) {
192-
throw 'HealthMonitoring.BaseUrl must be an absolute URI.'
193-
}
194-
195-
if ([int] $configuration.HealthMonitoring.TimeoutSeconds -le 0) {
196-
throw 'HealthMonitoring.TimeoutSeconds must be greater than zero.'
197-
}
207+
Assert-HttpEndpointConfiguration -SectionName 'HealthMonitoring' -Settings $configuration.HealthMonitoring
198208
}
199209

200210
if ($configuration.PSObject.Properties['SubscriptionService']) {
201211
if (-not [bool] $configuration.SubscriptionService.Enabled) {
202212
return $configuration
203213
}
204214

205-
$subscriptionServiceUri = $null
206-
if (-not [uri]::TryCreate([string] $configuration.SubscriptionService.BaseUrl, [UriKind]::Absolute, [ref] $subscriptionServiceUri)) {
207-
throw 'SubscriptionService.BaseUrl must be an absolute URI.'
208-
}
209-
210-
if ([int] $configuration.SubscriptionService.TimeoutSeconds -le 0) {
211-
throw 'SubscriptionService.TimeoutSeconds must be greater than zero.'
212-
}
215+
Assert-HttpEndpointConfiguration -SectionName 'SubscriptionService' -Settings $configuration.SubscriptionService
213216
}
214217

215218
if ($configuration.PSObject.Properties['KurrentDbProjections']) {
216219
if (-not [bool] $configuration.KurrentDbProjections.Enabled) {
217220
return $configuration
218221
}
219222

220-
$kurrentDbUri = $null
221-
if (-not [uri]::TryCreate([string] $configuration.KurrentDbProjections.BaseUrl, [UriKind]::Absolute, [ref] $kurrentDbUri)) {
222-
throw 'KurrentDbProjections.BaseUrl must be an absolute URI.'
223-
}
224-
225-
if ([int] $configuration.KurrentDbProjections.TimeoutSeconds -le 0) {
226-
throw 'KurrentDbProjections.TimeoutSeconds must be greater than zero.'
227-
}
223+
Assert-HttpEndpointConfiguration -SectionName 'KurrentDbProjections' -Settings $configuration.KurrentDbProjections
228224

229225
$hasUsername = $configuration.KurrentDbProjections.PSObject.Properties['Username'] -and -not [string]::IsNullOrWhiteSpace([string] $configuration.KurrentDbProjections.Username)
230226
$hasPasswordEnvironmentVariable = $configuration.KurrentDbProjections.PSObject.Properties['PasswordEnvironmentVariable'] -and -not [string]::IsNullOrWhiteSpace([string] $configuration.KurrentDbProjections.PasswordEnvironmentVariable)
@@ -944,6 +940,20 @@ function ConvertTo-HtmlEncodedText {
944940
[System.Net.WebUtility]::HtmlEncode([string] $Value)
945941
}
946942

943+
function Get-SupportStatusIcon {
944+
param([string] $Status)
945+
946+
switch ($Status) {
947+
'Passed' { '🟢' }
948+
'Healthy' { '🟢' }
949+
'Warning' { '🟠' }
950+
'Degraded' { '🟠' }
951+
'Failed' { '🔴' }
952+
'Unhealthy' { '🔴' }
953+
default { '⚪' }
954+
}
955+
}
956+
947957
function Write-SupportReports {
948958
[CmdletBinding()]
949959
param(
@@ -973,12 +983,7 @@ function Write-SupportReports {
973983
$summaryText = $summaryText.Substring(0, 157).TrimEnd() + '…'
974984
}
975985
$summary = [System.Net.WebUtility]::HtmlEncode($summaryText)
976-
$statusIcon = switch ([string] $check.Status) {
977-
'Passed' { '🟢' }
978-
'Warning' { '🟠' }
979-
'Failed' { '🔴' }
980-
default { '⚪' }
981-
}
986+
$statusIcon = Get-SupportStatusIcon -Status ([string] $check.Status)
982987
[void] $rows.AppendLine("<tr class=`"status-$status`"><td>$name</td><td><span class=`"status-icon`" role=`"img`" aria-label=`"$status`">$statusIcon</span> $status</td><td>$summary</td></tr>")
983988
}
984989

@@ -994,12 +999,7 @@ function Write-SupportReports {
994999
foreach ($subscription in $subscriptionItems) {
9951000
$detailStatus = ConvertTo-HtmlEncodedText $subscription.Status
9961001
$detailStatusClass = [System.Net.WebUtility]::HtmlEncode("status-$([string] $subscription.Status)")
997-
$detailStatusIcon = switch ([string] $subscription.Status) {
998-
'Passed' { '🟢' }
999-
'Warning' { '🟠' }
1000-
'Failed' { '🔴' }
1001-
default { '⚪' }
1002-
}
1002+
$detailStatusIcon = Get-SupportStatusIcon -Status ([string] $subscription.Status)
10031003
$reasonParts = @(
10041004
if ($subscription.PSObject.Properties['operationalReason'] -and -not [string]::IsNullOrWhiteSpace([string] $subscription.OperationalReason)) { "Operational: $($subscription.OperationalReason)" }
10051005
if ($subscription.PSObject.Properties['runtimeFailureReason'] -and -not [string]::IsNullOrWhiteSpace([string] $subscription.RuntimeFailureReason)) { "Runtime: $($subscription.RuntimeFailureReason)" }
@@ -1022,15 +1022,7 @@ function Write-SupportReports {
10221022
foreach ($service in $healthMonitoringItems) {
10231023
$detailStatus = ConvertTo-HtmlEncodedText $service.Status
10241024
$detailStatusClass = [System.Net.WebUtility]::HtmlEncode("status-$([string] $service.Status)")
1025-
$detailStatusIcon = switch ([string] $service.Status) {
1026-
'Passed' { '🟢' }
1027-
'Healthy' { '🟢' }
1028-
'Warning' { '🟠' }
1029-
'Degraded' { '🟠' }
1030-
'Failed' { '🔴' }
1031-
'Unhealthy' { '🔴' }
1032-
default { '⚪' }
1033-
}
1025+
$detailStatusIcon = Get-SupportStatusIcon -Status ([string] $service.Status)
10341026
[void] $healthMonitoringDetails.AppendLine("<tr class=`"$detailStatusClass`"><td>$(ConvertTo-HtmlEncodedText $service.ServiceId)</td><td>$(ConvertTo-HtmlEncodedText $service.Name)</td><td><span class=`"status-icon`" role=`"img`" aria-label=`"$detailStatus`">$detailStatusIcon</span> $detailStatus</td><td>$(ConvertTo-HtmlEncodedText $service.LastObservedAtUtc)</td><td>$(ConvertTo-HtmlEncodedText $service.LastError)</td></tr>")
10351027
}
10361028
[void] $healthMonitoringDetails.AppendLine('</tbody></table></div>')
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Daily Support Check Script Simplification Implementation Plan
2+
3+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4+
5+
**Goal:** Remove repeated status-icon and HTTP endpoint configuration validation logic without changing script behavior.
6+
7+
**Architecture:** Keep the script standalone. Add one status-icon helper covering the current status aliases and one HTTP endpoint configuration helper used by the three sections that currently validate both `BaseUrl` and `TimeoutSeconds`.
8+
9+
**Tech Stack:** PowerShell.
10+
11+
**Spec:** `docs/superpowers/specs/2026-11-07-daily-support-check-script-simplification-design.md`
12+
13+
## Global Constraints
14+
15+
- Keep `Invoke-DailySupportCheck.ps1` as a single self-contained script.
16+
- Preserve current validation order, messages, optional-section behavior, and disabled-section early returns.
17+
- Preserve icon mappings: `Passed`/`Healthy` → green, `Warning`/`Degraded` → orange, `Failed`/`Unhealthy` → red, and all other values → white.
18+
- Do not change any check's request, status calculation, fallback, report, or email behavior.
19+
- Do not add or run tests.
20+
21+
## Review Focus
22+
23+
- A disabled optional endpoint section must retain the existing early return behavior.
24+
- Invalid endpoint URI and non-positive timeout errors must preserve their current section-specific messages.
25+
- Status values with and without aliases must render the same icon, including unknown values.
26+
27+
---
28+
29+
## Task 1: Extract repeated status and endpoint configuration helpers
30+
31+
**Files:** `ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1`
32+
33+
**Interfaces:** `Get-SupportStatusIcon([string] $Status) -> [string]`; `Assert-HttpEndpointConfiguration([string] $SectionName, [object] $Settings) -> void`.
34+
35+
- [x] Add `Get-SupportStatusIcon` with the approved mapping and replace only the three existing HTML status-icon switches.
36+
- [x] Add `Assert-HttpEndpointConfiguration`; preserve the exact URI and timeout validation logic and error messages.
37+
- [x] Replace the repeated validation blocks for `HealthMonitoring`, `SubscriptionService`, and `KurrentDbProjections` with helper calls while keeping their existing property checks, ordering, domain-specific validation, and early returns.
38+
- [x] Parse the updated script with PowerShell's parser, review the diff for behavior changes, and run `git diff --check`; do not run tests.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Daily Support Check script simplification
2+
3+
## Intent
4+
5+
Make repeated presentation and configuration-validation logic easier to maintain in `Invoke-DailySupportCheck.ps1` without changing report output, configuration behavior, or how the standalone script is deployed.
6+
7+
## Goals
8+
9+
- Replace the three duplicated status-to-icon switches in HTML report generation with one helper that preserves the current mappings: `Passed`/`Healthy` → green, `Warning`/`Degraded` → orange, `Failed`/`Unhealthy` → red, and all other values → white.
10+
- Replace the repeated absolute-URI and positive-timeout validation for `HealthMonitoring`, `SubscriptionService`, and `KurrentDbProjections` with one helper.
11+
- Preserve the current validation order, messages, optional-section behavior, and early return when a present section is disabled.
12+
- Keep `Invoke-DailySupportCheck.ps1` as a single self-contained script.
13+
14+
## Non-goals
15+
16+
- Split the script into modules or change installation/sourcing requirements.
17+
- Change any check's request, status calculation, fallback, report or email behavior.
18+
- Rewrite the entire configuration validator as a table-driven framework.
19+
- Change KurrentDB write-activity validation, which has no matching timeout requirement.
20+
21+
## Chosen approach
22+
23+
Add a small `Get-SupportStatusIcon` helper for the existing icon mappings and an `Assert-HttpEndpointConfiguration` helper that accepts the section name, base URL, and timeout. Call the endpoint helper from the three existing validation blocks while leaving their order, enable checks, optional settings, and early returns in place. Replace only the repeated icon switches with helper calls; leave HTML structure and text encoding as they are.
24+
25+
## Alternatives considered
26+
27+
1. **Extract the repeated helpers in the existing script (chosen).** Reduces duplicated logic with minimal behavioral and packaging risk.
28+
2. **Split checks, reporting, and transports into separate files.** Could improve navigation further, but changes how callers load and deploy the script and exceeds this focused cleanup.
29+
3. **Rewrite all validation as declarative metadata.** More compact, but risks changing validation order and disabled-section short-circuit behavior for little added value.
30+
31+
## Constraints and implementation calls
32+
33+
- Preserve current user-visible messages and configuration behavior byte-for-byte where applicable.
34+
- Keep the current script API and deployment layout.
35+
- The existing PR #843 is the target branch and should receive this cleanup as a follow-up commit.
36+
- Do not add or run tests; use static inspection and syntax parsing if needed.

0 commit comments

Comments
 (0)