Skip to content

Commit e7d33c1

Browse files
Vijay IyengarVijay Iyengar
authored andcommitted
fix: Use safe attribute access for commit objects
- Fixed unsafe direct attribute access in get_commits, get_commit, create_commit methods - Fixed similar issues in get_user_merge_commits and get_user_code_changes_summary - All commit attributes now use getattr() with None defaults to prevent AttributeError - This fixes the gitlab_list_commits tool failure reported by user
1 parent 17e1973 commit e7d33c1

File tree

2 files changed

+88
-53
lines changed

2 files changed

+88
-53
lines changed

src/mcp_gitlab/gitlab_client.py

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,19 +1047,19 @@ def get_commits(self, project_id: str, ref_name: Optional[str] = None,
10471047
return {
10481048
"commits": [
10491049
{
1050-
"id": commit.id,
1051-
"short_id": commit.short_id,
1052-
"title": commit.title,
1053-
"message": commit.message,
1054-
"author_name": commit.author_name,
1055-
"author_email": commit.author_email,
1056-
"authored_date": commit.authored_date,
1057-
"committer_name": commit.committer_name,
1058-
"committer_email": commit.committer_email,
1059-
"committed_date": commit.committed_date,
1060-
"created_at": commit.created_at,
1061-
"parent_ids": commit.parent_ids,
1062-
"web_url": commit.web_url
1050+
"id": getattr(commit, "id", None),
1051+
"short_id": getattr(commit, "short_id", None),
1052+
"title": getattr(commit, "title", None),
1053+
"message": getattr(commit, "message", None),
1054+
"author_name": getattr(commit, "author_name", None),
1055+
"author_email": getattr(commit, "author_email", None),
1056+
"authored_date": getattr(commit, "authored_date", None),
1057+
"committer_name": getattr(commit, "committer_name", None),
1058+
"committer_email": getattr(commit, "committer_email", None),
1059+
"committed_date": getattr(commit, "committed_date", None),
1060+
"created_at": getattr(commit, "created_at", None),
1061+
"parent_ids": getattr(commit, "parent_ids", None),
1062+
"web_url": getattr(commit, "web_url", None)
10631063
}
10641064
for commit in commits
10651065
],
@@ -1085,19 +1085,19 @@ def get_commit(self, project_id: str, commit_sha: str, include_stats: bool = Fal
10851085
commit = project.commits.get(commit_sha, stats=include_stats)
10861086

10871087
result = {
1088-
"id": commit.id,
1089-
"short_id": commit.short_id,
1090-
"title": commit.title,
1091-
"message": commit.message,
1092-
"author_name": commit.author_name,
1093-
"author_email": commit.author_email,
1094-
"authored_date": commit.authored_date,
1095-
"committer_name": commit.committer_name,
1096-
"committer_email": commit.committer_email,
1097-
"committed_date": commit.committed_date,
1098-
"created_at": commit.created_at,
1099-
"parent_ids": commit.parent_ids,
1100-
"web_url": commit.web_url
1088+
"id": getattr(commit, "id", None),
1089+
"short_id": getattr(commit, "short_id", None),
1090+
"title": getattr(commit, "title", None),
1091+
"message": getattr(commit, "message", None),
1092+
"author_name": getattr(commit, "author_name", None),
1093+
"author_email": getattr(commit, "author_email", None),
1094+
"authored_date": getattr(commit, "authored_date", None),
1095+
"committer_name": getattr(commit, "committer_name", None),
1096+
"committer_email": getattr(commit, "committer_email", None),
1097+
"committed_date": getattr(commit, "committed_date", None),
1098+
"created_at": getattr(commit, "created_at", None),
1099+
"parent_ids": getattr(commit, "parent_ids", None),
1100+
"web_url": getattr(commit, "web_url", None)
11011101
}
11021102

11031103
if include_stats and hasattr(commit, 'stats'):
@@ -1173,15 +1173,15 @@ def create_commit(self, project_id: str, branch: str, commit_message: str,
11731173
commit = project.commits.create(commit_data)
11741174

11751175
return {
1176-
"id": commit.id,
1177-
"short_id": commit.short_id,
1178-
"title": commit.title,
1179-
"message": commit.message,
1180-
"author_name": commit.author_name,
1181-
"author_email": commit.author_email,
1182-
"created_at": commit.created_at,
1183-
"parent_ids": commit.parent_ids,
1184-
"web_url": commit.web_url
1176+
"id": getattr(commit, "id", None),
1177+
"short_id": getattr(commit, "short_id", None),
1178+
"title": getattr(commit, "title", None),
1179+
"message": getattr(commit, "message", None),
1180+
"author_name": getattr(commit, "author_name", None),
1181+
"author_email": getattr(commit, "author_email", None),
1182+
"created_at": getattr(commit, "created_at", None),
1183+
"parent_ids": getattr(commit, "parent_ids", None),
1184+
"web_url": getattr(commit, "web_url", None)
11851185
}
11861186
except gitlab.exceptions.GitlabCreateError as e:
11871187
return {"error": f"Failed to create commit: {str(e)}"}
@@ -2015,24 +2015,24 @@ def get_user_merge_commits(self, username: str, project_id: Optional[str] = None
20152015
merge_commits = []
20162016
for commit in response:
20172017
try:
2018-
commit_detail = project.commits.get(commit.id)
2018+
commit_detail = project.commits.get(getattr(commit, "id", None))
20192019
parent_ids = getattr(commit_detail, 'parent_ids', [])
20202020

20212021
# Only include if it's a merge commit (has multiple parents)
20222022
if len(parent_ids) > 1:
20232023
commit_data = {
2024-
"id": commit.id,
2025-
"short_id": commit.short_id,
2026-
"title": commit.title,
2027-
"message": commit.message,
2028-
"author_name": commit.author_name,
2029-
"author_email": commit.author_email,
2030-
"authored_date": commit.authored_date,
2031-
"committer_name": commit.committer_name,
2032-
"committer_email": commit.committer_email,
2033-
"committed_date": commit.committed_date,
2034-
"created_at": commit.created_at,
2035-
"web_url": commit.web_url,
2024+
"id": getattr(commit, "id", None),
2025+
"short_id": getattr(commit, "short_id", None),
2026+
"title": getattr(commit, "title", None),
2027+
"message": getattr(commit, "message", None),
2028+
"author_name": getattr(commit, "author_name", None),
2029+
"author_email": getattr(commit, "author_email", None),
2030+
"authored_date": getattr(commit, "authored_date", None),
2031+
"committer_name": getattr(commit, "committer_name", None),
2032+
"committer_email": getattr(commit, "committer_email", None),
2033+
"committed_date": getattr(commit, "committed_date", None),
2034+
"created_at": getattr(commit, "created_at", None),
2035+
"web_url": getattr(commit, "web_url", None),
20362036
"parent_ids": parent_ids,
20372037
"parent_count": len(parent_ids)
20382038
}
@@ -2085,7 +2085,7 @@ def get_user_code_changes_summary(self, username: str, project_id: Optional[str]
20852085
commits_data = []
20862086
for commit in response:
20872087
try:
2088-
commit_detail = project.commits.get(commit.id)
2088+
commit_detail = project.commits.get(getattr(commit, "id", None))
20892089
stats = getattr(commit_detail, 'stats', {})
20902090
additions = stats.get('additions', 0)
20912091
deletions = stats.get('deletions', 0)
@@ -2094,10 +2094,10 @@ def get_user_code_changes_summary(self, username: str, project_id: Optional[str]
20942094
total_deletions += deletions
20952095

20962096
commits_data.append({
2097-
"id": commit.id,
2098-
"short_id": commit.short_id,
2099-
"title": commit.title,
2100-
"authored_date": commit.authored_date,
2097+
"id": getattr(commit, "id", None),
2098+
"short_id": getattr(commit, "short_id", None),
2099+
"title": getattr(commit, "title", None),
2100+
"authored_date": getattr(commit, "authored_date", None),
21012101
"additions": additions,
21022102
"deletions": deletions,
21032103
"total_changes": additions + deletions,

test_commits.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env python3
2+
"""Test script for GitLab commits functionality"""
3+
4+
import os
5+
from mcp_gitlab.gitlab_client import GitLabClient, GitLabConfig
6+
7+
# Setup configuration
8+
config = GitLabConfig(
9+
url=os.getenv("GITLAB_URL", "https://gitlab.com"),
10+
private_token=os.getenv("GITLAB_TOKEN")
11+
)
12+
13+
# Create client
14+
client = GitLabClient(config)
15+
16+
# Test with the project ID from the error
17+
project_id = "48563418"
18+
ref_name = "master"
19+
per_page = 3
20+
21+
print(f"Testing get_commits for project {project_id}...")
22+
print(f"Parameters: ref_name={ref_name}, per_page={per_page}")
23+
24+
try:
25+
result = client.get_commits(
26+
project_id=project_id,
27+
ref_name=ref_name,
28+
per_page=per_page
29+
)
30+
print("Success!")
31+
print(f"Result: {result}")
32+
except Exception as e:
33+
print(f"Error: {type(e).__name__}: {str(e)}")
34+
import traceback
35+
traceback.print_exc()

0 commit comments

Comments
 (0)