Skip to content

Commit 80dfc73

Browse files
committed
Merge branch 'dev' of github.com:simvue-io/simvue-cli into dev
2 parents f692420 + 619e6dc commit 80dfc73

File tree

9 files changed

+640
-407
lines changed

9 files changed

+640
-407
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: bug
6+
assignees: ''
7+
8+
---
9+
10+
## Description of Bug
11+
A clear and concise description of what the bug is.
12+
13+
## Steps To Reproduce
14+
Steps to reproduce the behavior:
15+
1. Go to '...'
16+
2. Click on '....'
17+
3. Scroll down to '....'
18+
4. See error
19+
20+
## Expected behavior
21+
A clear and concise description of what you expected to happen.
22+
23+
## Actual Behaviour
24+
A clear and concise description of what you actually see happen.
25+
26+
## Screenshots
27+
If applicable, add screenshots to help explain your problem.
28+
29+
## Setup
30+
- OS: [e.g. Windows 11]
31+
- Python Version [e.g. v3.13.3]
32+
- Simvue Python API Version: [e.g v1.2.0]
33+
34+
## Additional context
35+
Add any other context about the problem here.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Feature request
3+
about: Suggest a new feature or enhancement to the Simvue CLI
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
## Problem Statement
11+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12+
13+
## Solution
14+
A clear and concise description of what you want to happen.
15+
16+
## Alternatives Considered
17+
A clear and concise description of any alternative solutions or features you've considered.
18+
19+
## Additional Context
20+
Add any other context or screenshots about the feature request here.

