Skip to content

Commit 05294a8

Browse files
fschlzclaude
andcommitted
fix: scope REST delete by project, drop update --surface no-op, cover span-python in CI
- via_rest delete now sends project_id (matches the SDK's batch-delete scoping); previously delete --surface rest omitted it. - update no longer accepts --surface (it always uses REST): the flag was a silent no-op, now argparse rejects it. Dry-run message reports "rest" for update. - run.sh now also exercises create-span --python (RULE_SPAN_PY), previously uncovered in the CI entry point. - Regression test: update rejects --surface. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 62858e2 commit 05294a8

3 files changed

Lines changed: 23 additions & 8 deletions

File tree

scripts/online_eval_rules/create_online_eval_rules.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ def build_parser() -> argparse.ArgumentParser:
3636
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
3737
sub = parser.add_subparsers(dest="command", required=True)
3838

39-
def add_common(p: argparse.ArgumentParser) -> None:
40-
p.add_argument("--surface", choices=["sdk", "rest"], default="sdk",
41-
help="Which surface runs on a live call (default: sdk). DRY_RUN always prints both.")
39+
def add_common(p: argparse.ArgumentParser, *, surface: bool = True) -> None:
40+
if surface:
41+
p.add_argument("--surface", choices=["sdk", "rest"], default="sdk",
42+
help="Surface for a live call (default: sdk). DRY_RUN always prints both.")
4243
p.add_argument("--project", default=DEFAULT_PROJECT, help="Project name (created if absent).")
4344
p.add_argument("--dry-run", action="store_true", help="Print SDK + curl; touch nothing.")
4445

@@ -64,7 +65,7 @@ def add_create(p: argparse.ArgumentParser) -> None:
6465

6566
p_upd = sub.add_parser("update",
6667
help="Update a rule's sampling rate and/or enabled flag (always uses REST).")
67-
add_common(p_upd)
68+
add_common(p_upd, surface=False) # update has no SDK path; don't offer a --surface no-op
6869
p_upd.add_argument("--id", required=True, help="Rule id (UUID).")
6970
p_upd.add_argument("--sampling-rate", type=float, default=None, help="New sampling rate.")
7071
enabled = p_upd.add_mutually_exclusive_group()
@@ -145,8 +146,9 @@ def _dump(result) -> str:
145146

146147
def _dispatch_manage(args, dry_run: bool) -> int:
147148
if dry_run:
148-
print(f"[DRY RUN] would '{args.command}' via {getattr(args, 'surface', 'sdk')} "
149-
f"at {OPIK_URL}{EVALUATORS_PATH}")
149+
# update has no --surface (always REST); other manage commands default to sdk.
150+
surface = getattr(args, "surface", None) or "rest"
151+
print(f"[DRY RUN] would '{args.command}' via {surface} at {OPIK_URL}{EVALUATORS_PATH}")
150152
if args.command == "delete":
151153
print("[DRY RUN] delete requires --yes on a live run.")
152154
return 0
@@ -189,7 +191,7 @@ def _dispatch_manage(args, dry_run: bool) -> int:
189191
if args.surface == "sdk":
190192
via_sdk(client, "delete", rule_id=args.id, project_id=project_id)
191193
else:
192-
via_rest("delete", rule_id=args.id)
194+
via_rest("delete", rule_id=args.id, project_id=project_id)
193195
print(f"Deleted rule {args.id}.")
194196
return 0
195197
raise ValueError(f"unknown command: {args.command}")
@@ -334,7 +336,10 @@ def via_rest(op: str, *, payload=None, rule_id=None, project_id=None, session=No
334336
_check(resp)
335337
return resp
336338
if op == "delete":
337-
resp = http.post(f"{base}/delete", headers=headers, json={"ids": [rule_id]})
339+
# Pass project_id to match the SDK's delete_automation_rule_evaluator_batch, which scopes
340+
# the batch delete by project; requests drops params whose value is None.
341+
resp = http.post(f"{base}/delete", headers=headers, json={"ids": [rule_id]},
342+
params={"project_id": project_id})
338343
_check(resp)
339344
return resp
340345
raise ValueError(f"unknown op: {op}")

scripts/online_eval_rules/run.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ for cmd in create-llm-judge create-python create-thread create-span; do
1111
echo "=== ${cmd} ==="
1212
uv run create-online-eval-rules "${cmd}" --name "example-${cmd}"
1313
done
14+
15+
# The span-level Python metric is a distinct rule type (--python flag on create-span).
16+
echo "=== create-span --python ==="
17+
uv run create-online-eval-rules create-span --name "example-create-span-python" --python

scripts/online_eval_rules/test_create_online_eval_rules.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ def test_parser_defaults_surface_to_sdk():
2020
assert args.surface == "sdk"
2121

2222

23+
def test_update_rejects_surface_flag():
24+
# update has no SDK path; --surface must error loudly, not be a silent no-op.
25+
with pytest.raises(SystemExit):
26+
cli.build_parser().parse_args(["update", "--id", "x", "--surface", "sdk"])
27+
28+
2329
def test_build_payload_llm_judge_shape():
2430
p = cli.build_payload(cli.RULE_LLM_JUDGE, name="rel", project_id="pid",
2531
sampling_rate=0.5, model="gpt-4o")

0 commit comments

Comments
 (0)