Skip to content

Commit 4607a2e

Browse files
committed
Add: Extend GitHub API for code scanning default setup
Implement the code scanning default setup API of GitHub.
1 parent 15b6df4 commit 4607a2e

File tree

4 files changed

+234
-1
lines changed

4 files changed

+234
-1
lines changed

pontos/github/api/code_scanning.py

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# SPDX-License-Identifier: GPL-3.0-or-later
44

5-
from typing import AsyncIterator, Optional, Union
5+
from typing import AsyncIterator, Iterable, Optional, Union
66

77
from pontos.github.api.client import GitHubAsyncREST
88
from pontos.github.models.base import SortOrder
@@ -12,8 +12,12 @@
1212
Analysis,
1313
CodeQLDatabase,
1414
CodeScanningAlert,
15+
DefaultSetup,
16+
DefaultSetupState,
1517
DismissedReason,
1618
Instance,
19+
Language,
20+
QuerySuite,
1721
Severity,
1822
)
1923
from pontos.helper import enum_or_value
@@ -535,3 +539,94 @@ async def codeql_database(
535539
response = await self._client.get(api)
536540
response.raise_for_status()
537541
return CodeQLDatabase.from_dict(response.json())
542+
543+
async def default_setup(
544+
self,
545+
repo: str,
546+
) -> DefaultSetup:
547+
"""
548+
Gets a code scanning default setup configuration
549+
550+
https://docs.github.com/en/rest/code-scanning/code-scanning#get-a-code-scanning-default-setup-configuration
551+
552+
Args:
553+
repo: GitHub repository (owner/name)
554+
555+
Raises:
556+
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
557+
failed.
558+
559+
Returns:
560+
Code scanning default setup
561+
562+
Example:
563+
.. code-block:: python
564+
565+
from pontos.github.api import GitHubAsyncRESTApi
566+
567+
async with GitHubAsyncRESTApi(token) as api:
568+
setup = await api.code_scanning.default_setup(
569+
"org/repo"
570+
)
571+
print(setup)
572+
"""
573+
574+
api = f"/repos/{repo}/code-scanning/default-setup"
575+
response = await self._client.get(api)
576+
response.raise_for_status()
577+
return DefaultSetup.from_dict(response.json())
578+
579+
async def update_default_setup(
580+
self,
581+
repo: str,
582+
state: Union[str, DefaultSetupState],
583+
query_suite: Union[str, QuerySuite],
584+
languages: Iterable[Union[str, Language]],
585+
) -> dict[str, str]:
586+
"""
587+
Updates a code scanning default setup configuration
588+
589+
https://docs.github.com/en/rest/code-scanning/code-scanning#update-a-code-scanning-default-setup-configuration
590+
591+
Args:
592+
repo: GitHub repository (owner/name)
593+
state: Whether code scanning default setup has been configured or
594+
not
595+
query_suite: CodeQL query suite to be used
596+
languages: CodeQL languages to be analyzed
597+
598+
Raises:
599+
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
600+
failed.
601+
602+
Returns:
603+
See the GitHub documentation for the response object
604+
605+
Example:
606+
.. code-block:: python
607+
608+
from pontos.github.api import GitHubAsyncRESTApi
609+
from pontos.github.models.code_scanning import (
610+
DefaultSetupState,
611+
Language,
612+
QuerySuite,
613+
)
614+
615+
async with GitHubAsyncRESTApi(token) as api:
616+
await api.code_scanning.update_default_setup(
617+
"org/repo",
618+
state=DefaultSetupState.CONFIGURED,
619+
query_suite=QuerySuite.EXTENDED,
620+
languages=[Language.PYTHON, Language.JAVASCRIPT]
621+
)
622+
"""
623+
624+
api = f"/repos/{repo}/code-scanning/code-scanning/default-setup"
625+
data = {
626+
"state": enum_or_value(state),
627+
"query_suite": enum_or_value(query_suite),
628+
"languages": [enum_or_value(value) for value in languages],
629+
}
630+
response = await self._client.patch(api, data=data)
631+
response.raise_for_status()
632+
return response.json()

pontos/github/models/code_scanning.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,58 @@ class CodeQLDatabase(GitHubModel):
313313
updated_at: datetime
314314
url: str
315315
commit_oid: Optional[str] = None
316+
317+
318+
class DefaultSetupState(Enum):
319+
"""
320+
State of a default setup
321+
"""
322+
323+
CONFIGURED = "configured"
324+
NOT_CONFIGURED = "not-configured"
325+
326+
327+
class Language(Enum):
328+
"""
329+
Analyzed Language
330+
"""
331+
332+
C_CPP = "c-cpp"
333+
CSHARP = "csharp"
334+
GO = "go"
335+
JAVA_KOTLIN = "java-kotlin"
336+
JAVASCRIPT_TYPESCRIPT = "javascript-typescript"
337+
JAVASCRIPT = "javascript"
338+
PYTHON = "python"
339+
RUBY = "ruby"
340+
TYPESCRIPT = "typescript"
341+
SWIFT = "swift"
342+
343+
344+
class QuerySuite(Enum):
345+
"""
346+
Used code scanning query suite
347+
"""
348+
349+
DEFAULT = "default"
350+
EXTENDED = "extended"
351+
352+
353+
@dataclass
354+
class DefaultSetup(GitHubModel):
355+
"""
356+
Code scanning default setup configuration
357+
358+
Attributes:
359+
state: Code scanning default setup has been configured or not
360+
languages: Languages to be analyzed
361+
query_suite: CodeQL query suite to be used
362+
updated_at: Timestamp of latest configuration update
363+
schedule: The frequency of the periodic analysis
364+
"""
365+
366+
state: DefaultSetupState
367+
languages: list[Language]
368+
query_suite: QuerySuite
369+
updated_at: Optional[datetime] = None
370+
schedule: Optional[str] = None

tests/github/api/test_code_scanning.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
from pontos.github.models.code_scanning import (
1010
AlertSort,
1111
AlertState,
12+
DefaultSetupState,
1213
DismissedReason,
14+
Language,
15+
QuerySuite,
1316
Severity,
1417
)
1518
from tests import AsyncIteratorMock, aiter, anext
@@ -1194,3 +1197,57 @@ async def test_codeql_database(self):
11941197
)
11951198

