From 0fbe701c3f75ea37148aa949bf0e25f170fcb461 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 17:33:33 +0000 Subject: [PATCH 1/4] fix: stop Consul Windows service before starting dev agent The chocolatey package registers Consul as a Windows service which races with the dev agent for port binding. Stop and disable the service before starting the dev agent, and add a readiness check that polls the leader endpoint to confirm the agent is ready. Co-Authored-By: mkeeler@launchdarkly.com --- actions/persistent-stores/action.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/actions/persistent-stores/action.yml b/actions/persistent-stores/action.yml index 8bb5ad3..9cf7b6a 100644 --- a/actions/persistent-stores/action.yml +++ b/actions/persistent-stores/action.yml @@ -82,8 +82,34 @@ runs: # 1.20.1 until they fix the issue run: | choco install consul --version=1.20.1 + + # The chocolatey package registers Consul as a Windows service which + # races with the dev agent for port binding. Stop and disable it. + Stop-Service consul -ErrorAction SilentlyContinue + Set-Service consul -StartupType Disabled -ErrorAction SilentlyContinue + Start-Process consul -ArgumentList 'agent', '-dev', '-http-port=${{ inputs.consul_port }}' + # Wait for the dev agent to complete Raft leader election. + $timeout = 30 + $elapsed = 0 + while ($elapsed -lt $timeout) { + try { + $response = Invoke-RestMethod -Uri 'http://127.0.0.1:${{ inputs.consul_port }}/v1/status/leader' -TimeoutSec 2 + if ($response -and $response -ne '""') { + Write-Host "Consul is ready (leader: $response)" + break + } + } catch {} + Write-Host "Waiting for Consul to elect a leader... ($elapsed/$timeout seconds)" + Start-Sleep -Seconds 1 + $elapsed++ + } + if ($elapsed -eq $timeout) { + Write-Error "Consul did not become ready within $timeout seconds" + exit 1 + } + - name: "DynamoDB for Windows" shell: powershell if: ${{ inputs.dynamodb == 'true' && runner.os == 'Windows' }} From 3352941832ebe7eb12ee80531d798263401b0c65 Mon Sep 17 00:00:00 2001 From: Matthew Keeler Date: Mon, 8 Jun 2026 10:11:21 -0400 Subject: [PATCH 2/4] fix: Skip Consul Windows service registration with /noservice Use the chocolatey /noservice package parameter so Consul is never registered as a Windows service, instead of registering it and then stopping and disabling it. This removes the service that raced with the dev agent for the port, so the Stop-Service and Set-Service steps are no longer needed. --- actions/persistent-stores/action.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/actions/persistent-stores/action.yml b/actions/persistent-stores/action.yml index 9cf7b6a..b9d3006 100644 --- a/actions/persistent-stores/action.yml +++ b/actions/persistent-stores/action.yml @@ -81,12 +81,10 @@ runs: # https://github.com/hashicorp/consul/issues/22822 so we need to run # 1.20.1 until they fix the issue run: | - choco install consul --version=1.20.1 - - # The chocolatey package registers Consul as a Windows service which - # races with the dev agent for port binding. Stop and disable it. - Stop-Service consul -ErrorAction SilentlyContinue - Set-Service consul -StartupType Disabled -ErrorAction SilentlyContinue + # The chocolatey package would otherwise register Consul as a Windows + # service which races with the dev agent for port binding. /noservice + # skips that registration so only the dev agent runs. + choco install consul --version=1.20.1 --params="'/noservice'" Start-Process consul -ArgumentList 'agent', '-dev', '-http-port=${{ inputs.consul_port }}' From 87b1e401bc030826362e5f2cef32e66c904a354c Mon Sep 17 00:00:00 2001 From: Matthew Keeler Date: Mon, 8 Jun 2026 10:32:39 -0400 Subject: [PATCH 3/4] docs: Clarify Consul readiness poll comment The dev agent elects itself leader effectively instantly, so the poll is not waiting on slow Raft election. Reword the comment to reflect its actual purpose: Start-Process returns immediately, so we wait until the HTTP API is up and serving before tests run. --- actions/persistent-stores/action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/actions/persistent-stores/action.yml b/actions/persistent-stores/action.yml index b9d3006..bbd405c 100644 --- a/actions/persistent-stores/action.yml +++ b/actions/persistent-stores/action.yml @@ -88,7 +88,8 @@ runs: Start-Process consul -ArgumentList 'agent', '-dev', '-http-port=${{ inputs.consul_port }}' - # Wait for the dev agent to complete Raft leader election. + # Start-Process returns immediately, so wait until the dev agent's HTTP + # API is up and serving (leader elected) before tests run. $timeout = 30 $elapsed = 0 while ($elapsed -lt $timeout) { From dcd7d2facac601fe74f1d9c57da89ae7ae735d96 Mon Sep 17 00:00:00 2001 From: Matthew Keeler Date: Mon, 8 Jun 2026 10:39:06 -0400 Subject: [PATCH 4/4] refactor: Use consul members for the Windows readiness check Replace the /v1/status/leader HTTP poll with consul members, which exits non-zero until the agent's HTTP API responds. This drops the HTTP request construction and JSON parsing in favor of a self-describing check using a binary already on PATH after install. --- actions/persistent-stores/action.yml | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/actions/persistent-stores/action.yml b/actions/persistent-stores/action.yml index bbd405c..1e022fd 100644 --- a/actions/persistent-stores/action.yml +++ b/actions/persistent-stores/action.yml @@ -88,24 +88,18 @@ runs: Start-Process consul -ArgumentList 'agent', '-dev', '-http-port=${{ inputs.consul_port }}' - # Start-Process returns immediately, so wait until the dev agent's HTTP - # API is up and serving (leader elected) before tests run. - $timeout = 30 - $elapsed = 0 - while ($elapsed -lt $timeout) { - try { - $response = Invoke-RestMethod -Uri 'http://127.0.0.1:${{ inputs.consul_port }}/v1/status/leader' -TimeoutSec 2 - if ($response -and $response -ne '""') { - Write-Host "Consul is ready (leader: $response)" - break - } - } catch {} - Write-Host "Waiting for Consul to elect a leader... ($elapsed/$timeout seconds)" + # consul members exits non-zero until the agent's HTTP API responds. + # In dev mode the leader is self-elected immediately on startup, so + # this is purely a process-readiness check. + $deadline = (Get-Date).AddSeconds(30) + $ready = $false + while ((Get-Date) -lt $deadline) { + consul members -http-addr="http://127.0.0.1:${{ inputs.consul_port }}" 2>&1 | Out-Null + if ($LASTEXITCODE -eq 0) { $ready = $true; break } Start-Sleep -Seconds 1 - $elapsed++ } - if ($elapsed -eq $timeout) { - Write-Error "Consul did not become ready within $timeout seconds" + if (-not $ready) { + Write-Error "Consul did not become ready within 30 seconds" exit 1 }