Skip to content

Commit

Permalink
src/reports.py: Commits in electrical member reports are fetched across
Browse files Browse the repository at this point in the history
all branches (closes #78)
  • Loading branch information
cbrxyz committed Sep 9, 2024
1 parent d447283 commit 382feb3
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 17 deletions.
5 changes: 4 additions & 1 deletion src/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,12 @@ async def change_status(self):
]
await self.change_presence(activity=random.choice(activities))

async def get_member(self, user_id: int) -> discord.Member:
async def get_or_fetch_member(self, user_id: int) -> discord.Member:
"""
Gets a member from the active guild, fetching them if necessary.
Raises:
NotFound: The member was not in the guild.
"""
member = self.active_guild.get_member(user_id)
if not member:
Expand Down
82 changes: 82 additions & 0 deletions src/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,88 @@ async def pvt_title_url_org(self, id: str) -> tuple[str, str, str]:
properties["data"]["node"]["owner"]["login"],
)

async def commits_across_branches(
self,
user_token: str,
*,
organization: str = "uf-mil-electrical",
) -> list[dict[str, Any]]:
previous_monday_midnight = (
datetime.datetime.now().astimezone()
- datetime.timedelta(
days=datetime.datetime.now().weekday(),
)
)
previous_monday_midnight = previous_monday_midnight.replace(
hour=0,
minute=0,
second=0,
microsecond=0,
)
previous_monday_format = previous_monday_midnight.isoformat()
query = f"""
{{
viewer {{
login
}}
organization(login: "{organization}") {{
repositories(first: 10, orderBy: {{field: PUSHED_AT, direction: DESC}}) {{
nodes {{
refs(first: 30, refPrefix: "refs/heads/") {{
nodes {{
... on Ref {{
name
target {{
... on Commit {{
history(first: 10, since: "{previous_monday_format}") {{
nodes {{
... on Commit {{
author {{
date
email
user {{
login
}}
}}
oid
message
repository {{
nameWithOwner
}}
}}
}}
}}
}}
}}
}}
}}
}}
}}
}}
}}
}}
"""
properties = await self.fetch(
"https://api.github.com/graphql",
method="POST",
data=json.dumps({"query": query}),
user_access_token=user_token,
)
commits = []
login = properties["data"]["viewer"]["login"]
for repo in properties["data"]["organization"]["repositories"]["nodes"]:
for branch in repo["refs"]["nodes"]:
for commit in branch["target"]["history"]["nodes"]:
if commit["author"]["user"]["login"] == login:
commits.append(commit)
commits.sort(
key=lambda commit: datetime.datetime.fromisoformat(
commit["author"]["date"],
),
reverse=True,
)
return commits

async def project_item_content_title_number_url(
self,
id: str,
Expand Down
58 changes: 43 additions & 15 deletions src/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,13 @@ def _format_commit_str(self, payload: dict) -> str:
)
return f"* {format_dt} {payload['repository']['full_name']} @ {payload['sha'][:8]} ({payload['commit']['message']})"

def _format_commit_str_from_all_branches(self, payload: dict) -> str:
format_dt = discord.utils.format_dt(
datetime.datetime.fromisoformat(payload["author"]["date"]),
"F",
)
return f"* {format_dt} {payload['repository']['nameWithOwner']} @ {payload['oid'][:8]} ({payload['message']})"

async def refresh_sheet(self) -> None:
main_worksheet = await self.bot.sh.get_worksheet(0)
cur_semester = semester_given_date(datetime.datetime.now())
Expand All @@ -890,7 +897,29 @@ async def refresh_sheet(self) -> None:
async with self.bot.db_factory() as db:
for member in await db.authenticated_members():
token = str(member.access_token)
contributions = await self.bot.github.get_user_contributions(token)
try:
contributions = await self.bot.github.get_user_contributions(token)
except Exception:
logger.exception(
f"Error fetching contributions for {member.discord_id}",
)
continue
try:
discord_member = await self.bot.get_or_fetch_member(
member.discord_id,
)
except discord.NotFound:
logger.info(
f"Could not find member with ID {member.discord_id}.",
)
continue
electrical_role = discord.utils.get(
self.bot.active_guild.roles,
name="EGN4912 Electrical",
)
if not electrical_role:
raise RuntimeError("Could not find EGN4912 Electrical role.")
is_electrical_member = electrical_role in discord_member.roles
summaries = {}
if contributions.issue_comments:
summaries["Comments"] = [
Expand All @@ -907,27 +936,26 @@ async def refresh_sheet(self) -> None:
self._format_issue_str(payload)
for payload in contributions.pull_requests
]
if contributions.commits:
if contributions.commits and not is_electrical_member:
summaries["Commits"] = [
self._format_commit_str(payload)
for payload in contributions.commits
]
if is_electrical_member:
try:
commits = await self.bot.github.commits_across_branches(token)
if commits:
summaries["Commits"] = [
self._format_commit_str_from_all_branches(payload)
for payload in commits
]
except Exception:
logger.exception(
f"Error fetching commits across branches for user {member.discord_id}",
)
summary_str = "\n\n".join(
f"**{k}**:\n" + "\n".join(v) for k, v in summaries.items()
)
discord_member = self.bot.active_guild.get_member(
int(member.discord_id),
)
if not discord_member:
try:
discord_member = await self.bot.active_guild.fetch_member(
int(member.discord_id),
)
except discord.NotFound:
logger.info(
f"Could not find member with ID {member.discord_id}.",
)
continue
id_cell = await main_worksheet.find(discord_member.name)
a1_notation = gspread.utils.rowcol_to_a1(id_cell.row, week.report_column) # type: ignore
summary_str = summary_str.strip()
Expand Down
2 changes: 1 addition & 1 deletion src/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ async def parse_embed_field(
id = re.findall(r"<@!?(\d+)>", mention_str)
swimming = "(swimming)" in mention_str
if id:
member = await self.bot.get_member(int(id[0]))
member = await self.bot.get_or_fetch_member(int(id[0]))
members.append(TestingMember(member, swimming))
return members

Expand Down

0 comments on commit 382feb3

Please sign in to comment.