Skip to content

Commit b92526b

Browse files
authored
feat: add client restart retries and orphan container cleanup options (#18)
* feat: add client restart retries and orphan container cleanup options * fix: preserve 120s execution client stop timeout in refactored cleanup The cleanup refactor moved the execution client teardown into _teardown_container with stop_timeout=60/5, which would revert the 120s flush window (PGO profiles, RocksDB flush, dotTrace snapshots) introduced on main. Use 120s unconditionally to keep that behavior. * fix: validate client_restart_retries and correct run_k6 return type Address PR review: reject negative client_restart_retries with a clear ValueError (and min=0 at the CLI), and annotate run_k6 as returning bytes since detach=False returns the container logs, not a Container. * ci: add ruff and ty checks and fix existing lint/type issues Add ruff and ty as dev dependencies and run them as dedicated CI jobs alongside pytest. Fix the issues they surface: - drop unused pydantic.NewPath import in scenarios.py - annotate get_execution_client_volumes as list[dict[str, Any]] - guard container.attrs before subscripting in the compressor
1 parent 78013be commit b92526b

9 files changed

Lines changed: 375 additions & 125 deletions

File tree

.github/workflows/tests.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,37 @@ jobs:
2222

2323
- name: Run tests
2424
run: uv run pytest -v
25+
26+
ruff:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- uses: actions/checkout@v4
30+
31+
- name: Install uv
32+
uses: astral-sh/setup-uv@v6
33+
34+
- name: Set up Python
35+
run: uv python install
36+
37+
- name: Install dependencies
38+
run: uv sync --dev
39+
40+
- name: Run ruff
41+
run: uv run ruff check .
42+
43+
ty:
44+
runs-on: ubuntu-latest
45+
steps:
46+
- uses: actions/checkout@v4
47+
48+
- name: Install uv
49+
uses: astral-sh/setup-uv@v6
50+
51+
- name: Set up Python
52+
run: uv python install
53+
54+
- name: Install dependencies
55+
run: uv sync --dev
56+
57+
- name: Run ty
58+
run: uv run ty check

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ packages = ["src/expb"]
3939
dev = [
4040
"hatchling>=1.29.0",
4141
"pytest>=8.0.0",
42+
"ruff>=0.10.0",
43+
"ty>=0.0.1a1",
4244
]
4345

4446
[tool.pytest.ini_options]

src/expb/configs/scenarios.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
BaseModel,
55
Field,
66
FilePath,
7-
NewPath,
87
field_serializer,
98
field_validator,
109
model_validator,

src/expb/execute_scenario.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ def execute_scenario(
8383
help="Enable JetBrains dotTrace profiling. Auto-installs if needed. Snapshot saved to outputs directory.",
8484
),
8585
] = False,
86+
client_restart_retries: Annotated[
87+
int,
88+
typer.Option(
89+
min=0,
90+
help="Auto-restart the execution client on failure up to N times (0 = never restart). Infrastructure containers (K6, Alloy, payload server) never restart.",
91+
),
92+
] = 0,
93+
reap_orphans: Annotated[
94+
bool,
95+
typer.Option(
96+
"--reap-orphans/--no-reap-orphans",
97+
help="Before running, force-remove leftover containers/networks from prior runs of this same scenario (e.g. orphaned by a hard-killed run). Scoped to the scenario, so it won't disturb other runs on the machine. Off by default.",
98+
),
99+
] = False,
86100
use_lock: Annotated[
87101
bool,
88102
typer.Option(
@@ -150,6 +164,8 @@ def execute_scenario(
150164
client_metrics=client_metrics,
151165
stable_cpu=stable_cpu,
152166
dottrace=dottrace,
167+
client_restart_retries=client_restart_retries,
168+
reap_orphans=reap_orphans,
153169
),
154170
)
155171
except ExecutionLockError as e:

src/expb/execute_scenarios.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,20 @@ def execute_scenarios(
8989
help="Enable JetBrains dotTrace profiling. Auto-installs if needed. Snapshot saved to outputs directory.",
9090
),
9191
] = False,
92+
client_restart_retries: Annotated[
93+
int,
94+
typer.Option(
95+
min=0,
96+
help="Auto-restart the execution client on failure up to N times (0 = never restart). Infrastructure containers (K6, Alloy, payload server) never restart.",
97+
),
98+
] = 0,
99+
reap_orphans: Annotated[
100+
bool,
101+
typer.Option(
102+
"--reap-orphans/--no-reap-orphans",
103+
help="Before running, force-remove leftover containers/networks from prior runs of this same scenario (e.g. orphaned by a hard-killed run). Scoped to the scenario, so it won't disturb other runs on the machine. Off by default.",
104+
),
105+
] = False,
92106
use_lock: Annotated[
93107
bool,
94108
typer.Option(
@@ -186,6 +200,8 @@ def execute_scenarios(
186200
client_metrics=client_metrics,
187201
stable_cpu=stable_cpu,
188202
dottrace=dottrace,
203+
client_restart_retries=client_restart_retries,
204+
reap_orphans=reap_orphans,
189205
),
190206
)
191207
if not loop:

src/expb/payloads/compressor/compressor.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ def start_nethermind(
236236
)
237237

238238
container.reload()
239+
if container.attrs is None:
240+
raise ValueError("Container attributes are not available")
239241
container_ip = container.attrs["NetworkSettings"]["Networks"][
240242
container_network.name
241243
]["IPAddress"]

0 commit comments

Comments
 (0)