UNPKG

git-aiflow

Version:

🚀 An AI-powered workflow automation tool for effortless Git-based development, combining smart GitLab/GitHub merge & pull request creation with Conan package management.

124 lines 5.13 kB
import { HttpClient } from '../http/http-client.js'; import { GitService } from './git-service.js'; /** * GitLab Merge Request service */ export class GitlabService { constructor(token, baseUrl, gitService, http) { this.token = token; this.http = http || new HttpClient(); if (gitService instanceof GitService && gitService) { // New usage: GitService for auto-detection this.gitService = gitService; } else { // Create a default GitService with Shell for auto-detection this.gitService = GitService.instance(); } // Auto-detect baseUrl from git remote if not provided if (baseUrl) { this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash } else { this.baseUrl = this.extractBaseUrlFromRemote(); } } /** * Extract GitLab base URL from git remote URL * @returns Base URL (e.g., "http://gitlab.com") */ extractBaseUrlFromRemote() { const remoteUrl = this.gitService?.getRemoteUrl() || ''; const sshMatch = remoteUrl.match(/^git@([^:]+):(.+?)(?:\.git)?$/); if (sshMatch) { return `http://${sshMatch[1]}`; } const httpMatch = remoteUrl.match(/^(https?:\/\/[^\/]+)/); if (httpMatch) { return httpMatch[1]; } // Fallback if no remote URL detected console.warn('⚠️ Could not extract GitLab base URL from remote, using default'); return 'http://gitlab.example.com'; } parseProjectPathFromUrl(remoteUrl) { try { const sshMatch = remoteUrl.match(/^git@([^:]+):(.+?)(?:\.git)?$/); if (sshMatch) { return sshMatch[2]; } const httpMatch = remoteUrl.match(/^https?:\/\/[^\/]+\/(.+?)(?:\.git)?$/); if (httpMatch) { return httpMatch[1]; } return null; } catch (error) { console.error(`❌ Failed to parse git remote URL: ${remoteUrl}`, error); return null; } } /** * Get project ID from GitLab API using project path * @param projectPath Project path * @returns Project ID */ async getProjectIdByPath(projectPath) { const encodedPath = encodeURIComponent(projectPath); const apiUrl = `${this.baseUrl}/api/v4/projects/${encodedPath}`; console.log(`🔍 Fetching project info from: ${apiUrl}`); try { const project = await this.http.requestJson(apiUrl, "GET", { "PRIVATE-TOKEN": this.token, "Content-Type": "application/json" }); console.log(`✅ Found project: ${project.name} (ID: ${project.id})`); console.log(`📋 Full path: ${project.path_with_namespace}`); return project.id.toString(); } catch (error) { throw new Error(`Failed to get project info for path "${projectPath}": ${error}`); } } /** * Get project ID (auto-detect if not provided) * @returns Project ID */ async getProjectId() { // Auto-detect project ID from git remote URL if (this.gitService) { const remoteUrl = this.gitService.getRemoteUrl(); console.log(`🔍 Git remote URL: ${remoteUrl}`); // Check for error messages from git commands if (remoteUrl.startsWith('Error getting URL') || remoteUrl === 'No remote configured') { throw new Error(`Git remote URL error: ${remoteUrl}`); } const projectPath = this.parseProjectPathFromUrl(remoteUrl); if (!projectPath) { throw new Error(`Failed to parse project path from git remote URL: ${remoteUrl}`); } console.log(`📋 Parsed project path: ${projectPath}`); // Get and cache project ID return await this.getProjectIdByPath(projectPath); } throw new Error('No project ID provided and no GitService available for auto-detection'); } async createMergeRequest(sourceBranch, targetBranch, title, squash = true, removeSourceBranch = true) { // Get project ID (auto-detect if needed) const projectId = await this.getProjectId(); // Build request body with all parameters const bodyParams = [ `source_branch=${encodeURIComponent(sourceBranch)}`, `target_branch=${encodeURIComponent(targetBranch)}`, `title=${encodeURIComponent(title)}`, `squash=${squash}`, // Squash all commits into one `remove_source_branch=${removeSourceBranch}` // Delete source branch after merge ]; const resp = await this.http.requestJson(`${this.baseUrl}/api/v4/projects/${projectId}/merge_requests`, "POST", { "PRIVATE-TOKEN": this.token, "Content-Type": "application/x-www-form-urlencoded", }, bodyParams.join('&')); return resp.web_url; } } //# sourceMappingURL=gitlab-service.js.map