Skip to content

Commit a2b5e2f

Browse files
authored
AzLocal.UpdateManagement v0.8.78: pipeline-summary UX polish (JUnit reclassification, Up-to-Date surfacing, download-artifact@v7) (#84)
* AzLocal.UpdateManagement v0.8.78: pipeline-summary UX polish Three improvements driven by operator feedback on Step.07: 1. JUnit reclassification - ScheduleBlocked / SideloadedBlocked / ExcludedByTag are designed gate-respect outcomes, not failures. Export-ResultsToJUnitXml now renders them as <skipped> instead of <failure>, so dorny/test-reporter no longer flips Step.07 RED on otherwise-successful schedule-aware / sideload-gated / tag-excluded runs. HealthCheckBlocked stays a failure (real operational issue). 2. Apply Updates summary shows the FULL ring picture - new optional -UpToDateCount / -NotReadyCount parameters on Add-AzLocalApplyUpdatesStepSummary add 'Already Up to Date' and 'Not Ready (needs attention before updating)' rows to the Readiness KPI table. Both apply-updates YAMLs (GHA + ADO) wire the upstream readiness.UpToDateCount / readiness.NotReadyCount outputs (emitted since v0.8.74) through to the summary task. 3. actions/download-artifact@v6 -> @v7 in GHA apply-updates.yml. Silences Node.js 20 deprecation warning. v7 deliberately chosen over v8 (v8 has breaking digest-mismatch=error default). Readiness gate verified ROBUST against operator question 'do we show Ready clusters that have a previously-failed in-progress run?' - the answer is no. Get-AzLocalClusterUpdateReadiness and Start-AzLocalClusterUpdate (Step 3) both predicate Ready on updateSummary.properties.state -in @('UpdateAvailable','Ready', 'ReadyToInstall'). NeedsAttention / UpdateInProgress / UpdateFailed / PreparationFailed clusters correctly land in Not-Ready (no code change needed). Tests: - Updated 'JUnit XML export handles ScheduleBlocked' / 'SideloadedBlocked' to assert <skipped> not <failure> + matching summary attrs (failures=0, skipped=1). - New 'Export-ResultsToJUnitXml renders ExcludedByTag as <skipped>' regression. - New 'Has v0.8.78 optional readiness-breakdown parameters UpToDateCount/NotReadyCount' on Add-AzLocalApplyUpdatesStepSummary. No public API change or new exports (still 60). All bundled pipeline templates bump GENERATED_AGAINST_MODULE_VERSION '0.8.77' -> '0.8.78'. * v0.8.78: bump module-version assertion 0.8.77 -> 0.8.78 + test-timings * v0.8.78: in-package doc refresh (Pipeline-Examples README + appendix-pipelines)
1 parent e6e2363 commit a2b5e2f

33 files changed

Lines changed: 268 additions & 67 deletions

AzLocal.UpdateManagement/Automation-Pipeline-Examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ By the end of this guide you will have:
6464
- **Fleet Connectivity Status** (Step.4, v0.7.79+, enhanced in v0.7.85) - read-only daily snapshot of Arc agent connectivity, physical NIC health, Azure Resource Bridge status, and the node-count reconciliation between cluster `reportedProperties.nodes` and Arc-tagged physical machines. *Scheduled daily 05:30 UTC + manual.*
6565
- **Assess Update Readiness** (Step.5) - pre-flight, report-only readiness + blocking-health snapshot, published as JUnit XML. *Manual only.*
6666
- **Sideload Updates** (Step.6, v0.8.7) - **opt-in, off by default, on-prem self-hosted runner/agent required.** Pre-stages solution-update media onto clusters that cannot pull updates from Azure directly (dark / air-gapped fabrics): Robocopy to the cluster import share, remote SHA256 verify, `Add-SolutionUpdate` import, then flip `UpdateSideloaded=True` for the downstream Step.7 apply. Re-entrant state machine driven by a frequent CRON; the multi-hour copy runs in a detached Scheduled Task. *Inert unless `SIDELOAD_UPDATES=true`. See [sideload.md](docs/sideload.md) and [sideload-robocopy.md](docs/sideload-robocopy.md).*
67-
- **Apply Updates** (Step.7) - apply updates to a single `UpdateRing` wave at a time, with WhatIf / dry-run support. *Manual only by default - **you must add a schedule** that lines up with your cluster `UpdateStartWindow` tags, see [Step 7 - Apply Updates](docs/appendix-pipelines.md#step-7---apply-updates) and [section 8](#8-scheduling-maintenance-windows-and-change-freeze-periods).*
67+
- **Apply Updates** (Step.7; **v0.8.78 step-summary UX polish**: ``ScheduleBlocked`` / ``SideloadedBlocked`` / ``ExcludedByTag`` outcomes render as JUnit ``<skipped>`` instead of ``<failure>`` so ``dorny/test-reporter`` no longer flips Step.07 RED on by-design gate-respect outcomes - ``HealthCheckBlocked`` deliberately stays a ``<failure>``; the Readiness KPI table now also surfaces **Already Up to Date** and **Not Ready (needs attention before updating)** rows so operators see the full ring breakdown - eligible, started, skipped, blocked, up-to-date, needs-attention - in one place; GHA-only: ``actions/download-artifact@v6 -> @v7`` silences the Node 20 deprecation warning) - apply updates to a single `UpdateRing` wave at a time, with WhatIf / dry-run support. *Manual only by default - **you must add a schedule** that lines up with your cluster `UpdateStartWindow` tags, see [Step 7 - Apply Updates](docs/appendix-pipelines.md#step-7---apply-updates) and [section 8](#8-scheduling-maintenance-windows-and-change-freeze-periods).*
6868
- **Monitor In-Flight Updates** (Step.8, v0.7.90; v0.7.96 surfaces `Status` + deepest `ErrorMessage` columns, adds the `StepError` stuck-step JUnit type for runs that have hit an error inside a step without crossing the long-running threshold, and renders portal-linked Cluster Name / Update Name cells in the markdown summary; **v0.7.98 UX overhaul**: composite `SeverityScore` sort, per-cell `StateIcon` + `StatusIcon`, horizontal chip stack (`STEP-STUCK` / `RUN-STUCK` / `UNRESOLVED` / `RECENT-FAIL`), `CRITICAL / WARN / OK` fleet status badge at the top of the job summary, collapsible `<details>` Verbose Error block per row, and JUnit `<testsuite time="..">` + `<testcase time="..">` populated with real run elapsed seconds). Operational snapshot during an active wave: lists each cluster whose latest update run is `InProgress`, with current step, progress (`completed/total steps`), elapsed duration, the `Status` column (`Success`/`Error`/`InProgress`/...), and the deepest `errorMessage` walked out of the nested ARM `steps[]` tree; flags long-running runs (default >6h) AND step-errored stuck runs as JUnit failures in the Checks tab. *Scheduled 5x/day at 20:00, 22:00, 00:00, 02:00, 04:00 UTC (every 2h across the typical overnight maintenance window) + manual; default cadence is editable in `monitor-updates.yml` (v0.7.92+).*
6969
- **Fleet Update Status** (Step.9, formerly Step.8; v0.7.96 promotes `NeedsAttention` into the **Update Failed** bucket, adds a new **Action Required** bucket for `PreparationFailed`, and folds `PreparationInProgress` into **Update In Progress**; **v0.7.98** populates JUnit `time=` on each `<testcase>` in the `📜 Update Run History and Error Details` testsuite using `DurationMinutes * 60`). Scheduled daily snapshot of fleet update state, surfaced in the Tests tab. Markdown summary's `📜 Update Run History and Error Details` table now also carries portal-linked Cluster Name / Update Name cells plus the deepest-step `ErrorMessage`. *Scheduled daily 06:00 UTC + manual.*
7070
- **Fleet Health Status** (Step.10, formerly Step.9) - scheduled daily snapshot of 24-hour system health-check failures, surfaced in the Tests tab. *Scheduled daily 07:00 UTC + manual.*

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/apply-updates-schedule-audit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ parameters:
8787
default: false
8888

8989
variables:
90-
GENERATED_AGAINST_MODULE_VERSION: '0.8.77'
90+
GENERATED_AGAINST_MODULE_VERSION: '0.8.78'
9191
REQUIRED_MODULE_VERSION: '${{ parameters.moduleVersion }}'
9292
reportsPath: '$(Build.ArtifactStagingDirectory)/reports'
9393
# v0.8.7 sideload advisor defaults. Override at the pipeline / variable-group

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/apply-updates.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ variables:
120120
# log if the YAML appears stale - prompting you to refresh via
121121
# Copy-AzLocalPipelineExample -Update. See Automation-Pipeline-Examples/README.md section 5.
122122
- name: GENERATED_AGAINST_MODULE_VERSION
123-
value: '0.8.77'
123+
value: '0.8.78'
124124
# Resolution order for the module version pin (leave all unset to install the latest,
125125
# which is the default "fix-forward" behaviour): queue-time parameter > pipeline variable
126126
# 'REQUIRED_MODULE_VERSION' overridden at queue time > empty (latest).
@@ -276,6 +276,14 @@ stages:
276276
variables:
277277
readyCount: $[ stageDependencies.CheckReadiness.ReadinessCheck.outputs['readiness.ReadyCount'] ]
278278
totalCount: $[ stageDependencies.CheckReadiness.ReadinessCheck.outputs['readiness.TotalCount'] ]
279+
# v0.8.78: surface the readiness gate's Up-to-Date / Not-Ready breakdown
280+
# in the apply-updates summary so the operator sees the FULL ring picture
281+
# (not just the clusters that entered Apply Updates). Up-to-Date is a
282+
# healthy steady state; Not-Ready includes clusters held back by a
283+
# previously-failed run (state=NeedsAttention / UpdateFailed), an
284+
# in-progress run, pending SBE prerequisites or a critical health failure.
285+
upToDateCount: $[ stageDependencies.CheckReadiness.ReadinessCheck.outputs['readiness.UpToDateCount'] ]
286+
notReadyCount: $[ stageDependencies.CheckReadiness.ReadinessCheck.outputs['readiness.NotReadyCount'] ]
279287
# pull the upstream artifact-stamp through so the download step
280288
# can reconstruct the timestamped artifact name produced by CheckReadiness.
281289
readinessArtifactStamp: $[ stageDependencies.CheckReadiness.ReadinessCheck.outputs['stamp.artifactStamp'] ]
@@ -486,6 +494,11 @@ stages:
486494
UpdateRing = $env:RESOLVED_UPDATE_RING
487495
TotalCount = "$(totalCount)"
488496
ReadyCount = "$(readyCount)"
497+
# v0.8.78: pass the readiness gate's Up-to-Date / Not-Ready breakdown
498+
# so the Readiness KPI surfaces the FULL ring picture, not just the
499+
# clusters that entered Apply Updates.
500+
UpToDateCount = "$(upToDateCount)"
501+
NotReadyCount = "$(notReadyCount)"
489502
Succeeded = "$(applyUpdates.Succeeded)"
490503
Skipped = "$(applyUpdates.Skipped)"
491504
Failed = "$(applyUpdates.Failed)"

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/assess-update-readiness.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ variables:
7070
# the version actually installed and to the latest on PSGallery, and emits a warning
7171
# log if the YAML appears stale - prompting you to refresh via
7272
# Copy-AzLocalPipelineExample -Update. See Automation-Pipeline-Examples/README.md section 5.
73-
GENERATED_AGAINST_MODULE_VERSION: '0.8.77'
73+
GENERATED_AGAINST_MODULE_VERSION: '0.8.78'
7474
# Resolution order for the module version pin (leave all unset to install the latest,
7575
# which is the default "fix-forward" behaviour): queue-time parameter > pipeline variable
7676
# 'REQUIRED_MODULE_VERSION' overridden at queue time > empty (latest).

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/authentication-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ variables:
6060
# log if the YAML appears stale - prompting you to refresh via
6161
# Copy-AzLocalPipelineExample -Update. See Automation-Pipeline-Examples/README.md section 5.
6262
- name: GENERATED_AGAINST_MODULE_VERSION
63-
value: '0.8.77'
63+
value: '0.8.78'
6464
# Resolution order for the module version pin (leave all unset to install the latest,
6565
# which is the default "fix-forward" behaviour): queue-time parameter > pipeline variable
6666
# 'REQUIRED_MODULE_VERSION' overridden at queue time > empty (latest).

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/fleet-connectivity-status.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ variables:
110110
# the version actually installed and to the latest on PSGallery, and emits a warning
111111
# log if the YAML appears stale - prompting you to refresh via
112112
# Copy-AzLocalPipelineExample -Update. See Automation-Pipeline-Examples/README.md section 5.
113-
GENERATED_AGAINST_MODULE_VERSION: '0.8.77'
113+
GENERATED_AGAINST_MODULE_VERSION: '0.8.78'
114114
# Resolution order for the module version pin (leave all unset to install the latest,
115115
# which is the default "fix-forward" behaviour): queue-time parameter > pipeline variable
116116
# 'REQUIRED_MODULE_VERSION' overridden at queue time > empty (latest).

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/fleet-health-status.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ variables:
105105
# the version actually installed and to the latest on PSGallery, and emits a warning
106106
# log if the YAML appears stale - prompting you to refresh via
107107
# Copy-AzLocalPipelineExample -Update. See Automation-Pipeline-Examples/README.md section 5.
108-
GENERATED_AGAINST_MODULE_VERSION: '0.8.77'
108+
GENERATED_AGAINST_MODULE_VERSION: '0.8.78'
109109
# Resolution order for the module version pin (leave all unset to install the latest,
110110
# which is the default "fix-forward" behaviour): queue-time parameter > pipeline variable
111111
# 'REQUIRED_MODULE_VERSION' overridden at queue time > empty (latest).

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/fleet-update-status.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ variables:
9393
# the version actually installed and to the latest on PSGallery, and emits a warning
9494
# log if the YAML appears stale - prompting you to refresh via
9595
# Copy-AzLocalPipelineExample -Update. See Automation-Pipeline-Examples/README.md section 5.
96-
GENERATED_AGAINST_MODULE_VERSION: '0.8.77'
96+
GENERATED_AGAINST_MODULE_VERSION: '0.8.78'
9797
# Resolution order for the module version pin (leave all unset to install the latest,
9898
# which is the default "fix-forward" behaviour): queue-time parameter > pipeline variable
9999
# 'REQUIRED_MODULE_VERSION' overridden at queue time > empty (latest).

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/inventory-clusters.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ variables:
4343
# log if the YAML appears stale - prompting you to refresh via
4444
# Copy-AzLocalPipelineExample -Update. See Automation-Pipeline-Examples/README.md section 5.
4545
- name: GENERATED_AGAINST_MODULE_VERSION
46-
value: '0.8.77'
46+
value: '0.8.78'
4747
# Resolution order for the module version pin (leave all unset to install the latest,
4848
# which is the default "fix-forward" behaviour): queue-time parameter > pipeline variable
4949
# 'REQUIRED_MODULE_VERSION' overridden at queue time > empty (latest).

AzLocal.UpdateManagement/Automation-Pipeline-Examples/azure-devops/manage-updatering-tags.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ variables:
4646
# log if the YAML appears stale - prompting you to refresh via
4747
# Copy-AzLocalPipelineExample -Update. See Automation-Pipeline-Examples/README.md section 5.
4848
- name: GENERATED_AGAINST_MODULE_VERSION
49-
value: '0.8.77'
49+
value: '0.8.78'
5050
# Resolution order for the module version pin (leave all unset to install the latest,
5151
# which is the default "fix-forward" behaviour): queue-time parameter > pipeline variable
5252
# 'REQUIRED_MODULE_VERSION' overridden at queue time > empty (latest).

0 commit comments

Comments
 (0)