Skip to content

Commit 867b529

Browse files
committed
Add tests for Github importer
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
1 parent fbad307 commit 867b529

6 files changed

Lines changed: 8795 additions & 55 deletions

File tree

vulnerabilities/importers/github.py

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
from typing import Set
2828
from typing import Tuple
2929
from typing import List
30+
from typing import Mapping
31+
from typing import Optional
3032
import xml.etree.ElementTree as ET
3133

3234
import requests
@@ -38,6 +40,37 @@
3840
from vulnerabilities.data_source import DataSourceConfiguration
3941

4042

43+
# set of all possible values of first '%s' = {'MAVEN','COMPOSER', 'NUGET'}
44+
# second '%s' is interesting, it will have the value '' for the first request,
45+
# since we don't have any value for endCursor at the beginning
46+
# for all the subsequent requests it will have value 'after: "{endCursor}"'
47+
query = """
48+
query MyQuery {
49+
securityVulnerabilities(first: 100, ecosystem: %s, %s) {
50+
edges {
51+
node {
52+
advisory {
53+
identifiers {
54+
type
55+
value
56+
}
57+
summary
58+
}
59+
package {
60+
name
61+
}
62+
vulnerableVersionRange
63+
}
64+
}
65+
pageInfo {
66+
hasNextPage
67+
endCursor
68+
}
69+
}
70+
}
71+
"""
72+
73+
4174
class GitHubTokenError(Exception):
4275
pass
4376

@@ -65,36 +98,8 @@ def __enter__(self):
6598
def updated_advisories(self) -> Set[Advisory]:
6699
return self.batch_advisories(self.process_response())
67100

68-
def fetch(self):
69-
# set of all possible values of first '%s' = {'MAVEN','COMPOSER', 'NUGET'}
70-
# second '%s' is interesting, it will have the value '' for the first request,
71-
# since we don't have any value for endCursor at the beginning
72-
# for all the subsequent requests it will have value 'after: "{endCursor}"'
73-
query = """
74-
query MyQuery {
75-
securityVulnerabilities(first: 100, ecosystem: %s, %s) {
76-
edges {
77-
node {
78-
advisory {
79-
identifiers {
80-
type
81-
value
82-
}
83-
summary
84-
}
85-
package {
86-
name
87-
}
88-
vulnerableVersionRange
89-
}
90-
}
91-
pageInfo {
92-
hasNextPage
93-
endCursor
94-
}
95-
}
96-
}
97-
"""
101+
def fetch(self) -> Mapping[str, List[Mapping]]:
102+
98103
headers = {"Authorization": "token " + self.gh_token}
99104
api_data = {}
100105
for ecosystem in self.config.ecosystems:
@@ -122,10 +127,9 @@ def fetch(self):
122127
"hasNextPage"
123128
]:
124129
break
125-
126130
return api_data
127131

128-
def set_version_api(self, ecosystem):
132+
def set_version_api(self, ecosystem: str) -> None:
129133

130134
if ecosystem == "MAVEN":
131135
self.version_api = MavenVersionAPI()
@@ -137,7 +141,9 @@ def set_version_api(self, ecosystem):
137141
self.version_api = ComposerVersionAPI()
138142

139143
@staticmethod
140-
def process_name(ecosystem, pkg_name):
144+
def process_name(
145+
ecosystem: str, pkg_name: str
146+
) -> Optional[Tuple[Optional[str], str]]:
141147

142148
if ecosystem == "MAVEN":
143149

@@ -206,7 +212,6 @@ def process_response(self) -> List[Advisory]:
206212
reference_ids=ref_ids,
207213
)
208214
)
209-
# print(adv_list[-1])
210215
return adv_list
211216

212217
@staticmethod
@@ -227,7 +232,7 @@ def __init__(self):
227232
def get(self, pkg_name: str) -> Set[str]:
228233
return self.cache.get(pkg_name, set())
229234

230-
def load_to_api(self, pkg_name: str):
235+
def load_to_api(self, pkg_name: str) -> None:
231236

232237
if pkg_name in self.cache:
233238
return
@@ -270,30 +275,30 @@ class NugetVersionAPI:
270275
def __init__(self):
271276
self.cache = {}
272277

273-
def get(self, pkg_name):
278+
def get(self, pkg_name: str) -> Set[str]:
274279
return self.cache.get(pkg_name.lower(), set())
275280

276-
def load_to_api(self, pkg_name: str):
281+
def load_to_api(self, pkg_name: str) -> None:
277282
if pkg_name in self.cache:
278283
return
279284
endpoint = self.nuget_url(pkg_name)
280285
try:
281286
resp = requests.get(endpoint).json()
282287
# pkg_name=Microsoft.NETCore.UniversalWindowsPlatform triggers
283288
# JSONDecodeError.
284-
except (json.decoder.JSONDecodeError, KeyError):
289+
except json.decoder.JSONDecodeError:
285290
self.cache[pkg_name.lower()] = set()
286291
return
287292

288293
self.cache[pkg_name.lower()] = self.extract_versions(resp)
289294

290295
@staticmethod
291-
def nuget_url(pkg_name):
296+
def nuget_url(pkg_name: str) -> str:
292297
base_url = "https://api.nuget.org/v3/registration5-semver1/{}/index.json"
293298
return base_url.format(pkg_name.lower())
294299

295300
@staticmethod
296-
def extract_versions(json_resp):
301+
def extract_versions(json_resp: dict) -> Set[str]:
297302
all_versions = set()
298303
try:
299304
for entry in json_resp["items"][0]["items"]:
@@ -309,33 +314,28 @@ class ComposerVersionAPI:
309314
def __init__(self):
310315
self.cache = {}
311316

312-
def get(self, pkg_name):
317+
def get(self, pkg_name: str) -> Set[str]:
313318
return self.cache.get(pkg_name.lower(), set())
314319

315-
def load_to_api(self, pkg_name):
320+
def load_to_api(self, pkg_name: str) -> None:
316321
if pkg_name in self.cache:
317322
return
318323
endpoint = self.composer_url(pkg_name)
319324
json_resp = requests.get(endpoint).json()
320325
self.cache[pkg_name] = self.extract_versions(json_resp, pkg_name)
321326

322327
@staticmethod
323-
def composer_url(pkg_name):
328+
def composer_url(pkg_name: str) -> str:
324329
vendor, name = pkg_name.split("/")
325330
return f"https://repo.packagist.org/p/{vendor}/{name}.json"
326331

327332
@staticmethod
328-
def extract_versions(json_resp, pkg_name):
333+
def extract_versions(json_resp: dict, pkg_name: str) -> Set[str]:
329334
all_versions = json_resp["packages"][pkg_name].keys()
330335
# This filter ensures, that all_versions contains only released versions
331336
all_versions = set(filter(lambda x: "dev" not in x, all_versions))
332-
# more_versions ensures that we have a version with and without version tag for
333-
# each version present in all_versions
334-
more_versions = set()
335-
for version in all_versions:
336-
if version.startswith("v"):
337-
more_versions.add(version[1:])
338-
else:
339-
more_versions.add("v" + version)
340-
341-
return all_versions.union(more_versions)
337+
# See https://github.com/composer/composer/blob/44a4429978d1b3c6223277b875762b2930e83e8c/doc/articles/versions.md#tags # nopep8
338+
# for explanation of removing 'v'
339+
all_versions = set(map(lambda x: x.replace("v", ""), all_versions))
340+
341+
return all_versions

0 commit comments

Comments
 (0)