企业网络背后的 Azure Devops Pull Request 和 Jenkins

问题描述 投票:0回答:2

我想知道如何将我的 Jenkins 构建服务器连接到 Azure DevOps 拉取请求。我的 Jenkins 服务器在公司防火墙后面,我无法在公司网络之外访问此服务器。

由于公司网络规则,我无法在 Azure 中添加挂钩来调用我的 Jenkins 服务器,但我的服务器可以访问 Microsoft Azure 网站。

我尝试在我的 Linux Jenkins 服务器上成功运行 VSTS 代理。它有效,但它没有做我需要做的事情。我不想更改所有构建过程以在此代理中构建我的应用程序。我真的希望能够从我的服务器启动 Jenkins Pipeline 构建并将构建结果转发到 Azure DevOps。

我不能使用 Azure DevOps 提供的 Jenkins VM,因为我的 Jenkins 构建过程必须在我们实验室的真实硬件单元上运行一些回归测试工具,以将构建标记为成功。

换句话说:

1- 我不能使用 VSTS 代理,因为我需要使用我的 Jenkins 构建服务器

2- 我无法使用 Azure DevOps 提供的 Jenkins VM,因为我需要访问真正的 Hardware Unite

3- 我想我无法检测我的 Jenkins 以查看我们是否有新的 Pull Request 分支,因为我无法将 Jenkins 构建结果发送到 Microsoft Azure DeveOps 服务器。

有人必须做那样的事吗?

有什么阅读建议吗?

谢谢!

azure-devops jenkins-pipeline jenkins-plugins
2个回答
1
投票

由于单向通信将成为可能(从 Jenkins 到 Azure DevOps),您必须执行以下操作:

  • 设置您的 Jenkins 管道以定期轮询 Azure DevOps 以获取新的 PR 分支并构建 PRs
  • 外部服务批准
  • 设置分支策略
  • 让 Jenkins 将构建状态发布回外部服务 API,以便 Azure DevOps 知道构建是成功还是失败

0
投票

我没有完整的解决方案,但如果您还没有弄明白的话,我可以提供部分解决方案 Stephane,最后会详细介绍。但这些情况的一般想法是使用公司 Jenkins 公开的 Azure Devops REST API 来更新提交/PR 的特定状态。

假设:

  • 您已为名为“azure”的 http 调用定义了凭据
  • organization 和 projectName 可能是硬编码的
  • 您也可以从 Azure API 中找到您的 azureRepositoryId,只需列出存储库

Azure 的文档:https://learn.microsoft.com/en-us/rest/api/azure/devops/git/statuses/create?view=azure-devops-rest-7.0&tabs=HTTP

import com.cloudbees.groovy.cps.NonCPS
import groovy.json.JsonSlurper 
import groovy.json.JsonOutput


@NonCPS
def retrievePrIds(content) {
    def json = new JsonSlurper().parseText(content)
    return json.value.collect{it.pullRequestId}
}

def notifyAzure(repositoryId, status, desc) {
    def azureQueryUrl = "https://dev.azure.com/${organization}/${projectName}/_apis/git/pullrequests?searchCriteria.sourceRefName=refs%2Fheads%2F${env.BRANCH_NAME.replaceAll('\\/','%2F')}&searchCriteria.sourceRepositoryId=${repositoryId}&searchCriteria.status=active&searchCriteria.repositoryId=${repositoryId}&api-version=5.1"
    
    try {
        def res = httpRequest authentication: 'azure', timeout: 5, url: azureQueryUrl
        
        echo "${res.content}"

        def prIds = retrievePrIds(res.content)

        for (prId in prIds) {
            echo "${prId}"
            def azurePRUdateUrl = "https://dev.azure.com/${organization}/${projectName}/_apis/git/repositories/${repositoryId}/pullRequests/${prId}/statuses?api-version=5.1-preview.1"
            def json = JsonOutput.toJson([state: status, description: desc, targetUrl: env.BUILD_URL, context: [name: 'jenkins build', genre: 'continuous-integration']])
            
            httpRequest authentication: 'azure', contentType: 'APPLICATION_JSON', httpMode: 'POST', requestBody: json, responseHandle: 'NONE', timeout: 5, url: azurePRUdateUrl 
        }
    } catch(Exception e) {
        echo "Error: Failed to update azure PR status, cause: ${e.getCause()}"
    }
    
    notifyAzureCommit(repositoryId, status, desc)
}

def notifyAzureCommit(repositoryId, status, desc) {
    def azureUrl = "https://dev.azure.com/${organization}/${projectName}/_apis/git/repositories/${repositoryId}/commits/${env.GIT_COMMIT}/statuses?api-version=5.1"
    def json = JsonOutput.toJson([state: status, description: desc, targetUrl: env.BUILD_URL, context: [name: 'jenkins build', genre: 'continuous-integration']])
    try {
        httpRequest authentication: 'azure', contentType: 'APPLICATION_JSON', httpMode: 'POST', requestBody: json, responseHandle: 'NONE', timeout: 5, url: azureUrl 
    } catch(Exception e) {
        echo "Error: Failed to update azure commit status, cause: ${e.getCause()}"
    }
}

然后在阶段开始时使用它

notifyAzure(azureRepositoryId, 'pending', 'Job started') //last one could be the stage name

并在后期行动中

post{
    success {
        notifyAzure(azureRepositoryId, 'succeeded', 'Job successful')
    }
    failure {
        notifyAzure(azureRepositoryId, 'failed', 'Job failed')
    }
    unstable {
        notifyAzure(azureRepositoryId, 'error', 'Job unstable')
    }
}

在你的分支机构的 Azure 政策中,你现在可能有一个状态检查,这肯定会保护你的 PR:

虽然有一个差距,但在这段代码中有一个 hack 可以找到正在构建的源代码分支的活动 PR。从公关本身的角度来看,这是不正确的。原因是天蓝色在 git refspec

+refs/heads/*:refs/remotes/origin/*
下进行常规分支,而干净的 PR 分支在
+refs/pull/*:refs/remotes/origin-pull/
下没有需要的主题分支,我的 Jenkins 实例无法签出。

所以一个完整的解决方案实际上应该在 Jenkins 中为 PRs 构建

+refs/pull/*:refs/remotes/origin-pull/
refspec 并根据当前分支名称(因为它包含 PR 编号)调用 API,这样你就可以调用 Azure Devops REST API用它。无需更新那些的提交状态。然后为更新提交状态的非 PR 分支定期构建。

如果我设法让我的詹金斯构建那些我会更新这个答案。

© www.soinside.com 2019 - 2024. All rights reserved.