Skip to content

Commit 1d457e7

Browse files
committed
workflow runs parser
1 parent 56b519a commit 1d457e7

File tree

10 files changed

+168
-30
lines changed

10 files changed

+168
-30
lines changed

.github/workflows/smoke-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
- "--issues"
1818
- "--wikis"
1919
- "--contributors"
20+
- "--workflow_runs"
2021

2122
runs-on: ubuntu-latest
2223

GitHubRepoAPI.py

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
User,
1414
WikiPage,
1515
logging,
16+
WorkflowRun,
1617
)
1718

1819

@@ -37,7 +38,7 @@ def get_user_data(self, user) -> User:
3738
return User(
3839
login=user.login,
3940
username=user.name,
40-
email=user.email,
41+
email=user.email, # always None
4142
html_url=user.html_url,
4243
node_id=user.node_id,
4344
type=user.type,
@@ -46,6 +47,17 @@ def get_user_data(self, user) -> User:
4647
_id=user.id,
4748
)
4849

50+
def get_commit_data(self, commit, files=False) -> Commit:
51+
return Commit(
52+
_id=commit.sha,
53+
message=commit.commit.message,
54+
author=self.get_user_data(commit.author),
55+
date=commit.commit.author.date,
56+
files=[f.filename for f in commit.files] if files else None,
57+
additions=commit.stats.additions,
58+
deletions=commit.stats.deletions,
59+
)
60+
4961
def get_repository(self, id: str) -> Repository | None:
5062
try:
5163
repo = self.client.get_repo(id)
@@ -66,18 +78,7 @@ def get_collaborator_permission(self, repo: Repository, user: User) -> str:
6678
def get_commits(self, repo: Repository, files: bool = True) -> list[Commit]:
6779
try:
6880
commits = self.client.get_repo(repo._id).get_commits()
69-
return [
70-
Commit(
71-
_id=c.sha,
72-
message=c.commit.message,
73-
author=self.get_user_data(c.author),
74-
date=c.commit.author.date,
75-
files=[f.filename for f in c.files] if files else None,
76-
additions=c.stats.additions,
77-
deletions=c.stats.deletions,
78-
)
79-
for c in commits
80-
]
81+
return [self.get_commit_data(c, files) for c in commits]
8182
except Exception as e:
8283
logging.error(
8384
f"Failed to get commits from GitHub for repo {repo.name}: {e}"
@@ -153,18 +154,7 @@ def get_branches(self, repo: Repository) -> list[Branch]:
153154
for branch in branches:
154155
commit = repo_client.get_commit(branch.commit.sha)
155156

156-
author = commit.author
157-
contributor = Contributor(
158-
username=author.login if author else "unknown",
159-
email=commit.commit.author.email or "",
160-
)
161-
162-
commit_obj = Commit(
163-
_id=commit.sha,
164-
message=commit.commit.message,
165-
author=contributor,
166-
date=commit.commit.author.date,
167-
)
157+
commit_obj = self.get_commit_data(commit)
168158

169159
result.append(Branch(name=branch.name, last_commit=commit_obj))
170160

@@ -182,10 +172,21 @@ def get_wiki_pages(self, repo: Repository) -> list[WikiPage]:
182172
def get_forks(self, repo: Repository) -> list[Repository]:
183173
repo_client = self.client.get_repo(repo._id)
184174
result = []
175+
185176
for r in repo_client.get_forks():
177+
default_branch = (Branch(name=r.default_branch, last_commit=None),)
178+
owner = (self.get_user_data(r.owner),)
179+
186180
result.append(
187-
Repository(_id=repo.full_name, name=repo.name, url=repo.html_url)
181+
Repository(
182+
_id=r.full_name,
183+
name=r.name,
184+
url=r.html_url,
185+
default_branch=default_branch,
186+
owner=owner,
187+
)
188188
)
189+
189190
return result
190191

191192
def get_comments(self, repo, obj) -> list[Comment]:
@@ -246,6 +247,34 @@ def get_invites(self, repo: Repository) -> list[Invite]:
246247
def get_rate_limiting(self) -> tuple[int, int]:
247248
return self.client.rate_limiting
248249

250+
def get_workflow_runs(self, repo) -> list[WorkflowRun]:
251+
try:
252+
runs = self.client.get_repo(repo._id).get_workflow_runs()
253+
254+
return [
255+
WorkflowRun(
256+
display_title=r.display_title,
257+
event=r.event,
258+
head_branch=r.head_branch,
259+
head_sha=r.head_sha,
260+
name=r.name,
261+
path=r.path,
262+
created_at=r.created_at,
263+
run_started_at=r.run_started_at,
264+
updated_at=r.updated_at,
265+
conclusion=r.conclusion,
266+
status=r.status,
267+
url=r.url,
268+
)
269+
for r in runs
270+
]
271+
272+
except Exception as e:
273+
logging.error(
274+
f"Failed to get workflow runs from GitHub for repo {repo.name}: {e}"
275+
)
276+
return []
277+
249278

250279
# Точка входа для тестирования
251280
if __name__ == "__main__":

commits_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def log_commits(
8484
log_repository_commits(client, repo, csv_name, start, finish, branch)
8585
if fork_flag:
8686
for forked_repo in client.get_forks(repo):
87-
logger.log_title("FORKED:", forked_repo.full_name)
87+
logger.log_title(f"FORKED: {forked_repo.name}")
8888
log_repository_commits(
8989
client, forked_repo, csv_name, start, finish, branch
9090
)

contributors_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def log_contributors(
9494

9595
if fork_flag:
9696
for forked_repo in client.get_forks(repo):
97-
logger.log_title("FORKED:", forked_repo.name)
97+
logger.log_title(f"FORKED: {forked_repo.name}")
9898
log_repository_contributors(client, forked_repo, csv_name)
9999
sleep(TIMEDELTA)
100100

interface_wrapper.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,22 @@ class WikiPage:
111111
content: str
112112

113113

114+
@dataclass
115+
class WorkflowRun:
116+
display_title: str
117+
event: str
118+
head_branch: str
119+
head_sha: str
120+
name: str
121+
path: str
122+
created_at: datetime
123+
run_started_at: datetime
124+
updated_at: datetime
125+
conclusion: str
126+
status: str
127+
url: str
128+
129+
114130
# Интерфейс API
115131
class IRepositoryAPI(ABC):
116132

@@ -173,6 +189,10 @@ def get_invites(self, repo: Repository) -> list[Invite]:
173189
def get_rate_limiting(self) -> tuple[int, int]:
174190
pass
175191

192+
@abstractmethod
193+
def get_workflow_runs(self, repo: Repository) -> list[WorkflowRun]:
194+
pass
195+
176196

177197
# Фабрика для создания API
178198
class RepositoryFactory:

issues_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ def log_issues(
205205
if fork_flag:
206206
forked_repos = client.get_forks(repo)
207207
for forked_repo in forked_repos:
208-
logger.log_title("FORKED:", forked_repo.name)
208+
logger.log_title(f"FORKED: {forked_repo.name}")
209209
log_repository_issues(
210210
client, forked_repo, csv_name, token, start, finish
211211
)

main.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import issues_parser
1010
import pull_requests_parser
1111
import wikipars
12+
import workflow_runs_parser
1213
from utils import parse_time
1314

1415

@@ -22,6 +23,9 @@ def parse_args():
2223
parser.add_argument("-i", "--issues", help="log issues", action="store_true")
2324
parser.add_argument("-w", "--wikis", help="log wikis", action="store_true")
2425
parser.add_argument("--contributors", help="log contributors", action="store_true")
26+
parser.add_argument(
27+
"--workflow_runs", help="log workflow runs", action="store_true"
28+
)
2529
parser.add_argument(
2630
"--forks_include", help="logging data from forks", action="store_true"
2731
)
@@ -144,6 +148,10 @@ def run(args, binded_repos, repos_for_wiki=None):
144148
)
145149
if args.contributors:
146150
contributors_parser.log_contributors(binded_repos, args.out, args.forks_include)
151+
if args.workflow_runs:
152+
workflow_runs_parser.log_workflow_runs(
153+
binded_repos, args.out, args.forks_include
154+
)
147155
if args.wikis:
148156
wikipars.wikiparser(repos_for_wiki, args.download_repos, args.out)
149157
if args.export_google_sheets:

pull_requests_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def log_pull_requests(
208208
if fork_flag:
209209
forked_repos = client.get_repo(repo._id).get_forks()
210210
for forked_repo in forked_repos:
211-
logger.log_title("FORKED:", forked_repo.full_name)
211+
logger.log_title(f"FORKED: {forked_repo.name}")
212212
log_repositories_pr(
213213
client,
214214
forked_repo,

test_token_usage.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def setUp(self):
4040
wikis=False,
4141
contributors=False,
4242
invites=False,
43+
workflow_runs=False,
4344
start="2000/01/01-00:00:00",
4445
finish="2400/01/01-00:00:00",
4546
branch="default",
@@ -88,6 +89,7 @@ def _get_usage(self, binded_repos, clients):
8889
param({'issues': True}, id='issues'),
8990
param({'invites': True}, id='invites'),
9091
param({'pull_requests': True}, id='pull_requests'),
92+
param({'workflow_runs': True}, id='workflow_runs'),
9193
],
9294
)
9395
def test_commits_parser(self, args: dict[str, bool]):

workflow_runs_parser.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from dataclasses import asdict, dataclass
2+
from time import sleep
3+
from typing import Generator
4+
5+
from constants import TIMEDELTA
6+
from interface_wrapper import IRepositoryAPI, Repository
7+
from utils import logger
8+
9+
10+
@dataclass(kw_only=True, frozen=True)
11+
class WorkflowRunData:
12+
repository_name: str = ''
13+
display_title: str = ''
14+
event: str = ''
15+
head_branch: str = ''
16+
head_sha: str = ''
17+
name: str = ''
18+
path: str = ''
19+
started_at: str = ''
20+
total_duration: float = 0.0
21+
conclusion: str = ''
22+
status: str = ''
23+
url: str = ''
24+
25+
26+
def log_repository_workflow_runs(
27+
client: IRepositoryAPI, repository: Repository, csv_name: str
28+
):
29+
workflow_runs = client.get_workflow_runs(repository)
30+
31+
for run in workflow_runs:
32+
total_duration = (run.updated_at - run.created_at).total_seconds()
33+
34+
workflow_run_data = WorkflowRunData(
35+
repository_name=repository.name,
36+
display_title=run.display_title,
37+
event=run.event,
38+
head_branch=run.head_branch,
39+
head_sha=run.head_sha,
40+
name=run.name,
41+
path=run.path,
42+
started_at=run.run_started_at,
43+
total_duration=total_duration,
44+
conclusion=run.conclusion,
45+
status=run.status,
46+
url=run.url,
47+
)
48+
49+
info_dict = asdict(workflow_run_data)
50+
51+
logger.log_to_csv(csv_name, list(info_dict.keys()), info_dict)
52+
logger.log_to_stdout(info_dict)
53+
54+
sleep(TIMEDELTA)
55+
56+
57+
def log_workflow_runs(
58+
binded_repos: Generator[tuple[IRepositoryAPI, Repository, str], None, None],
59+
csv_name: str,
60+
fork_flag: bool,
61+
):
62+
info = asdict(WorkflowRunData())
63+
logger.log_to_csv(csv_name, list(info.keys()))
64+
65+
for client, repo, token in binded_repos:
66+
try:
67+
logger.log_title(repo.name)
68+
log_repository_workflow_runs(client, repo, csv_name)
69+
70+
if fork_flag:
71+
for forked_repo in client.get_forks(repo):
72+
logger.log_title(f"FORKED: {forked_repo.name}")
73+
log_repository_workflow_runs(client, forked_repo, csv_name)
74+
sleep(TIMEDELTA)
75+
76+
except Exception as e:
77+
print(e)
78+
exit(1)

0 commit comments

Comments
 (0)