feat: add DevOps DAG

This commit is contained in:
Conrado Gouvea 2022-05-19 18:16:29 -03:00
parent 0c23c5de30
commit 9559668eb4
3 changed files with 26 additions and 3 deletions

View File

@ -70,6 +70,15 @@ jobs:
DAG_VIEW: zf-frost DAG_VIEW: zf-frost
SHOW_EPICS: true SHOW_EPICS: true
- name: Render ZF DevOps DAG
run: python3 ./zcash-issue-dag.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ZENHUB_TOKEN: ${{ secrets.ZENHUB_TOKEN }}
DAG_VIEW: zf-devops
SHOW_EPICS: true
ONLY_LABEL: A-devops
- name: Copy the index page - name: Copy the index page
run: cp ./index.html ./public run: cp ./index.html ./public

View File

@ -12,6 +12,7 @@
<main> <main>
<p><a href="zcash-zf-dag">Zebra & related repos</a></p> <p><a href="zcash-zf-dag">Zebra & related repos</a></p>
<p><a href="zcash-zf-frost-dag">FROST</a></p> <p><a href="zcash-zf-frost-dag">FROST</a></p>
<p><a href="zcash-zf-devops-dag">DevOps</a></p>
</main> </main>
<footer>Generated with a <a href="https://github.com/ZcashFoundation/developers">script</a> <footer>Generated with a <a href="https://github.com/ZcashFoundation/developers">script</a>
forked from <a href="https://github.com/zcash/developers">ECC</a>. forked from <a href="https://github.com/zcash/developers">ECC</a>.

View File

@ -80,6 +80,7 @@ REPO_SETS = {
'wallet-android': ANDROID_REPOS, 'wallet-android': ANDROID_REPOS,
'zf': ZF_REPOS, 'zf': ZF_REPOS,
'zf-frost': ZF_FROST_REPOS, 'zf-frost': ZF_FROST_REPOS,
'zf-devops': {**ZF_REPOS, **ZF_FROST_REPOS},
} }
REPOS = REPO_SETS[DAG_VIEW] REPOS = REPO_SETS[DAG_VIEW]
@ -96,6 +97,9 @@ SHOW_MILESTONES = strtobool(os.environ.get('SHOW_MILESTONES', 'false'))
# Whether to group issues and PRs by ZenHub epics. # Whether to group issues and PRs by ZenHub epics.
SHOW_EPICS = strtobool(os.environ.get('SHOW_EPICS', 'false')) SHOW_EPICS = strtobool(os.environ.get('SHOW_EPICS', 'false'))
# Whether to only show issues with a specified label.
ONLY_LABEL = os.environ.get('ONLY_LABEL', '')
class GitHubIssue: class GitHubIssue:
def __init__(self, repo_id, issue_number, data): def __init__(self, repo_id, issue_number, data):
@ -105,6 +109,7 @@ class GitHubIssue:
if data is not None: if data is not None:
labels = [label['name'] for label in data['labels']['nodes']] labels = [label['name'] for label in data['labels']['nodes']]
self.labels = labels
self.title = data['title'] self.title = data['title']
self.is_pr = 'merged' in data self.is_pr = 'merged' in data
self.is_committed = 'S-committed' in labels self.is_committed = 'S-committed' in labels
@ -284,12 +289,17 @@ def main():
attrs = dg.edges[source, sink] attrs = dg.edges[source, sink]
attrs['is_open'] = 0 if source.state == 'closed' else 1 attrs['is_open'] = 0 if source.state == 'closed' else 1
def should_ignore(n):
if ONLY_LABEL:
return n.state == 'closed' or ONLY_LABEL not in n.labels
return n.state == 'closed'
if not INCLUDE_FINISHED: if not INCLUDE_FINISHED:
# Identify the disconnected subgraphs. # Identify the disconnected subgraphs.
subgraphs = [dg.subgraph(c) for c in nx.connected_components(dg.to_undirected())] subgraphs = [dg.subgraph(c) for c in nx.connected_components(dg.to_undirected())]
# Identify subgraphs comprised entirely of closed issues. # Identify subgraphs comprised entirely of closed issues.
ignore = [g for g in subgraphs if all([n.state == 'closed' for n in g])] ignore = [g for g in subgraphs if all([should_ignore(n) for n in g])]
# Remove fully-closed subgraphs. # Remove fully-closed subgraphs.
if len(ignore) > 0: if len(ignore) > 0:
@ -299,10 +309,10 @@ def main():
if PRUNE_FINISHED: if PRUNE_FINISHED:
# - It would be nice to keep the most recently-closed issues on the DAG, but # - It would be nice to keep the most recently-closed issues on the DAG, but
# dg.out_degree seems to be broken... # dg.out_degree seems to be broken...
to_prune = [n for (n, degree) in dg.in_degree() if degree == 0 and n.state == 'closed'] to_prune = [n for (n, degree) in dg.in_degree() if degree == 0 and should_ignore(n)]
while len(to_prune) > 0: while len(to_prune) > 0:
dg.remove_nodes_from(to_prune) dg.remove_nodes_from(to_prune)
to_prune = [n for (n, degree) in dg.in_degree() if degree == 0 and n.state == 'closed'] to_prune = [n for (n, degree) in dg.in_degree() if degree == 0 and should_ignore(n)]
do_next = [n for (n, degree) in dg.in_degree(weight='is_open') if degree == 0 and n.state != 'closed'] do_next = [n for (n, degree) in dg.in_degree(weight='is_open') if degree == 0 and n.state != 'closed']
@ -320,6 +330,9 @@ def main():
else: else:
attrs['class'] = 'open' attrs['class'] = 'open'
attrs['fillcolor'] = '#c2e0c6' attrs['fillcolor'] = '#c2e0c6'
# Color downstream nodes without the specified label
if ONLY_LABEL and ONLY_LABEL not in n.labels:
attrs['fillcolor'] = '#a7c2aa'
attrs['penwidth'] = 2 if n in do_next else 1 attrs['penwidth'] = 2 if n in do_next else 1
attrs['shape'] = 'component' if n.is_pr else 'box' attrs['shape'] = 'component' if n.is_pr else 'box'
attrs['style'] = 'filled' attrs['style'] = 'filled'