Skip to content

Commit e2efb7f

Browse files
author
Emerson Knapp
committed
Add option to report for specific repositories
Signed-off-by: Emerson Knapp <eknapp@amazon.com>
1 parent 969e971 commit e2efb7f

1 file changed

Lines changed: 28 additions & 14 deletions

File tree

ros_github_scripts/generate_contribution_report.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,35 +62,37 @@
6262

6363

6464
def graphql_query(query: str, token: Optional[str] = None) -> dict:
65-
headers = {'Authorization': 'Bearer {}'.format(token)} if token else None
65+
headers = {'Authorization': f'Bearer {token}'} if token else None
6666
request = requests.post(
6767
'https://api.github.com/graphql',
6868
json={'query': query},
6969
headers=headers)
7070
if request.status_code == 200:
7171
return request.json()
7272
else:
73-
raise RuntimeError('Query failed with code {}'.format(request.status_code))
73+
raise RuntimeError(f'Query failed with code {request.status_code}')
7474

7575

7676
def query_contributions(
7777
token: Optional[str],
7878
authors: List[str],
7979
orgs: List[str],
80+
repos: List[str],
8081
since: datetime.date,
8182
until: Optional[datetime.date] = None,
8283
) -> List[dict]:
8384
if until:
84-
date_range = '{}..{}'.format(since.isoformat(), until.isoformat())
85+
date_range = f'{since.isoformat()}..{until.isoformat()}'
8586
else:
86-
date_range = '>={}'.format(since.isoformat())
87+
date_range = f'>={since.isoformat()}'
8788

8889
search_query = ' '.join([
8990
'sort:updated-desc',
9091
'is:pr is:merged',
91-
' '.join(['author:{}'.format(a) for a in authors]),
92-
' '.join(['org:{}'.format(o) for o in orgs]),
93-
'merged:{}'.format(date_range),
92+
' '.join([f'author:{a}' for a in authors]),
93+
' '.join([f'org:{o}' for o in orgs]),
94+
' '.join([f'repo:{r}' for r in repos]),
95+
f'merged:{date_range}',
9496
])
9597

9698
cursor = 'null'
@@ -128,7 +130,7 @@ def format_github_time_to_date(value: str) -> str:
128130
def line_format_contribution(node: dict) -> str:
129131
"""Format an individual GitHub PR into our contribution line format."""
130132
title = node['title']
131-
author = node['author']['name']
133+
author = node['author'].get('name')
132134
link = node['permalink']
133135
merged = format_github_time_to_date(node['mergedAt'])
134136
return f'[{title}]({link}) - {author} (merged {merged})'
@@ -145,7 +147,8 @@ def line_format_contributions(
145147
146148
:returns: A list of markdown lines
147149
"""
148-
contrib_authors = set(node['node']['author']['login'] for node in contributions)
150+
contrib_authors = {node['node'].get('author', {}).get('login', 'None') for node in contributions}
151+
print(f'Authos: {contrib_authors}')
149152
lines = [
150153
'* By Authors: {}'.format(', '.join(contrib_authors)),
151154
'* To Repositories in Organizations: {}'.format(', '.join(orgs)), '',
@@ -159,12 +162,15 @@ def line_format_contributions(
159162
for contrib_json in contributions:
160163
node = contrib_json['node']
161164
repo = node['repository']['nameWithOwner']
165+
# skip bots
166+
if node['author'].get('login') is None:
167+
continue
162168
byrepo.setdefault(repo, []).append(line_format_contribution(node))
163169

164170
for repo, contribs in sorted(byrepo.items()):
165-
lines.append('* {}'.format(repo))
171+
lines.append(f'* {repo}')
166172
for contrib_str in contribs:
167-
lines.append(' * {}'.format(contrib_str))
173+
lines.append(f' * {contrib_str}')
168174

169175
return lines
170176

@@ -215,6 +221,7 @@ class ContributionReportOptions(NamedTuple):
215221
until: Optional[datetime.date]
216222
authors: List[str]
217223
orgs: List[str]
224+
repos: List[str]
218225
token: str
219226
formatter: Callable
220227
render_html: bool
@@ -270,6 +277,12 @@ def parse_args(args=None) -> ContributionReportOptions:
270277
required=False,
271278
default=[],
272279
help='Report contributions only to repos these github organizations')
280+
parser.add_argument(
281+
'--repos',
282+
nargs='+',
283+
required=False,
284+
default=[],
285+
help='Report contributions to these specific repositories (in addition to --orgs)')
273286
parser.add_argument(
274287
'-f', '--format',
275288
type=str,
@@ -288,9 +301,9 @@ def parse_args(args=None) -> ContributionReportOptions:
288301
parsed = parser.parse_args(args)
289302

290303
if not parsed.authors and not parsed.authors_from_org:
291-
parser.error(
304+
print(
292305
'Neither --authors nor --authors-from-org specified, '
293-
'at least one is required to narrow the potentially huge search results.')
306+
'the results might be huge...')
294307

295308
authors = all_authors(parsed.authors, parsed.authors_from_org, parsed.token)
296309

@@ -300,14 +313,15 @@ def parse_args(args=None) -> ContributionReportOptions:
300313
authors=authors,
301314
token=parsed.token,
302315
orgs=parsed.orgs,
316+
repos=parsed.repos,
303317
formatter=formatters[parsed.format],
304318
render_html=parsed.render_html)
305319

306320

307321
def main(args=None):
308322
options = parse_args(args)
309323
contributions = query_contributions(
310-
options.token, options.authors, options.orgs, options.since, options.until)
324+
options.token, options.authors, options.orgs, options.repos, options.since, options.until)
311325
lines = options.formatter(
312326
contributions, options.since, options.authors, options.orgs)
313327
md_content = '\n'.join(lines)

0 commit comments

Comments
 (0)