Skip to content

Instantly share code, notes, and snippets.

@aarongorka
Last active April 30, 2021 12:33
Show Gist options
  • Save aarongorka/f454fcdab27ace61ce9bcfdab49829ca to your computer and use it in GitHub Desktop.
Save aarongorka/f454fcdab27ace61ce9bcfdab49829ca to your computer and use it in GitHub Desktop.
Prints a PlantUML diagram that shows the DAG of the GitLab pipeline
#!/usr/bin/env python3
"""Prints a PlantUML diagram that shows the DAG of the GitLab pipeline"""
import sys
import yaml
from pprint import pprint
def merge(user, default):
if isinstance(user,dict) and isinstance(default,dict):
for k,v in default.items():
if k not in user:
user[k] = v
else:
user[k] = merge(user[k],v)
return user
merged = {}
with open('.gitlab-ci.yml') as file:
tmp = yaml.load(file)
filenames = tmp['include']
filenames.append('.gitlab-ci.yml')
for filename in filenames:
with open(f'./{filename}') as file:
tmp = yaml.load(file)
merge(merged, tmp)
tmp = {}
print('@startuml')
print('left to right direction')
jobs = {k: v for k, v in merged.items() if k not in ['image', 'services', 'stages', 'include']}
branches = {}
all_changes = [v['only']['changes'] for k, v in jobs.items() if type(v.get('only')) is dict and v.get('only', {}).get('changes', {}) and not v.get('needs')] # gather all `only:changes`
for changes in all_changes:
branches[str(changes)] = [] # list of e.g. {"kibana/**/*": deployKibanaDev}
if len(sys.argv) > 1:
for stage in merged['stages']: # This groups by stage, which looks nice but may be misleading
matching_jobs = [k for k, v in jobs.items() if v['stage'] == stage]
print(f'partition "{stage}" {{')
for job in matching_jobs:
needs = merged[job].get('needs')
if needs:
for need in needs:
print(f' "{need}" --> "{job}" ')
else:
print(f' (*) --> "{job}" ')
print("}")
else:
for job in jobs:
changes = []
needs = merged[job].get('needs')
try:
changes = merged[job]['only']['changes']
except:
pass
if needs: # if `needs:` exists, `only:changes` is implied from transitive depenencies
for need in needs:
print(f'"{need}" --> "{job}" ')
else:
if changes: # first job, has `only:changes`
branches[str(changes)].append(job)
else: # first job, triggers off all commits
print(f'(*) --> "{job}" ')
if branches:
for branch in branches:
print(f'(*) --> if "{branch}" then')
for job in branches[branch]:
print(f' --> "{job}"')
print(f'else') # this is probably not how `else` is supposed to be used but it looks good.
print('}')
print('@enduml')
@ragsonline
Copy link

ragsonline commented Mar 3, 2020

python3 ../../../plantuml.py
Traceback (most recent call last):
File "../../../plantuml.py", line 5, in
import yaml
ModuleNotFoundError: No module named 'yaml'

did
pip install pyyaml
and
pip3 install virtualenv [google recommend]

@ragsonline
Copy link

python3 -m pip install pyyaml fixed my issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment