add ZebHub epics support

This commit is contained in:
Conrado Gouvea 2022-03-14 11:55:58 -03:00
parent dedf0a4878
commit e53cc43933
3 changed files with 59 additions and 0 deletions

View File

@ -73,6 +73,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ZENHUB_TOKEN: ${{ secrets.ZENHUB_TOKEN }}
DAG_VIEW: zf
SHOW_EPICS: true
- name: Render Halo2-focused DAG
run: python3 ./zcash-issue-dag.py

View File

@ -7,6 +7,10 @@ For now, this repo hosts the script used to generate ECC's development dependenc
## Setup
This project uses `poetry` for dependency management: https://python-poetry.org/
It also depends on the Graphviz library; for Debian-based distros, install the `graphviz-dev`
package.
After installing `poetry`, run `poetry install`.
The scripts provided by this project require two environment variables:
@ -36,6 +40,7 @@ also supplied as environment variables:
- `DAG_VIEW=[core|wallet|zf]`: The DAG to render (default: `core`).
- `SHOW_MILESTONES=[true|false]`: Whether or not to render GitHub milestones as boxes (default: `false`).
- `SHOW_EPICS=[true|false]`: Whether or not to render ZenHub epics as boxes (default: `false`).
- `INCLUDE_FINISHED=[true|false]`: Whether or not to include closed issues with no open blockers (default: `false`).
Here's an example script for easily running the DAG generator:

View File

@ -75,6 +75,9 @@ PRUNE_FINISHED = strtobool(os.environ.get('PRUNE_FINISHED', 'true'))
# Whether to group issues and PRs by milestone.
SHOW_MILESTONES = strtobool(os.environ.get('SHOW_MILESTONES', 'false'))
# Whether to group issues and PRs by ZenHub epics.
SHOW_EPICS = strtobool(os.environ.get('SHOW_EPICS', 'false'))
class GitHubIssue:
def __init__(self, repo_id, issue_number, data):
@ -177,6 +180,30 @@ class ZHDepsResourceHandler(drest.resource.ResourceHandler):
for edge in response.data['dependencies']
])
class ZHEpicsResourceHandler(drest.resource.ResourceHandler):
def get(self, repo_id):
path = '/repositories/%d/epics' % repo_id
try:
response = self.api.make_request('GET', path, {})
except drest.exc.dRestRequestError as e:
msg = "%s (repo_id: %s)" % (e.msg, repo_id)
raise drest.exc.dRestRequestError(msg, e.response)
return [i['issue_number'] for i in response.data['epic_issues']]
class ZHEpicsIssuesResourceHandler(drest.resource.ResourceHandler):
def get(self, repo_id, epic_id):
path = '/repositories/%d/epics/%d' % (repo_id, epic_id)
try:
response = self.api.make_request('GET', path, {})
except drest.exc.dRestRequestError as e:
msg = "%s (repo_id: %s)" % (e.msg, repo_id)
raise drest.exc.dRestRequestError(msg, e.response)
return [(i['repo_id'], i['issue_number']) for i in response.data['issues']]
class ZenHubAPI(drest.api.API):
class Meta:
baseurl = 'https://api.zenhub.com/p1'
@ -188,6 +215,8 @@ class ZenHubAPI(drest.api.API):
def __init__(self, *args, **kw):
super(ZenHubAPI, self).__init__(*args, **kw)
self.add_resource('dependencies', ZHDepsResourceHandler)
self.add_resource('epics', ZHEpicsResourceHandler)
self.add_resource('epics_issues', ZHEpicsIssuesResourceHandler)
def auth(self, *args, **kw):
pass
@ -203,6 +232,24 @@ def main():
# Build the full dependency graph from ZenHub's per-repo APIs.
dg = nx.compose_all([zapi.dependencies.get(x) for x in REPOS])
if SHOW_EPICS:
epics_issues = []
for repo_id in REPOS:
for epic_id in zapi.epics.get(repo_id):
epics_issues.append((repo_id, epic_id))
epics_mapping = download_issues(gapi, epics_issues)
epics_mapping = {k: v for (k, v) in epics_mapping.items() if v.state != 'closed'}
issues_by_epic = {}
for (i, ((repo_id, epic_id), epic)) in enumerate(epics_mapping.items()):
issues = set(zapi.epics_issues.get(repo_id, epic_id))
issues_by_epic[epic] = issues
for i in issues:
# zapi.dependencies only returns nodes that have some connection,
# but we'd like to show all issues from epics even if they are
# disconnected.
dg.add_node(i)
# Fetch the issues within the graph.
mapping = download_issues(gapi, dg.nodes)
@ -273,6 +320,12 @@ def main():
for (i, (milestone, nodes)) in enumerate(milestones.items()):
ag.add_subgraph(nodes, 'cluster_%d' % i, label=milestone, color='blue')
if SHOW_EPICS:
for (i, (epic, issues)) in enumerate(issues_by_epic.items()):
issues = [n for n in dg if (n.repo_id, n.issue_number) in issues]
if issues:
ag.add_subgraph(issues, 'cluster_%d' % i, label=epic.title, color='blue')
# Draw the result!
ag.graph_attr['rankdir'] = 'LR'
ag.graph_attr['stylesheet'] = 'zcash-dag.css'