diff --git a/.gitignore b/.gitignore index 8bc348e..6498037 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.venv/ venv/ __pycache__ \ No newline at end of file diff --git a/automation.py b/automation.py index d6fe58e..4371346 100644 --- a/automation.py +++ b/automation.py @@ -44,7 +44,7 @@ total_tickets=total_tickets, t_releases=t_releases, existing_codebase=existing_codebase, - target_data_file=target_data_file, isHotFix=isHotFix, includesBugs=includesBugs) + target_data_file=target_data_file, isHotFix=isHotFix, includesBugs=includesBugs, parent_branch=parent_branch) calculate_releases( number_of_features=number_of_features, number_of_bugs=number_of_bugs, diff --git a/requirements.txt b/requirements.txt index be2b74d..725529d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,13 @@ -PyYAML==6.0.1 +certifi==2024.6.2 +charset-normalizer==3.3.2 +DateTime==5.5 +idna==3.7 +numpy==1.26.4 +pandas==2.2.2 +python-dateutil==2.9.0.post0 +pytz==2024.1 +requests==2.32.3 +six==1.16.0 +tzdata==2024.1 +urllib3==2.2.1 +zope.interface==6.4.post2 diff --git a/utils/math.py b/utils/calc.py similarity index 100% rename from utils/math.py rename to utils/calc.py diff --git a/utils/calcMetrics.py b/utils/calcMetrics.py index d636bdb..fdef03b 100644 --- a/utils/calcMetrics.py +++ b/utils/calcMetrics.py @@ -1,15 +1,16 @@ import os import yaml from utils.date import get_current_date -from utils.math import calc_avg, calc_cfr_hotfix_to_release, calc_cfr_bugs_to_tasks_ratio, calc_cfr_bug_to_feature, calc_cfr_bug_release_ratio +from utils.calc import calc_avg, calc_cfr_hotfix_to_release, calc_cfr_bugs_to_tasks_ratio, calc_cfr_bug_to_feature, calc_cfr_bug_release_ratio from utils.dir import create_directory_and_file +from utils.leadTimeToChange import calcLeadTimeToChange current_date = get_current_date() # yields data.yaml -def calculate_metrics(number_of_features, number_of_bugs, number_of_hotfixes, total_tickets, t_releases, existing_codebase=True, target_data_file='metrics/data.yaml', isHotFix="true", includesBugs="true"): +def calculate_metrics(number_of_features, number_of_bugs, number_of_hotfixes, total_tickets, t_releases, existing_codebase=True, target_data_file='metrics/data.yaml', isHotFix="true", includesBugs="true", parent_branch='main'): if os.path.exists(target_data_file): print("Found existing target file, updating it with the latest release...") @@ -62,6 +63,7 @@ def calculate_metrics(number_of_features, number_of_bugs, number_of_hotfixes, to average_hotfixes_per_release = calc_avg( revised_total_hotfixes, current_release) + lead_time_to_chage = calcLeadTimeToChange(parent_branch) yaml_content = f""" .total_releases = {current_release} | .total_feature_releases = {revised_total_features} | @@ -71,6 +73,7 @@ def calculate_metrics(number_of_features, number_of_bugs, number_of_hotfixes, to .average_features_per_release = {average_features_per_release} | .average_bugs_per_release = {average_bugs_per_release} | .average_hotfixes_per_release = {average_hotfixes_per_release} | + .lead_time_to_change = {lead_time_to_chage} | .cfr_hotfix_to_release = "{cfr_hotfix_to_release} %" | .cfr_bugs_to_tasks_ratio = "{cfr_bugs_to_tasks_ratio} %" | .cfr_bug_to_feature = "{cfr_bug_to_feature} %" | diff --git a/utils/leadTimeToChange.py b/utils/leadTimeToChange.py new file mode 100644 index 0000000..791d18e --- /dev/null +++ b/utils/leadTimeToChange.py @@ -0,0 +1,79 @@ +# dora_metrics.py +import os +import requests +import pandas as pd +from datetime import datetime + +GITHUB_TOKEN = os.getenv('GITHUB_TOKEN') + +# GitHub repository details +REPO_OWNER = 'wednesday-solutions' +REPO_NAME = 'gen-ai-audio' + +# GitHub API base URL +BASE_URL = f'https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}' + +# Headers for authentication +HEADERS = { + 'Authorization': f'token {GITHUB_TOKEN}', + 'Accept': 'application/vnd.github.v3+json' +} + + +def fetch_pull_requests(branch): + url = f'{BASE_URL}/pulls' + params = { + 'state': 'closed', + 'base': branch + } + response = requests.get(url, headers=HEADERS, params=params) + response.raise_for_status() + return response.json() + + +def fetch_commits(branch): + url = f'{BASE_URL}/commits' + params = {'sha': branch} + response = requests.get(url, headers=HEADERS, params=params) + response.raise_for_status() + return response.json() + + +def get_commit_date(commit_url): + response = requests.get(commit_url, headers=HEADERS) + response.raise_for_status() + commit_data = response.json() + return commit_data['commit']['committer']['date'] + + +def calculate_lead_time(pr): + pr_created_at = datetime.strptime(pr['created_at'], '%Y-%m-%dT%H:%M:%SZ') + pr_merged_at = datetime.strptime(pr['merged_at'], '%Y-%m-%dT%H:%M:%SZ') + lead_time = pr_merged_at - pr_created_at + return lead_time + + +def calcLeadTimeToChange(branch='main'): + # Fetch pull requests merged into the base branch + prs = fetch_pull_requests(branch) + lead_times = [] + prCount = len(prs) + + if prCount > 0: + for pr in prs: + if pr['merged_at'] is None: + continue + lead_time = calculate_lead_time(pr) + lead_times.append({ + 'PR': pr['title'], + 'Lead Time': lead_time.total_seconds() / 3600 # Convert to hours + }) + + # Create a DataFrame for analysis + df = pd.DataFrame(lead_times) + print(df) + + # Calculate average lead time + average_lead_time = df['Lead Time'].mean() + print(f'Average Lead Time for Changes: {average_lead_time:.2f} hours') + return average_lead_time