Skip to content
This repository has been archived by the owner on Nov 10, 2022. It is now read-only.

Commit

Permalink
Move linked issues adjacent to their linked PRs
Browse files Browse the repository at this point in the history
  • Loading branch information
mbestavros committed Jul 23, 2020
1 parent 52b8b6d commit 0af3222
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .github/workflows/hourly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ jobs:
run: LD_PRELOAD=libnss_wrapper.so enarx-prstate
- name: assigned
run: LD_PRELOAD=libnss_wrapper.so enarx-assigned
- name: adjacent-linked-issues
run: LD_PRELOAD=libnss_wrapper.so enarx-adjacent-linked-issues
44 changes: 44 additions & 0 deletions enarx-adjacent-linked-issues
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/python3
# SPDX-License-Identifier: Apache-2.0


import enarxbot
import re

github = enarxbot.connect()

# Get the Enarx org.
org = github.get_organization('enarx')

# Get the Sprint board.
sprint = {p.name: p for p in org.get_projects(state='open')}['Sprint']

# Cache the Sprint board to avoid redundant network requests.
sprint_cached = enarxbot.cache_boards([sprint])

for issue in github.search_issues(f"org:enarx is:pr is:public is:open linked:issue -is:draft project:enarx/{sprint.number}"):
# Some attributes change when converting to PR; get them beforehand.
repo = issue.repository
(pr_project, pr_column, pr_card) = sprint_cached[issue.id]

# Convert to a PR.
pr = issue.as_pull_request()

# Get a list of related issues to the PR.
related = {repo.get_issue(i) for i in enarxbot.get_related_issues(pr)}

# Move every related issue adjacent to the PR in the sprint board.
for issue in related:
try:
(issue_project, issue_column, issue_card) = sprint_cached[issue.id]
except:
# If an exception, the issue isn't in the board. Add it directly.
print(f"Adding issue {repo.name}#{issue.number} adjacent to PR {repo.name}#{pr.number}")
issue_card = enarxbot.create_card(pr_column, issue.id, "Issue")
issue_card.move(f"after:{pr_card.id}", pr_column)
continue

# Only move if the issue is in a different column to the PR.
if issue_column != pr_column:
print(f"Moving issue {repo.name}#{issue.number} adjacent to PR {repo.name}#{pr.number}")
issue_card.move(f"after:{pr_card.id}", pr_column)
29 changes: 28 additions & 1 deletion enarxbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import requests
import github
import os
import re

class Suggestion:
@classmethod
Expand Down Expand Up @@ -52,9 +53,35 @@ def graphql(query):

def create_card(column, content_id, content_type):
try:
column.create_card(content_id=content_id, content_type=content_type)
return column.create_card(content_id=content_id, content_type=content_type)
except github.GithubException as e:
error = e.data["errors"][0]
if error["resource"] != "ProjectCard" or error["code"] != "unprocessable":
raise
print("Card already in project.")

# Get all issue numbers related to a PR.
def get_related_issues(pr):
# Regex to pick out closing keywords.
regex = re.compile("(close[sd]?|fix|fixe[sd]?|resolve[sd]?)\s*:?\s+#(\d+)", re.I)

# Extract all associated issues from closing keyword in PR
for verb, num in regex.findall(pr.body):
yield int(num)

# Extract all associated issues from PR commit messages
for c in pr.get_commits():
for verb, num in regex.findall(c.commit.message):
yield int(num)

# Takes a project as input and caches all cards in a dictionary for easy lookup
# (and to avoid redundant network requests).
def cache_boards(projects):
cache = {}
for project in projects:
for column in project.get_columns():
for card in column.get_cards():
content = card.get_content()
if content:
cache.setdefault(content.id, []).append((project, column, card))
return cache

0 comments on commit 0af3222

Please sign in to comment.