Skip to content

Commit 32eb9a1

Browse files
Merge pull request #13 from Veridise:nikos/projects-work
Nikos/projects-work
2 parents ce80742 + b54a892 commit 32eb9a1

22 files changed

+707
-162
lines changed

audithub_client/__main__.py

Lines changed: 7 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import logging
2-
import sys
31
from typing import Annotated, Literal
42

53
from cyclopts import Group, Parameter
64

7-
from .library.context import AuditHubContext
8-
from .library.invocation_common import app
5+
from audithub_client.library.logging_level import set_logging_level
96

10-
app.meta.group_parameters = Group("Global Parameters")
7+
from .library.invocation_common import app
118
from .scripts.create_version_via_local_archive import ( # noqa
129
create_version_via_local_archive,
1310
)
@@ -23,6 +20,7 @@
2320
from .scripts.get_users import get_users # noqa
2421
from .scripts.get_version_archive import get_version_archive # noqa
2522
from .scripts.monitor_task import monitor_task # noqa
23+
from .scripts.qa_cleanup import qa_cleanup # noqa
2624
from .scripts.start_orca_task import start_orca_task # noqa
2725
from .scripts.start_picus_v2_task import start_picus_v2_task # noqa
2826
from .scripts.start_vanguard_task import ( # noqa
@@ -31,45 +29,12 @@
3129
start_zk_vanguard_task,
3230
)
3331

34-
35-
class LevelFormatter(logging.Formatter):
36-
def __init__(self, formats, default_fmt=None):
37-
super().__init__()
38-
self.formats = formats
39-
self.default_fmt = default_fmt or "%(levelname)s: %(message)s"
40-
41-
def format(self, record):
42-
fmt = self.formats.get(record.levelno, self.default_fmt)
43-
formatter = logging.Formatter(fmt)
44-
return formatter.format(record)
32+
app.meta.group_parameters = Group("Global Parameters", sort_key=99)
4533

4634