.github/workflows/deploy.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ jobs:
77
build:
88
name: Build Wheels and Package 🛠️
99
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
1012
steps:
1113
- name: Checkout Code
1214
uses: actions/checkout@v4

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "simvue-cli"
3-
version = "1.0.1"
3+
version = "1.0.2"
44
description = "Command Line Interface for interaction with a Simvue v3 server"
55
authors = [
66
{name = "Simvue Development Team", email = "[email protected]"}
@@ -35,7 +35,7 @@ keywords = [
3535
dependencies = [
3636
"click-option-group>=0.5.7",
3737
"click>=8.1.8",
38-
"simvue>=2.1.0",
38+
"simvue>=2.1.1",
3939
"click-log>=0.4.0",
4040
"click-params>=0.5.0",
4141
"toml>=0.10.2",

src/simvue_cli/actions.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,31 @@ def create_user_alert(
436436
return _alert
437437

438438

439+
def trigger_user_alert(
440+
run_id: str, alert_id: str, status: typing.Literal["ok", "critical"]
441+
) -> None:
442+
"""Trigger a manually defined user alert.
443+
444+
Parameters
445+
----------
446+
run_id: str
447+
the unique identifier for the run to alert on
448+
alert_id : str
449+
the unique identifier for the alert
450+
status: Literal['ok', 'critical']
451+
the state to set the alert to
452+
453+
"""
454+
_alert = get_alert(alert_id=alert_id)
455+
456+
if not isinstance(_alert, UserAlert):
457+
raise ValueError(f"Alert '{alert_id}' is not a user alert.")
458+
459+
_alert.read_only(False)
460+
_alert.set_status(run_id=run_id, status=status)
461+
_alert.commit()
462+
463+
439464
def create_simvue_user(
440465
username: str,
441466
email: str,

src/simvue_cli/cli/__init__.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,31 @@ def simvue_alert(ctx) -> None:
507507
pass
508508

509509

510+
@simvue_alert.command("trigger")
511+
@click.pass_context
512+
@click.argument("run_id")
513+
@click.argument("alert_id")
514+
@click.option(
515+
"--ok",
516+
"is_ok",
517+
is_flag=True,
518+
help="Set alert to status 'ok' as opposed to critical.",
519+
show_default=True,
520+
)
521+
def trigger_alert(ctx, is_ok: bool, **kwargs) -> None:
522+
"""Trigger a user alert"""
523+
try:
524+
simvue_cli.actions.trigger_user_alert(
525+
status="ok" if is_ok else "critical", **kwargs
526+
)
527+
except ValueError as e:
528+
if ctx.obj["plain"]:
529+
print(e.args[0])
530+
else:
531+
click.secho(e.args[0], fg="red", bold=True)
532+
sys.exit(1)
533+
534+
510535
@simvue_alert.command("list")
511536
@click.pass_context
512537
@click.option(
@@ -927,7 +952,6 @@ def simvue_tag(ctx) -> None:
927952
@click.option("--reverse", help="Reverse ordering", default=False, is_flag=True)
928953
def tag_list(
929954
ctx,
930-
count: int,
931955
enumerate_: bool,
932956
created: bool,
933957
table_format: str | None,
@@ -1131,7 +1155,6 @@ def tenant_list(
11311155
ctx,
11321156
table_format: str,
11331157
enumerate_: bool,
1134-
count: int,
11351158
max_runs: bool,
11361159
max_data_volume: bool,
11371160
max_request_rate: bool,
@@ -1215,7 +1238,6 @@ def user(ctx) -> None:
12151238
def list_user(
12161239
ctx,
12171240
enumerate_: bool,
1218-
count: int,
12191241
table_format: str | None,
12201242
username: bool,
12211243
email: bool,
@@ -1521,6 +1543,7 @@ def delete_storage(ctx, storage_ids: list[str] | None, interactive: bool) -> Non
15211543
@click.pass_context
15221544
@click.option(
15231545
"--format",
1546+
"table_format",
15241547
type=click.Choice(list(tabulate._table_formats.keys())),
15251548
help="Display as table with output format",
15261549
default=None,
@@ -1548,7 +1571,7 @@ def delete_storage(ctx, storage_ids: list[str] | None, interactive: bool) -> Non
15481571
@click.option("--enabled", is_flag=True, help="Show if storage is enabled")
15491572
def list_storages(
15501573
ctx,
1551-
format: str,
1574+
table_format: str,
15521575
backend: bool,
15531576
tenant_usable: bool,
15541577
default: bool,
@@ -1578,7 +1601,7 @@ def list_storages(
15781601
storages,
15791602
plain_text=ctx.obj["plain"],
15801603
enumerate_=enumerate_,
1581-
format=format,
1604+
format=table_format,
15821605
)
15831606
click.echo(table)
15841607

@@ -1622,6 +1645,7 @@ def simvue_artifact(ctx):
16221645
@click.pass_context
16231646
@click.option(
16241647
"--format",
1648+
"table_format",
16251649
type=click.Choice(list(tabulate._table_formats.keys())),
16261650
help="Display as table with output format",
16271651
default=None,
@@ -1669,10 +1693,9 @@ def simvue_artifact(ctx):
16691693
show_default=True,
16701694
)
16711695
@click.option("--reverse", help="Reverse ordering", default=False, is_flag=True)
1672-
@click.pass_context
16731696
def artifact_list(
16741697
ctx,
1675-
format_: str,
1698+
table_format: str | None,
16761699
enumerate_: bool,
16771700
original_path: bool,
16781701
storage: bool,
@@ -1713,7 +1736,7 @@ def artifact_list(
17131736
storages,
17141737
plain_text=ctx.obj["plain"],
17151738
enumerate_=enumerate_,
1716-
format=format,
1739+
format=table_format,
17171740
)
17181741
click.echo(table)
17191742

tests/test_command_line_interface.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
from logging import critical
12
import random
23
import string
4+
import typing
35
from uuid import uuid4
46
from _pytest.compat import LEGACY_PATH
57
from simvue.api.objects import Alert, Storage, Tenant, User
@@ -252,6 +254,31 @@ def test_user_alert() -> None:
252254
Alert(identifier=_alert)
253255

254256

257+
@pytest.mark.parametrize("status", ("ok", "critical"))
258+
def test_user_alert_trigger(create_plain_run: tuple[simvue.Run, dict], status: typing.Literal["ok", "critical"]) -> None:
259+
run, _ = create_plain_run
260+
_alert_id = run.create_user_alert(
261+
name="test_user_alert_triggered_alert_cli",
262+
description="Test alert for CLI triggering",
263+
trigger_abort=True
264+
)
265+
_command = [
266+
"alert",
267+
"trigger",
268+
run.id,
269+
_alert_id
270+
]
271+
runner = click.testing.CliRunner()
272+
result = runner.invoke(
273+
sv_cli.simvue,
274+
_command + ([] if status == "critical" else ["--ok"])
275+
)
276+
assert result.exit_code == 0, result.output
277+
_alert: UserAlert = Alert(_alert_id)
278+
assert _alert.get_status(run.id) == status
279+
280+
281+
255282
def test_server_ping() -> None:
256283
runner = click.testing.CliRunner()
257284
result = runner.invoke(
@@ -337,8 +364,9 @@ def test_artifact_list(create_test_run: tuple[simvue.Run, dict]) -> None:
337364
"--mime-type",
338365
"--count=20",
339366
"--enumerate",
340-
f"--format=simple"
341-
]
367+
"--format=simple"
368+
],
369+
catch_exceptions=False
342370
)
343371
assert result.exit_code == 0, result.output
344372
assert run_data["file_1"] in result.output

tests/unit/test_cli_actions.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
import time
33
import re
44
import pathlib
5+
import typing
56
import pytest
67
import uuid
78
import os
89
import simvue
910
from simvue.api.objects import Alert, Run, Events, Storage, Tenant, User
1011
from simvue.exception import ObjectNotFoundError
12+
from simvue.run import UserAlert
1113
import simvue_cli.actions
1214

1315

@@ -162,3 +164,20 @@ def test_run_abort(create_test_run, monkeypatch) -> None:
162164
assert _run._status == "terminated"
163165

164166

167+
@pytest.mark.parametrize(
168+
"status", ("ok", "critical")
169+
)
170+
def test_user_alert_triggered(create_plain_run: tuple[simvue.Run, dict], status: typing.Literal["ok", "critical"]) -> None:
171+
run, _ = create_plain_run
172+
_alert_id = run.create_user_alert(
173+
name="test_user_alert_triggered_alert",
174+
description="Test alert for CLI triggering",
175+
trigger_abort=True
176+
)
177+
simvue_cli.actions.trigger_user_alert(
178+
run.id,
179+
_alert_id,
180+
status
181+
)
182+
_alert: UserAlert = Alert(_alert_id)
183+
assert _alert.get_status(run.id) == status

0 commit comments

Comments
 (0)