Skip to content

AzLocal.UpdateManagement v0.8.6: Step.3 cycle-calendar enrichment + 6 v0.8.5 pipeline regression fixes#75

Merged
NeilBird merged 2 commits into
mainfrom
users/nebird/v0.8.6-step3-cycle-calendar-cols
Jun 10, 2026
Merged

AzLocal.UpdateManagement v0.8.6: Step.3 cycle-calendar enrichment + 6 v0.8.5 pipeline regression fixes#75
NeilBird merged 2 commits into
mainfrom
users/nebird/v0.8.6-step3-cycle-calendar-cols

Conversation

@NeilBird

Copy link
Copy Markdown
Owner

AzLocal.UpdateManagement v0.8.6

Step.3 cycle-calendar enrichment + six v0.8.5 thin-YAML pipeline regression fixes + 11 new Pester regression-guard tests. Same 55 public exports; no parameter changes on existing cmdlets.

NEW (Step.3 cycle calendar)

  • Get-AzLocalApplyUpdatesScheduleCycleCalendar gains two opt-in render-time columns:
    • -CronFiringsByDate ([hashtable], keys = yyyy-MM-dd UTC, values = [string[]] of HH:mm UTC firing times) → centered Ring CRON Start Time (UTC) (Step 6 pipeline) column between Date (UTC) and Day. 0 firings → _(none)_; 1-2 → comma-joined; 3+ → first 2 + " (+N)"; dead day → _(none - dead day)_.
    • -WindowMatchByRingAndDate ([hashtable[string,hashtable]]) → Tag Start Window Match (>=95%) column after Eligible rings. Per-ring line: `Ring`: True/False mat/tot (pct%).
  • Export-AzLocalApplyUpdatesScheduleAudit auto-wires both via Read-AzLocalApplyUpdatesYamlCrons + ConvertFrom-AzLocalUpdateWindow. Pure render-time contract preserved; failure mode is non-fatal (degrades to v0.8.5 calendar with Write-Warning).

FIX (v0.8.5 thin-YAML port regressions)

  • Step.0 Export-AzLocalAuthValidationReport: @() wrap on unary-comma Invoke-AzResourceGraphQuery collapsed visible-cluster count to 1. Switched to direct assignment + $clusterRows = @($clusterRows) variable-level coerce.
  • Step.3 Test-AzLocalApplyUpdatesScheduleCoverage: array-level .MatchingCrons enumeration crashed under strict mode on empty $segmentStatuses. Guarded with Count check.
  • Step.4 Get-AzLocalFleetConnectivityStatus: single-cluster RG crashed because if-as-expression silently unwrapped @() to scalar. Now $matchedList$matched = @($matchedList) at variable level.
  • Step.6 Get-AzLocalClusterUpdateReadiness: $cluster.NotFound strict-mode error — three builder paths missing the key, all now set NotFound=$false.
  • Step.9 Export-AzLocalFleetHealthStatusReport: @() wrap on both Get-AzLocalFleetHealthFailures and Get-AzLocalFleetHealthOverview collapsed row sets. Switched to direct assignment.
  • Step.2 Set-AzLocalClusterUpdateRingTag: Format-Table without | Out-Host leaked formatter wrapper objects into -PassThru pipeline (Total clusters processed = 44 on a 20-row CSV). Added | Out-Host + defence-in-depth ClusterName -is [string] filter in Set-AzLocalClusterUpdateRingTagFromCsv.
  • Step.2 UX: per-cluster Message now names changed tags (Tags updated: UpdateExcluded: 'False' -> 'True') instead of always "UpdateRing tag updated successfully". Summary split into 3 collapsible buckets (Tag Updates Applied / Skipped or Failed / No Tag Updates).
  • Node.js 20 deprecation: bumped actions/upload-artifact@v4@v6 in Step.0_authentication-test.yml (every other Step YAML already on v6).

TESTS (11 new regression-guard It blocks across 7 Describe blocks)

  • @() wrap on unary-comma return helpers (Invoke-AzResourceGraphQuery, Get-AzLocalFleetHealth{Failures,Overview}, Read-AzLocalApplyUpdatesYamlCrons).
  • Step.3 .MatchingCrons strict-mode crash; Step.4 $matched if/else { @() } branch; Step.6 NotFound key on every $clustersToProcess builder; Step.0 $clusterRows variable-level @() coerce; Step.2 Format-Table | Out-Host.
  • GHA Node.js 20 deprecation (artifact action versions across every bundled GHA YAML).
  • 12 new cycle-calendar It blocks for backwards compat / both-params header / (+N) suffix / 95% boundary / case-insensitivity / -ClusterRingCounts coexistence.