4735
@app.meta.default
4836
def meta(
4937
*tokens: Annotated[str, Parameter(show=False, allow_leading_hyphen=True)],
50-
base_url: Annotated[
51-
str, Parameter(env_var="AUDITHUB_BASE_URL", help="AuditHub base URL")
52-
],
53-
oidc_configuration_url: Annotated[
54-
str,
55-
Parameter(
56-
env_var="AUDITHUB_OIDC_CONFIGURATION_URL",
57-
help="AuditHub OpenID Connect configuration URL",
58-
),
59-
],
60-
oidc_client_id: Annotated[
61-
str,
62-
Parameter(
63-
env_var="AUDITHUB_OIDC_CLIENT_ID", help="AuditHub OpenID Connect client id"
64-
),
65-
],
66-
oidc_client_secret: Annotated[
67-
str,
68-
Parameter(
69-
env_var="AUDITHUB_OIDC_CLIENT_SECRET",
70-
help="AuditHub OpenID Connect client secret. Please note that this is confidential information.",
71-
),
72-
],
7338
log_level: Annotated[
7439
Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
7540
Parameter(
@@ -79,49 +44,11 @@ def meta(
7944
),
8045
] = "INFO",
8146
):
82-
# Leave all levels except DEBUG "simple", without outputting the module name.
83-
# At debug level, also show the module name that produces the log message.
84-
default_log_format = "%(asctime)s %(levelname)s %(message)s"
85-
debug_log_format = "%(asctime)s %(levelname)s %(name)s %(message)s"
86-
87-
# Setup logging as usual
88-
logging.basicConfig(
89-
level=log_level,
90-
format=default_log_format,
91-
datefmt="%H:%M:%S",
92-
stream=sys.stderr,
93-
)
94-
# Now modify the root logger
95-
root_logger = logging.getLogger()
96-
handler = root_logger.handlers[0] # basicConfig creates one handler by default
97-
handler.setFormatter(
98-
LevelFormatter(
99-
{logging.DEBUG: debug_log_format}, default_fmt=default_log_format
100-
)
101-
)
102-
103-
# For these modules, raise the log level to reduce noise
104-
for module in ["httpx", "httpcore"]:
105-
module_logger = logging.getLogger(module)
106-
module_logger.setLevel(logging.WARNING)
47+
set_logging_level(log_level)
10748

10849
command, bound, _ignored = app.parse_args(tokens)
109-
# When this script runs with no args, help_print is automatically invoked
110-
# Only in this situation however, it fails with: "TypeError: App.help_print() got an unexpected keyword argument 'rpc_context'"
111-
# By only, I mean it does not fail when invoked with "--help".
112-
# So let's treat it differently
113-
if command == app.help_print:
114-
return command(*bound.args, **bound.kwargs)
115-
return command(
116-
*bound.args,
117-
**bound.kwargs,
118-
rpc_context=AuditHubContext(
119-
base_url=base_url,
120-
oidc_configuration_url=oidc_configuration_url,
121-
oidc_client_id=oidc_client_id,
122-
oidc_client_secret=oidc_client_secret,
123-
),
124-
)
50+
51+
return command(*bound.args, **bound.kwargs)
12552

12653

12754
def main():
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env python3
2+
from dataclasses import dataclass
3+
4+
from ..library.auth import authentication_retry
5+
from ..library.context import AuditHubContext
6+
from ..library.http import POST
7+
from ..library.net_utils import ensure_success, response_json
8+
from .models import ProjectInfo
9+
10+
11+
@dataclass
12+
class CreateProjectArgs:
13+
organization_id: int
14+
project_definition: ProjectInfo
15+
temp_version_id: int | None
16+
17+
18+
def api_create_project(context: AuditHubContext, input: CreateProjectArgs) -> dict:
19+
params = {}
20+
if input.temp_version_id:
21+
params["temp_version_id"] = input.temp_version_id
22+
response = authentication_retry(
23+
context,
24+
POST,
25+
url=f"{context.base_url}/organizations/{input.organization_id}/projects",
26+
json=input.project_definition.model_dump(),
27+
params=params,
28+
)
29+
ensure_success(response)
30+
ret = response_json(response)
31+
return ret
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env python3
2+
from dataclasses import dataclass
3+
4+
from ..library.auth import authentication_retry
5+
from ..library.context import AuditHubContext
6+
from ..library.http import POST
7+
from ..library.net_utils import ensure_success, response_json
8+
9+
10+
@dataclass
11+
class CreateTempVersionViaLocalArchiveArgs:
12+
organization_id: int
13+
name: str
14+
15+
16+
def api_create_temp_version_via_local_archive(
17+
context: AuditHubContext, input: CreateTempVersionViaLocalArchiveArgs, fp
18+
):
19+
data = {"name": input.name}
20+
21+
response = authentication_retry(
22+
context,
23+
POST,
24+
url=f"{context.base_url}/organizations/{input.organization_id}/temp-versions",
25+
data=data,
26+
files={"archive": ("sources.zip", fp, "application/zip")},
27+
)
28+
ensure_success(response)
29+
ret = response_json(response)
30+
return ret
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env python3
2+
from dataclasses import dataclass
3+
from typing import Literal, Optional
4+
5+
from ..library.auth import authentication_retry
6+
from ..library.context import AuditHubContext
7+
from ..library.http import POST
8+
from ..library.net_utils import ensure_success, response_json
9+
from ..library.utils import get_dict_of_fields_except
10+
11+
12+
@dataclass
13+
class CreateTempVersionViaUrlArgs:
14+
organization_id: int
15+
name: str
16+
input_type: Literal["git", "archive"]
17+
url: str
18+
revision: Optional[str] = None
19+
includes_submodules: Optional[bool] = None
20+
21+
22+
def api_create_temp_version_via_url(
23+
context: AuditHubContext, input: CreateTempVersionViaUrlArgs
24+
):
25+
data = get_dict_of_fields_except(input, {"organization_id"})
26+
27+
response = authentication_retry(
28+
context,
29+
POST,
30+
url=f"{context.base_url}/organizations/{input.organization_id}/temp-versions-url",
31+
data=data,
32+
)
33+
ensure_success(response)
34+
ret = response_json(response)
35+
return ret

audithub_client/api/get_configuration.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
from ..library.context import AuditHubContext
44
from ..library.http import get
55
from ..library.net_utils import ensure_success, response_json
6+
from ..library.ssl import get_verify_ssl
67

78

89
def api_get_configuration(context: AuditHubContext):
9-
response = get(url=f"{context.base_url}/configuration")
10+
url = f"{context.base_url}/configuration"
11+
response = get(url=url, verify=get_verify_ssl(url))
1012
ensure_success(response)
1113
return response_json(response)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env python3
2+
from dataclasses import dataclass
3+
4+
from ..library.auth import authentication_retry
5+
from ..library.context import AuditHubContext
6+
from ..library.http import GET
7+
from ..library.net_utils import ensure_success, response_json
8+
9+
10+
@dataclass
11+
class GetLatestVersionArgs:
12+
organization_id: int
13+
project_id: int
14+
15+
16+
def api_get_latest_version(
17+
context: AuditHubContext, input: GetLatestVersionArgs
18+
) -> dict:
19+
response = authentication_retry(
20+
context,
21+
GET,
22+
url=f"{context.base_url}/organizations/{input.organization_id}/projects/{input.project_id}/versions/latest",
23+
)
24+
ensure_success(response)
25+
ret = response_json(response)
26+
return ret

audithub_client/api/get_project.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env python3
2+
from dataclasses import dataclass
3+
4+
from ..library.auth import authentication_retry
5+
from ..library.context import AuditHubContext
6+
from ..library.http import GET
7+
from ..library.net_utils import ensure_success, response_json
8+
9+
10+
@dataclass
11+
class GetProjectArgs:
12+
organization_id: int
13+
project_id: int
14+
15+
16+
def api_get_project(context: AuditHubContext, input: GetProjectArgs) -> dict:
17+
response = authentication_retry(
18+
context,
19+
GET,
20+
url=f"{context.base_url}/organizations/{input.organization_id}/projects/{input.project_id}",
21+
)
22+
ensure_success(response)
23+
ret = response_json(response)
24+
return ret
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from datetime import datetime
2+
from typing import Literal, Optional
3+
4+
from pydantic import BaseModel, Field, RootModel
5+
6+
7+
class EnvVar(BaseModel):
8+
name: str
9+
value: str
10+
11+
12+
class GitInput(BaseModel):
13+
url: str
14+
input_type: Literal["git"] = "git"
15+
includes_submodules: bool = False
16+
revision: Optional[str] = None
17+
18+
19+
class ArchiveInput(BaseModel):
20+
input_type: Literal["archive"] = "archive"
21+
url: Optional[str] = None
22+
23+
24+
class NPMProjectDependency(BaseModel):
25+
tool: Literal["npm", "yarn", "pnpm"]
26+
lockfile: bool
27+
node_version: Optional[str] = None
28+
29+
30+
class ProjectDependency(BaseModel):
31+
npm: Optional[NPMProjectDependency] = None
32+
foundry: Optional[bool] = False
33+
34+
35+
class ProjectInfo(BaseModel):
36+
name: str
37+
project_root: str
38+
env_vars: list[EnvVar] = Field(default_factory=list)
39+
dependencies: Optional[ProjectDependency] = None
40+
build_system: Optional[Literal["hardhat", "hardhat-ignition", "foundry"]] = None
41+
contents: Optional[list[Literal["circom", "solidity", "picus", "llzk"]]] = Field(
42+
default_factory=list
43+
)
44+
src_path: str
45+
include_path: Optional[str] = None
46+
specs_path: Optional[str] = None
47+
hints_path: Optional[str] = None
48+
deployment_script_path: Optional[str] = None
49+
input_info: GitInput | ArchiveInput
50+
51+
52+
class Project(ProjectInfo):
53+
id: int
54+
created_at: datetime
55+
56+
57+
class IdAndMessageResponse(BaseModel):
58+
id: int
59+
message: str
60+
61+
62+
class UserProfile(BaseModel):
63+
id: str
64+
name: str
65+
email: str
66+
rights: list[str]
67+
disable_online_notifications: bool
68+
disable_digest_notifications: bool
69+
70+
71+
class OrganizationAccessRestriction(BaseModel):
72+
function: str
73+
value: Optional[int] = None
74+
detector: Optional[str] = None
75+
76+
77+
OrganizationAccessRestrictions = RootModel[list[OrganizationAccessRestriction]]

audithub_client/api/monitor_task.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from websockets import ConnectionClosedOK
77
from websockets.sync.client import connect
88

9+
from audithub_client.library.ssl import get_websocket_ssl_context
10+
911
from ..library.auth import get_access_token, get_token_header
1012
from ..library.context import AuditHubContext
1113

@@ -39,7 +41,9 @@ def api_monitor_task(context: AuditHubContext, input: MonitorTaskArgs) -> bool:
3941
f"{url}/organizations/{input.organization_id}/tasks/{input.task_id}/progress"
4042
)
4143
status: ALLOWED_STATUS_OPTIONS
42-
with connect(endpoint, max_size=100 * 1024 * 1024) as websocket:
44+
with connect(
45+
endpoint, max_size=100 * 1024 * 1024, **get_websocket_ssl_context(url)
46+
) as websocket:
4347
try:
4448
# send initial authentication
4549
websocket.send(token)

0 commit comments

Comments
 (0)