Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Overview
devops-scm提供了一套统一的源代码接口,使得开发者能够方便地调用各大源代码管理平台的接口和接收源码管理平台的webhook事件。这样开发者就无需熟悉每个平台的API文档和webhook事件请求体,只需通过devops-scm提供的标准接口即可实现对源代码平台的管理。

目前支持的提供商有-工蜂。后续会陆续对接github、gitlab、gitee、apache svn
目前支持工蜂、GitLab、Gitee、BKCode 和 SVN 等源码管理平台。

## 代码目录说明
- devops-scm-api: api接口定义
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
object Release {
const val Group = "com.tencent.bk.devops.scm"
const val Version = "1.1.9"
const val Version = "1.2.0"
}

object Versions {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
dependencies {
api(project(":devops-scm-api"))
api(project(":devops-scm-provider:devops-scm-provider-git:devops-scm-provider-git-common"))
api(project(":devops-scm-sdk:devops-scm-sdk-gitlab"))
api("org.apache.commons:commons-lang3")

testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("ch.qos.logback:logback-core")
testImplementation("ch.qos.logback:logback-classic")
testImplementation("org.mockito:mockito-core")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.tencent.devops.scm.provider.git.gitlab

import com.tencent.devops.scm.api.pojo.auth.IScmAuth
import com.tencent.devops.scm.api.pojo.repository.git.GitScmProviderRepository
import com.tencent.devops.scm.provider.common.GitScmApiTemplate
import com.tencent.devops.scm.provider.git.gitlab.auth.GitlabAuthProviderFactory
import com.tencent.devops.scm.sdk.gitlab.GitlabApi
import com.tencent.devops.scm.sdk.gitlab.GitlabApiException
import com.tencent.devops.scm.sdk.gitlab.GitlabApiFactory

object GitlabApiTemplate : GitScmApiTemplate<GitlabApi, GitlabApiFactory, GitlabApiException>() {
override fun getApi(repository: GitScmProviderRepository, apiFactory: GitlabApiFactory): GitlabApi {
val auth = requireNotNull(repository.auth) { "GitLab repository auth cannot be null" }
require(repository.projectIdOrPath.toString().isNotBlank()) { "GitLab project id or path cannot be blank" }
return apiFactory.fromAuthProvider(GitlabAuthProviderFactory.create(auth))
}

override fun getApi(auth: IScmAuth, apiFactory: GitlabApiFactory): GitlabApi =
apiFactory.fromAuthProvider(GitlabAuthProviderFactory.create(auth))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.tencent.devops.scm.provider.git.gitlab

import com.tencent.devops.scm.api.CheckRunService
import com.tencent.devops.scm.api.pojo.CheckRun
import com.tencent.devops.scm.api.pojo.CheckRunInput
import com.tencent.devops.scm.api.pojo.CheckRunListOptions
import com.tencent.devops.scm.api.pojo.repository.ScmProviderRepository
import com.tencent.devops.scm.sdk.gitlab.GitlabApiFactory

class GitlabCheckRunService(private val apiFactory: GitlabApiFactory) : CheckRunService {
override fun create(repository: ScmProviderRepository, input: CheckRunInput): CheckRun {
val sha = requireNotNull(input.ref).takeIf(String::isNotBlank)
?: throw IllegalArgumentException("check run ref cannot be blank")
val state = GitlabObjectConverter.convertCheckRunState(input.status, input.conclusion)
return GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
GitlabObjectConverter.convertCheckRun(
api.commitStatusesApi.create(
repo.projectIdOrPath,
sha,
state,
input.name,
null,
input.detailsUrl,
input.output?.summary
)
)
}
}

override fun update(repository: ScmProviderRepository, input: CheckRunInput): CheckRun = create(repository, input)

override fun getCheckRuns(repository: ScmProviderRepository, opts: CheckRunListOptions): List<CheckRun> =
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
api.commitStatusesApi.getStatuses(
repo.projectIdOrPath,
opts.ref,
null,
null,
opts.page,
(opts.pageSize ?: 100).coerceIn(1, 100)
).map(GitlabObjectConverter::convertCheckRun)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.tencent.devops.scm.provider.git.gitlab

import com.tencent.devops.scm.api.FileService
import com.tencent.devops.scm.api.pojo.Content
import com.tencent.devops.scm.api.pojo.ContentInput
import com.tencent.devops.scm.api.pojo.Tree
import com.tencent.devops.scm.api.pojo.repository.ScmProviderRepository
import com.tencent.devops.scm.sdk.gitlab.GitlabApiFactory

class GitlabFileService(private val apiFactory: GitlabApiFactory) : FileService {
override fun find(repository: ScmProviderRepository, path: String, ref: String): Content =
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
GitlabObjectConverter.convertContent(api.repositoryFilesApi.getFile(repo.projectIdOrPath, path, ref))
}

override fun create(repository: ScmProviderRepository, path: String, input: ContentInput) {
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
api.repositoryFilesApi.createFile(
repo.projectIdOrPath, path, input.ref, input.content, input.message
)
}
}

override fun update(repository: ScmProviderRepository, path: String, input: ContentInput) {
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
api.repositoryFilesApi.updateFile(
repo.projectIdOrPath, path, input.ref, input.content, input.message
)
}
}

override fun listTree(
repository: ScmProviderRepository,
path: String,
ref: String,
recursive: Boolean
): List<Tree> = GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
val trees = mutableListOf<Tree>()
var page = 1
do {
val current = api.repositoryFilesApi.getTree(repo.projectIdOrPath, path, ref, recursive, page++, PAGE_SIZE)
trees += current.map { GitlabObjectConverter.convertTree(it, path) }
} while (current.size == PAGE_SIZE)
trees
}

