From 33e3c89089abeba4da58a1933e3fc0a5080963e8 Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Wed, 24 Dec 2025 17:41:48 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20Bkcode=E6=94=AF=E6=8C=81Commit=20Ch?= =?UTF-8?q?eck=20#46?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scm/api/pojo/CheckRunListOptions.kt | 3 +- .../git/bkcode/BkCodeCheckRunService.kt | 21 +++- .../git/bkcode/BkCodeObjectConverter.kt | 60 +++++++++- .../git/bkcode/BkCodeWebhookParser.kt | 4 +- .../git/bkcode/BkCodeCheckRunServiceTest.kt | 106 +++++++++++++++++ .../src/test/resources/bkcode_mr_event.json | 4 +- .../test/resources/bkcode_mr_note_event.json | 4 +- .../devops/scm/sdk/bkcode/BkCodeApi.java | 12 ++ .../scm/sdk/bkcode/BkCodeCheckRunApi.java | 73 ++++++++++++ .../bkcode/enums/BkCodeCommitStateType.java | 8 ++ .../sdk/bkcode/pojo/BkCodeCommitStatus.java | 94 +++++++++++++++ .../bkcode/pojo/BkCodeCommitStatusInput.java | 39 +++++++ .../pojo/webhook/BkCodeEventMergeRequest.java | 4 + .../scm/sdk/bkcode/BkCodeCheckRunApiTest.java | 109 ++++++++++++++++++ .../resources/create_check_run_result.json | 35 ++++++ .../test/resources/get_check_runs_result.json | 70 +++++++++++ .../scm/sdk/common/util/ScmJsonUtil.java | 8 ++ 17 files changed, 642 insertions(+), 12 deletions(-) create mode 100644 devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeCheckRunServiceTest.kt create mode 100644 devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/BkCodeCheckRunApi.java create mode 100644 devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/enums/BkCodeCommitStateType.java create mode 100644 devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/BkCodeCommitStatus.java create mode 100644 devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/BkCodeCommitStatusInput.java create mode 100644 devops-scm-sdk/devops-scm-sdk-bkcode/src/test/java/com/tencent/devops/scm/sdk/bkcode/BkCodeCheckRunApiTest.java create mode 100644 devops-scm-sdk/devops-scm-sdk-bkcode/src/test/resources/create_check_run_result.json create mode 100644 devops-scm-sdk/devops-scm-sdk-bkcode/src/test/resources/get_check_runs_result.json diff --git a/devops-scm-api/src/main/kotlin/com/tencent/devops/scm/api/pojo/CheckRunListOptions.kt b/devops-scm-api/src/main/kotlin/com/tencent/devops/scm/api/pojo/CheckRunListOptions.kt index f8dbdac4..7d697c34 100644 --- a/devops-scm-api/src/main/kotlin/com/tencent/devops/scm/api/pojo/CheckRunListOptions.kt +++ b/devops-scm-api/src/main/kotlin/com/tencent/devops/scm/api/pojo/CheckRunListOptions.kt @@ -4,5 +4,6 @@ data class CheckRunListOptions( val page: Int? = null, val pageSize: Int? = null, val ref: String, - val pullRequestId: Long? = null + val pullRequestId: Long? = null, + val targetBranch: String? = null ) \ No newline at end of file diff --git a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeCheckRunService.kt b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeCheckRunService.kt index d31f3112..5ced8e70 100644 --- a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeCheckRunService.kt +++ b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeCheckRunService.kt @@ -10,14 +10,29 @@ import com.tencent.devops.scm.sdk.bkcode.BkCodeApiFactory class BkCodeCheckRunService(private val apiFactory: BkCodeApiFactory) : CheckRunService { override fun create(repository: ScmProviderRepository, input: CheckRunInput): CheckRun { - throw UnsupportedOperationException("bkcode not support create check run") + return BkCodeApiTemplate.execute(repository, apiFactory) { repo, bkCodeApi -> + val bkCodeCommitStatus = bkCodeApi.checkRunApi.create( + repo.projectIdOrPath, + input.ref ?: throw IllegalArgumentException("ref is required for BKCode check run"), + BkCodeObjectConverter.convertCheckRunInput(input) + ) + BkCodeObjectConverter.convertCheckRun(bkCodeCommitStatus) + } } override fun update(repository: ScmProviderRepository, input: CheckRunInput): CheckRun { - throw UnsupportedOperationException("bkcode not support update check run") + // BkCode API不支持更新check run,直接调用创建接口进行覆盖 + return create(repository, input) } override fun getCheckRuns(repository: ScmProviderRepository, opts: CheckRunListOptions): List { - throw UnsupportedOperationException("bkcode not support get check run") + return BkCodeApiTemplate.execute(repository, apiFactory) { repo, bkCodeApi -> + val checkRuns = bkCodeApi.checkRunApi.getCheckRuns( + repo.projectIdOrPath, + opts.ref, + opts.targetBranch + ) + checkRuns.map { BkCodeObjectConverter.convertCheckRun(it) } + } } } \ No newline at end of file diff --git a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeObjectConverter.kt b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeObjectConverter.kt index c1d59fdc..1bb6825b 100644 --- a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeObjectConverter.kt +++ b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeObjectConverter.kt @@ -1,8 +1,12 @@ package com.tencent.devops.scm.provider.git.bkcode +import com.tencent.devops.scm.api.enums.CheckRunConclusion +import com.tencent.devops.scm.api.enums.CheckRunStatus import com.tencent.devops.scm.api.enums.ScmEventType import com.tencent.devops.scm.api.enums.Visibility import com.tencent.devops.scm.api.pojo.Change +import com.tencent.devops.scm.api.pojo.CheckRun +import com.tencent.devops.scm.api.pojo.CheckRunInput import com.tencent.devops.scm.api.pojo.Comment import com.tencent.devops.scm.api.pojo.Commit import com.tencent.devops.scm.api.pojo.Content @@ -18,6 +22,9 @@ import com.tencent.devops.scm.api.pojo.repository.ScmProviderRepository import com.tencent.devops.scm.api.pojo.repository.git.GitRepositoryUrl import com.tencent.devops.scm.api.pojo.repository.git.GitScmProviderRepository import com.tencent.devops.scm.api.pojo.repository.git.GitScmServerRepository +import com.tencent.devops.scm.sdk.bkcode.enums.BkCodeCommitStateType +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeCommitStatus +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeCommitStatusInput import com.tencent.devops.scm.sdk.bkcode.enums.BkCodeEventType import com.tencent.devops.scm.sdk.bkcode.enums.BkCodeNoteableType import com.tencent.devops.scm.sdk.bkcode.enums.BkCodeRepoType @@ -122,11 +129,10 @@ object BkCodeObjectConverter { sshUrl = srcSource.sshUrl, webUrl = srcSource.httpUrl ) - // :TODO 最新commitId - val lastCommitSha = "" + val lastCommitSha = eventMergeRequest.headCommitId val base = Reference( name = eventMergeRequest.targetBranch, - sha = "", + sha = eventMergeRequest.baseCommitId, linkUrl = "" ) @@ -431,4 +437,52 @@ object BkCodeObjectConverter { sha = "", blobId = "" ) + + /*========================================check run====================================================*/ + fun convertCheckRunInput(input: CheckRunInput) = with(input) { + BkCodeCommitStatusInput.builder() + .context(name) + .state(convertCheckRunStatus(status, conclusion)) + .description(output?.summary ?: "") + .targetUrl(detailsUrl) + .reportHtml(output?.text ?: "") + .targetBranches(targetBranches) + .build() + } + + fun convertCheckRun(from: BkCodeCommitStatus) = with(from) { + CheckRun( + id = id, + name = context, + status = convertCheckRunStatus(state), + summary = description, + detailsUrl = targetUrl, + detail = reportHtml, + conclusion = convertCheckRunConclusion(state) + ) + } + + private fun convertCheckRunStatus(status: CheckRunStatus, conclusion: CheckRunConclusion?): BkCodeCommitStateType { + return when (status) { + CheckRunStatus.QUEUED, CheckRunStatus.IN_PROGRESS -> BkCodeCommitStateType.PENDING + CheckRunStatus.COMPLETED -> when (conclusion) { + CheckRunConclusion.SUCCESS -> BkCodeCommitStateType.SUCCESS + else -> BkCodeCommitStateType.FAILURE + } + + else -> BkCodeCommitStateType.FAILURE + } + } + + private fun convertCheckRunStatus(state: BkCodeCommitStateType) = when (state) { + BkCodeCommitStateType.PENDING -> CheckRunStatus.IN_PROGRESS + else -> CheckRunStatus.COMPLETED + } + + private fun convertCheckRunConclusion(state: BkCodeCommitStateType) = when (state) { + BkCodeCommitStateType.SUCCESS -> CheckRunConclusion.SUCCESS + BkCodeCommitStateType.FAILURE -> CheckRunConclusion.FAILURE + BkCodeCommitStateType.ERROR -> CheckRunConclusion.FAILURE + else -> null + } } diff --git a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeWebhookParser.kt b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeWebhookParser.kt index c9d41f40..e07d5dd4 100644 --- a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeWebhookParser.kt +++ b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/main/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeWebhookParser.kt @@ -168,15 +168,13 @@ class BkCodeWebhookParser : WebhookParser { ) val user = BkCodeObjectConverter.convertUser(src.sender) val pullRequest = BkCodeObjectConverter.convertPullRequest(user, src.mergeRequest) - // TODO: 完善commit - // val commit = BkCodeObjectConverter.convertCommit(src.commits.first()) return PullRequestHook( action = action, repo = repo, eventType = MERGE_REQUEST.name, pullRequest = pullRequest, sender = getSender(src), - commit = Commit(sha = "", message = ""), + commit = Commit(sha = src.mergeRequest.headCommitId, message = ""), extras = extras, changes = listOf() ) diff --git a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeCheckRunServiceTest.kt b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeCheckRunServiceTest.kt new file mode 100644 index 00000000..510a82d7 --- /dev/null +++ b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/kotlin/com/tencent/devops/scm/provider/git/bkcode/BkCodeCheckRunServiceTest.kt @@ -0,0 +1,106 @@ +package com.tencent.devops.scm.provider.git.bkcode + +import com.fasterxml.jackson.core.type.TypeReference +import com.tencent.devops.scm.api.enums.CheckRunConclusion +import com.tencent.devops.scm.api.enums.CheckRunStatus +import com.tencent.devops.scm.api.pojo.CheckRunInput +import com.tencent.devops.scm.api.pojo.CheckRunListOptions +import com.tencent.devops.scm.api.pojo.CheckRunOutput +import com.tencent.devops.scm.sdk.bkcode.BkCodeApiFactory +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeCommitStatus +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeResult +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyString +import org.mockito.Mockito +import java.time.LocalDateTime +import org.mockito.Mockito.`when` as whenMock + +class BkCodeCheckRunServiceTest : AbstractBkCodeServiceTest() { + + companion object { + private lateinit var checkRunService: BkCodeCheckRunService + } + + private val TEST_REF = "0cfeacad6fd5ceb7dc5dece5252b1bbdc3da3cc8" + + private val checkRunInput = CheckRunInput( + name = "devops-scm-bkcode-check", + ref = TEST_REF, + pullRequestId = 12345, + status = CheckRunStatus.IN_PROGRESS, + startedAt = LocalDateTime.now(), + output = CheckRunOutput( + title = "BKCode Check Run Test", + summary = "BKCode check run service test summary", + text = "BKCode check run service test details" + ), + targetBranches = listOf("master", "develop"), + conclusion = CheckRunConclusion.FAILURE, + detailsUrl = "https://github.com" + ) + + init { + apiFactory = createBkCodeApiFactory() + checkRunService = BkCodeCheckRunService(apiFactory) + mockData() + } + + private fun mockData() { + val apiFactory = Mockito.mock(BkCodeApiFactory::class.java) + checkRunService = BkCodeCheckRunService(apiFactory) + + val bkCodeApi = Mockito.mock(com.tencent.devops.scm.sdk.bkcode.BkCodeApi::class.java) + whenMock(apiFactory.fromAuthProvider(any())) + .thenReturn(bkCodeApi) + + val checkRunApi = Mockito.mock(com.tencent.devops.scm.sdk.bkcode.BkCodeCheckRunApi::class.java) + whenMock(bkCodeApi.checkRunApi).thenReturn(checkRunApi) + + whenMock(checkRunApi.create(anyString(), anyString(), any())) + .thenReturn( + read( + "create_check_run_result.json", + object : TypeReference>() {} + ).data + ) + + whenMock(checkRunApi.getCheckRuns(anyString(), anyString(), anyString())) + .thenReturn( + read( + "get_check_runs_result.json", + object : TypeReference>>() {} + ).data + ) + } + + @Test + fun create() { + val result = checkRunService.create(providerRepository, checkRunInput) + Assertions.assertEquals(result.status, CheckRunStatus.COMPLETED) + Assertions.assertEquals(result.conclusion, CheckRunConclusion.SUCCESS) + } + + @Test + fun update() { + val updateCheckRun = checkRunInput.copy( + status = CheckRunStatus.COMPLETED, + completedAt = LocalDateTime.now(), + conclusion = CheckRunConclusion.SUCCESS, + id = 67890 + ) + val result = checkRunService.update(providerRepository, updateCheckRun) + println("Updated check run: $result") + } + + @Test + fun getCheckRuns() { + val opts = CheckRunListOptions( + ref = TEST_REF, + targetBranch = "master" + ) + val results = checkRunService.getCheckRuns(providerRepository, opts) + println("Found ${results.size} check runs") + } +} \ No newline at end of file diff --git a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/resources/bkcode_mr_event.json b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/resources/bkcode_mr_event.json index 646999bc..9a79bebf 100644 --- a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/resources/bkcode_mr_event.json +++ b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/resources/bkcode_mr_event.json @@ -89,7 +89,9 @@ "closedAt": "null", "createdAt": "2025-11-07T19:53:38", "updatedAt": "2025-11-07T19:53:38", - "url": "https://bkcode.template.com/hejieehe/devops_trigger/-/mergeRequest/detail/2" + "url": "https://bkcode.template.com/hejieehe/devops_trigger/-/mergeRequest/detail/2", + "baseCommitId": "7eaa451cdfd155338f113f1bb2d57527f34fc657", + "headCommitId": "0cfeacad6fd5ceb7dc5dece5252b1bbdc3da3cc8" }, "changes": null, "requestedReviewers": null, diff --git a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/resources/bkcode_mr_note_event.json b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/resources/bkcode_mr_note_event.json index d9cd569d..c7142779 100644 --- a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/resources/bkcode_mr_note_event.json +++ b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-bkcode/src/test/resources/bkcode_mr_note_event.json @@ -112,7 +112,9 @@ "closedAt": "null", "createdAt": "2025-11-07T19:53:38", "updatedAt": "2025-11-07T19:53:38", - "url": "https://bkcode.template.com/hejieehe/devops_trigger/-/mergeRequest/detail/2" + "url": "https://bkcode.template.com/hejieehe/devops_trigger/-/mergeRequest/detail/2", + "baseCommitId": "7eaa451cdfd155338f113f1bb2d57527f34fc657", + "headCommitId": "0cfeacad6fd5ceb7dc5dece5252b1bbdc3da3cc8" }, "event": "COMMENT_EVENT", "action": "created", diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/BkCodeApi.java b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/BkCodeApi.java index 4432bbda..92b41b64 100644 --- a/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/BkCodeApi.java +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/BkCodeApi.java @@ -25,6 +25,7 @@ public class BkCodeApi { private volatile BkCodeCommitApi commitApi; private volatile BkCodeTagApi tagApi; private volatile BkCodeUserApi userApi; + private volatile BkCodeCheckRunApi checkRunApi; public BkCodeApi(BkCodeApiClient client) { @@ -134,4 +135,15 @@ public BkCodeUserApi getUserApi() { } return userApi; } + + public BkCodeCheckRunApi getCheckRunApi() { + if (checkRunApi == null) { + synchronized (this) { + if (checkRunApi == null) { + checkRunApi = new BkCodeCheckRunApi(this); + } + } + } + return checkRunApi; + } } diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/BkCodeCheckRunApi.java b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/BkCodeCheckRunApi.java new file mode 100644 index 00000000..235ebc59 --- /dev/null +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/BkCodeCheckRunApi.java @@ -0,0 +1,73 @@ +package com.tencent.devops.scm.sdk.bkcode; + + +import com.fasterxml.jackson.core.type.TypeReference; +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeCommitStatus; +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeCommitStatusInput; +import com.tencent.devops.scm.sdk.common.ScmHttpMethod; +import com.tencent.devops.scm.sdk.common.util.MapBuilder; +import com.tencent.devops.scm.sdk.common.util.ScmJsonUtil; +import java.io.IOException; +import java.util.List; + +public class BkCodeCheckRunApi extends AbstractBkCodeApi { + + private static final String CHECK_RUN_URI_PATTERN = "repos/:id/commit/status/ref"; + private static final String CHECK_RUN_SHA_URI_PATTERN = "repos/:id/commit/status/:sha"; + + public BkCodeCheckRunApi(BkCodeApi bkCodeApi) { + super(bkCodeApi); + } + + /** + * 创建检查项 + * + * @param projectIdOrPath 仓库名 + */ + public BkCodeCommitStatus create( + Object projectIdOrPath, + String sha, + BkCodeCommitStatusInput input + ) { + String repoId = getProjectIdOrPath(projectIdOrPath); + return bkCodeApi.createRequest() + .method(ScmHttpMethod.POST) + .withUrlPath( + CHECK_RUN_SHA_URI_PATTERN, + MapBuilder.newBuilder() + .add("id", repoId) + .add("sha", sha) + .build() + ) + .withRepoId(repoId) + .with(ScmJsonUtil.toJson(input)) + .fetch(BkCodeCommitStatus.class); + } + + /** + * 获取某个提交的检查项 + * + * @param projectIdOrPath 仓库名 + * @param ref commit sha + */ + public List getCheckRuns( + Object projectIdOrPath, + String ref, + String targetBranch + ) { + String repoId = getProjectIdOrPath(projectIdOrPath); + return bkCodeApi.createRequest() + .method(ScmHttpMethod.GET) + .withUrlPath( + CHECK_RUN_URI_PATTERN, + MapBuilder.newBuilder() + .add("id", repoId) + .build() + ) + .withRepoId(repoId) + .with("ref", ref) + .with("targetBranch", targetBranch) + .fetch(new TypeReference<>() { + }); + } +} diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/enums/BkCodeCommitStateType.java b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/enums/BkCodeCommitStateType.java new file mode 100644 index 00000000..a7d258c5 --- /dev/null +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/enums/BkCodeCommitStateType.java @@ -0,0 +1,8 @@ +package com.tencent.devops.scm.sdk.bkcode.enums; + +public enum BkCodeCommitStateType { + PENDING, + SUCCESS, + ERROR, + FAILURE +} diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/BkCodeCommitStatus.java b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/BkCodeCommitStatus.java new file mode 100644 index 00000000..24904c32 --- /dev/null +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/BkCodeCommitStatus.java @@ -0,0 +1,94 @@ +package com.tencent.devops.scm.sdk.bkcode.pojo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.tencent.devops.scm.sdk.bkcode.enums.BkCodeCommitStateType; +import java.util.List; +import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 提交状态实体类 + * 用于描述代码提交后的检测状态信息 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BkCodeCommitStatus { + + /** + * 提交状态ID(主键) + */ + private Long id; + + /** + * 仓库ID(关联代码仓库表) + */ + @JsonProperty("repoId") + private Long repoId; + + /** + * 提交SHA值(唯一标识某次代码提交) + */ + @JsonProperty("commitSha") + private String commitSha; + + /** + * 检测状态 + * 可选值:PENDING(待检测)、SUCCESS(检测通过)、ERROR(系统错误)、FAILURE(检测失败) + */ + private BkCodeCommitStateType state; + + /** + * 检测系统标签(用于区分不同检测维度,如:单元测试、代码规范、安全扫描等) + */ + private String context; + + /** + * 检测结果详情页面URL(跳转至具体检测报告页面) + */ + @JsonProperty("targetUrl") + private String targetUrl; + + /** + * 检测结果简短描述(如:"单元测试全部通过"、"发现2处代码规范问题") + */ + private String description; + + /** + * 检测结果HTML报告(包含完整HTML标签的富文本内容) + */ + @JsonProperty("reportHtml") + private String reportHtml; + + /** + * 检查结果关联的MR目标分支列表 + * 1. 非空时:仅展示在指定分支的MR中 + * 2. 为空时(默认):展示在所有MR中 + */ + @JsonProperty("targetBranches") + private List targetBranches; + + /** + * 创建人信息(关联用户实体) + */ + private BkCodeUser creator; + + /** + * 创建时间(格式:yyyy-MM-dd HH:mm:ss) + */ + @JsonProperty("createTime") + private String createTime; + + /** + * 更新人信息(关联用户实体) + */ + private BkCodeUser updater; + + /** + * 更新时间(格式:yyyy-MM-dd HH:mm:ss) + */ + @JsonProperty("updateTime") + private String updateTime; +} \ No newline at end of file diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/BkCodeCommitStatusInput.java b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/BkCodeCommitStatusInput.java new file mode 100644 index 00000000..1cfd4403 --- /dev/null +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/BkCodeCommitStatusInput.java @@ -0,0 +1,39 @@ +package com.tencent.devops.scm.sdk.bkcode.pojo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.tencent.devops.scm.sdk.bkcode.enums.BkCodeCommitStateType; +import java.util.List; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class BkCodeCommitStatusInput { + /** + * 检测系统标签,默认为 'default' + */ + private String context; + /** + * 检测结果状态 + */ + private BkCodeCommitStateType state; + /** + * 检测结果描述 + */ + private String description; + /** + * 检测结果详情页面URL + */ + @JsonProperty("targetUrl") + private String targetUrl; + /** + * 检测结果 HTML 报告 + */ + @JsonProperty("reportHtml") + private String reportHtml; + /** + * 检查结果关联的 MR(按目标分支识别),target_branches 为空时(默认),检查展示在所有 MR 中 + */ + @JsonProperty("targetBranches") + private List targetBranches; +} diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/webhook/BkCodeEventMergeRequest.java b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/webhook/BkCodeEventMergeRequest.java index 8a8583ee..d24938c0 100644 --- a/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/webhook/BkCodeEventMergeRequest.java +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/main/java/com/tencent/devops/scm/sdk/bkcode/pojo/webhook/BkCodeEventMergeRequest.java @@ -57,4 +57,8 @@ public class BkCodeEventMergeRequest { private String mergeCommitSha; @JsonProperty("reviewers") private List reviewers; + @JsonProperty("baseCommitId") + private String baseCommitId; + @JsonProperty("headCommitId") + private String headCommitId; } \ No newline at end of file diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/java/com/tencent/devops/scm/sdk/bkcode/BkCodeCheckRunApiTest.java b/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/java/com/tencent/devops/scm/sdk/bkcode/BkCodeCheckRunApiTest.java new file mode 100644 index 00000000..d3494842 --- /dev/null +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/java/com/tencent/devops/scm/sdk/bkcode/BkCodeCheckRunApiTest.java @@ -0,0 +1,109 @@ +package com.tencent.devops.scm.sdk.bkcode; + +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.tencent.devops.scm.sdk.bkcode.enums.BkCodeCommitStateType; +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeCommitStatus; +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeCommitStatusInput; +import com.tencent.devops.scm.sdk.bkcode.pojo.BkCodeResult; +import java.io.IOException; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class BkCodeCheckRunApiTest extends AbstractBkCodeTest { + + private static final String TEST_REF = "0cfeacad6fd5ceb7dc5dece5252b1bbdc3da3cc8"; + private static final String TEST_TARGET_BRANCH = "master"; + private static final BkCodeCommitStateType TEST_CHECK_RUN_STATE = BkCodeCommitStateType.SUCCESS; + private static final String TEST_CHECK_RUN_CONTEXT = "devops repo check"; + private static final String TEST_CHECK_RUN_DESC = "devops repo check desc"; + private static final String TEST_CHECK_RUN_TARGET_URL = "github.com"; + private static final String TEST_CHECK_RUN_REPORT_HTML = "
构建成功
"; + private static final List targetBranches = List.of("master"); + private static final BkCodeCommitStatusInput input = BkCodeCommitStatusInput.builder() + .state(TEST_CHECK_RUN_STATE) + .context(TEST_CHECK_RUN_CONTEXT) + .description(TEST_CHECK_RUN_DESC) + .targetUrl(TEST_CHECK_RUN_TARGET_URL) + .reportHtml(TEST_CHECK_RUN_REPORT_HTML) + .build(); + + public BkCodeCheckRunApiTest() { + super(); + } + + @BeforeAll + public static void setup() { + if (MOCK_DATA) { + mock(); + } else { + bkCodeApi = createBkCodeApi(); + } + } + + public static void mock() { + bkCodeApi = mockBkCodeApi(); + when(bkCodeApi.getCheckRunApi()).thenReturn(Mockito.mock(BkCodeCheckRunApi.class)); + when(bkCodeApi.getCheckRunApi() + .getCheckRuns( + TEST_PROJECT_NAME, + TEST_REF, + TEST_TARGET_BRANCH + ) + ).thenReturn( + read( + "get_check_runs_result.json", + new TypeReference>>() {} + ).getData() + ); + when(bkCodeApi.getCheckRunApi() + .create( + TEST_PROJECT_NAME, + TEST_REF, + input + ) + ).thenReturn( + read( + "create_check_run_result.json", + new TypeReference>() {} + ).getData() + ); + } + + @Test + public void create() throws IOException { + BkCodeCommitStatus bkCodeCommitStatus = bkCodeApi.getCheckRunApi().create( + TEST_PROJECT_NAME, + TEST_REF, + input + ); + Assertions.assertEquals(bkCodeCommitStatus.getContext(), TEST_CHECK_RUN_CONTEXT); + Assertions.assertEquals(bkCodeCommitStatus.getState(), TEST_CHECK_RUN_STATE); + Assertions.assertEquals(bkCodeCommitStatus.getDescription(), TEST_CHECK_RUN_DESC); + Assertions.assertEquals(bkCodeCommitStatus.getTargetUrl(), TEST_CHECK_RUN_TARGET_URL); + Assertions.assertEquals(bkCodeCommitStatus.getReportHtml(), TEST_CHECK_RUN_REPORT_HTML); + } + + @Test + public void getCheckRuns() { + List checkRuns = bkCodeApi.getCheckRunApi().getCheckRuns( + TEST_PROJECT_NAME, + TEST_REF, + TEST_TARGET_BRANCH + ); + Assertions.assertNotNull(checkRuns); + Assertions.assertFalse(checkRuns.isEmpty()); + + // 验证第一个check run的字段 + BkCodeCommitStatus firstCheckRun = checkRuns.get(0); + Assertions.assertNotNull(firstCheckRun.getContext()); + Assertions.assertNotNull(firstCheckRun.getState()); + Assertions.assertNotNull(firstCheckRun.getDescription()); + Assertions.assertNotNull(firstCheckRun.getTargetUrl()); + Assertions.assertNotNull(firstCheckRun.getReportHtml()); + } +} diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/resources/create_check_run_result.json b/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/resources/create_check_run_result.json new file mode 100644 index 00000000..795d29c1 --- /dev/null +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/resources/create_check_run_result.json @@ -0,0 +1,35 @@ +{ + "data" : { + "id" : 2, + "repoId" : 1121, + "commitSha" : "0cfeacad6fd5ceb7dc5dece5252b1bbdc3da3cc8", + "state" : "SUCCESS", + "context" : "devops repo check", + "targetUrl" : "github.com", + "description" : "devops repo check desc", + "reportHtml" : "
构建成功
", + "targetBranches" : [ ], + "creator" : { + "id" : "01e37622ab90437b99f4892df65deb18", + "username" : "admin", + "displayName" : "admin", + "email" : "admin@bkcode.com", + "tenantId" : "default", + "admin" : true, + "locale" : "zh", + "createTime" : "2025-10-15 11:37:36" + }, + "createTime" : "2025-12-31 10:23:03", + "updater" : { + "id" : "01e37622ab90437b99f4892df65deb18", + "username" : "admin", + "displayName" : "admin", + "email" : "admin@bkcode.com", + "tenantId" : "default", + "admin" : true, + "locale" : "zh", + "createTime" : "2025-10-15 11:37:36" + }, + "updateTime" : "2025-12-31 14:24:24" + } +} \ No newline at end of file diff --git a/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/resources/get_check_runs_result.json b/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/resources/get_check_runs_result.json new file mode 100644 index 00000000..4d8fbb3c --- /dev/null +++ b/devops-scm-sdk/devops-scm-sdk-bkcode/src/test/resources/get_check_runs_result.json @@ -0,0 +1,70 @@ +{ + "data": [ + { + "id": 1, + "repoId": 1121, + "commitSha": "0cfeacad6fd5ceb7dc5dece5252b1bbdc3da3cc8", + "state": "SUCCESS", + "context": "devops repo check", + "targetUrl": "github.com", + "description": "devops repo check desc", + "reportHtml": "
构建成功
", + "targetBranches": [], + "creator": { + "id": "01e37622ab90437b99f4892df65deb18", + "username": "admin", + "displayName": "admin", + "email": "admin@bkcode.com", + "tenantId": "default", + "admin": true, + "locale": "zh", + "createTime": "2025-10-15 11:37:36" + }, + "createTime": "2025-12-31 10:23:03", + "updater": { + "id": "01e37622ab90437b99f4892df65deb18", + "username": "admin", + "displayName": "admin", + "email": "admin@bkcode.com", + "tenantId": "default", + "admin": true, + "locale": "zh", + "createTime": "2025-10-15 11:37:36" + }, + "updateTime": "2025-12-31 14:24:24" + }, + { + "id": 2, + "repoId": 1121, + "commitSha": "0cfeacad6fd5ceb7dc5dece5252b1bbdc3da3cc8", + "state": "PENDING", + "context": "code quality check", + "targetUrl": "bkcode.com", + "description": "code quality check in progress", + "reportHtml": "
代码质量检查中...
", + "targetBranches": ["master"], + "creator": { + "id": "01e37622ab90437b99f4892df65deb18", + "username": "admin", + "displayName": "admin", + "email": "admin@bkcode.com", + "tenantId": "default", + "admin": true, + "locale": "zh", + "createTime": "2025-10-15 11:37:36" + }, + "createTime": "2025-12-31 14:25:00", + "updater": { + "id": "01e37622ab90437b99f4892df65deb18", + "username": "admin", + "displayName": "admin", + "email": "admin@bkcode.com", + "tenantId": "default", + "admin": true, + "locale": "zh", + "createTime": "2025-10-15 11:37:36" + }, + "updateTime": "2025-12-31 14:25:00" + } + ] +} \ No newline at end of file diff --git a/devops-scm-sdk/devops-scm-sdk-common/src/main/java/com/tencent/devops/scm/sdk/common/util/ScmJsonUtil.java b/devops-scm-sdk/devops-scm-sdk-common/src/main/java/com/tencent/devops/scm/sdk/common/util/ScmJsonUtil.java index d990a384..2b287d44 100644 --- a/devops-scm-sdk/devops-scm-sdk-common/src/main/java/com/tencent/devops/scm/sdk/common/util/ScmJsonUtil.java +++ b/devops-scm-sdk/devops-scm-sdk-common/src/main/java/com/tencent/devops/scm/sdk/common/util/ScmJsonUtil.java @@ -32,4 +32,12 @@ public static T fromJson(String jsonStr, TypeReference typeReference) { throw new ScmSdkException(exception); } } + + public static String toJson(Object object) { + try { + return JSON_FACTORY.toJson(object); + } catch (Exception exception) { + throw new ScmSdkException(exception); + } + } } From 40b33d0bc1ea283461c5f89bd5404a0ac7634ec5 Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Sun, 4 Jan 2026 11:33:26 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20Bkcode=E6=94=AF=E6=8C=81Commit=20Ch?= =?UTF-8?q?eck=20#46?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- buildSrc/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 924148b5..20753cfc 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -1,6 +1,6 @@ object Release { const val Group = "com.tencent.bk.devops.scm" - const val Version = "1.1.7" + const val Version = "1.1.8" } object Versions { From fcfa6082ad10312ef4914069ae8ca226f48c93dc Mon Sep 17 00:00:00 2001 From: hejieehe <904696180@qq.com> Date: Tue, 6 Jan 2026 18:25:50 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20Bkcode=E6=94=AF=E6=8C=81Commit=20Ch?= =?UTF-8?q?eck=20#46=20=E4=BF=AE=E5=A4=8DTGIT=20review=20state=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devops/scm/provider/git/tgit/TGitWebhookParser.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-tgit/src/main/kotlin/com/tencent/devops/scm/provider/git/tgit/TGitWebhookParser.kt b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-tgit/src/main/kotlin/com/tencent/devops/scm/provider/git/tgit/TGitWebhookParser.kt index b7064eae..16829540 100644 --- a/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-tgit/src/main/kotlin/com/tencent/devops/scm/provider/git/tgit/TGitWebhookParser.kt +++ b/devops-scm-provider/devops-scm-provider-git/devops-scm-provider-tgit/src/main/kotlin/com/tencent/devops/scm/provider/git/tgit/TGitWebhookParser.kt @@ -330,7 +330,14 @@ class TGitWebhookParser : WebhookParser { "approved" -> ReviewState.APPROVED "change_required" -> ReviewState.CHANGE_REQUIRED "change_denied" -> ReviewState.CHANGE_DENIED - "close" -> ReviewState.UNKNOWN + "close" -> ReviewState.CLOSED + "empty" -> { + // review状态为空,则尝试使用[event]字段进行转换 + when (src.event) { + EventAction.CREATE.value, EventAction.REOPEN.value -> ReviewState.APPROVING + else -> ReviewState.UNKNOWN + } + } else -> ReviewState.UNKNOWN }