Skip to content

Commit a6f63ac

Browse files
authored
30813 make tests deterministic (#35889)
* make py39-cloudcoverage deterministic (#30813) * increase grpc timeouts (#30813) * fix linting (#30813) * revert timeout increase (#30813)
1 parent bb63475 commit a6f63ac

File tree

5 files changed

+439
-8
lines changed

5 files changed

+439
-8
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
name: "Start and Prepare DinD"
19+
description: "Launch, verify, and prepare a Docker-in-Docker environment."
20+
inputs:
21+
# --- Core DinD Config ---
22+
container-name:
23+
description: "Name for the DinD container."
24+
default: dind-daemon
25+
bind-address:
26+
default: 127.0.0.1
27+
port:
28+
default: "2375"
29+
storage-volume:
30+
default: dind-storage
31+
execroot-volume:
32+
default: dind-execroot
33+
ephemeral-volumes:
34+
description: "Generate unique per-run volume names (recommended)."
35+
default: "true"
36+
auto-prune-dangling:
37+
description: "Prune dangling ephemeral DinD volumes from previous runs."
38+
default: "true"
39+
tmpfs-run-size:
40+
default: 1g
41+
tmpfs-varrun-size:
42+
default: 1g
43+
storage-driver:
44+
default: overlay2
45+
additional-dockerd-args:
46+
default: ""
47+
use-host-network:
48+
description: "Run DinD with --network host instead of publishing a TCP port."
49+
default: "false"
50+
51+
# --- Health & Wait Config ---
52+
health-interval:
53+
default: 2s
54+
health-retries:
55+
default: "60"
56+
health-start-period:
57+
default: 10s
58+
wait-timeout:
59+
default: "180"
60+
61+
# --- NEW: Optional Setup & Verification Steps ---
62+
cleanup-dind-on-start:
63+
description: "Run 'docker system prune' inside DinD immediately after it starts."
64+
default: "true"
65+
smoke-test-port-mapping:
66+
description: "Run a quick test to ensure port mapping from DinD is working."
67+
default: "true"
68+
prime-testcontainers:
69+
description: "Start and stop a small container via the testcontainers library to prime Ryuk."
70+
default: "false"
71+
72+
# --- Output Config ---
73+
export-gh-env:
74+
description: "Also write DOCKER_HOST and DIND_IP to $GITHUB_ENV for the rest of the job."
75+
default: "false"
76+
77+
outputs:
78+
docker-host:
79+
description: "The TCP address for the DinD daemon (e.g., tcp://127.0.0.1:2375)."
80+
value: ${{ steps.set-output.outputs.docker-host }}
81+
dind-ip:
82+
description: "The discovered bridge IP address of the DinD container."
83+
value: ${{ steps.discover-ip.outputs.dind-ip }}
84+
container-name:
85+
description: "The name of the running DinD container."
86+
value: ${{ inputs.container-name || 'dind-daemon' }}
87+
storage-volume:
88+
value: ${{ steps.set-output.outputs.storage_volume }}
89+
execroot-volume:
90+
value: ${{ steps.set-output.outputs.execroot_volume }}
91+
92+
runs:
93+
using: "composite"
94+
steps:
95+
- name: Prune old dangling ephemeral DinD volumes
96+
if: ${{ inputs.auto-prune-dangling == 'true' }}
97+
shell: bash
98+
run: |
99+
docker volume ls -q \
100+
--filter "label=com.github.dind=1" \
101+
--filter "label=com.github.repo=${GITHUB_REPOSITORY}" \
102+
--filter "dangling=true" | xargs -r docker volume rm || true
103+
104+
- name: Start docker:dind
105+
shell: bash
106+
run: |
107+
# (Your original 'Start docker:dind' script is perfect here - no changes needed)
108+
set -euo pipefail
109+
NAME="${{ inputs.container-name || 'dind-daemon' }}"
110+
BIND="${{ inputs.bind-address || '127.0.0.1' }}"
111+
PORT="${{ inputs.port || '2375' }}"
112+
SD="${{ inputs.storage-driver || 'overlay2' }}"
113+
TRS="${{ inputs.tmpfs-run-size || '1g' }}"
114+
TVRS="${{ inputs.tmpfs-varrun-size || '1g' }}"
115+
HI="${{ inputs.health-interval || '2s' }}"
116+
HR="${{ inputs.health-retries || '60' }}"
117+
HSP="${{ inputs.health-start-period || '10s' }}"
118+
EXTRA="${{ inputs.additional-dockerd-args }}"
119+
USE_HOST_NET="${{ inputs.use-host-network || 'false' }}"
120+
121+
if [[ "${{ inputs.ephemeral-volumes }}" == "true" ]]; then
122+
SUFFIX="${GITHUB_RUN_ID:-0}-${GITHUB_RUN_ATTEMPT:-0}-${GITHUB_JOB:-job}"
123+
STORAGE_VOL="dind-storage-${SUFFIX}"
124+
EXECROOT_VOL="dind-execroot-${SUFFIX}"
125+
else
126+
STORAGE_VOL="${{ inputs.storage-volume || 'dind-storage' }}"
127+
EXECROOT_VOL="${{ inputs.execroot-volume || 'dind-execroot' }}"
128+
fi
129+
130+
docker volume create --name "${STORAGE_VOL}" --label "com.github.dind=1" --label "com.github.repo=${GITHUB_REPOSITORY}" >/dev/null
131+
docker volume create --name "${EXECROOT_VOL}" --label "com.github.dind=1" --label "com.github.repo=${GITHUB_REPOSITORY}" >/dev/null
132+
docker rm -f -v "$NAME" 2>/dev/null || true
133+
134+
NET_ARGS=""
135+
PUBLISH_ARGS="-p ${BIND}:${PORT}:${PORT}"
136+
if [[ "${USE_HOST_NET}" == "true" ]]; then
137+
NET_ARGS="--network host"
138+
PUBLISH_ARGS=""
139+
fi
140+
141+
docker run -d --privileged --name "$NAME" \
142+
--cgroupns=host \
143+
-e DOCKER_TLS_CERTDIR= \
144+
${NET_ARGS} \
145+
${PUBLISH_ARGS} \
146+
-v "${STORAGE_VOL}:/var/lib/docker" \
147+
-v "${EXECROOT_VOL}:/execroot" \
148+
--tmpfs /run:rw,exec,size=${TRS} \
149+
--tmpfs /var/run:rw,exec,size=${TVRS} \
150+
--label "com.github.dind=1" \
151+
--health-cmd='docker info > /dev/null' \
152+
--health-interval=${HI} \
153+
--health-retries=${HR} \
154+
--health-start-period=${HSP} \
155+
docker:dind \
156+
--host=tcp://0.0.0.0:${PORT} \
157+
--host=unix:///var/run/docker.sock \
158+
--storage-driver=${SD} \
159+
--exec-root=/execroot ${EXTRA}
160+
161+
{
162+
echo "STORAGE_VOL=${STORAGE_VOL}"
163+
echo "EXECROOT_VOL=${EXECROOT_VOL}"
164+
} >> "$GITHUB_ENV"
165+
166+
- name: Wait for DinD daemon
167+
shell: bash
168+
run: |
169+
set -euo pipefail
170+
NAME="${{ inputs.container-name || 'dind-daemon' }}"
171+
HOST="${{ inputs.bind-address || '127.0.0.1' }}"
172+
PORT="${{ inputs.port || '2375' }}"
173+
TIMEOUT="${{ inputs.wait-timeout || '180' }}"
174+
echo "Waiting for Docker-in-Docker to be ready..."
175+
if ! timeout ${TIMEOUT}s bash -c 'until docker -H "tcp://'"${HOST}"':'"${PORT}"'" info >/dev/null 2>&1; do sleep 2; done'; then
176+
echo "::error::DinD failed to start within ${TIMEOUT}s."
177+
docker logs "$NAME" || true
178+
exit 1
179+
fi
180+
echo "DinD is ready."
181+
docker -H "tcp://${HOST}:${PORT}" info --format 'Daemon OK → OS={{.OperatingSystem}} Version={{.ServerVersion}}'
182+
183+
- id: set-output
184+
shell: bash
185+
run: |
186+
HOST="${{ inputs.bind-address || '127.0.0.1' }}"
187+
PORT="${{ inputs.port || '2375' }}"
188+
echo "docker-host=tcp://${HOST}:${PORT}" >> "$GITHUB_OUTPUT"
189+
echo "storage_volume=${STORAGE_VOL:-}" >> "$GITHUB_OUTPUT"
190+
echo "execroot_volume=${EXECROOT_VOL:-}" >> "$GITHUB_OUTPUT"
191+
192+
# --- NEW: Integrated Setup & Verification Steps ---
193+
194+
- name: Cleanup DinD Environment
195+
if: ${{ inputs.cleanup-dind-on-start == 'true' }}
196+
shell: bash
197+
run: |
198+
echo "Performing initial cleanup of DinD environment..."
199+
DIND_HOST="${{ steps.set-output.outputs.docker-host }}"
200+
docker -H "${DIND_HOST}" system prune -af --volumes
201+
docker -H "${DIND_HOST}" image prune -af
202+
203+
- id: discover-ip
204+
name: Discover DinD Container IP
205+
shell: bash
206+
run: |
207+
set -euo pipefail
208+
NAME="${{ inputs.container-name || 'dind-daemon' }}"
209+
210+
# Use host daemon to inspect the DinD container
211+
nm=$(docker inspect -f '{{.HostConfig.NetworkMode}}' "$NAME")
212+
echo "DinD NetworkMode=${nm}"
213+
214+
# Try to find the bridge network IP
215+
ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$NAME" || true)
216+
217+
# If still empty, likely host networking -> use loopback
218+
if [[ -z "${ip}" || "${nm}" == "host" ]]; then
219+
echo "No bridge IP found or using host network. Falling back to 127.0.0.1."
220+
ip="127.0.0.1"
221+
fi
222+
223+
echo "Discovered DinD IP: ${ip}"
224+
echo "dind-ip=${ip}" >> "$GITHUB_OUTPUT"
225+
226+
- name: Smoke Test Port Mapping
227+
if: ${{ inputs.smoke-test-port-mapping == 'true' }}
228+
env:
229+
DOCKER_HOST: ${{ steps.set-output.outputs.docker-host }}
230+
DIND_IP: ${{ steps.discover-ip.outputs.dind-ip }}
231+
shell: bash
232+
run: |
233+
set -euo pipefail
234+
echo "Running port mapping smoke test..."
235+
docker pull redis:7.2-alpine
236+
cid=$(docker run -d -p 0:6379 --name redis-smoke redis:7-alpine)
237+
hostport=$(docker port redis-smoke 6379/tcp | sed 's/.*://')
238+
echo "Redis container started, mapped to host port ${hostport}"
239+
echo "Probing connection to ${DIND_IP}:${hostport} ..."
240+
241+
timeout 5 bash -c 'exec 3<>/dev/tcp/$DIND_IP/'"$hostport"
242+
if [[ $? -eq 0 ]]; then
243+
echo "TCP connection successful. Port mapping is working."
244+
else
245+
echo "::error::Failed to connect to mapped port on ${DIND_IP}:${hostport}"
246+
docker logs redis-smoke
247+
exit 1
248+
fi
249+
docker rm -f "$cid"
250+
251+
- name: Prime Testcontainers (Ryuk)
252+
if: ${{ inputs.prime-testcontainers == 'true' }}
253+
env:
254+
DOCKER_HOST: ${{ steps.set-output.outputs.docker-host }}
255+
TESTCONTAINERS_HOST_OVERRIDE: ${{ steps.discover-ip.outputs.dind-ip }}
256+
shell: bash
257+
run: |
258+
echo "Priming Testcontainers/Ryuk..."
259+
python -m pip install -q --upgrade pip testcontainers
260+
# Use a tiny image for a fast and stable prime
261+
docker pull alpine:3.19
262+
python - <<'PY'
263+
from testcontainers.core.container import DockerContainer
264+
c = DockerContainer("alpine:3.19").with_command("true")
265+
c.start()
266+
c.stop()
267+
print("Ryuk primed and ready.")
268+
PY
269+
270+
- name: Export Environment Variables
271+
if: ${{ inputs.export-gh-env == 'true' }}
272+
shell: bash
273+
run: |
274+
echo "DOCKER_HOST=${{ steps.set-output.outputs.docker-host }}" >> "$GITHUB_ENV"
275+
echo "DIND_IP=${{ steps.discover-ip.outputs.dind-ip }}" >> "$GITHUB_ENV"

.github/workflows/beam_PreCommit_Python_Coverage.yml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ env:
5959
jobs:
6060
beam_PreCommit_Python_Coverage:
6161
name: ${{ matrix.job_name }} (${{ matrix.job_phrase }})
62-
runs-on: [self-hosted, ubuntu-20.04, main]
62+
runs-on: [self-hosted, ubuntu-20.04, highmem]
6363
strategy:
6464
matrix:
6565
job_name: [beam_PreCommit_Python_Coverage]
@@ -84,7 +84,29 @@ jobs:
8484
with:
8585
java-version: default
8686
python-version: default
87+
- name: Start DinD
88+
uses: ./.github/actions/dind-up-action
89+
id: dind
90+
with:
91+
# Enable all the new features
92+
cleanup-dind-on-start: "true"
93+
smoke-test-port-mapping: "true"
94+
prime-testcontainers: "true"
95+
tmpfs-run-size: 2g
96+
tmpfs-varrun-size: 4g
97+
export-gh-env: "true"
8798
- name: Run preCommitPyCoverage
99+
env:
100+
DOCKER_HOST: ${{ steps.dind.outputs.docker-host }}
101+
TOX_TESTENV_PASSENV: "DOCKER_*,TESTCONTAINERS_*,TC_*,BEAM_*,GRPC_*,OMP_*,OPENBLAS_*,PYTHONHASHSEED,PYTEST_*"
102+
TESTCONTAINERS_HOST_OVERRIDE: ${{ env.DIND_IP }}
103+
TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: "/var/run/docker.sock"
104+
TESTCONTAINERS_RYUK_DISABLED: "false"
105+
TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED: "true"
106+
PYTEST_ADDOPTS: "-v --tb=short --maxfail=3 --durations=20 --reruns=2 --reruns-delay=5"
107+
TC_TIMEOUT: "120"
108+
TC_MAX_TRIES: "120"
109+
TC_SLEEP_TIME: "1"
88110
uses: ./.github/actions/gradle-command-self-hosted-action
89111
with:
90112
gradle-command: :sdks:python:test-suites:tox:py39:preCommitPyCoverage
@@ -99,6 +121,8 @@ jobs:
99121
name: Python Test Results
100122
path: '**/pytest*.xml'
101123
- name: Publish Python Test Results
124+
env:
125+
DOCKER_HOST: "" # Unset DOCKER_HOST to run on host Docker daemon
102126
uses: EnricoMi/publish-unit-test-result-action@v2
103127
if: always()
104128
with:

sdks/python/apache_beam/ml/rag/enrichment/milvus_search_it_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def __init__(
297297
class MilvusEnrichmentTestHelper:
298298
@staticmethod
299299
def start_db_container(
300-
image="milvusdb/milvus:v2.5.10",
300+
image="milvusdb/milvus:v2.3.9",
301301
max_vec_fields=5,
302302
vector_client_max_retries=3,
303303
tc_max_retries=TC_MAX_TRIES) -> Optional[MilvusDBContainerInfo]:
@@ -481,7 +481,7 @@ class TestMilvusSearchEnrichment(unittest.TestCase):
481481
"""Tests for search functionality across all search strategies"""
482482

483483
_db: MilvusDBContainerInfo
484-
_version = "milvusdb/milvus:v2.5.10"
484+
_version = "milvusdb/milvus:v2.3.9"
485485

486486
@classmethod
487487
def setUpClass(cls):

0 commit comments

Comments
 (0)