private companion object {
const val PAGE_SIZE = 100
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.tencent.devops.scm.provider.git.gitlab

import com.tencent.devops.scm.api.IssueService
import com.tencent.devops.scm.api.enums.IssueState
import com.tencent.devops.scm.api.pojo.Comment
import com.tencent.devops.scm.api.pojo.CommentInput
import com.tencent.devops.scm.api.pojo.Issue
import com.tencent.devops.scm.api.pojo.IssueInput
import com.tencent.devops.scm.api.pojo.IssueListOptions
import com.tencent.devops.scm.api.pojo.ListOptions
import com.tencent.devops.scm.api.pojo.repository.ScmProviderRepository
import com.tencent.devops.scm.sdk.gitlab.GitlabApiFactory
import com.tencent.devops.scm.sdk.gitlab.pojo.GitlabIssueParams

class GitlabIssueService(private val apiFactory: GitlabApiFactory) : IssueService {
override fun find(repository: ScmProviderRepository, number: Int): Issue =
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
GitlabObjectConverter.convertIssue(api.issuesApi.getIssue(repo.projectIdOrPath, number.toLong()))
}

override fun create(repository: ScmProviderRepository, input: IssueInput): Issue {
require(input.title.isNotBlank()) { "issue title cannot be blank" }
val params = GitlabIssueParams.builder().title(input.title).description(input.body).build()
return GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
GitlabObjectConverter.convertIssue(api.issuesApi.createIssue(repo.projectIdOrPath, params))
}
}

override fun list(repository: ScmProviderRepository, opts: IssueListOptions): List<Issue> =
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
api.issuesApi.getIssues(repo.projectIdOrPath, state(opts.state), null, opts.page, size(opts.pageSize))
.map(GitlabObjectConverter::convertIssue)
}

override fun close(repository: ScmProviderRepository, number: Int) {
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
api.issuesApi.closeIssue(repo.projectIdOrPath, number.toLong())
}
}

override fun findComment(repository: ScmProviderRepository, number: Int, commentId: Long): Comment =
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
GitlabObjectConverter.convertComment(api.notesApi.getIssueNote(repo.projectIdOrPath, number.toLong(), commentId))
}

override fun listComments(repository: ScmProviderRepository, number: Int, opts: ListOptions): List<Comment> =
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
api.notesApi.getIssueNotes(repo.projectIdOrPath, number.toLong(), opts.page, size(opts.pageSize))
.map(GitlabObjectConverter::convertComment)
}

override fun createComment(repository: ScmProviderRepository, number: Int, input: CommentInput): Comment {
require(input.body.isNotBlank()) { "comment body cannot be blank" }
return GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
GitlabObjectConverter.convertComment(api.notesApi.createIssueNote(repo.projectIdOrPath, number.toLong(), input.body))
}
}

override fun deleteComment(repository: ScmProviderRepository, number: Int, commentId: Long) {
GitlabApiTemplate.execute(repository, apiFactory) { repo, api ->
api.notesApi.deleteIssueNote(repo.projectIdOrPath, number.toLong(), commentId)
}
}

private fun state(value: IssueState?) = when (value) {
IssueState.OPENED, IssueState.REOPENED -> "opened"
IssueState.CLOSED -> "closed"
else -> null
}

private fun size(value: Int?) = (value ?: 100).coerceIn(1, 100)
}
Loading