arga-cli 0.1.2__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arga-cli
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Command-line interface for Arga authentication, MCP installation, and browser validation
5
5
  Author: Arga Labs
6
6
  Project-URL: Homepage, https://github.com/ArgaLabs/arga-cli
@@ -198,6 +198,7 @@ arga runs cancel <run_id>
198
198
  - `arga runs logs <run_id>` prints worker logs plus recent runtime logs for a run you own.
199
199
  - When you omit `<run_id>`, `arga runs logs` falls back to `./.arga-session.json` when present, which makes wizard-created twin sessions easy to inspect from the same directory.
200
200
  - Add `--json` to `arga runs logs` for a machine-readable response.
201
+ - Add `--errors-only` to keep only failed worker logs plus warning/error runtime entries.
201
202
  - `arga runs cancel <run_id>` cancels the run through the validation API.
202
203
 
203
204
  ### Git Wrappers
@@ -178,6 +178,7 @@ arga runs cancel <run_id>
178
178
  - `arga runs logs <run_id>` prints worker logs plus recent runtime logs for a run you own.
179
179
  - When you omit `<run_id>`, `arga runs logs` falls back to `./.arga-session.json` when present, which makes wizard-created twin sessions easy to inspect from the same directory.
180
180
  - Add `--json` to `arga runs logs` for a machine-readable response.
181
+ - Add `--errors-only` to keep only failed worker logs plus warning/error runtime entries.
181
182
  - `arga runs cancel <run_id>` cancels the run through the validation API.
182
183
 
183
184
  ### Git Wrappers
@@ -905,6 +905,40 @@ def _print_runtime_logs(runtime_logs: list[dict[str, Any]]) -> None:
905
905
  print()
906
906
 
907
907
 
908
+ def _is_error_runtime_log(runtime_log: dict[str, Any]) -> bool:
909
+ severity = str(runtime_log.get("severity") or "").strip().upper()
910
+ return severity in {"WARNING", "ERROR", "CRITICAL", "ALERT", "EMERGENCY"}
911
+
912
+
913
+ def _is_error_worker_log(worker_log: dict[str, Any]) -> bool:
914
+ status = str(worker_log.get("status") or "").strip().lower()
915
+ error = str(worker_log.get("error") or "").strip()
916
+ return status in {"failed", "error", "cancelled"} or bool(error)
917
+
918
+
919
+ def _filter_run_logs_payload(payload: dict[str, Any], *, errors_only: bool) -> dict[str, Any]:
920
+ if not errors_only:
921
+ return payload
922
+
923
+ filtered_payload = dict(payload)
924
+ worker_logs = payload.get("worker_logs")
925
+ runtime_logs = payload.get("runtime_logs")
926
+ warnings = payload.get("warnings")
927
+
928
+ filtered_payload["worker_logs"] = (
929
+ [item for item in worker_logs if isinstance(item, dict) and _is_error_worker_log(item)]
930
+ if isinstance(worker_logs, list)
931
+ else []
932
+ )
933
+ filtered_payload["runtime_logs"] = (
934
+ [item for item in runtime_logs if isinstance(item, dict) and _is_error_runtime_log(item)]
935
+ if isinstance(runtime_logs, list)
936
+ else []
937
+ )
938
+ filtered_payload["warnings"] = warnings if isinstance(warnings, list) else []
939
+ return filtered_payload
940
+
941
+
908
942
  def _print_run_logs(payload: dict[str, Any], fallback_run_id: str) -> None:
909
943
  run = payload.get("run")
910
944
  run_data = run if isinstance(run, dict) else {}
@@ -996,6 +1030,8 @@ def run_runs_logs(args: argparse.Namespace) -> int:
996
1030
  finally:
997
1031
  client.close()
998
1032
 
1033
+ payload = _filter_run_logs_payload(payload, errors_only=args.errors_only)
1034
+
999
1035
  if args.json:
1000
1036
  print(json.dumps(payload, indent=2))
1001
1037
  return 0
@@ -1291,6 +1327,11 @@ def build_parser() -> argparse.ArgumentParser:
1291
1327
  help=f"Validation run ID. Defaults to {WIZARD_SESSION_FILE} in the current directory when available.",
1292
1328
  )
1293
1329
  runs_logs_parser.add_argument("--json", action="store_true", help="Print the raw JSON response")
1330
+ runs_logs_parser.add_argument(
1331
+ "--errors-only",
1332
+ action="store_true",
1333
+ help="Show only failed worker logs and warning/error runtime logs",
1334
+ )
1294
1335
  runs_logs_parser.set_defaults(func=run_runs_logs)
1295
1336
 
1296
1337
  runs_cancel_parser = runs_subparsers.add_parser("cancel", help="Cancel a validation run")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arga-cli
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Command-line interface for Arga authentication, MCP installation, and browser validation
5
5
  Author: Arga Labs
6
6
  Project-URL: Homepage, https://github.com/ArgaLabs/arga-cli
@@ -198,6 +198,7 @@ arga runs cancel <run_id>
198
198
  - `arga runs logs <run_id>` prints worker logs plus recent runtime logs for a run you own.
199
199
  - When you omit `<run_id>`, `arga runs logs` falls back to `./.arga-session.json` when present, which makes wizard-created twin sessions easy to inspect from the same directory.
200
200
  - Add `--json` to `arga runs logs` for a machine-readable response.
201
+ - Add `--errors-only` to keep only failed worker logs plus warning/error runtime entries.
201
202
  - `arga runs cancel <run_id>` cancels the run through the validation API.
