Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
188bb50
Publish v0.8.4
NeilBird Jun 9, 2026
ed638aa
v0.8.4 follow-up: correct ADO Step.6 banner count + allow migration-t…
NeilBird Jun 9, 2026
8d46fe5
Merge remote-tracking branch 'origin/main' into users/nebird/development
NeilBird Jun 9, 2026
01de887
Add CRON for Step 6 - Apply Updates
NeilBird Jun 9, 2026
c11816e
v0.8.5: thin-YAML foundation cmdlet Add-AzLocalPipelineVersionBanner
NeilBird Jun 10, 2026
c5d3327
v0.8.5: Step.6 manual schedule-file inputs (use_schedule_file + resol…
NeilBird Jun 10, 2026
2603bb2
v0.8.5 docs: CHANGELOG + README What's New entry
NeilBird Jun 10, 2026
c0b0a84
v0.8.5 Step.0 thin-YAML port: Export-AzLocalAuthValidationReport + sh…
NeilBird Jun 10, 2026
043ff19
v0.8.5 Step.1 thin-YAML port: Add Invoke-AzLocalClusterInventory
NeilBird Jun 10, 2026
68480ff
v0.8.5 Step.2 thin-YAML port: Add Set-AzLocalClusterUpdateRingTagFromCsv
NeilBird Jun 10, 2026
d8c019f
v0.8.5 Step.7 thin-YAML port: Add Export-AzLocalUpdateRunMonitorReport
NeilBird Jun 10, 2026
e3649c9
v0.8.5 Step.8 thin-YAML: Export-AzLocalFleetUpdateStatusReport
NeilBird Jun 10, 2026
347f377
v0.8.5 Step.5 thin-YAML: Export-AzLocalClusterUpdateReadinessReport
NeilBird Jun 10, 2026
b14832a
v0.8.5 Step.4 thin-YAML: Export-AzLocalFleetConnectivityStatusReport
NeilBird Jun 10, 2026
40b0d3d
v0.8.5 Step.3 thin-YAML: Export-AzLocalApplyUpdatesScheduleAudit
NeilBird Jun 10, 2026
b879292
v0.8.5 Step.7 test: lock in target=_blank on In-flight runs links
NeilBird Jun 10, 2026
f1fe26a
v0.8.5 Step.9 thin-YAML: Export-AzLocalFleetHealthStatusReport
NeilBird Jun 10, 2026
3ee1650
v0.8.5 Step.6 thin-YAML: apply-updates pipeline refactor
NeilBird Jun 10, 2026
98d177f
v0.8.5 docs: CHANGELOG + README updated for thin-YAML refactor
NeilBird Jun 10, 2026
d060fd5
ci: add GitHub Actions Pester workflow for AzLocal.UpdateManagement
NeilBird Jun 10, 2026
1989473
ci: fix Windows-runner test failures + switch test reporter
NeilBird Jun 10, 2026
cc7d4ed
ci+tests: fix EnricoMi BOM parse error + add Live-Integration coverag…
NeilBird Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions .github/workflows/AzLocal.UpdateManagement-pester.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
name: AzLocal.UpdateManagement - Pester

# Runs the AzLocal.UpdateManagement Pester unit suite on every PR + push to main
# that touches the module. Live-tagged Azure integration tests are excluded
# (they need az login + the AdaptiveCloudLab subscription and are gated by
# -IncludeLive in the local Invoke-Tests.ps1).
#
# Runner choice: windows-latest is required so the tests exercise the same
# Windows PowerShell 5.1 + .NET 4.x surface that the published module targets.
# Cost mitigation: path-filtered to AzLocal.UpdateManagement/** only, and only
# fires on the three useful PR activities (opened, synchronize, reopened).

on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'AzLocal.UpdateManagement/**'
- '.github/workflows/AzLocal.UpdateManagement-pester.yml'
push:
branches: [main]
paths:
- 'AzLocal.UpdateManagement/**'
- '.github/workflows/AzLocal.UpdateManagement-pester.yml'
workflow_dispatch:

concurrency:
group: azlocal-updatemanagement-pester-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
checks: write
pull-requests: write

jobs:
pester:
name: Pester (Windows PowerShell 5.1)
runs-on: windows-latest
timeout-minutes: 20

defaults:
run:
shell: powershell
working-directory: AzLocal.UpdateManagement

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Show PowerShell + Pester baseline
run: |
$PSVersionTable | Format-List | Out-String | Write-Host
Get-Module Pester -ListAvailable | Select-Object Name, Version, Path | Format-Table -AutoSize | Out-String | Write-Host

- name: Install Pester 5.x
run: |
$needed = $true
$installed = Get-Module Pester -ListAvailable | Where-Object { $_.Version -ge [version]'5.0.0' } | Sort-Object Version -Descending | Select-Object -First 1
if ($installed) {
Write-Host "Pester $($installed.Version) already available at $($installed.Path)"
$needed = $false
}
if ($needed) {
Write-Host 'Installing Pester 5.x from PSGallery (CurrentUser scope)'
Install-Module Pester -MinimumVersion 5.5.0 -Force -SkipPublisherCheck -Scope CurrentUser
}
Import-Module Pester -MinimumVersion 5.0.0 -Force
(Get-Module Pester).Version | Write-Host

- name: Install powershell-yaml
# Required by one Describe block ('ITSM: Get-AzLocalItsmConfig normalises
# non-Hashtable YAML dictionaries') which Mock-overrides ConvertFrom-Yaml.
# Mock can only intercept commands that exist, so the source module must
# be present even though no actual YAML parsing happens at test time.
run: |
if (-not (Get-Module powershell-yaml -ListAvailable)) {
Write-Host 'Installing powershell-yaml from PSGallery (CurrentUser scope)'
Install-Module powershell-yaml -Force -SkipPublisherCheck -Scope CurrentUser
} else {
Write-Host 'powershell-yaml already available'
}
(Get-Module powershell-yaml -ListAvailable | Select-Object -First 1).Version | Write-Host

- name: Import module (smoke test)
run: |
Get-Module AzLocal.UpdateManagement -All | Remove-Module -Force -ErrorAction SilentlyContinue
Import-Module .\AzLocal.UpdateManagement.psd1 -Force -ErrorAction Stop
$m = Get-Module AzLocal.UpdateManagement
Write-Host "Loaded module $($m.Name) $($m.Version) with $($m.ExportedFunctions.Count) exported functions"

- name: Run Pester (unit suite, Live excluded)
run: |
New-Item -ItemType Directory -Path Tests\TestResults -Force | Out-Null
Get-Module AzLocal.UpdateManagement -All | Remove-Module -Force -ErrorAction SilentlyContinue
$config = New-PesterConfiguration
$config.Run.Path = '.\Tests'
$config.Run.PassThru = $true
$config.Run.Exit = $false
$config.Filter.ExcludeTag = @('Live')
$config.TestResult.Enabled = $true
$config.TestResult.OutputPath = 'Tests\TestResults\pester-junit.xml'
# JUnitXml is supported by Pester 5.4+ and is consumable by
# dorny/test-reporter with reporter=jest-junit below.
$config.TestResult.OutputFormat = 'JUnitXml'
$config.Output.Verbosity = 'Normal'
$result = Invoke-Pester -Configuration $config
"Passed=$($result.PassedCount) Failed=$($result.FailedCount) Skipped=$($result.SkippedCount) Duration=$($result.Duration)" | Tee-Object -FilePath Tests\TestResults\summary.txt
if ($result.FailedCount -gt 0) {
$result.Failed | ForEach-Object { "FAIL: $($_.ExpandedPath) :: $($_.ErrorRecord.Exception.Message)" } | Out-File Tests\TestResults\failures.txt
Write-Error "Pester reported $($result.FailedCount) failing test(s)."
exit 1
}

- name: Strip UTF-8 BOM from JUnit XML
# Windows PowerShell 5.1's UTF-8 writer (which Pester uses for the
# JUnit output) emits a 3-byte BOM. The EnricoMi publish-test-results
# action's lxml parser rejects it with: "Start tag expected, '<' not
# found, line 1, column 1" / "missing toplevel element". Re-write the
# file without BOM (read with BOM-aware UTF-8, write with BOM-less
# UTF-8). Idempotent: if the file is already BOM-less this is a no-op.
if: always()
run: |
$xml = 'Tests\TestResults\pester-junit.xml'
if (Test-Path -LiteralPath $xml) {
$bytes = [System.IO.File]::ReadAllBytes($xml)
$hasBom = ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF)
if ($hasBom) {
$text = [System.IO.File]::ReadAllText($xml, [System.Text.UTF8Encoding]::new($true))
[System.IO.File]::WriteAllText($xml, $text, [System.Text.UTF8Encoding]::new($false))
Write-Host "Stripped UTF-8 BOM from $xml (was $($bytes.Length) bytes, now $((Get-Item -LiteralPath $xml).Length) bytes)"
} else {
Write-Host "$xml has no BOM; nothing to strip."
}
} else {
Write-Host "$xml not found; skipping BOM strip."
}

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: pester-results-${{ github.run_id }}
path: AzLocal.UpdateManagement/Tests/TestResults/
if-no-files-found: warn
retention-days: 14

- name: Publish test report (PR check)
# EnricoMi/publish-unit-test-result-action understands Pester's
# JUnitXml output natively. dorny/test-reporter was rejected because
# its 'jest-junit' parser threw `stackTrace.split is not a function`
# on Pester's stackTrace shape (Pester serialises it as a multi-line
# string array, not the single-string shape jest produces).
if: always() && github.event_name == 'pull_request'
uses: EnricoMi/publish-unit-test-result-action/windows@v2
with:
check_name: AzLocal.UpdateManagement Pester
junit_files: AzLocal.UpdateManagement/Tests/TestResults/pester-junit.xml
comment_mode: off
ignore_runs: true
Loading
Loading