Skip to content

Latest commit

 

History

History
120 lines (91 loc) · 30.6 KB

File metadata and controls

120 lines (91 loc) · 30.6 KB

Pipeline release history (Appendix B)

What you will find here: A pipeline-focused history of every release that changed the bundled Step.*.yml templates, the Step.*_<job> job names, or the Update-AzLocalPipelineExample upgrade behaviour. For the module's full release history (cmdlet behaviour, KQL fixes, ARM dedup, ...), see ../../docs/release-history.md.


Appendix B: Release history

Latest version: the GENERATED_AGAINST_MODULE_VERSION env / pipeline variable in every bundled Step.*.yml template is bumped on each release; check that value (or the CHANGELOG.md) for the current pin. Releases after v0.7.70 are mechanical pipeline-pin bumps only (no template-shape changes) and are documented in the module CHANGELOG; the per-release entries below capture the last set of releases that materially changed the bundled YAMLs.

The body of this document tracks v0.7.70 behaviour. Older versions are preserved below for reference.

B.1 v0.7.70

Backward compatible. All v0.7.70 changes are additive over v0.7.69. The Step.0 validation pipeline (Step.0_authentication-test.yml) is repositioned from a one-shot smoke test to a recurring Authentication Validation and Subscription Scope Report; the existing inline-script structure is preserved underneath. Pipeline pin bumps to '0.7.70'; refresh existing copies with Update-AzLocalPipelineExample.

  • Step.0 repositioned as a recurring audit (Step.0_authentication-test.yml, GH + ADO). Renamed from "Authentication Validation Test" to "Step.0 - Authentication Validation and Subscription Scope Report". Now emits a JUnit XML report (Authentication / Subscription Scope / Resource Graph Reachability suites - one testcase per subscription accessible to the pipeline identity), a markdown summary with the subscription count + per-subscription detail table (rendered in the GitHub Checks UI via dorny/test-reporter@v3 and the ADO Tests + Summary tabs via PublishTestResults@2 + ##vso[task.uploadsummary]), and a auth-report artifact (XML + subscriptions.json + subscriptions.csv). Operator guidance updated: run the validation periodically (recommended monthly, or after any RBAC change in the tenant) instead of deleting the file after the first green run - drift in subscription scope is the earliest signal that downstream fleet reports are about to under- or over-count clusters.
  • New cmdlet Get-AzLocalFleetHealthOverview. ARG-first fleet health summary - one row per cluster, joining microsoft.azurestackhci/clusters with the cluster's updateSummaries extensibility resource via a single Azure Resource Graph batch read for fleet-scale performance. 12 columns including ClusterName, ClusterPortalUrl, HealthStatus, UpdateStatus, CurrentVersion, SbeVersion, AzureConnection, LastChecked, HealthResultsAgeDays. Supports -SubscriptionId, -UpdateRingTag (incl. wildcard *** + semicolon-list), -ExportPath, -PassThru.
  • Step.6 Fleet Update Status pipeline (Step.6_fleet-update-status.yml, GH + ADO) - new "Update Run History and Error Details" section. A new <testsuite name="Update Run History and Error Details"> in the JUnit XML and a matching ### Update Run History and Error Details markdown table in the run summary surface up to 25 of the most recent unresolved Failed update runs across the fleet (last 30 days). Each row links to the Azure portal SingleInstanceHistoryDetails deep-link and includes Status / CurrentStep / Duration / LastUpdated / DeepestErrMsg for at-a-glance triage. Sourced from Get-AzLocalUpdateRunFailures -State Failed -OnlyUnresolved (ARG-first, fleet-scale).
  • Step.7 Fleet Health Status pipeline (Step.7_fleet-health-status.yml, GH + ADO) - cluster portal hyperlinks + 3 new detailed columns + new Fleet Health Overview section. Summary and Detailed Results tables now render cluster cells as [ClusterName](portalUrl) markdown links. Detailed Results adds three columns: Failure Remediation (auto-renders as [link](url) when the value starts with https://), Target Resource Name, and Target Resource Type. A new ### Fleet Health Overview (fleet rollup) section calls Get-AzLocalFleetHealthOverview and publishes fleet-health-overview.csv / .json to the Reports list.
  • Test-AzLocalApplyUpdatesScheduleCoverage Audit rows now carry a Section discriminator (Schedule for ring-level rows, Cron for cron-coverage rows). Default sort is Schedule-section first, then cron coverage. -View Recommend emits a multi-section markdown report with "add these rings to apply-updates-schedule.yml" first, then the cron-paste section.
  • Get-AzLocalFleetHealthFailures Summary now sorts Critical-first (Severity then ClusterCount desc then FailureCount desc). Detail rows gain TargetResourceName, TargetResourceType, and ClusterPortalUrl. Summary rows gain AffectedClusterPortalUrls aligned 1:1 with AffectedClusters (semicolon-space separator).
  • New durable Live-Integration Pester suite (Tests/Live-Integration.Tests.ps1). 16 tests across 4 Describe blocks, all tagged Live and excluded from the default 565-test unit run. Asserts the v0.7.70 ARG-first projections (Get-AzLocalFleetHealthOverview, Get-AzLocalFleetHealthFailures, Get-AzLocalUpdateRunFailures) against a real Azure Local fleet. Each Describe auto-skips when az is not logged in or not pointed at the expected subscription, so the suite is safe to leave permanently in the repo. Opt-in via .\Tests\Invoke-Tests.ps1 -IncludeLive (unit + live) or -LiveOnly (live only). Validated end-to-end against the AdaptiveCloudLab 20-cluster fleet (49 unresolved health failures, 9 unresolved Failed update runs) in 1m26s.
  • Module version pin bumped to 0.7.70 in every production sample YAML. Run Update-AzLocalPipelineExample (preferred, marker-aware) or Copy-AzLocalPipelineExample -Update after upgrading.

B.2 v0.7.69

Hard break vs v0.7.68. Schema schemaVersion: 1 for apply-updates-schedule.yml is the first stable version of this file. If you were running an experimental schedule from earlier development builds, regenerate via New-AzLocalApplyUpdatesScheduleConfig.

  • Ring-aware apply-updates schedule (5 new cmdlets). Day-grain apply-updates-schedule.yml (schema v1) is now the single source of truth for which UpdateRing is eligible on a given UTC date. Three independent layers control "what runs when":
    1. This file (day-grain) says WHICH UpdateRing tag values are eligible TODAY.
    2. The Step.5 cron schedule (intra-day-grain) says HOW OFTEN the apply-updates job wakes up.
    3. The per-cluster UpdateWindow tag (minute-grain) says WHEN, during an eligible day, the actual update is allowed to start.
  • New cmdlets: Get-AzLocalApplyUpdatesScheduleConfig (parse + validate), Resolve-AzLocalApplyUpdatesScheduleRing (date -> ring with cycle-week math + union semantics on overlap), Get-AzLocalApplyUpdatesScheduleNextFirings (preview the next N days), New-AzLocalApplyUpdatesScheduleConfig (strawman generator from live fleet UpdateRing tags; every row emitted commented out by design so the apply-updates pipeline hard-stops at the reader until the operator reviews and uncomments at least one row), Update-AzLocalApplyUpdatesScheduleConfig (idempotent recipe-driven migrator; recipes table ships empty for v1).
  • Test-AzLocalApplyUpdatesScheduleCoverage gained -SchedulePath (two-way ring diff). Emits two new status rows: RingMissingFromSchedule (fleet ring with no schedule row) and RingOrphanedInSchedule (schedule ring no cluster carries). Surfaced in the summary table, the JUnit XML failure list, and the Step.3 Markdown summary.
  • Step.5_apply-updates.yml (GH + ADO) now resolves the UpdateRing value from apply-updates-schedule.yml on every scheduled firing. Manual workflow_dispatch (GH) / non-Schedule Build.Reason (ADO) runs still honour the operator-supplied -UpdateRingValue input verbatim, so back-compat for ad-hoc maintenance is preserved.
  • Concurrency on Step.5. GitHub Actions gained a workflow-level concurrency: block to prevent overlapping cron firings. Azure DevOps has no first-class YAML concurrency primitive; the ADO version documents the equivalent Pipeline Settings -> Triggers -> Limit concurrent runs option in a banner comment.
  • Step.3_apply-updates-schedule-audit.yml (GH + ADO) gained a schedule_path / schedulePath input (defaulted to the standard layout), a debug toggle for self-service triage ($VerbosePreference=Continue, $DebugPreference=Continue, plus a one-shot environment snapshot), and surfaces the new RingMissingFromSchedule / RingOrphanedInSchedule counts in the summary + JUnit failure list. When pipeline_path is empty and schedule_path is set, the audit runs schedule-file-only.
  • apply-updates-schedule.example.yml ships as documentation only. Copy-AzLocalPipelineExample / Update-AzLocalPipelineExample do not touch it. Operators run New-AzLocalApplyUpdatesScheduleConfig to generate a strawman starting from their live fleet's UpdateRing tag values.
  • Module version pin bumped to 0.7.69 in every production sample YAML. Run Update-AzLocalPipelineExample (preferred, marker-aware) or Copy-AzLocalPipelineExample -Update after upgrading.
  • Test suite: 540 passed / 0 failed / 0 skipped. 19 new tests cover reader, resolver, next-firings, generator, and update across the new ring-aware schedule cmdlets.

B.3 v0.7.68

  • ARG-first refactor of every fleet-scale read cmdlet. Seven cmdlets - Get-AzLocalUpdateSummary, Get-AzLocalAvailableUpdates, Get-AzLocalClusterUpdateReadiness, Test-AzLocalClusterHealth, Get-AzLocalFleetProgress, Get-AzLocalFleetStatusData, New-AzLocalFleetStatusHtmlReport - and the new Get-AzLocalUpdateRunFailures and the existing Get-AzLocalUpdateRuns are now backed by a single Azure Resource Graph batch query each. No more N-way per-cluster ARM calls, no more Start-Job fan-out on the read path, no more 6-hour-runner-window failure mode on 1000+ cluster fleets. Read pipelines on a 1500-cluster fleet that previously consumed the bulk of a runner window complete in seconds.
  • -ThrottleLimit removed from those nine cmdlets. The value was a silent no-op against an ARG batch read, so the parameter is now explicitly absent and any pipeline still passing it fails parameter binding loudly. All bundled pipeline YAMLs were updated to stop passing -ThrottleLimit. The apply-side cmdlet Start-AzLocalClusterUpdate retains its internal job-pool throttle (no operator-facing parameter). See Section 9 for the migration story.
  • New cmdlet Get-AzLocalUpdateRunFailures. ARG-only cmdlet that pulls failure rows out of microsoft.azurestackhci/clusters/updates/updateruns with a 9-deep mv-expand over the nested actions[] tree, returning a flat row per failed step with full breadcrumb path, error code, and operator-friendly message. Used by Step.5 Apply Updates post-mortem and ad-hoc triage. No equivalent ARM read path; this cmdlet is intentionally ARG-only.
  • Update-AzLocalPipelineExample - marker-aware in-place YAML upgrade. New cmdlet that refreshes a customer's copy of any bundled pipeline YAML to the version shipped with the current module while preserving operator edits inside BEGIN-AZLOCAL-CUSTOMIZE:<region> / END-AZLOCAL-CUSTOMIZE:<region> marker pairs. Customer-side cron schedules in schedule-triggers and ITSM secret bindings in itsm-secrets (Step.5 only) survive a module upgrade. Supports -WhatIf, -Force, and -PassThru. Recommended companion to Copy-AzLocalPipelineExample: copy on first install, update on every module bump.
  • Step.N - <description> display-name prefix on every bundled GitHub Actions workflow and Azure DevOps pipeline. Display ordering in the Actions / Pipelines UI now matches the runbook order in this README (Step.0 auth test, Step.1 inventory, Step.2 manage tags, Step.3 schedule audit, Step.4 readiness, Step.5 apply, Step.6 fleet status, Step.7 fleet health). See Section 1.1 for the rationale.
  • Latent single-element-array unwrap bug fixed in Get-AzLocalUpdateRuns and Get-AzLocalClusterUpdateReadiness. The per-cluster lookup pattern $x = if (ContainsKey) { @($list) } else { @() } silently unwrapped a single-element Object[] to its bare element under the if-block's pipeline return semantics on PowerShell 5.1, causing one-update-per-cluster results to be dropped. Replaced with assignment outside the if-block.
  • Invoke-AzResourceGraphQuery retries on 429. The shared helper behind every ARG-first cmdlet now inspects the Retry-After response header when present and otherwise applies bounded exponential backoff capped at the documented ARG throttling envelope. Large fleet sweeps no longer fall over at the throttling boundary.
  • Test suite: 511 passed / 0 failed / 0 skipped. Five previously-skipped Describes for the ARG-first read cmdlets were rewritten against the new code paths and now pass deterministically with InModuleScope + function global:az { ... } shim + Mock Invoke-AzResourceGraphQuery; the five rewritten Describes contribute 10 new tests. The v0.7.68 entry also adds +4 throttle-handling tests against Invoke-AzResourceGraphQuery (retry-then-succeed on 429, max-retries-exhausted, no-retry on non-throttle errors, diagnostic flags reset per call) and +3 Get-AzLocalFleetStatusData schema-contract tests (top-level shape + types, ValidateNotNullOrEmpty on -ClusterResourceIds, ModuleVersion field tracks the module-scope constant).
  • Module version pin bumped to 0.7.68 in every production sample YAML. Run Update-AzLocalPipelineExample (preferred) or Copy-AzLocalPipelineExample -Update after upgrading.

B.4 v0.7.66

  • Fixed (critical) - Get-AzLocalFleetHealthFailures failed JSON parsing on hosted Windows runners when the Azure CLI emitted a cp1252 encoding warning to stderr. On windows-latest GitHub Actions runners (and any ADO Windows agent whose console code page is cp1252) the Azure CLI's underlying Python layer can surface WARNING: Unable to encode the output with cp1252 encoding. Unsupported characters are discarded. to stderr; the shared Invoke-AzResourceGraphQuery helper was capturing 2>&1 into a single merged stream and feeding it to ConvertFrom-Json, which then threw Unexpected character encountered while parsing value: W. Path '', line 0, position 0. The actual fix is the post-capture stream split: stderr lines surface as [System.Management.Automation.ErrorRecord] objects under 2>&1, stdout lines as strings, and only the string stream is fed to ConvertFrom-Json. (The helper already passed --only-show-errors since v0.7.2, matching the existing Invoke-AzRestJson hardening, but the cp1252 encode warning can still leak through on some character paths, hence the belt-and-braces split.) The helper also sets PYTHONIOENCODING=utf-8 as cosmetic defence-in-depth only - this is a structural no-op for stock az.cmd because az.cmd launches Python with -I (isolated) which implies -E and forces Python to ignore every PYTHON* env var per Azure/azure-cli#28497 and the v0.7.2 root-cause analysis; it only takes effect on hosts that have manually patched az.cmd to remove -I.
  • Fixed (critical) - Step.3_apply-updates-schedule-audit.yml default pipeline_path only existed in this module's source repo. The shipped default was AzLocal.UpdateManagement/Automation-Pipeline-Examples (i.e. the in-source path for this repo); every default-trigger run in a consumer repo therefore failed with PipelineYamlPath '...' does not exist on the runner before the schedule advisor could emit its JUnit XML, which then crashed dorny/test-reporter with No test report files were found. Defaults are now '.github/workflows' on GH Actions and '.azure-pipelines' on Azure DevOps - the standard consumer locations - and the path-missing error message now lists which common pipeline folders do exist in the checked-out repo so the operator knows what value to pass via workflow_dispatch / queue-time override.
  • Module version pin bumped to 0.7.66 in every production sample YAML that installs the module from PowerShell Gallery (14 across GitHub Actions and Azure DevOps; the two Step.0 validation YAMLs do not install the module and so are not version-pinned). Run Copy-AzLocalPipelineExample -Update after upgrading to refresh the samples in your repo.

v0.7.66 UX + capability refresh

  • Status emojis in the Fleet Update Status summary. Step.6_fleet-update-status.yml on both platforms now uses a green tick / red cross / refresh / yellow circle / info glyph in the Critical Health and Primary Status summary tables instead of the legacy [ok] / [fail] / [ready] / [running] / [blocked] / [info] bracket markers. Plain markdown, so it renders identically on the GH Actions step summary, the ADO pipeline run extension, and any markdown viewer.

  • Generation timestamp in the Fleet Update Status H2 heading. The summary heading on both platforms is now ## Fleet Update Status Summary _(generated YYYY-MM-DD HH:MM:SS UTC)_. Operators no longer have to cross-reference the pipeline run start time to know when the data was collected.

  • Failed clusters appear before passing clusters in the JUnit per-cluster block. The per-cluster <testcase> ordering in Step.6_fleet-update-status.yml (both platforms) is now bucketed: failed first (sorted alphabetically), then passed (sorted alphabetically). Failing clusters lead the dorny/test-reporter view (GitHub) and the Tests tab (Azure DevOps).

  • Every downloadable artifact carries a UTC timestamp suffix. All actions/upload-artifact (GH) and PublishBuildArtifacts@1 / PublishPipelineArtifact@1 (ADO) names now follow azlocal-<purpose>_yyyyMMdd_HHmmss. Two runs of the same pipeline on the same day produce distinct zip downloads (azlocal-fleet-update-status-report_20260518_140000.zip vs azlocal-fleet-update-status-report_20260518_180000.zip). Each job computes the timestamp once in a dedicated Compute Artifact Timestamp step. Affected artifact renames: fleet-status-reports -> azlocal-fleet-update-status-report; fleet-health-reports -> azlocal-fleet-health-status-report; cluster-inventory -> azlocal-cluster-inventory; updatering-tag-logs -> azlocal-updatering-tag-logs; schedule-coverage-reports / ScheduleCoverageReports -> azlocal-apply-updates-schedule-audit-report; readiness-report -> azlocal-apply-updates-readiness-report; readiness-assessment -> azlocal-readiness-assessment-report; update-logs -> azlocal-apply-updates-logs; itsm-results -> azlocal-apply-updates-itsm-results.

  • Pipeline UpdateRing inputs accept multi-value lists and the literal *** wildcard. Every pipeline that exposes update_ring: (GH workflow_dispatch) or updateRing: (ADO parameters:) now accepts:

    • A single ring (unchanged): Wave1
    • A semicolon-delimited list: Prod;Ring2 (whitespace around each ring is trimmed)
    • The wildcard *** (three stars, deliberate gesture) to match every cluster that has a non-empty UpdateRing tag. Untagged clusters are excluded so the wildcard preserves the existing opt-in gate. A single *, double **, or quadruple **** are all REJECTED by the cmdlet's [ValidatePattern] so a one-character typo can no longer accidentally scope a fleet-wide write.

    The ADO Step.5_apply-updates.yml lost its closed values: enum (kept type: string so users still get a free-text editor in the ADO run dialog). The cmdlet-side [ValidatePattern] is tightened to ^(\*\*\*|[A-Za-z0-9_-]{1,64}(;[A-Za-z0-9_-]{1,64})*)$ on 14 cmdlets that take -UpdateRingValue and on the 1 cmdlet (Get-AzLocalFleetHealthFailures) that takes -UpdateRingTag. Hostile/malformed inputs (spaces, embedded quotes, <script>, leading/trailing ;) are still rejected at the parameter binder before any Azure call.

  • New private helper ConvertTo-AzLocalUpdateRingKqlFilter. Centralises the KQL clause construction for the three forms above. Returns | where isnotempty(tags['UpdateRing']) for *** (matches only tagged clusters), a | where tags['UpdateRing'] =~ 'single' clause for a single value, and a | where tags['UpdateRing'] in~ ('a','b') clause for a list. Embedded single quotes are doubled (KQL string-literal escape). All 12 ARG-query call sites in the public cmdlets now go through this helper.

B.5 v0.7.65

  • Test-AzLocalApplyUpdatesScheduleCoverage cmdlet + apply-updates-schedule-audit pipelines (GitHub Actions + Azure DevOps). Read-only weekly audit (Mon 05:00 UTC + manual) that compares the cron schedule(s) in your apply-updates pipeline to the UpdateRing / UpdateWindow tags actually present on your clusters and flags any pair that no cron will ever reach. Three views (Audit, Matrix, Recommend), per-segment cron generation for multi-window tags (Sat-Sun_02:00-06:00;Mon-Fri_22:00-04:00) and day ranges (Fri-Mon), configurable -LeadTimeMinutes (0-60, default 5). Each pipeline run emits JUnit XML (one <testcase> per (Ring, Window)), three CSV/MD exports (schedule-coverage-audit.csv, schedule-coverage-matrix.csv, schedule-coverage-recommend.md), and a Markdown step summary. Full step-by-step runbook in Section 8.3; reference card in Appendix A.7.
  • Get-AzLocalFleetHealthFailures cmdlet + fleet-health-status pipelines (GitHub Actions + Azure DevOps). Dedicated entry point for surfacing the in-flight 24-hour system health-check failures across every readable cluster - independent of update activity (clusters that are already "up to date" can still surface Critical / Warning issues that need triage). Daily 07:00 UTC schedule (offset from fleet-update-status at 06:00). JUnit XML grouped under Critical Health Failures / Warning Health Failures testsuites + per-failure-reason and per-cluster CSV exports + Markdown step summary pivoted by FailureReason. Reference card in Appendix A.6.
  • Set-AzLocalClusterUpdateRingTag now uses the dedicated Microsoft.Resources/tags/default PATCH endpoint instead of PATCH-ing the cluster resource. CI/CD service principals scoped to the built-in Tag Contributor role on the cluster (or resource group) can now write UpdateRing / UpdateWindow / UpdateExclusions tags without needing microsoft.azurestackhci/clusters/write. If you scoped your tag-management SP to "Contributor" purely as a workaround, you can safely drop it back to Tag Contributor. The custom-role guidance in Section 4.1 and the per-step RBAC bullets in Section 6.3 and Appendix A.2 have been updated accordingly.
  • Pester guardrail prevents pipeline-YAML version drift. A new Pester context discovers every *.yml file under Automation-Pipeline-Examples/ that installs the module from PSGallery and asserts that the GENERATED_AGAINST_MODULE_VERSION constant in each YAML matches the module manifest version. Supports both the inline GitHub Actions shape and the two-line Azure DevOps shape. Build fails if a sample YAML is forgotten when the manifest is bumped.
  • Fleet Update Status summary now reconciles with the JUnit pass/fail counts. Two bug fixes ensure the summary table always adds up to Total Clusters: Up to Date now counts both UpToDate and AppliedSuccessfully states; each cluster is assigned to exactly one primary status via a priority cascade (Update Failed -> Health Failure -> SBE Prerequisite Blocked -> Update In Progress -> Ready for Update -> Up to Date -> Needs Investigation).
  • JUnit / step-summary ordering changed in both Step.6_fleet-update-status.yml and Step.7_fleet-health-status.yml (both platforms): Summary block FIRST, JUnit Test Results SECOND, so the run-extensions / job-summary view leads with the operator-facing numbers.
  • Module version pin bumped to 0.7.65 in all 13 sample workflow YAMLs (11 pre-existing + the two new Step.3_apply-updates-schedule-audit.yml files). Run Copy-AzLocalPipelineExample -Update after upgrading to refresh the samples in your repo.

B.5 v0.7.4

  • ITSM Connector - Phase 1 (ServiceNow). Apply Updates can now open ServiceNow incidents for clusters that need operator action (Failed, Error, HealthCheckBlocked, SideloadedBlocked) via the new New-AzLocalIncident function, with idempotent SHA256 dedupe so re-running the same workflow does not create duplicates. Fully opt-in - pipelines that do not set raise_itsm_ticket=true are byte-identical to v0.7.3 behaviour. Sample config + Mustache ticket-body template ship at ./.itsm/. Setup, secret sourcing, and troubleshooting documented in ../ITSM/README.md; design + decisions log in ../ITSM/ITSM-Connector-Plan.md.
  • OAuth 2.0 client_credentials only in Phase 1. Secrets resolve from Azure Key Vault (kv://<vault>/<secret>, recommended), environment variables (env://NAME, native-secret fallback), or explicit literal://... values guarded by -AllowLiteral. The pipeline service principal needs Key Vault Secrets User on the configured vault; no other new RBAC.
  • DryRun mode (-DryRun on New-AzLocalIncident, or pipeline input itsm_dry_run=true) resolves secrets, runs the read-only dedupe lookup, builds the full ticket payload, but does not POST. Output CSV + JUnit projection let you validate the trigger matrix and template rendering before pointing at production ServiceNow.
  • Test-AzLocalItsmConnection runs the OAuth token grant and a one-row read against /api/now/table/incident, matching the least-privilege scope used by ticket creation. Run it manually before flipping raise_itsm_ticket=true.
  • New JUnit projection (-ExportJUnitPath on New-AzLocalIncident) emits per-cluster ITSM actions as a JUnit XML artefact - CreateFailed -> <failure>, Skipped / WhatIf -> <skipped>, default -> success. Consumed by dorny/test-reporter / PublishTestResults@2 so ITSM activity is visible in the Tests tab.
  • Phase 2 (Sync-AzLocalIncident close-out) and Phase 3 (Teams + Slack mirror) are designed in ITSM-Connector-Plan.md and deferred to a future release. The lifecycle and notifications sections of the config schema are parsed and stored but not yet acted on.

B.6 v0.7.2

  • Fleet read paths now work as documented under -ThrottleLimit > 1. The Step.6_fleet-update-status.yml workflow (and any direct caller of Get-AzLocalUpdateRuns, Get-AzLocalUpdateSummary, or Get-AzLocalClusterUpdateReadiness with -ThrottleLimit greater than 1) previously failed for every cluster with The term 'Get-AzLocalClusterUpdateRuns' is not recognized... because module-private helpers were not visible inside Start-Job child runspaces. Resolved via & $module { ... } dispatch through the loaded module's session state. Action: re-enable -ThrottleLimit in your fleet workflows.
  • Stray cp1252 warnings no longer break JSON parsing on hosted Windows runners. Default windows-latest GitHub runners and Azure DevOps windows-2022 agents both run with the cp1252 console code page; the Azure CLI emitted WARNING: Unable to encode the output with cp1252 encoding... on any ARM response containing non-ASCII characters. Captured via 2>&1, that warning was prepended to the JSON body and silently broke ConvertFrom-Json, dropping update runs and available updates from pipeline reports. v0.7.2 passes --only-show-errors to every az rest and az graph query invocation. No pipeline configuration change required - upgrade and the runs/summaries are simply complete again.
  • Full root-cause writeup: main README v0.7.2 entry.

B.7 v0.7.1

  • Sideloaded payload workflow. Two new tags coordinate human-driven sideloaded update payloads with the apply-updates pipeline:
    • UpdateSideloaded (operator-set, True/False/1/0) gates Start-AzLocalClusterUpdate. When False, the apply-updates pipeline skips the cluster with Status = SideloadedBlocked.
    • UpdateVersionInProgress (module-managed; do not set manually) holds the staged update name. Get-AzLocalUpdateRuns auto-resets UpdateSideloaded -> False and clears UpdateVersionInProgress when the latest run is Succeeded and its update name matches. Use -SkipSideloadedReset on read-only paths.
  • New public function Reset-AzLocalSideloadedTag for explicit-scope manual reset. Three parameter sets: -ClusterNames, -ClusterResourceIds, or -ScopeByUpdateRingTag -UpdateRingValue. Supports -WhatIf/-Confirm. Default behaviour requires latest run = Succeeded and a case-insensitive update-name match against UpdateVersionInProgress. -Force bypasses the version-match check (still requires Succeeded state). Returns one row per cluster with Action / PreviousSideloaded / NewSideloaded / StagedVersion / MatchedRunUpdateName / Message.
  • No new RBAC - the existing Microsoft.Resources/tags/read|write permissions cover it.
  • Fully opt-in - clusters without the UpdateSideloaded tag behave exactly as in v0.7.0.
  • Full runbook: main README sideloaded workflow section.

B.8 v0.7.0

  • Parallel per-cluster operations. Get-AzLocalClusterUpdateReadiness, Test-AzLocalClusterHealth, Get-AzLocalUpdateSummary, Get-AzLocalAvailableUpdates, Get-AzLocalUpdateRuns, and Set-AzLocalClusterUpdateRingTag now run per-cluster ARM calls in parallel Start-Job batches. Invoke-AzLocalFleetOperation -ThrottleLimit is honoured end-to-end. Expected 5-10x speedup on 1500-cluster runs.
  • -ThrottleLimit is a workflow input on Apply Updates and Fleet Update Status (default 4, range 1-16).
  • ARG queries paginate. All scope-resolving queries follow the $skipToken until exhausted (previously capped silently at 1000).
  • -AllClusters cap removed. New-AzLocalFleetStatusHtmlReport -AllClusters and Get-AzLocalFleetStatusData -AllClusters no longer truncate at 100; use -MaxClusters <n> to trim explicitly.
  • CSV sanitisation. Every CSV field is protected against Excel formula injection (=, +, -, @, tab leaders neutralised, CR/LF stripped).
  • Token refresh mid-run. Invoke-AzRestJson refreshes on HTTP 401 so long-running apply jobs no longer die at the 1-hour token boundary.
  • Schedule-tag parse errors are blocking by default unless -Force. A malformed UpdateWindow / UpdateExclusions no longer lets the update sneak through with just a warning.