@cyphbt/gitlab-mcp-server
Version:
GitLab MCP Server with tag and merge request functionality - supports both Token and SSH modes
202 lines • 7.46 kB
JavaScript
import { execSync } from 'child_process';
export class SSHGitLabClient {
config;
constructor(config) {
this.config = config;
}
/**
* 通过 Git 命令获取标签列表
*/
async getLatestTags(limit = 10) {
try {
// 使用 git ls-remote 获取远程标签
const output = execSync('git ls-remote --tags origin', {
cwd: process.cwd(),
encoding: 'utf8',
});
const lines = output.trim().split('\n').filter(line => line);
const tags = [];
for (const line of lines) {
const [hash, ref] = line.split('\t');
const tagName = ref.replace('refs/tags/', '');
// 跳过轻量标签的引用
if (ref.endsWith('^{}'))
continue;
tags.push({
name: tagName,
commit: {
id: hash,
short_id: hash.substring(0, 8),
title: `Tag: ${tagName}`,
created_at: new Date().toISOString(),
},
protected: false,
});
}
// 按版本号排序(降序)
tags.sort((a, b) => this.compareVersions(b.name, a.name));
return tags.slice(0, limit);
}
catch (error) {
throw new Error(`获取标签失败: ${error instanceof Error ? error.message : '未知错误'}`);
}
}
/**
* 通过 Git 命令创建标签
*/
async createTag(tagRequest) {
try {
const { tag_name, ref, message } = tagRequest;
// 创建本地标签
if (message) {
execSync(`git tag -a ${tag_name} ${ref} -m "${message}"`, {
cwd: process.cwd(),
});
}
else {
execSync(`git tag ${tag_name} ${ref}`, {
cwd: process.cwd(),
});
}
// 推送标签到远程
execSync(`git push origin ${tag_name}`, {
cwd: process.cwd(),
});
// 如果有发布描述,创建 GitLab Release
if (tagRequest.release_description) {
await this.createGitLabRelease(tag_name, tagRequest.release_description);
}
return {
name: tag_name,
message,
commit: {
id: execSync(`git rev-parse ${ref}`, { cwd: process.cwd(), encoding: 'utf8' }).trim(),
short_id: execSync(`git rev-parse --short ${ref}`, { cwd: process.cwd(), encoding: 'utf8' }).trim(),
title: `Tag: ${tag_name}`,
created_at: new Date().toISOString(),
},
protected: false,
};
}
catch (error) {
throw new Error(`创建标签失败: ${error instanceof Error ? error.message : '未知错误'}`);
}
}
/**
* 通过 Git 命令创建合并请求(使用 GitLab CLI)
*/
async createMergeRequest(mrRequest) {
try {
// 检查是否安装了 GitLab CLI
try {
execSync('glab --version', { stdio: 'ignore' });
}
catch {
throw new Error('需要安装 GitLab CLI (glab)。请运行: brew install glab 或访问 https://gitlab.com/gitlab-org/cli');
}
// 构建 glab 命令
const args = [
'mr', 'create',
'--source-branch', mrRequest.source_branch,
'--target-branch', mrRequest.target_branch,
'--title', mrRequest.title,
];
if (mrRequest.description) {
args.push('--description', mrRequest.description);
}
if (mrRequest.remove_source_branch) {
args.push('--delete-source-branch');
}
if (mrRequest.squash) {
args.push('--squash');
}
// 执行命令
const output = execSync(`glab ${args.join(' ')}`, {
cwd: process.cwd(),
encoding: 'utf8',
});
// 解析输出获取 MR 信息
const mrMatch = output.match(/!(\d+)/);
const mrId = mrMatch ? parseInt(mrMatch[1]) : 0;
return {
id: mrId,
iid: mrId,
title: mrRequest.title,
description: mrRequest.description,
state: 'opened',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
target_branch: mrRequest.target_branch,
source_branch: mrRequest.source_branch,
web_url: `${this.config.url}/${this.config.projectId}/-/merge_requests/${mrId}`,
};
}
catch (error) {
throw new Error(`创建合并请求失败: ${error instanceof Error ? error.message : '未知错误'}`);
}
}
/**
* 获取项目信息
*/
async getProjectInfo() {
try {
// 使用 git remote 获取项目信息
const remoteUrl = execSync('git remote get-url origin', {
cwd: process.cwd(),
encoding: 'utf8',
}).trim();
const currentBranch = execSync('git branch --show-current', {
cwd: process.cwd(),
encoding: 'utf8',
}).trim();
const defaultBranch = execSync('git symbolic-ref refs/remotes/origin/HEAD', {
cwd: process.cwd(),
encoding: 'utf8',
}).trim().replace('refs/remotes/origin/', '');
return {
id: this.config.projectId,
name: remoteUrl.split('/').pop()?.replace('.git', '') || 'Unknown',
description: '',
path_with_namespace: remoteUrl.replace(/^.*?[:/](.+?)\.git$/, '$1'),
default_branch: defaultBranch,
visibility: 'private',
web_url: remoteUrl.replace('.git', ''),
};
}
catch (error) {
throw new Error(`获取项目信息失败: ${error instanceof Error ? error.message : '未知错误'}`);
}
}
/**
* 创建 GitLab Release(使用 GitLab CLI)
*/
async createGitLabRelease(tagName, description) {
try {
execSync(`glab release create ${tagName} --notes "${description}"`, {
cwd: process.cwd(),
});
}
catch (error) {
console.warn(`创建 GitLab Release 失败: ${error instanceof Error ? error.message : '未知错误'}`);
}
}
/**
* 比较版本号
*/
compareVersions(a, b) {
const normalize = (v) => {
return v.replace(/^v/, '').split('.').map(n => parseInt(n) || 0);
};
const va = normalize(a);
const vb = normalize(b);
for (let i = 0; i < Math.max(va.length, vb.length); i++) {
const na = va[i] || 0;
const nb = vb[i] || 0;
if (na !== nb) {
return na - nb;
}
}
return 0;
}
}
//# sourceMappingURL=ssh-gitlab-client.js.map