202
203
 
203
204
  ### Git Wrappers
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "arga-cli"
7
- version = "0.1.2"
7
+ version = "0.1.3"
8
8
  description = "Command-line interface for Arga authentication, MCP installation, and browser validation"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -293,6 +293,117 @@ def test_runs_logs_prints_json(monkeypatch, capsys) -> None:
293
293
  assert json.loads(output) == payload
294
294
 
295
295
 
296
+ def test_runs_logs_errors_only_filters_plain_output(monkeypatch, capsys) -> None:
297
+ monkeypatch.setattr(main, "load_api_key", lambda: "arga_api_key")
298
+ monkeypatch.setattr(main.ApiClient, "close", lambda self: None)
299
+
300
+ def fake_get_logs(self, run_id: str):
301
+ assert run_id == "run_123"
302
+ return {
303
+ "run": {
304
+ "id": run_id,
305
+ "status": "ready",
306
+ "run_type": "twin_quickstart",
307
+ "mode": "staging",
308
+ "repo_full_name": None,
309
+ "commit_sha": None,
310
+ "created_at": "2026-03-25T12:30:00Z",
311
+ "environment_url": "https://preview.example.com",
312
+ "event_log_json": [],
313
+ },
314
+ "worker_logs": [
315
+ {
316
+ "job_id": "job_ok",
317
+ "job_type": "build",
318
+ "target_role": "builder",
319
+ "status": "succeeded",
320
+ "content": "all good",
321
+ "truncated": False,
322
+ "error": None,
323
+ },
324
+ {
325
+ "job_id": "job_bad",
326
+ "job_type": "deploy",
327
+ "target_role": "warm-vm",
328
+ "status": "failed",
329
+ "content": "deploy failed output",
330
+ "truncated": False,
331
+ "error": None,
332
+ },
333
+ ],
334
+ "runtime_logs": [
335
+ {
336
+ "timestamp": "2026-03-25T12:31:00Z",
337
+ "service_name": "arga-api",
338
+ "severity": "INFO",
339
+ "event": "environment_ready",
340
+ "code": None,
341
+ "request_id": "req_ok",
342
+ "job_id": None,
343
+ "surface_name": None,
344
+ "message": "Environment ready.",
345
+ },
346
+ {
347
+ "timestamp": "2026-03-25T12:32:00Z",
348
+ "service_name": "preview-proxy",
349
+ "severity": "WARNING",
350
+ "event": "preview.request.finish",
351
+ "code": None,
352
+ "request_id": "req_warn",
353
+ "job_id": None,
354
+ "surface_name": "slack",
355
+ "message": "Preview request completed.",
356
+ },
357
+ ],
358
+ "warnings": ["Cloud Logging query was partially truncated."],
359
+ }
360
+
361
+ monkeypatch.setattr(main.ApiClient, "get_run_logs", fake_get_logs)
362
+
363
+ args = main.build_parser().parse_args(["runs", "logs", "run_123", "--errors-only"])
364
+ exit_code = args.func(args)
365
+ output = capsys.readouterr().out
366
+
367
+ assert exit_code == 0
368
+ assert "job_bad" in output
369
+ assert "deploy failed output" in output
370
+ assert "job_ok" not in output
371
+ assert "all good" not in output
372
+ assert "Preview request completed." in output
373
+ assert "Environment ready." not in output
374
+ assert "Warnings:" in output
375
+
376
+
377
+ def test_runs_logs_errors_only_filters_json(monkeypatch, capsys) -> None:
378
+ monkeypatch.setattr(main, "load_api_key", lambda: "arga_api_key")
379
+ monkeypatch.setattr(main.ApiClient, "close", lambda self: None)
380
+
381
+ payload = {
382
+ "run": {"id": "run_123", "status": "ready"},
383
+ "worker_logs": [
384
+ {"job_id": "job_ok", "status": "succeeded", "error": None},
385
+ {"job_id": "job_bad", "status": "failed", "error": None},
386
+ ],
387
+ "runtime_logs": [
388
+ {"severity": "INFO", "message": "Environment ready."},
389
+ {"severity": "WARNING", "message": "Preview request completed."},
390
+ ],
391
+ "warnings": ["Cloud Logging query was partially truncated."],
392
+ }
393
+
394
+ monkeypatch.setattr(main.ApiClient, "get_run_logs", lambda self, run_id: payload)
395
+
396
+ args = main.build_parser().parse_args(["runs", "logs", "run_123", "--json", "--errors-only"])
397
+ exit_code = args.func(args)
398
+ output = capsys.readouterr().out
399
+
400
+ assert exit_code == 0
401
+ parsed = json.loads(output)
402
+ assert parsed["worker_logs"] == [{"job_id": "job_bad", "status": "failed", "error": None}]
403
+ assert parsed["runtime_logs"] == [{"severity": "WARNING", "message": "Preview request completed."}]
404
+ assert parsed["warnings"] == ["Cloud Logging query was partially truncated."]
405
+
406
+
296
407
  def test_runs_logs_uses_wizard_session_file_when_run_id_missing(monkeypatch, capsys, tmp_path) -> None:
297
408
  monkeypatch.chdir(tmp_path)
298
409
  (tmp_path / main.WIZARD_SESSION_FILE).write_text(json.dumps({"run_id": "run_from_session"}) + "\n")
File without changes
File without changes
File without changes
File without changes
File without changes