-
Notifications
You must be signed in to change notification settings - Fork 738
Fix infinite retry loop in SetResource.ps1 (missing $iterator increment) - #198
Fix infinite retry loop in SetResource.ps1 (missing $iterator increment) #198madanmishra1223 wants to merge 2 commits into
Conversation
UpdateLoop initializes $iterator to 1 but never increments it, so the loop guard ($iterator -le $maxIterations) stays true forever whenever Set-AzResource keeps failing. Instead of giving up after maxIterations attempts, the function retries indefinitely with a 5 second sleep between tries, hanging the pipeline task, and the "Failed to update resources" throw below the loop is unreachable. Increment $iterator in the catch block so the retry budget passed by the caller (-maxIterations 3) is honored and a persistent failure surfaces as an error instead of a hang. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
madanmishra1223
commented
Aug 17, 2026
@microsoft-github-policy-service agree
@ArshVermaGit
Arsh Verma (ArshVermaGit)
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix looks correct and the retry counter now advances on failures as expected. Could you add a small test covering persistent Set-AzResource failure and verifying that -maxIterations is respected? That would prevent this infinite-loop regression from coming back. Otherwise the change looks good.
Review feedback: cover persistent Set-AzResource failure and assert that -maxIterations is respected, so the infinite loop cannot come back. The failing-forever case needs care: a test that simply keeps failing would hang rather than fail if the counter regressed. So the mock fails well past the retry budget and then starts succeeding. A loop that never counts its attempts still terminates, and the test fails on the assertions instead of hanging the run. Against the pre-fix script the first test fails in ~180ms with "Expected an exception ... but no exception was thrown". Az cmdlets are stubbed and Get-AzResource returns nothing, so dot-sourcing the script only imports its functions and no Azure call is ever made. Verified with Pester 6.1.0 on PowerShell 7.6.5: 3 passed with the fix, 1 failed without it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
madanmishra1223
commented
Aug 19, 2026
Thanks Arsh Verma (@ArshVermaGit) — test added in .ci/scripts/SetResource.Tests.ps1 (Pester).
The tricky part
A test that just fails forever is the wrong shape here: if the counter ever regressed, that test would hang the run rather than fail it — the same failure mode as the bug. So the mock fails well past the retry budget and then starts succeeding. A loop that never counts its attempts still terminates, and the test fails on the assertions instead of hanging:
$script:attempts = 0 Mock Set-AzResource { $script:attempts++ if ($script:attempts -le 20) { throw 'persistent failure' } } { UpdateLoop -maxIterations 3 -resource $script:resource } | Should -Throw 'Failed to update resources' $script:attempts | Should -Be 3
Three cases covered: gives up after maxIterations on persistent failure, stops retrying as soon as a retry succeeds, and no retry when the first attempt succeeds.
No Azure is touched — the Az cmdlets are stubbed so Pester has something to mock, and Get-AzResource returns nothing, so dot-sourcing the script just imports its functions and the top-level tagging pass is a no-op.
Verified both ways
Pester 6.1.0 on PowerShell 7.6.5.
With the fix:
[+] gives up after maxIterations when Set-AzResource keeps failing 140ms
[+] stops retrying as soon as Set-AzResource succeeds 16ms
[+] does not retry when the first attempt succeeds 35ms
Tests Passed: 3, Failed: 0
With the $iterator++ reverted (bug reintroduced):
[-] gives up after maxIterations when Set-AzResource keeps failing 181ms
Expected an exception with message like 'Failed to update resources' to be thrown, but no exception was thrown.
Tests Passed: 2, Failed: 1
181ms, not a hang — which is the point of the escape hatch above.
One note
This repo has no PowerShell test runner wired up (no GitHub Actions workflows at all, and the .ci/ YAML files are Azure DevOps templates for the linked tutorial repos rather than checks on this repo). So nothing runs this file automatically yet — it is run with:
Install-Module Pester -Scope CurrentUser -Force Invoke-Pester .ci/scripts/SetResource.Tests.ps1
Happy to add a small workflow to run it on PRs if you'd like that, though I left it out to keep this PR scoped to the fix you reviewed.
Problem
UpdateLoopin.ci/scripts/SetResource.ps1is meant to retry a failingSet-AzResourcecall a bounded number of times:$iteratoris initialized to1but is never incremented. WhenSet-AzResourcekeeps failing,$successstays$falseand$iteratorstays1, so the guard($iterator -le $maxIterations)is always true.Consequences:
UpdateLoop -maxIterations 3 -resource $_) is ignored.throw "Failed to update resources"below the loop is unreachable on persistent failure, so a genuine failure is reported as a hung/timed-out job instead of a clear error.Fix
Increment
$iteratorin thecatchblock, so the loop honors-maxIterationsand a persistent failure exits via the existingthrow.Write-Host($_.Exception.Message) + $iterator++ Start-Sleep -Seconds 5One line changed; no behavior change on the success path (that path still
breaks on the first successful call).