Skip to content

Commit 078db3d

Browse files
eisenzopfclaude
andcommitted
ci: the sip codec gate names its features instead of asking for all
With the gate split, codec-features-sip finished inside its budget and then failed honestly: perf_ai_agent_load panics with "perf tests must be run with --release; debug-build numbers are not citable". That guard is deliberate. The perf targets are release-only by contract -- the release catalog runs them as `--release --features perf-tests,... --test <name>` -- so a debug gate that enables perf-tests measures nothing and fails by construction. `--all-features` was enabling them only as a side effect of asking for everything. So rvoip-sip now names its features: all thirteen except the `perf-*` family. The codec surface the gate exists for is untouched, and generated-validation and dev-insecure-tls stay on, so nothing this gate covered before goes uncovered now. The other three packages keep --all-features, having no perf harness to exclude. The list is written out to keep the command readable, and a test derives the same set from rvoip-sip's manifest, so a new feature fails the suite rather than silently sitting outside the gate. Verified with the gate's exact command: 20 test targets, no failures. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent c76ce33 commit 078db3d

2 files changed

Lines changed: 82 additions & 38 deletions

File tree

scripts/ci/run_checks.py

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232
"codec-features-core": "rvoip-core",
3333
}
3434

35+
# Every `rvoip-sip` feature except the release-only `perf-*` harness. Written
36+
# out rather than computed so the command is inspectable from here; the
37+
# accompanying test derives the same set from the manifest and fails if a new
38+
# feature is added without a decision about this gate.
39+
NON_PERF_SIP_FEATURES = (
40+
"all-codecs,amr,amr-nb,amr-wb,dev-insecure-tls,dhat,event-history,g729,"
41+
"generated-validation,opus,opus-sim,persistence,tokio-console"
42+
)
43+
3544

3645
class CheckError(RuntimeError):
3746
"""Invalid CI input or environment."""
@@ -372,42 +381,51 @@ def specialty_commands(
372381
# and its own cache key. The patterns in `policy.json` stay identical
373382
# across the four, so any change that selected the combined gate still
374383
# verifies all four packages.
375-
commands = []
376-
for package in (CODEC_FEATURE_GATES[gate],):
377-
commands.extend(
384+
package = CODEC_FEATURE_GATES[gate]
385+
# `--all-features` everywhere except `rvoip-sip`, whose feature set
386+
# includes the `perf-*` harness. Those targets are release-only by
387+
# contract -- `EnvironmentBlock::capture` panics under
388+
# `debug_assertions` rather than publish a number nobody should cite,
389+
# and the release catalog runs them as `--release --features
390+
# perf-tests,... --test <name>`. Turning them on in a debug gate does
391+
# not measure anything, it just fails. Every other feature stays on,
392+
# so the codec surface this gate exists for is unchanged.
393+
selection = (
394+
["--features", NON_PERF_SIP_FEATURES]
395+
if package == "rvoip-sip"
396+
else ["--all-features"]
397+
)
398+
return [
399+
(
378400
[
379-
(
380-
[
381-
"cargo",
382-
"test",
383-
"--locked",
384-
"--all-features",
385-
"--lib",
386-
"--tests",
387-
"--bins",
388-
"--examples",
389-
"-p",
390-
package,
391-
],
392-
None,
393-
None,
394-
),
395-
(
396-
[
397-
"cargo",
398-
"clippy",
399-
"--locked",
400-
"--all-features",
401-
"--all-targets",
402-
"-p",
403-
package,
404-
],
405-
None,
406-
None,
407-
),
408-
]
409-
)
410-
return commands
401+
"cargo",
402+
"test",
403+
"--locked",
404+
*selection,
405+
"--lib",
406+
"--tests",
407+
"--bins",
408+
"--examples",
409+
"-p",
410+
package,
411+
],
412+
None,
413+
None,
414+
),
415+
(
416+
[
417+
"cargo",
418+
"clippy",
419+
"--locked",
420+
*selection,
421+
"--all-targets",
422+
"-p",
423+
package,
424+
],
425+
None,
426+
None,
427+
),
428+
]
411429
if gate == "rtp-interop":
412430
return [(["bash", "scripts/test_libsrtp_interop.sh"], None, None)]
413431
if gate == "amazon-connect-aws-control":

scripts/ci/test_run_checks.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import importlib.util
44
from pathlib import Path
55
import sys
6+
import tomllib
67
import unittest
78

89

10+
ROOT = Path(__file__).resolve().parents[2]
911
SCRIPT = Path(__file__).with_name("run_checks.py")
1012
SPEC = importlib.util.spec_from_file_location("run_checks", SCRIPT)
1113
assert SPEC and SPEC.loader
@@ -153,10 +155,17 @@ def test_codec_gate_runs_what_the_default_feature_shards_compile_out(self) -> No
153155
# a gate that quietly grew a second package would restore the
154156
# timeout this split exists to remove.
155157
self.assertEqual(len(argv), 2)
156-
# Every command asks for all features. A command here without
157-
# it is a command that duplicates the shard and proves nothing.
158+
# Every command turns the optional features on. A command here
159+
# limited to the defaults duplicates the shard and proves
160+
# nothing. `rvoip-sip` names them instead of asking for all,
161+
# because "all" includes the release-only perf harness.
158162
for command in argv:
159-
self.assertIn("--all-features", command)
163+
if package == "rvoip-sip":
164+
self.assertIn("--features", command)
165+
self.assertIn(run_checks.NON_PERF_SIP_FEATURES, command)
166+
self.assertNotIn("--all-features", command)
167+
else:
168+
self.assertIn("--all-features", command)
160169
# Exact list membership, not a substring match, so
161170
# "rvoip-core" does not also claim rvoip-codec-core's rows.
162171
owned = [command for command in argv if package in command]
@@ -165,6 +174,23 @@ def test_codec_gate_runs_what_the_default_feature_shards_compile_out(self) -> No
165174
sorted(command[1] for command in owned), ["clippy", "test"]
166175
)
167176

177+
def test_sip_codec_gate_names_every_feature_except_the_perf_harness(self) -> None:
178+
# Derived from the manifest rather than restated, so adding a feature
179+
# to rvoip-sip fails here instead of silently going ungated -- the
180+
# same staleness that let the hard-coded package count above rot.
181+
manifest = ROOT / "crates/sip/rvoip-sip/Cargo.toml"
182+
with manifest.open("rb") as handle:
183+
features = tomllib.load(handle)["features"]
184+
expected = sorted(
185+
name
186+
for name in features
187+
if name != "default" and not name.startswith("perf")
188+
)
189+
self.assertEqual(run_checks.NON_PERF_SIP_FEATURES.split(","), expected)
190+
# The exclusion is the perf harness and nothing else. If rvoip-sip
191+
# ever stops having one, this gate should go back to --all-features.
192+
self.assertTrue(any(name.startswith("perf") for name in features))
193+
168194
def test_shards_alone_never_reach_the_optional_codecs(self) -> None:
169195
# The reason the gate above exists, asserted rather than assumed: the
170196
# shard that owns rvoip-codec-core builds it with its default features,

0 commit comments

Comments
 (0)