Last active
August 26, 2021 17:34
-
-
Save mojowen/0a868385088942974e647fd6d8924cfe to your computer and use it in GitHub Desktop.
Analyze DORA metrics for gitlab deploys https://gitlab.com/groups/gitlab-org/-/epics/4358
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import os | |
from datetime import datetime, timedelta, timezone | |
from dateutil import parser | |
from urllib.parse import quote | |
import time | |
import requests | |
APIKEY = os.getenv("GITLAB_APIKEY", "") | |
DOMAIN = os.getenv("GITLAB_DOMAIN", "https://gitlab.com") | |
PROJECT = os.getenv("GITLAB_PROJECT", "") | |
if not PROJECT: | |
raise "Missing gitlab project, e.g. zapier/explore" | |
if not APIKEY: | |
raise "Missing gitlab api key, visit {}/{}/-/settings/access_tokens".format( | |
DOMAIN, PROJECT | |
) | |
def get_more(since): | |
return json.loads( | |
requests.get( | |
"{}/api/v4/projects/{}/deployments".format(DOMAIN, quote(PROJECT, safe="")), | |
params={ | |
"environment": "production", | |
"status": "success", | |
"sort": "desc", | |
"updated_before": since, | |
}, | |
headers={ | |
"Private-Token": APIKEY, | |
"Accept": "application/json", | |
"Content-Type": "application/json", | |
}, | |
).text | |
) | |
def get_data(starting, ending): | |
data = get_more(ending) | |
last = data[-1]["updated_at"] | |
while parser.parse(last) > starting: | |
data += get_more(last) | |
last = data[-1]["updated_at"] | |
return [deploy for deploy in data if parser.parse(deploy["created_at"]) > starting] | |
def workdays_between(starting, ending): | |
return sum( | |
1 | |
for day in ( | |
starting + timedelta(x + 1) for x in range((ending - starting).days) | |
) | |
if day.weekday() < 5 | |
) | |
def main(): | |
ending = datetime.today().replace(tzinfo=timezone.utc) | |
starting = ending - timedelta(days=30) | |
deploys = get_data(starting, ending) | |
times_to_deploy = [ | |
( | |
parser.parse(deploy["deployable"]["finished_at"]) | |
- parser.parse(deploy["deployable"]["commit"]["committed_date"]) | |
).seconds | |
for deploy in deploys | |
] | |
reverts = set( | |
[ | |
deploy["deployable"]["commit"]["id"] | |
for deploy in deploys | |
if "Revert" in deploy["deployable"]["commit"]["message"] | |
] | |
) | |
commits = set([deploy["deployable"]["commit"]["id"] for deploy in deploys]) | |
print("From {} till {}".format(starting.date(), ending.date())) | |
print("Total deploys: {}".format(len(commits))) | |
print( | |
"Deploys per workday: {}".format( | |
round(len(commits) / workdays_between(starting, ending), 2) | |
) | |
) | |
print( | |
"Time from merge to deployed: {}".format( | |
time.strftime("%H:%M:%S", time.gmtime(sum(times_to_deploy) / len(deploys))) | |
) | |
) | |
print( | |
"Deploys reverted: {}% ({} out of {})".format( | |
round(len(reverts) / len(commits) * 100.0, 1), len(reverts), len(commits) | |
) | |
) | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
requests |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment