harbor-check-cli 0.1.0__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.
@@ -0,0 +1,76 @@
1
+ Metadata-Version: 2.4
2
+ Name: harbor-check-cli
3
+ Version: 0.1.0
4
+ Summary: CLI for Harbor Check review status and rubric summaries
5
+ License: MIT
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Environment :: Console
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: httpx>=0.27
11
+
12
+ # Harbor Check CLI
13
+
14
+ Install with `python -m pip install ./saas/harbor-check-cli`.
15
+
16
+ Login once; the token is stored with mode 0600 and reused by later commands:
17
+
18
+ ```bash
19
+ harbor-check login --server 101.46.8.169 --username alice --password 'secret'
20
+ harbor-check tasks
21
+ ```
22
+
23
+ An address without a scheme is treated as `http://`; use `--server
24
+ http://101.46.8.169:8000` when Harbor Check is listening on a non-default port.
25
+
26
+ ```bash
27
+ harbor-check --server https://review.example.com tasks
28
+ harbor-check --server https://review.example.com folders
29
+ harbor-check --server https://review.example.com folder-tasks batch-name
30
+ ```
31
+
32
+ The CLI authenticates with the server's `/api/auth/login` endpoint. Configure
33
+ Django with `HARBOR_CHECK_AUTH_REQUIRED=1` and `HARBOR_CHECK_USERS_JSON`.
34
+ Values may be plaintext for local development or `pbkdf2_sha256$rounds$salt$hex`
35
+ hashes for deployment. Authenticated users can see all users' tasks and folders.
36
+ Use `--json` for machine-readable output.
37
+
38
+ For cloud hosts whose users are real SSH/system accounts, set
39
+ `HARBOR_CHECK_OS_AUTH=1` on the server. The login endpoint then verifies the
40
+ same username/password against the server's SSH daemon (optionally using
41
+ `HARBOR_CHECK_SSH_HOST`). This lets a laptop authenticate without copying the
42
+ password into the application database.
43
+
44
+ Plain HTTP exposes the login password and review data to anyone able to observe
45
+ the network path. For public access, put Django behind HTTPS, or use an SSH
46
+ tunnel from the laptop:
47
+
48
+ ```bash
49
+ ssh -N -L 8000:127.0.0.1:8000 alice@101.46.8.169
50
+ harbor-check login --server http://127.0.0.1:8000 --username alice
51
+ ```
52
+
53
+
54
+ ## Install and use from `101.46.8.169`
55
+
56
+ On a laptop with network access to the server:
57
+
58
+ ```bash
59
+ python -m pip install --upgrade harbor-check-cli
60
+ harbor-check login --server http://101.46.8.169:8000 --username YOUR_SERVER_USERNAME
61
+ harbor-check tasks
62
+ harbor-check folders
63
+ harbor-check folder-tasks YOUR_FOLDER_NAME
64
+ ```
65
+
66
+ The token is stored in `~/.config/harbor-check/credentials.json` with 0600
67
+ permissions. Use `--json` for scripts. If the server is exposed only through
68
+ SSH, create a tunnel first:
69
+
70
+ ```bash
71
+ ssh -N -L 8000:127.0.0.1:8000 YOUR_SERVER_USERNAME@101.46.8.169
72
+ harbor-check login --server http://127.0.0.1:8000 --username YOUR_SERVER_USERNAME
73
+ ```
74
+
75
+ The server must enable `HARBOR_CHECK_AUTH_REQUIRED=1` and configure either
76
+ `HARBOR_CHECK_USERS_JSON` or `HARBOR_CHECK_OS_AUTH=1`.
@@ -0,0 +1,65 @@
1
+ # Harbor Check CLI
2
+
3
+ Install with `python -m pip install ./saas/harbor-check-cli`.
4
+
5
+ Login once; the token is stored with mode 0600 and reused by later commands:
6
+
7
+ ```bash
8
+ harbor-check login --server 101.46.8.169 --username alice --password 'secret'
9
+ harbor-check tasks
10
+ ```
11
+
12
+ An address without a scheme is treated as `http://`; use `--server
13
+ http://101.46.8.169:8000` when Harbor Check is listening on a non-default port.
14
+
15
+ ```bash
16
+ harbor-check --server https://review.example.com tasks
17
+ harbor-check --server https://review.example.com folders
18
+ harbor-check --server https://review.example.com folder-tasks batch-name
19
+ ```
20
+
21
+ The CLI authenticates with the server's `/api/auth/login` endpoint. Configure
22
+ Django with `HARBOR_CHECK_AUTH_REQUIRED=1` and `HARBOR_CHECK_USERS_JSON`.
23
+ Values may be plaintext for local development or `pbkdf2_sha256$rounds$salt$hex`
24
+ hashes for deployment. Authenticated users can see all users' tasks and folders.
25
+ Use `--json` for machine-readable output.
26
+
27
+ For cloud hosts whose users are real SSH/system accounts, set
28
+ `HARBOR_CHECK_OS_AUTH=1` on the server. The login endpoint then verifies the
29
+ same username/password against the server's SSH daemon (optionally using
30
+ `HARBOR_CHECK_SSH_HOST`). This lets a laptop authenticate without copying the
31
+ password into the application database.
32
+
33
+ Plain HTTP exposes the login password and review data to anyone able to observe
34
+ the network path. For public access, put Django behind HTTPS, or use an SSH
35
+ tunnel from the laptop:
36
+
37
+ ```bash
38
+ ssh -N -L 8000:127.0.0.1:8000 alice@101.46.8.169
39
+ harbor-check login --server http://127.0.0.1:8000 --username alice
40
+ ```
41
+
42
+
43
+ ## Install and use from `101.46.8.169`
44
+
45
+ On a laptop with network access to the server:
46
+
47
+ ```bash
48
+ python -m pip install --upgrade harbor-check-cli
49
+ harbor-check login --server http://101.46.8.169:8000 --username YOUR_SERVER_USERNAME
50
+ harbor-check tasks
51
+ harbor-check folders
52
+ harbor-check folder-tasks YOUR_FOLDER_NAME
53
+ ```
54
+
55
+ The token is stored in `~/.config/harbor-check/credentials.json` with 0600
56
+ permissions. Use `--json` for scripts. If the server is exposed only through
57
+ SSH, create a tunnel first:
58
+
59
+ ```bash
60
+ ssh -N -L 8000:127.0.0.1:8000 YOUR_SERVER_USERNAME@101.46.8.169
61
+ harbor-check login --server http://127.0.0.1:8000 --username YOUR_SERVER_USERNAME
62
+ ```
63
+
64
+ The server must enable `HARBOR_CHECK_AUTH_REQUIRED=1` and configure either
65
+ `HARBOR_CHECK_USERS_JSON` or `HARBOR_CHECK_OS_AUTH=1`.
@@ -0,0 +1,5 @@
1
+ """Client library and command line interface for Harbor Check."""
2
+
3
+ from .client import HarborCheckClient
4
+
5
+ __all__ = ["HarborCheckClient"]
@@ -0,0 +1,40 @@
1
+ import argparse, getpass, json, os, sys, asyncio
2
+ from pathlib import Path
3
+ import httpx
4
+ CONFIG=Path(os.getenv('XDG_CONFIG_HOME', Path.home()/'.config'))/'harbor-check'/'credentials.json'
5
+
6
+ class Client:
7
+ def __init__(self, base):
8
+ if '://' not in base: base='http://'+base
9
+ self.base=base.rstrip('/'); self.token=None
10
+ def login(self,u,p):
11
+ r=httpx.post(self.base+'/api/auth/login',json={'username':u,'password':p},timeout=20); r.raise_for_status(); self.token=r.json()['token']
12
+ def get(self,path):
13
+ r=httpx.get(self.base+path,headers={'Authorization':'Bearer '+self.token},timeout=30); r.raise_for_status(); return r.json()
14
+
15
+ def main():
16
+ ap=argparse.ArgumentParser(prog='harbor-check'); ap.add_argument('--server',default=os.getenv('HARBOR_CHECK_SERVER','http://127.0.0.1:8000')); ap.add_argument('--local',action='store_true',help='read the server workspace directly (only when running on the review server)'); ap.add_argument('--username'); ap.add_argument('--password'); ap.add_argument('--json',action='store_true'); sub=ap.add_subparsers(dest='cmd',required=True); login=sub.add_parser('login'); login.add_argument('--server',dest='login_server'); login.add_argument('--username',dest='login_username'); login.add_argument('--password',dest='login_password'); sub.add_parser('tasks'); sub.add_parser('folders'); f=sub.add_parser('folder-tasks'); f.add_argument('folder')
17
+ a=ap.parse_args()
18
+ try:
19
+ if a.cmd=='login':
20
+ server=a.login_server or a.server; u=a.login_username or input('Username: '); p=a.login_password or getpass.getpass('Password: '); c=Client(server); c.login(u,p); CONFIG.parent.mkdir(parents=True,exist_ok=True); CONFIG.write_text(json.dumps({'server':server,'username':u,'token':c.token})); CONFIG.chmod(0o600); print(f'Logged in to {server} as {u}'); return 0
21
+ if a.local:
22
+ repo=Path(os.getenv('HARBOR_CHECK_REPO',Path.cwd())); sys.path.insert(0,str(repo/'saas/harbor-check')); from app import all_tasks; data=asyncio.run(all_tasks())
23
+ else:
24
+ saved=json.loads(CONFIG.read_text()) if CONFIG.exists() else {}; c=Client(saved.get('server') or a.server); c.token=saved.get('token');
25
+ if not c.token:
26
+ u=a.username or input('Username: '); p=a.password or getpass.getpass('Password: '); c.login(u,p)
27
+ data=c.get('/api/tasks')
28
+ except Exception as e: print(f'harbor-check: {e}',file=sys.stderr); return 2
29
+ if a.cmd=='folder-tasks': data=[x for x in data if x['dirname']==a.folder]
30
+ if a.json: print(json.dumps(data,indent=2)); return 0
31
+ if a.cmd=='tasks':
32
+ print('USER/FOLDER/TASK | STATE | RUNTIME | LAST ACTIVE | FAILS BY CATEGORY')
33
+ for g in data:
34
+ for t in g.get('tasks',[]): print(f"{g['username']}/{g['dirname']}/{t['task']} | {t.get('state','-')} | {t.get('elapsed_seconds','-')}s | {t.get('last_activity_at','-')} | {json.dumps((t.get('result') or {}).get('failed_by_category',{}),sort_keys=True)}")
35
+ else:
36
+ print('USER/FOLDER | TASKS | FAILS BY CATEGORY | FAIL RATE')
37
+ for g in data:
38
+ rep=g.get('report') or {}; groups=rep.get('groups') or {}; total=sum(v.get('total',0) for v in groups.values()); fails=sum(v.get('fail',0) for v in groups.values()); cats={k:v.get('fail',0) for k,v in groups.items()}; print(f"{g['username']}/{g['dirname']} | {len(g.get('tasks',[]))} | {json.dumps(cats,sort_keys=True)} | {fails}/{total} ({(fails/total*100 if total else 0):.1f}%)")
39
+ return 0
40
+ if __name__=='__main__': raise SystemExit(main())
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+
3
+ import httpx
4
+
5
+
6
+ class HarborCheckClient:
7
+ """Small authenticated client for embedding Harbor Check in Python tools."""
8
+
9
+ def __init__(self, server: str, token: str | None = None):
10
+ if "://" not in server:
11
+ server = "http://" + server
12
+ self.server = server.rstrip("/")
13
+ self.token = token
14
+
15
+ def login(self, username: str, password: str) -> dict:
16
+ response = httpx.post(f"{self.server}/api/auth/login", json={"username": username, "password": password}, timeout=20)
17
+ response.raise_for_status()
18
+ payload = response.json()
19
+ self.token = payload["token"]
20
+ return payload
21
+
22
+ def tasks(self) -> list[dict]:
23
+ headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
24
+ response = httpx.get(f"{self.server}/api/tasks", headers=headers, timeout=30)
25
+ response.raise_for_status()
26
+ return response.json()
@@ -0,0 +1,76 @@
1
+ Metadata-Version: 2.4
2
+ Name: harbor-check-cli
3
+ Version: 0.1.0
4
+ Summary: CLI for Harbor Check review status and rubric summaries
5
+ License: MIT
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Environment :: Console
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: httpx>=0.27
11
+
12
+ # Harbor Check CLI
13
+
14
+ Install with `python -m pip install ./saas/harbor-check-cli`.
15
+
16
+ Login once; the token is stored with mode 0600 and reused by later commands:
17
+
18
+ ```bash
19
+ harbor-check login --server 101.46.8.169 --username alice --password 'secret'
20
+ harbor-check tasks
21
+ ```
22
+
23
+ An address without a scheme is treated as `http://`; use `--server
24
+ http://101.46.8.169:8000` when Harbor Check is listening on a non-default port.
25
+
26
+ ```bash
27
+ harbor-check --server https://review.example.com tasks
28
+ harbor-check --server https://review.example.com folders
29
+ harbor-check --server https://review.example.com folder-tasks batch-name
30
+ ```
31
+
32
+ The CLI authenticates with the server's `/api/auth/login` endpoint. Configure
33
+ Django with `HARBOR_CHECK_AUTH_REQUIRED=1` and `HARBOR_CHECK_USERS_JSON`.
34
+ Values may be plaintext for local development or `pbkdf2_sha256$rounds$salt$hex`
35
+ hashes for deployment. Authenticated users can see all users' tasks and folders.
36
+ Use `--json` for machine-readable output.
37
+
38
+ For cloud hosts whose users are real SSH/system accounts, set
39
+ `HARBOR_CHECK_OS_AUTH=1` on the server. The login endpoint then verifies the
40
+ same username/password against the server's SSH daemon (optionally using
41
+ `HARBOR_CHECK_SSH_HOST`). This lets a laptop authenticate without copying the
42
+ password into the application database.
43
+
44
+ Plain HTTP exposes the login password and review data to anyone able to observe
45
+ the network path. For public access, put Django behind HTTPS, or use an SSH
46
+ tunnel from the laptop:
47
+
48
+ ```bash
49
+ ssh -N -L 8000:127.0.0.1:8000 alice@101.46.8.169
50
+ harbor-check login --server http://127.0.0.1:8000 --username alice
51
+ ```
52
+
53
+
54
+ ## Install and use from `101.46.8.169`
55
+
56
+ On a laptop with network access to the server:
57
+
58
+ ```bash
59
+ python -m pip install --upgrade harbor-check-cli
60
+ harbor-check login --server http://101.46.8.169:8000 --username YOUR_SERVER_USERNAME
61
+ harbor-check tasks
62
+ harbor-check folders
63
+ harbor-check folder-tasks YOUR_FOLDER_NAME
64
+ ```
65
+
66
+ The token is stored in `~/.config/harbor-check/credentials.json` with 0600
67
+ permissions. Use `--json` for scripts. If the server is exposed only through
68
+ SSH, create a tunnel first:
69
+
70
+ ```bash
71
+ ssh -N -L 8000:127.0.0.1:8000 YOUR_SERVER_USERNAME@101.46.8.169
72
+ harbor-check login --server http://127.0.0.1:8000 --username YOUR_SERVER_USERNAME
73
+ ```
74
+
75
+ The server must enable `HARBOR_CHECK_AUTH_REQUIRED=1` and configure either
76
+ `HARBOR_CHECK_USERS_JSON` or `HARBOR_CHECK_OS_AUTH=1`.
@@ -0,0 +1,11 @@
1
+ README.md
2
+ pyproject.toml
3
+ harbor_check_cli/__init__.py
4
+ harbor_check_cli/__main__.py
5
+ harbor_check_cli/client.py
6
+ harbor_check_cli.egg-info/PKG-INFO
7
+ harbor_check_cli.egg-info/SOURCES.txt
8
+ harbor_check_cli.egg-info/dependency_links.txt
9
+ harbor_check_cli.egg-info/entry_points.txt
10
+ harbor_check_cli.egg-info/requires.txt
11
+ harbor_check_cli.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ harbor-check = harbor_check_cli.__main__:main
@@ -0,0 +1 @@
1
+ harbor_check_cli
@@ -0,0 +1,14 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+ [project]
5
+ name = "harbor-check-cli"
6
+ version = "0.1.0"
7
+ description = "CLI for Harbor Check review status and rubric summaries"
8
+ requires-python = ">=3.10"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ classifiers = ["Programming Language :: Python :: 3", "Environment :: Console"]
12
+ dependencies = ["httpx>=0.27"]
13
+ [project.scripts]
14
+ harbor-check = "harbor_check_cli.__main__:main"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+