-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproof_of_concept_02_data_processing.py
More file actions
162 lines (138 loc) · 4.98 KB
/
Copy pathproof_of_concept_02_data_processing.py
File metadata and controls
162 lines (138 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import json
import os
import requests
import logging
from collections import defaultdict
from tqdm import tqdm
# Logging configuration
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# GitHub Token
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
headers = {
'Authorization': f'token {GITHUB_TOKEN}',
'Accept': 'application/vnd.github.v3+json'
}
# --- HELPER FUNCTIONS ---
# Keywords by tag type
KEYWORDS = {
'testing': ['test', 'testing', 'ci', 'unit', 'integration'],
'fix': ['fix', 'bug', 'error', 'fail'],
'mock': ['mock', 'stub'],
'config': ['config', 'configuration', 'setup'],
'model': ['model', 'schema'],
'extension': ['extend', 'extension', 'feature'],
'refactor': ['refactor', 'restructure'],
'obsolete': ['obsolete', 'deprecated', 'remove']
}
def extract_tags(text):
tags = set()
text = text.lower()
for tag, words in KEYWORDS.items():
if any(word in text for word in words):
tags.add(tag)
return tags
def detect_feature_from_path(file_path, valid_features):
parts = file_path.split('/')
for part in parts:
if part in valid_features:
return part
return None
def get_commit_files(owner, repo, sha):
url = f'https://api.github.com/repos/{owner}/{repo}/commits/{sha}'
response = requests.get(url, headers=headers)
if response.status_code == 200:
return [f['filename'] for f in response.json().get('files', [])]
logging.warning(f"⚠️ Failed to get files from commit {sha}: {response.status_code}")
return []
def get_pull_files(owner, repo, number):
files = []
page = 1
while True:
url = f'https://api.github.com/repos/{owner}/{repo}/pulls/{number}/files?page={page}&per_page=100'
response = requests.get(url, headers=headers)
if response.status_code != 200:
logging.warning(f"⚠️ Failed to get files from PR #{number}: {response.status_code}")
break
data = response.json()
if not data:
break
files += [f['filename'] for f in data]
page += 1
return files
def get_valid_features_from_repo(owner, repo):
url = f'https://api.github.com/repos/{owner}/{repo}/contents/app/modules'
response = requests.get(url, headers=headers)
if response.status_code != 200:
logging.warning(f"⚠️ Could not access app/modules for {owner}/{repo}")
return set()
contents = response.json()
valid_features = {item['name'] for item in contents if item['type'] == 'dir'}
logging.info("✅ Detected features:")
for f in sorted(valid_features):
print(f"- {f}")
return valid_features
# --- LOAD REPO CONFIGURATION ---
with open('proof_of_concept/commits.json') as f:
commits = json.load(f)
with open('proof_of_concept/issues.json') as f:
issues = json.load(f)
with open('proof_of_concept/pulls.json') as f:
pulls = json.load(f)
with open('forks.json', 'r') as f:
repos = json.load(f)
first_repo_entry = repos[0]
repo_full = first_repo_entry['repo'].replace('.csv', '')
owner, repo = repo_full.split('/')
# Automatically fetch valid features
VALID_FEATURES = get_valid_features_from_repo(owner, repo)
# --- PROCESSING ---
traceability_map = []
logging.info("Processing commits...")
for commit in tqdm(commits, desc="Commits"):
sha = commit.get('sha')
message = commit.get('commit', {}).get('message', '')
tags = extract_tags(message)
files = get_commit_files(owner, repo, sha)
features = set()
for file_path in files:
feature = detect_feature_from_path(file_path, VALID_FEATURES)
if feature:
features.add(feature)
for feature in features:
for tag in tags:
traceability_map.append((feature, 'commit', tag))
logging.info("Processing issues...")
for issue in tqdm(issues, desc="Issues"):
title = issue.get('title', '')
tags = extract_tags(title)
labels = issue.get('labels', [])
features = set()
for label in labels:
label_name = label.get('name', '')
if label_name in VALID_FEATURES:
features.add(label_name)
for feature in features:
for tag in tags:
traceability_map.append((feature, 'issue', tag))
logging.info("Processing pull requests...")
for pr in tqdm(pulls, desc="Pull Requests"):
number = pr.get('number')
title = pr.get('title', '')
tags = extract_tags(title)
files = get_pull_files(owner, repo, number)
features = set()
for file_path in files:
feature = detect_feature_from_path(file_path, VALID_FEATURES)
if feature:
features.add(feature)
for feature in features:
for tag in tags:
traceability_map.append((feature, 'pull_request', tag))
# Remove duplicates
traceability_map = list(set(traceability_map))
with open('proof_of_concept/traceability_map.json', 'w') as f:
json.dump(traceability_map, f, indent=2)
logging.info(f"✅ {len(traceability_map)} traceability tuples generated.")