This repository has been archived by the owner on Dec 4, 2024. It is now read-only.
forked from conan-io/conan-center-index
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate-matrix.py
133 lines (112 loc) · 5.28 KB
/
generate-matrix.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# pylint: disable = invalid-name,too-few-public-methods
import os
import json
import asyncio
import logging
from datetime import datetime
from typing import Dict, Set, Any
import sys
import yaml
import requests
import aiohttp
import packaging.version
class MatrixGenerator:
owner: str = "conan-io"
repo: str = "conan-center-index"
dry_run: bool = False
def __init__(self, keyword: str, token: str = "", user: str = "", pw: str = ""): # noqa: MC0001
self.session = requests.session()
if token:
self.session.headers["Authorization"] = f"token {token}"
self.session.headers["Accept"] = "application/vnd.github.v3+json"
self.session.headers["User-Agent"] = "request"
self.session.auth = None
if user and pw:
self.session.auth = requests.auth.HTTPBasicAuth(user, pw)
self.prs: Dict[int, Dict[str, Any]] = {}
page = 1
while True:
results = self._make_request("GET", f"/repos/{self.owner}/{self.repo}/pulls", params={
"state": "open",
"sort": "created",
"direction": "desc",
"per_page": 100,
"page": str(page)
}).json()
for p in results:
if int(p["number"]) in [13539, 16266, 18490, 19488, 20528, 23125]:
logging.warning("ignoring pr #%s because it is in deny list", p["number"])
continue
body = p["body"] or ""
if keyword in p["title"].lower() or keyword in body.lower():
self.prs[int(p["number"])] = p
page += 1
if not results:
break
for pr_number, pr in self.prs.items():
pr["libs"] = self._get_modified_libs_for_pr(pr_number)
async def generate_matrix(self) -> None: # noqa: MC0001
res = []
async with aiohttp.ClientSession() as session:
async def _add_package(package: str, repo: str, ref: str, pr: str = "0") -> None:
version = packaging.version.Version("0.0.0")
folder = ""
async with session.get(f"https://raw.githubusercontent.com/{repo}/{ref}/recipes/{package}/config.yml") as r:
if r.status == 404:
return
r.raise_for_status()
config = yaml.safe_load(await r.text())
for v in config["versions"]:
try:
tmpver = packaging.version.Version(v)
if tmpver > version:
version = tmpver
folder = config["versions"][v]["folder"]
except packaging.version.InvalidVersion:
logging.warning("Error parsing version %s for package %s in pr %s", v, package, pr)
if folder:
res.append({'package': package,
'version': str(version),
'repo': repo,
'ref': ref,
'folder': folder,
'pr': pr})
tasks = []
# for package in r.json():
# tasks.append(asyncio.create_task(_add_package(package['name'], '%s/%s' % (self.owner, self.repo), 'master')))
for pr in self.prs.values():
pr_number = str(pr["number"])
if not pr["head"]["repo"]:
logging.warning("no repo detected for pr #%s", pr_number)
continue
for package in pr['libs']:
if package in ["libbsd"]:
logging.warning("ignoring pr #%s because package %s is in deny list", pr_number, package)
continue
tasks.append(_add_package(package, pr["head"]["repo"]["full_name"], pr["head"]["ref"], pr_number))
await asyncio.gather(*tasks)
with open("matrix.yml", "w", encoding="latin_1") as f:
json.dump({"include": res}, f)
def _get_modified_libs_for_pr(self, pr: int) -> Set[str]:
res = set()
for file in self._make_request("GET", f"/repos/{self.owner}/{self.repo}/pulls/{pr}/files").json():
parts = file["filename"].split("/")
if len(parts) >= 2 and parts[0] == "recipes":
res.add(parts[1])
return res
def _make_request(self, method: str, url: str, **kwargs) -> requests.Response:
if self.dry_run and method in ["PATCH", "POST"]:
return requests.Response()
r = self.session.request(method, f"https://api.github.com{url}", **kwargs)
r.raise_for_status()
if int(r.headers["X-RateLimit-Remaining"]) < 10:
logging.warning("%s/%s github api call used, remaining %s until %s",
r.headers["X-Ratelimit-Used"], r.headers["X-RateLimit-Limit"], r.headers["X-RateLimit-Remaining"],
datetime.fromtimestamp(int(r.headers["X-Ratelimit-Reset"])))
return r
def main() -> None:
d = MatrixGenerator(sys.argv[1], token=os.getenv("GH_TOKEN", ""))
asyncio.run(d.generate_matrix())
if __name__ == "__main__":
# execute only if run as a script
main()