11961199
self.assertEqual(alert.id, 1)
1200+
1201+
async def test_default_setup(self):
1202+
response = create_response()
1203+
response.json.return_value = {
1204+
"state": "configured",
1205+
"languages": ["ruby", "python"],
1206+
"query_suite": "default",
1207+
"updated_at": "2023-01-19T11:21:34Z",
1208+
"schedule": "weekly",
1209+
}
1210+
self.client.get.return_value = response
1211+
1212+
setup = await self.api.default_setup(
1213+
"foo/bar",
1214+
)
1215+
1216+
self.client.get.assert_awaited_once_with(
1217+
"/repos/foo/bar/code-scanning/default-setup",
1218+
)
1219+
1220+
self.assertEqual(setup.state, DefaultSetupState.CONFIGURED)
1221+
1222+
async def test_update_default_setup(self):
1223+
response = create_response()
1224+
response.json.return_value = {
1225+
"run_id": 42,
1226+
"run_url": "https://api.github.com/repos/octoorg/octocat/actions/runs/42",
1227+
}
1228+
self.client.patch.return_value = response
1229+
1230+
resp = await self.api.update_default_setup(
1231+
"foo/bar",
1232+
state=DefaultSetupState.CONFIGURED,
1233+
query_suite=QuerySuite.EXTENDED,
1234+
languages=[Language.GO],
1235+
)
1236+
1237+
self.client.patch.assert_awaited_once_with(
1238+
"/repos/foo/bar/code-scanning/code-scanning/default-setup",
1239+
data={
1240+
"state": "configured",
1241+
"query_suite": "extended",
1242+
"languages": ["go"],
1243+
},
1244+
)
1245+
1246+
self.assertEqual(
1247+
resp["run_id"],
1248+
42,
1249+
)
1250+
self.assertEqual(
1251+
resp["run_url"],
1252+
"https://api.github.com/repos/octoorg/octocat/actions/runs/42",
1253+
)

tests/github/models/test_code_scanning.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
Analysis,
1313
CodeQLDatabase,
1414
CodeScanningAlert,
15+
DefaultSetup,
16+
DefaultSetupState,
1517
Instance,
18+
Language,
1619
Location,
20+
QuerySuite,
1721
Rule,
1822
Severity,
1923
Tool,
@@ -401,3 +405,25 @@ def test_from_dict(self):
401405
"https://api.github.com/repos/octocat/Hello-World/code-scanning/codeql/databases/java",
402406
)
403407
self.assertEqual(db.commit_oid, "12345678901234567000")
408+
409+
410+
class DefaultSetupTestCase(unittest.TestCase):
411+
def test_from_dict(self):
412+
setup = DefaultSetup.from_dict(
413+
{
414+
"state": "configured",
415+
"languages": ["ruby", "python"],
416+
"query_suite": "default",
417+
"updated_at": "2023-01-19T11:21:34Z",
418+
"schedule": "weekly",
419+
}
420+
)
421+
422+
self.assertEqual(setup.state, DefaultSetupState.CONFIGURED)
423+
self.assertEqual(setup.languages, [Language.RUBY, Language.PYTHON])
424+
self.assertEqual(setup.query_suite, QuerySuite.DEFAULT)
425+
self.assertEqual(
426+
setup.updated_at,
427+
datetime(2023, 1, 19, 11, 21, 34, tzinfo=timezone.utc),
428+
)
429+
self.assertEqual(setup.schedule, "weekly")

0 commit comments

Comments
 (0)