DRIFT

  • 20 bundled Step.{0..9}.yml templates bump GENERATED_AGAINST_MODULE_VERSION 0.8.50.8.6.
  • Pester $expectedVersion bumped to 0.8.6.

Local verification

  • Full Pester (excl. Live): 1102 passed / 0 failed / 1 skipped, ~8m45s.
  • Step.2 subset after Format-Table fix: 12/12 passed, 5.2s.
  • 3 Live-tagged Step.0 / Step.3 / Step.4 integration tests skipped here (env-only nebird@microsoft.com not visible to Azure AD Graph from workstation); CI also excludes the Live tag.

NeilBird added 2 commits June 10, 2026 18:35
… v0.8.5 pipeline regression fixes + 11 regression-guard tests

NEW (Step.3 cycle calendar)
- Get-AzLocalApplyUpdatesScheduleCycleCalendar: opt-in -CronFiringsByDate (per-day UTC CRON firing times) and -WindowMatchByRingAndDate (per-ring window-coverage >=95% indicator).
- Export-AzLocalApplyUpdatesScheduleAudit auto-wires both via Read-AzLocalApplyUpdatesYamlCrons + ConvertFrom-AzLocalUpdateWindow. Pure render-time contract preserved.

FIX (v0.8.5 thin-YAML port regressions)
- Step.0 Export-AzLocalAuthValidationReport: @() wrap on unary-comma Invoke-AzResourceGraphQuery collapsed cluster count to 1 - switched to direct assignment + variable-level @() coerce.
- Step.3 Test-AzLocalApplyUpdatesScheduleCoverage: array-level .MatchingCrons enumeration crashed under strict mode on empty $segmentStatuses - guarded with Count check.
- Step.4 Get-AzLocalFleetConnectivityStatus: single-cluster RG crashed because if-as-expression silently unwrapped @() to scalar - now $matchedList -> $matched = @($matchedList) at variable level.
- Step.6 Get-AzLocalClusterUpdateReadiness: $cluster.NotFound strict-mode error - 3 builder paths missing the key, all now set NotFound=$false.
- Step.9 Export-AzLocalFleetHealthStatusReport: @() wrap on both Get-AzLocalFleetHealthFailures and Get-AzLocalFleetHealthOverview collapsed row sets - switched to direct assignment.
- Step.2 Set-AzLocalClusterUpdateRingTag: Format-Table without | Out-Host leaked formatter wrapper objects into -PassThru pipeline (Total clusters processed = 44 vs 20 on a 20-row CSV). Added | Out-Host + defence-in-depth ClusterName -is [string] filter in Set-AzLocalClusterUpdateRingTagFromCsv.
- Step.2 per-cluster Message now names the changed tags ("Tags updated: UpdateExcluded: 'False' -> 'True'") instead of always "UpdateRing tag updated successfully".
- Step.2 summary table split into three independent collapsible buckets (Tag Updates Applied / Skipped or Failed / No Tag Updates).
- Node.js 20 deprecation: bumped actions/upload-artifact@v4 -> @v6 in Step.0 GHA YAML (other steps already on v6).

TESTS (11 new regression-guard It blocks across 7 Describe blocks)
- @() wrap on unary-comma return helpers (Invoke-AzResourceGraphQuery, Get-AzLocalFleetHealth{Failures,Overview}, Read-AzLocalApplyUpdatesYamlCrons).
- Step.3 .MatchingCrons strict-mode crash; Step.4 $matched if/else { @() } branch; Step.6 NotFound key on every $clustersToProcess builder; Step.0 $clusterRows variable-level @() coerce; Step.2 Format-Table | Out-Host.
- GitHub Actions Node.js 20 deprecation (artifact action versions across every bundled GHA YAML).
- 12 new cycle-calendar It blocks for backwards compat / both-params header / (+N) suffix / 95% boundary / case-insensitivity / -ClusterRingCounts coexistence.

DRIFT
- 20 bundled Step.{0..9}.yml templates bump GENERATED_AGAINST_MODULE_VERSION 0.8.5 -> 0.8.6.
- Pester $expectedVersion bumped to 0.8.6.
- Same 55 public exports; no parameter changes on existing cmdlets.
CI Pester 'Should have ReleaseNotes within the PSGallery character limit' caught this: previous block measured 10087 chars (over by 87). Collapsed the 7 verbose 'NEW Pester regression guards' sub-bullets into a single dense line listing the guard topics. Functionally identical disclosure; no source / test / behaviour changes.
@NeilBird
NeilBird merged commit 348c9c5 into main Jun 10, 2026
2 checks passed
@NeilBird
NeilBird deleted the users/nebird/v0.8.6-step3-cycle-calendar-cols branch June 10, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant