import * as plugins from '../plugins.ts'; import type * as interfaces from '../../ts_interfaces/index.ts'; import { BaseProvider, type ITestConnectionResult, type IListOptions } from './classes.baseprovider.ts'; /** * Gitea API v1 provider implementation */ export class GiteaProvider extends BaseProvider { private client: plugins.giteaClient.GiteaClient; constructor(connectionId: string, baseUrl: string, token: string) { super(connectionId, baseUrl, token); this.client = new plugins.giteaClient.GiteaClient(baseUrl, token); } async testConnection(): Promise { return this.client.testConnection(); } async getProjects(opts?: IListOptions): Promise { const repos = await this.client.getRepos(opts); return repos.map((r) => this.mapProject(r)); } async getGroups(opts?: IListOptions): Promise { const orgs = await this.client.getOrgs(opts); return orgs.map((o) => this.mapGroup(o)); } // --- Project Secrets --- async getProjectSecrets(projectId: string): Promise { const secrets = await this.client.getRepoSecrets(projectId); return secrets.map((s) => this.mapSecret(s, 'project', projectId)); } async createProjectSecret( projectId: string, key: string, value: string, ): Promise { await this.client.setRepoSecret(projectId, key, value); return { key, value: '***', protected: false, masked: true, scope: 'project', scopeId: projectId, connectionId: this.connectionId, environment: '*' }; } async updateProjectSecret( projectId: string, key: string, value: string, ): Promise { return this.createProjectSecret(projectId, key, value); } async deleteProjectSecret(projectId: string, key: string): Promise { await this.client.deleteRepoSecret(projectId, key); } // --- Group Secrets --- async getGroupSecrets(groupId: string): Promise { const secrets = await this.client.getOrgSecrets(groupId); return secrets.map((s) => this.mapSecret(s, 'group', groupId)); } async createGroupSecret( groupId: string, key: string, value: string, ): Promise { await this.client.setOrgSecret(groupId, key, value); return { key, value: '***', protected: false, masked: true, scope: 'group', scopeId: groupId, connectionId: this.connectionId, environment: '*' }; } async updateGroupSecret( groupId: string, key: string, value: string, ): Promise { return this.createGroupSecret(groupId, key, value); } async deleteGroupSecret(groupId: string, key: string): Promise { await this.client.deleteOrgSecret(groupId, key); } // --- Pipelines (Action Runs) --- async getPipelines( projectId: string, opts?: IListOptions, ): Promise { const runs = await this.client.getActionRuns(projectId, opts); return runs.map((r) => this.mapPipeline(r, projectId)); } async getPipelineJobs( projectId: string, pipelineId: string, ): Promise { const jobs = await this.client.getActionRunJobs(projectId, Number(pipelineId)); return jobs.map((j) => this.mapJob(j, pipelineId)); } async getJobLog(projectId: string, jobId: string): Promise { return this.client.getJobLog(projectId, Number(jobId)); } async retryPipeline(projectId: string, pipelineId: string): Promise { await this.client.rerunAction(projectId, Number(pipelineId)); } async cancelPipeline(projectId: string, pipelineId: string): Promise { await this.client.cancelAction(projectId, Number(pipelineId)); } // --- Mappers --- private mapProject(r: plugins.giteaClient.IGiteaRepository): interfaces.data.IProject { return { id: String(r.id), name: r.name || '', fullPath: r.full_name || '', description: r.description || '', defaultBranch: r.default_branch || 'main', webUrl: r.html_url || '', connectionId: this.connectionId, visibility: r.private ? 'private' : 'public', topics: r.topics || [], lastActivity: r.updated_at || '', }; } private mapGroup(o: plugins.giteaClient.IGiteaOrganization): interfaces.data.IGroup { return { id: String(o.id || o.name), name: o.name || '', fullPath: o.name || '', description: o.description || '', webUrl: `${this.baseUrl}/${o.name}`, connectionId: this.connectionId, visibility: o.visibility || 'public', projectCount: o.repo_count || 0, }; } private mapSecret(s: plugins.giteaClient.IGiteaSecret, scope: 'project' | 'group', scopeId: string): interfaces.data.ISecret { return { key: s.name || '', value: '***', protected: false, masked: true, scope, scopeId, connectionId: this.connectionId, environment: '*', }; } private mapPipeline(r: plugins.giteaClient.IGiteaActionRun, projectId: string): interfaces.data.IPipeline { return { id: String(r.id), projectId, projectName: projectId, connectionId: this.connectionId, status: this.mapStatus(r.status || r.conclusion), ref: r.head_branch || '', sha: r.head_sha || '', webUrl: r.html_url || '', duration: r.run_duration || 0, createdAt: r.created_at || '', source: r.event || 'push', }; } private mapJob(j: plugins.giteaClient.IGiteaActionRunJob, pipelineId: string): interfaces.data.IPipelineJob { return { id: String(j.id), pipelineId, name: j.name || '', stage: j.name || 'default', status: this.mapStatus(j.status || j.conclusion), duration: j.run_duration || 0, }; } private mapStatus(status: string): interfaces.data.TPipelineStatus { const map: Record = { success: 'success', completed: 'success', failure: 'failed', cancelled: 'canceled', waiting: 'waiting', running: 'running', queued: 'pending', in_progress: 'running', skipped: 'skipped', }; return map[status?.toLowerCase()] || 'pending'; } }