Skip to content

Pin ports in tests#1162

Open
acroca wants to merge 3 commits into
dapr:mainfrom
acroca:pin-test-ports
Open

Pin ports in tests#1162
acroca wants to merge 3 commits into
dapr:mainfrom
acroca:pin-test-ports

Conversation

@acroca

@acroca acroca commented Jul 16, 2026

Copy link
Copy Markdown
Member

Description

Fixes the "bind: address already in use" flakes that kill validate CI jobs at sidecar startup. The fix is one principle applied everywhere: tests never let the Dapr CLI pick random ports, and never launch a sidecar until its ports are actually bindable.

Root cause 1: the CLI random-port picker assigns duplicate ports

When ports are unset, the CLI picks random free ports independently per listener and can hand the same port to two listeners of one daprd. Observed across four listener pairs: metrics vs internal gRPC and metrics vs API gRPC (runs 28439709999, 28198520326, 27741369607, 29419165370), HTTP vs gRPC (29482935119), and metrics vs HTTP (29485069994). The last variant is why retry-on-output was abandoned entirely: the metrics listener satisfies the CLI's HTTP readiness probe, the sidecar reports "up and running", the app receives Prometheus text as API responses, and the run exits "successfully" with zero failure markers — structurally invisible to output matching. Worth filing against dapr/cli; this PR stops depending on the picker instead.

Root cause 2: pinned ports inside the OS ephemeral range get stolen

Dapr's conventional 500xx ports sit inside Linux's ephemeral source-port range (32768–60999). Any process's outbound localhost connection can be assigned one as its source port, and an established socket blocks daprd's listener bind. Proven twice on this PR (validate 3.14, validate 3.10): daprd retries the internal bind 10×1s and dies; in the second run the CLI's own preflight reported Port 50002 is not available over a minute after every managed process was dead. dapr/dapr#10149 doesn't cover this — it only stops daprd's own dials from stealing its ports. Hence all test-pinned ports live below 32768.

Root cause 3: teardown races

dapr run spawns daprd (and the app, in its own process group) which outlive the CLI, so "CLI exited" never meant "ports free". Rather than tracking process lifetimes, the startup gate verifies the actual invariant — the ports are bindable — which covers every straggler regardless of process-group membership.

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.78%. Comparing base (3457d0a) to head (65297fa).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1162   +/-   ##
=======================================
  Coverage   82.78%   82.78%           
=======================================
  Files         123      123           
  Lines       10127    10127           
=======================================
  Hits         8384     8384           
  Misses       1743     1743           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces CI flakes caused by Dapr sidecar startup failures where multiple daprd listeners can end up attempting to bind the same randomly-chosen port, leading to bind: address already in use and a fatal sidecar exit. It does this primarily by pinning additional daprd listener ports in the integration test harness and by making the example-test retry detection cover both internal and API gRPC startup failures.

Changes:

  • Pin daprd internal gRPC and metrics ports (in addition to existing gRPC/HTTP pins) for integration test sidecars.
  • Broaden the example-test “port bind failure” detection marker to match both internal and API gRPC fatal-start messages.
  • Update DaprRunner unit tests to validate retry behavior for both internal and API gRPC server startup failures.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
tests/integration/conftest.py Adds pinned internal_grpc_port and metrics_port to the integration sidecar launcher and passes the corresponding dapr run flags.
tests/integration/AGENTS.md Documents the expanded set of pinned ports and the motivation (avoiding daprd listener port-collision flakes).
tests/examples/test_dapr_runner.py Updates unit tests to cover both internal and API gRPC fatal-start variants for retry behavior.
tests/examples/conftest.py Broadens the port-bind failure marker to match the fatal line regardless of whether it references internal or API gRPC.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@acroca
acroca marked this pull request as ready for review July 16, 2026 07:03
@acroca
acroca requested review from a team as code owners July 16, 2026 07:03
@acroca
acroca force-pushed the pin-test-ports branch 3 times, most recently from 19d371d to 21854e9 Compare July 16, 2026 10:23
Signed-off-by: Albert Callarisa <albert@diagrid.io>
@acroca
acroca marked this pull request as draft July 16, 2026 10:33
@acroca
acroca requested a review from Copilot July 17, 2026 07:08
@acroca
acroca marked this pull request as ready for review July 17, 2026 07:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Comment thread tests/examples/conftest.py
Signed-off-by: Albert Callarisa <albert@diagrid.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants