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

Move linked issues adjacent to their linked PRs #14

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/hourly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ jobs:
run: LD_PRELOAD=libnss_wrapper.so enarx-assigned
- name: copy-labels-linked
run: LD_PRELOAD=libnss_wrapper.so enarx-copy-labels-linked
- name: adjacent-linked-issues
run: LD_PRELOAD=libnss_wrapper.so enarx-adjacent-linked-issues
45 changes: 45 additions & 0 deletions enarx-adjacent-linked-issues
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/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")
if issue_card is not None:
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)
14 changes: 13 additions & 1 deletion enarxbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def graphql(query, page=None, **kwargs):

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":
Expand All @@ -132,3 +132,15 @@ def get_related_issues(pr):
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