Skip to content

Commit d18795d

Browse files
committed
feat: link cli-run to its full_scan via report_run_id on finalize
The depscan side now joins cli_run → full_scans → repositories via the report_run_id field to surface the scanned repo in the admin dashboard view of each CLI run. Wire the CLI to send the full_scan_id (== the report_run_id depscan expects) when it has one. - finalize_cli_run accepts an optional report_run_id and includes it (nullable) in the POST body. - streaming.py adds a module-level _report_run_id holder and a set_report_run_id() setter; teardown passes it through to finalize. - socketcli.py captures diff.id at a single chokepoint after the diff-producing branches converge, guarded against the NO_DIFF_RAN / NO_SCAN_RAN sentinel values. The field is nullable end-to-end so CLI invocations that fail before producing a diff (or are run in modes that don't create one) still finalize cleanly.
1 parent 03b6126 commit d18795d

5 files changed

Lines changed: 38 additions & 13 deletions

File tree

socketsecurity/core/cli_run.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@ def finalize_cli_run(
5151
client: CliClient,
5252
run_id: str,
5353
status: str = "success",
54+
report_run_id: Optional[str] = None,
5455
) -> None:
5556
try:
5657
client.request(
5758
path=f"python-cli-runs/{run_id}/finalize",
5859
method="POST",
59-
payload=json.dumps({"status": status}),
60+
payload=json.dumps({"status": status, "report_run_id": report_run_id}),
6061
)
6162
except Exception as e:
6263
log.debug(f"cli-run finalize failed (swallowed): {e}")

socketsecurity/core/streaming.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,19 @@
1717
from .log_uploader import BatchedLogUploader, UploadingLogHandler
1818

1919
_run_status: str = "success"
20+
_report_run_id: Optional[str] = None
2021

2122

2223
def set_run_status(status: str) -> None:
2324
global _run_status
2425
_run_status = status
2526

2627

28+
def set_report_run_id(report_run_id: Optional[str]) -> None:
29+
global _report_run_id
30+
_report_run_id = report_run_id
31+
32+
2733
def setup_streaming(
2834
*,
2935
client: CliClient,
@@ -66,7 +72,7 @@ def teardown() -> None:
6672
cli_logger.removeHandler(upload_handler)
6773
sdk_logger.removeHandler(upload_handler)
6874
log_uploader.stop()
69-
finalize_cli_run(client, run_id, status=_run_status)
75+
finalize_cli_run(client, run_id, status=_run_status, report_run_id=_report_run_id)
7076
cli_logger.removeHandler(terminal_handler)
7177
sdk_logger.removeHandler(terminal_handler)
7278
cli_logger.setLevel(saved_levels[0])

socketsecurity/socketcli.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from socketsecurity.core.messages import Messages
2222
from socketsecurity.core.scm_comments import Comments
2323
from socketsecurity.core.socket_config import SocketConfig
24-
from socketsecurity.core.streaming import set_run_status, setup_streaming
24+
from socketsecurity.core.streaming import set_report_run_id, set_run_status, setup_streaming
2525
from socketsecurity.output import OutputHandler
2626

2727
socket_logger, log = initialize_logging()
@@ -761,6 +761,9 @@ def _is_unprocessed(c):
761761
)
762762
output_handler.handle_output(diff)
763763

764+
if diff.id not in ("NO_DIFF_RAN", "NO_SCAN_RAN"):
765+
set_report_run_id(diff.id)
766+
764767
# Handle license generation
765768
if not should_skip_scan and diff.id != "NO_DIFF_RAN" and diff.id != "NO_SCAN_RAN" and config.generate_license:
766769
all_packages = {}

tests/unit/test_cli_run.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,22 @@ def test_register_cli_run_returns_none_on_bad_json():
4949
assert register_cli_run(client, client_version="1.0.0") is None
5050

5151

52-
def test_finalize_cli_run_posts_status():
52+
def test_finalize_cli_run_posts_status_and_null_report_run_id_by_default():
5353
client = Mock(spec=CliClient)
5454
finalize_cli_run(client, "run-x", status="failure")
5555

5656
args, kwargs = client.request.call_args
5757
assert kwargs["path"] == "python-cli-runs/run-x/finalize"
5858
assert kwargs["method"] == "POST"
59-
assert json.loads(kwargs["payload"]) == {"status": "failure"}
59+
assert json.loads(kwargs["payload"]) == {"status": "failure", "report_run_id": None}
60+
61+
62+
def test_finalize_cli_run_includes_report_run_id_when_provided():
63+
client = Mock(spec=CliClient)
64+
finalize_cli_run(client, "run-x", status="success", report_run_id="fs-abc")
65+
66+
body = json.loads(client.request.call_args.kwargs["payload"])
67+
assert body == {"status": "success", "report_run_id": "fs-abc"}
6068

6169

6270
def test_finalize_cli_run_swallows_errors():

tests/unit/test_streaming.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@
44
import pytest
55

66
import socketsecurity.core.streaming as streaming_mod
7-
from socketsecurity.core.streaming import set_run_status, setup_streaming
7+
from socketsecurity.core.streaming import (
8+
set_report_run_id,
9+
set_run_status,
10+
setup_streaming,
11+
)
812

913

1014
@pytest.fixture(autouse=True)
11-
def reset_run_status():
15+
def reset_streaming_state():
1216
streaming_mod._run_status = "success"
17+
streaming_mod._report_run_id = None
1318
yield
1419
streaming_mod._run_status = "success"
20+
streaming_mod._report_run_id = None
1521

1622

1723
def test_setup_streaming_returns_none_when_register_fails():
@@ -32,8 +38,8 @@ def test_teardown_finalizes_with_current_run_status():
3238

3339
finalize_calls = []
3440

35-
def fake_finalize(client, run_id, status="success"):
36-
finalize_calls.append(status)
41+
def fake_finalize(client, run_id, status="success", report_run_id=None):
42+
finalize_calls.append((status, report_run_id))
3743

3844
with patch("socketsecurity.core.streaming.register_cli_run", return_value="run-1"), \
3945
patch("socketsecurity.core.streaming.finalize_cli_run", side_effect=fake_finalize), \
@@ -49,9 +55,10 @@ def fake_finalize(client, run_id, status="success"):
4955
assert teardown is not None
5056

5157
set_run_status("failure")
58+
set_report_run_id("fs-xyz")
5259
teardown()
5360

54-
assert finalize_calls == ["failure"]
61+
assert finalize_calls == [("failure", "fs-xyz")]
5562

5663

5764
def test_set_run_status_default_is_success():
@@ -60,8 +67,8 @@ def test_set_run_status_default_is_success():
6067

6168
finalize_calls = []
6269

63-
def fake_finalize(client, run_id, status="success"):
64-
finalize_calls.append(status)
70+
def fake_finalize(client, run_id, status="success", report_run_id=None):
71+
finalize_calls.append((status, report_run_id))
6572

6673
with patch("socketsecurity.core.streaming.register_cli_run", return_value="run-2"), \
6774
patch("socketsecurity.core.streaming.finalize_cli_run", side_effect=fake_finalize), \
@@ -76,7 +83,7 @@ def fake_finalize(client, run_id, status="success"):
7683
)
7784
teardown()
7885

79-
assert finalize_calls == ["success"]
86+
assert finalize_calls == [("success", None)]
8087

8188

8289
def test_setup_streaming_restores_logger_state_on_teardown():

0 commit comments

Comments
 (0)