From 43f742663fd147b1c2d385bed3de685981e285d0 Mon Sep 17 00:00:00 2001 From: Merill Fernando Date: Mon, 22 Jun 2026 13:08:14 +1000 Subject: [PATCH 1/2] refactor: rename Azure DevOps connection cache --- build/Build-MaesterModule.ps1 | 2 +- powershell/Maester.psm1 | 3 +- powershell/internal/Clear-ModuleVariable.ps1 | 2 +- powershell/public/core/Test-MtConnection.ps1 | 10 +-- .../functions/Test-MtConnection.Tests.ps1 | 69 +++++++++++++++++++ 5 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 powershell/tests/functions/Test-MtConnection.Tests.ps1 diff --git a/build/Build-MaesterModule.ps1 b/build/Build-MaesterModule.ps1 index 9370c954b..b1f58db05 100644 --- a/build/Build-MaesterModule.ps1 +++ b/build/Build-MaesterModule.ps1 @@ -476,7 +476,7 @@ $__MtSession = @{ ExoCache = @{} OrcaCache = @{} AIAgentInfo = $null - AzureDevOpsConnection = $null + AzureDevOpsConnectionCache = $null DataverseApiBase = $null # Resolved Dataverse OData API base URL (e.g. https://org123.api.crm.dynamics.com/api/data/v9.2) DataverseResourceUrl = $null # Dataverse resource URL for token acquisition (e.g. https://org123.crm.dynamics.com) DataverseEnvironmentId = $null # Environment identifier for display (e.g. org123.crm.dynamics.com) diff --git a/powershell/Maester.psm1 b/powershell/Maester.psm1 index d6a8e35d5..ddf10d03a 100644 --- a/powershell/Maester.psm1 +++ b/powershell/Maester.psm1 @@ -22,6 +22,7 @@ $__MtSession = @{ ExoCache = @{} OrcaCache = @{} AIAgentInfo = $null + AzureDevOpsConnectionCache = $null DataverseApiBase = $null # Resolved Dataverse OData API base URL (e.g. https://org123.api.crm.dynamics.com/api/data/v9.2) DataverseResourceUrl = $null # Dataverse resource URL for token acquisition (e.g. https://org123.crm.dynamics.com) DataverseEnvironmentId = $null # Environment identifier for display (e.g. org123.crm.dynamics.com) @@ -60,4 +61,4 @@ try { } catch { Write-Warning "Failed to load module manifest: $($_.Exception.Message)" $ModuleInfo = $null -} \ No newline at end of file +} diff --git a/powershell/internal/Clear-ModuleVariable.ps1 b/powershell/internal/Clear-ModuleVariable.ps1 index cb867785b..a01b7b523 100644 --- a/powershell/internal/Clear-ModuleVariable.ps1 +++ b/powershell/internal/Clear-ModuleVariable.ps1 @@ -20,7 +20,7 @@ Clear-MtDnsCache Clear-MtExoCache $__MtSession.AIAgentInfo = $null - $__MtSession.AzureDevOpsConnection = $null + $__MtSession.AzureDevOpsConnectionCache = $null $__MtSession.SpoCache = @{} # $__MtSession.Connections = @() # Do not clear connections as they are used to track the connection state. This module variable should only be set by Connect-Maester and Disconnect-Maester. } diff --git a/powershell/public/core/Test-MtConnection.ps1 b/powershell/public/core/Test-MtConnection.ps1 index da95e4bd8..fb5e122e1 100644 --- a/powershell/public/core/Test-MtConnection.ps1 +++ b/powershell/public/core/Test-MtConnection.ps1 @@ -165,12 +165,12 @@ #region AzureDevOps if ($Service -contains 'AzureDevOps' -or $Service -contains 'All') { $IsConnected = $false - if ($null -ne $__MtSession.AzureDevOpsConnection) { + if ($null -ne $__MtSession.AzureDevOpsConnectionCache) { # Use cached probe result to avoid re-running the connection check on every test. - if ($__MtSession.AzureDevOpsConnection -is [string] -and $__MtSession.AzureDevOpsConnection -eq 'NotConnected') { + if ($__MtSession.AzureDevOpsConnectionCache -is [string] -and $__MtSession.AzureDevOpsConnectionCache -eq 'NotConnected') { $IsConnected = $false } else { - $MtConnections.AzureDevOps = $__MtSession.AzureDevOpsConnection + $MtConnections.AzureDevOps = $__MtSession.AzureDevOpsConnectionCache $IsConnected = $true } } else { @@ -179,7 +179,7 @@ $connection = Get-ADOPSConnection if ($null -ne $connection -and $null -ne $connection['Organization']) { $MtConnections.AzureDevOps = $connection - $__MtSession.AzureDevOpsConnection = $connection + $__MtSession.AzureDevOpsConnectionCache = $connection $IsConnected = $true } } @@ -188,7 +188,7 @@ } if (-not $IsConnected) { # Cache negative result so subsequent calls skip the probe. - $__MtSession.AzureDevOpsConnection = 'NotConnected' + $__MtSession.AzureDevOpsConnectionCache = 'NotConnected' } } Write-Verbose "AzureDevOps: $IsConnected" diff --git a/powershell/tests/functions/Test-MtConnection.Tests.ps1 b/powershell/tests/functions/Test-MtConnection.Tests.ps1 new file mode 100644 index 000000000..cbff36ee2 --- /dev/null +++ b/powershell/tests/functions/Test-MtConnection.Tests.ps1 @@ -0,0 +1,69 @@ +BeforeAll { + Import-Module $PSScriptRoot/../../Maester.psd1 -Force +} + +Describe 'Test-MtConnection AzureDevOps cache' { + BeforeEach { + InModuleScope Maester { + $__MtSession.AzureDevOpsConnectionCache = $null + $__MtSession.Remove('AzureDevOpsConnection') + } + } + + AfterEach { + Remove-Item -Path function:global:Get-ADOPSConnection -ErrorAction SilentlyContinue + InModuleScope Maester { + $__MtSession.AzureDevOpsConnectionCache = $null + $__MtSession.Remove('AzureDevOpsConnection') + } + } + + It 'caches a successful Azure DevOps probe under a cache-specific key' { + Set-Item -Path function:global:Get-ADOPSConnection -Value { @{ Organization = 'ado-org' } } + + $result = Test-MtConnection -Service AzureDevOps -Details + + $result.AllConnected | Should -BeTrue + $result.AzureDevOps['Organization'] | Should -Be 'ado-org' + InModuleScope Maester { + $__MtSession.AzureDevOpsConnectionCache['Organization'] | Should -Be 'ado-org' + $__MtSession.ContainsKey('AzureDevOpsConnection') | Should -BeFalse + } + } + + It 'caches a failed Azure DevOps probe as NotConnected' { + Set-Item -Path function:global:Get-ADOPSConnection -Value { $null } + + $result = Test-MtConnection -Service AzureDevOps -Details + + $result.AllConnected | Should -BeFalse + $result.AzureDevOps | Should -BeNullOrEmpty + InModuleScope Maester { + $__MtSession.AzureDevOpsConnectionCache | Should -Be 'NotConnected' + $__MtSession.ContainsKey('AzureDevOpsConnection') | Should -BeFalse + } + } + + It 'uses the cached Azure DevOps probe result without re-querying the external command' { + InModuleScope Maester { + $__MtSession.AzureDevOpsConnectionCache = @{ Organization = 'cached-org' } + } + Set-Item -Path function:global:Get-ADOPSConnection -Value { throw 'Get-ADOPSConnection should not be called when cache exists.' } + + $result = Test-MtConnection -Service AzureDevOps -Details + + $result.AllConnected | Should -BeTrue + $result.AzureDevOps['Organization'] | Should -Be 'cached-org' + } + + It 'clears the Azure DevOps probe cache during module-variable reset' { + InModuleScope Maester { + $__MtSession.AzureDevOpsConnectionCache = @{ Organization = 'cached-org' } + + Clear-ModuleVariable + + $__MtSession.AzureDevOpsConnectionCache | Should -BeNullOrEmpty + $__MtSession.ContainsKey('AzureDevOpsConnection') | Should -BeFalse + } + } +} From 1d6c6297bcd30871fd57d39478a19f195484fd51 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 3 Jul 2026 10:31:02 +0000 Subject: [PATCH 2/2] test: scope Azure DevOps connection stubs to module --- .../functions/Test-MtConnection.Tests.ps1 | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/powershell/tests/functions/Test-MtConnection.Tests.ps1 b/powershell/tests/functions/Test-MtConnection.Tests.ps1 index fec819084..cf3384c6e 100644 --- a/powershell/tests/functions/Test-MtConnection.Tests.ps1 +++ b/powershell/tests/functions/Test-MtConnection.Tests.ps1 @@ -204,17 +204,18 @@ Describe 'Test-MtConnection AzureDevOps cache' { } AfterEach { - Remove-Item -Path function:global:Get-ADOPSConnection -ErrorAction SilentlyContinue InModuleScope Maester { + Remove-Item -Path function:Get-ADOPSConnection -ErrorAction SilentlyContinue $__MtSession.AzureDevOpsConnectionCache = $null $__MtSession.Remove('AzureDevOpsConnection') } } It 'caches a successful Azure DevOps probe under a cache-specific key' { - Set-Item -Path function:global:Get-ADOPSConnection -Value { @{ Organization = 'ado-org' } } - - $result = Test-MtConnection -Service AzureDevOps -Details + $result = InModuleScope Maester { + New-Item -Path function:Get-ADOPSConnection -Value { @{ Organization = 'ado-org' } } -Force | Out-Null + Test-MtConnection -Service AzureDevOps -Details + } $result.AllConnected | Should -BeTrue $result.AzureDevOps['Organization'] | Should -Be 'ado-org' @@ -225,9 +226,10 @@ Describe 'Test-MtConnection AzureDevOps cache' { } It 'caches a failed Azure DevOps probe as NotConnected' { - Set-Item -Path function:global:Get-ADOPSConnection -Value { $null } - - $result = Test-MtConnection -Service AzureDevOps -Details + $result = InModuleScope Maester { + New-Item -Path function:Get-ADOPSConnection -Value { $null } -Force | Out-Null + Test-MtConnection -Service AzureDevOps -Details + } $result.AllConnected | Should -BeFalse $result.AzureDevOps | Should -BeNullOrEmpty @@ -241,9 +243,10 @@ Describe 'Test-MtConnection AzureDevOps cache' { InModuleScope Maester { $__MtSession.AzureDevOpsConnectionCache = @{ Organization = 'cached-org' } } - Set-Item -Path function:global:Get-ADOPSConnection -Value { throw 'Get-ADOPSConnection should not be called when cache exists.' } - - $result = Test-MtConnection -Service AzureDevOps -Details + $result = InModuleScope Maester { + New-Item -Path function:Get-ADOPSConnection -Value { throw 'Get-ADOPSConnection should not be called when cache exists.' } -Force | Out-Null + Test-MtConnection -Service AzureDevOps -Details + } $result.AllConnected | Should -BeTrue $result.AzureDevOps['Organization'] | Should -Be 'cached-org'