import * as plugins from '../plugins.ts'; import type * as interfaces from '../../ts_interfaces/index.ts'; import { BaseProvider, type ITestConnectionResult, type IListOptions, type IPipelineListOptions } from './classes.baseprovider.ts'; /** * GitLab API v4 provider implementation */ export class GitLabProvider extends BaseProvider { private client: plugins.gitlabClient.GitLabClient; constructor(connectionId: string, baseUrl: string, token: string, groupFilterId?: string) { super(connectionId, baseUrl, token, groupFilterId); this.client = new plugins.gitlabClient.GitLabClient(baseUrl, token); } async testConnection(): Promise { return this.client.testConnection(); } async getProjects(opts?: IListOptions): Promise { const projects = this.groupFilterId ? await (await this.client.getGroup(this.groupFilterId)).getProjects(opts) : await this.client.getProjects(opts); return projects.map((p) => this.mapProject(p)); } async getGroups(opts?: IListOptions): Promise { if (this.groupFilterId) { const group = await this.client.getGroup(this.groupFilterId); const descendants = await group.getDescendantGroups(opts); return descendants.map((g) => this.mapGroup(g)); } const groups = await this.client.getGroups(opts); return groups.map((g) => this.mapGroup(g)); } async getGroupProjects(groupId: string, opts?: IListOptions): Promise { const group = await this.client.getGroup(groupId); const projects = await group.getProjects(opts); return projects.map((p) => this.mapProject(p)); } // --- Branches / Tags --- async getBranches(projectFullPath: string, opts?: IListOptions): Promise { const project = await this.client.getProject(projectFullPath); const branches = await project.getBranches(opts); return branches.map((b) => ({ name: b.name, commitSha: b.commitSha })); } async getTags(projectFullPath: string, opts?: IListOptions): Promise { const project = await this.client.getProject(projectFullPath); const tags = await project.getTags(opts); return tags.map((t) => ({ name: t.name, commitSha: t.commitSha })); } // --- Project Secrets (CI/CD Variables) --- async getProjectSecrets(projectId: string): Promise { const project = await this.client.getProject(projectId); const vars = await project.getVariables(); return vars.map((v) => this.mapVariable(v, 'project', projectId)); } async createProjectSecret( projectId: string, key: string, value: string, ): Promise { const project = await this.client.getProject(projectId); const v = await project.createVariable(key, value); return this.mapVariable(v, 'project', projectId); } async updateProjectSecret( projectId: string, key: string, value: string, ): Promise { const project = await this.client.getProject(projectId); const v = await project.updateVariable(key, value); return this.mapVariable(v, 'project', projectId); } async deleteProjectSecret(projectId: string, key: string): Promise { const project = await this.client.getProject(projectId); await project.deleteVariable(key); } // --- Group Secrets (CI/CD Variables) --- async getGroupSecrets(groupId: string): Promise { const group = await this.client.getGroup(groupId); const vars = await group.getVariables(); return vars.map((v) => this.mapVariable(v, 'group', groupId)); } async createGroupSecret( groupId: string, key: string, value: string, ): Promise { const group = await this.client.getGroup(groupId); const v = await group.createVariable(key, value); return this.mapVariable(v, 'group', groupId); } async updateGroupSecret( groupId: string, key: string, value: string, ): Promise { const group = await this.client.getGroup(groupId); const v = await group.updateVariable(key, value); return this.mapVariable(v, 'group', groupId); } async deleteGroupSecret(groupId: string, key: string): Promise { const group = await this.client.getGroup(groupId); await group.deleteVariable(key); } // --- Pipelines --- async getPipelines( projectId: string, opts?: IPipelineListOptions, ): Promise { const project = await this.client.getProject(projectId); const pipelines = await project.getPipelines({ page: opts?.page, perPage: opts?.perPage, status: opts?.status, ref: opts?.ref, source: opts?.source, }); return pipelines.map((p) => this.mapPipeline(p, projectId)); } async getPipelineJobs( projectId: string, pipelineId: string, ): Promise { const jobs = await this.client.requestGetPipelineJobs(projectId, Number(pipelineId)); return jobs.map((j) => this.mapJob(j, pipelineId)); } async getJobLog(projectId: string, jobId: string): Promise { return this.client.requestGetJobLog(projectId, Number(jobId)); } async retryPipeline(projectId: string, pipelineId: string): Promise { await this.client.requestRetryPipeline(projectId, Number(pipelineId)); } async cancelPipeline(projectId: string, pipelineId: string): Promise { await this.client.requestCancelPipeline(projectId, Number(pipelineId)); } // --- Mappers --- private mapProject(p: plugins.gitlabClient.GitLabProject): interfaces.data.IProject { return { id: String(p.id), name: p.name, fullPath: p.fullPath, description: p.description, defaultBranch: p.defaultBranch, webUrl: p.webUrl, connectionId: this.connectionId, visibility: p.visibility, topics: p.topics, lastActivity: p.lastActivityAt, }; } private mapGroup(g: plugins.gitlabClient.GitLabGroup): interfaces.data.IGroup { return { id: String(g.id), name: g.name, fullPath: g.fullPath, description: g.description, webUrl: g.webUrl, connectionId: this.connectionId, visibility: g.visibility, projectCount: 0, }; } private mapVariable( v: plugins.gitlabClient.GitLabVariable, scope: 'project' | 'group', scopeId: string, ): interfaces.data.ISecret { return { key: v.key, value: v.value || '***', protected: v.protected, masked: v.masked, scope, scopeId, scopeName: scopeId, connectionId: this.connectionId, environment: v.environmentScope, }; } private mapPipeline(p: plugins.gitlabClient.GitLabPipeline, projectId: string): interfaces.data.IPipeline { return { id: String(p.id), projectId, projectName: projectId, connectionId: this.connectionId, status: (p.status || 'pending') as interfaces.data.TPipelineStatus, ref: p.ref, sha: p.sha, webUrl: p.webUrl, duration: p.duration, createdAt: p.createdAt, source: p.source || 'push', }; } private mapJob(j: plugins.gitlabClient.IGitLabJob, pipelineId: string): interfaces.data.IPipelineJob { return { id: String(j.id), pipelineId: String(pipelineId), name: j.name || '', stage: j.stage || '', status: (j.status || 'pending') as interfaces.data.TPipelineStatus, duration: j.duration || 0, }; } }