Jenkins 从 GitHub 构建 PR 失败

Vis*_*ndu 5 github jenkins jenkins-pipeline jenkins-github-plugin

我正在使用 jenkins 管道来构建我的 github 项目。当我在 GitHub 上提出拉取请求 (PR) 时,它会创建一个工作“pr-head”

工作截图

一直失败并出现以下错误

错误截图

如果您对此有任何建议,请告诉我

甚至Git PullRequest 作业中的答案也失败了。找不到任何要构建的修订版。验证此作业的存储库和分支配置没有解决我的问题

Joe*_*g S 10

2019/03/22 更新:

快速答疑

使用适合您的 git 服务器的 PR 处理的 refspec。例如对于 Bitbucket 可能是:

+refs/pull-requests/*/merge:refs/remotes/@{remote}/PR-*
Run Code Online (Sandbox Code Playgroud)

完整答案

有一个关于这个的公开票:https : //issues.jenkins-ci.org/browse/JENKINS-52668?filter=18657

编辑:

我能够使用 Jenkins 多分支管道以及 github 插件和对该checkout步骤的手动调用来重现此问题。

对于 Bitbucket,我找到了几个如何构建 PR 的选项。我现在甚至找到了一种方法来跳过那里的条件。见下文。

推荐

只要有可能,我建议您使用checkout scm它轻松适用于 PR。

如果您需要checkout手动使用该步骤,您可以尝试调整您的 Jenkinsfile 以便像我检查 bitbucket 存储库那样手动执行操作。

最简单的方法应该是checkout scm至少做一次,看看应该如何做,并在手动结账步骤中相应地使用这些值。如果您没有建立 PR,您将需要一些 if 条件。


GitHub

我终于使用以下代码从 github 中获得了我的小示例项目 buildin PR。为了我的快速测试,我从某个分支做了一个 PR。如果您使用 fork 作为 PR 的来源,则可能需要进一步调整。

/sf/answers/2545179451/ 中所述,您可以省略“要构建的分支”选项以免出现此错误。但是,根据您的 PR 合并策略,您仍然需要相应地配置合并:

def isPr() {
    env.CHANGE_ID != null
}

// github-specific refspec
def refspec = "+refs/pull/${env.CHANGE_ID}/head:refs/remotes/origin/PR-${env.CHANGE_ID} +refs/heads/master:refs/remotes/origin/master"
def url = 'https://github.com/orgi/workflow-durable-task-step-plugin.git'

def extensions = []
if (isPr()) {
    extensions = [[$class: 'PreBuildMerge', options: [mergeRemote: "refs/remotes/origin", mergeTarget: "PR-${env.CHANGE_ID}"]]]
}

checkout([
    $class: 'GitSCM',
    doGenerateSubmoduleConfigurations: false,
    extensions: extensions,
    submoduleCfg: [],
    userRemoteConfigs: [[
        refspec: refspec,
        credentialsId: '<your credentials>',
        url: url
    ]]
])
Run Code Online (Sandbox Code Playgroud)

比特桶

对于 bitbucket,您必须执行几乎相同的操作。但是,您可以选择直接在 bitbucket 中完成合并提交,在这种情况下,您不需要在 Jenkins 中进行合并,而是需要切换到 PR 分支。您可以使用条件 refspec 或有条件地选择分支。这使得四个选项如下所示。到目前为止,我没有找到不涉及条件的选项。:(

推荐的解决方案

以下解决方案对我来说似乎最有用。它们不涉及任何条件并使用BRANCH_NAME变量。但是我突然想到,有时我会收到关于无效 refspec 的错误。在这些情况下,请使用下面所写的替代解决方案之一。

使用 Bitbucket 合并

使用 Bitbucket 服务器准备的合并

def respec = '+refs/heads/*:refs/remotes/origin/* +refs/pull-requests/*/merge:refs/remotes/origin/PR-*'
checkout([$class: 'GitSCM',
    branches: [[name: env.BRANCH_NAME]],
    doGenerateSubmoduleConfigurations: false,
    submoduleCfg: [],
    userRemoteConfigs: [[
        refspec: respec,
        url: '<repo URL>'
    ]]
])
Run Code Online (Sandbox Code Playgroud)

使用 Jenkins 合并

或者您决定让 Jenkins 进行合并。您可以使用条件 refspec 或条件合并到 PR。

def refspec = '+refs/heads/*:refs/remotes/origin/* +refs/pull-requests/*/merge:refs/remotes/origin/PR-*'
checkout([$class: 'GitSCM',
    doGenerateSubmoduleConfigurations: false,
    extensions: [[$class: 'PreBuildMerge', options: [mergeRemote: "refs/remotes/origin", mergeTarget: env.BRANCH_NAME]]],
    submoduleCfg: [],
    userRemoteConfigs: [[
        refspec: refspec,
        url: '<repo URL>'
    ]]
])
Run Code Online (Sandbox Code Playgroud)

共享库

要在全局共享库旁边使用 PR 分支,似乎最直接的方法是在Discover other refs为库配置源代码管理时使用该选项。但是这对我不起作用:(

在此处输入图片说明

要从某个拉取请求加载共享库,您必须做两件事:

  1. 将以下 refspec 添加到共享库的 Jenkins 全局配置中:

    +refs/pull-requests/*/merge:refs/remotes/@{remote}/PR-*
    
    Run Code Online (Sandbox Code Playgroud)
  2. 加载该库时,env.BRANCH_NAME您必须使用"origin/${env.BRANCH_NAME}",而不仅仅是使用,例如:

    libBranch = env.BRANCH_NAME
    libId= "myLib@origin/${libBranch}"
    lib = library(libId)
    
    Run Code Online (Sandbox Code Playgroud)

使用 Bitbucket Merge 的替代解决方案

条件参考规范

作为后备;我记得包括 PR 在内的 refspec 有时对我不起作用。在这种情况下,您可以使用:

def isPr() {
    env.CHANGE_ID != null
}

def respec = '+refs/heads/*:refs/remotes/origin/*'
if (isPr()) {
    respec += ' +refs/pull-requests/*/merge:refs/remotes/origin/PR-*'
}
checkout([$class: 'GitSCM',
    branches: [[name: env.BRANCH_NAME]],
    doGenerateSubmoduleConfigurations: false,
    submoduleCfg: [],
    userRemoteConfigs: [[
        refspec: respec,
        url: '<repo URL>'
    ]]
])
Run Code Online (Sandbox Code Playgroud)

条件分支名称

def isPr() {
    env.CHANGE_ID != null
}
def branch
if (isPr()) {
    branch = "refs/remotes/origin/pull-requests/${env.CHANGE_ID}/merge"
} else {
    branch = "*/master"
}

checkout([$class: 'GitSCM',
    branches: [[name: branch]],
    doGenerateSubmoduleConfigurations: false,
    submoduleCfg: [],
    userRemoteConfigs: [[
        refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull-requests/*:refs/remotes/origin/pull-requests/*',
        url: '<repo URL>'
    ]]
])
Run Code Online (Sandbox Code Playgroud)

在 Jenkins 中使用 Merge 的替代解决方案

有条件的refspec

def isPr() {
    env.CHANGE_ID != null
}
def refspec = '+refs/heads/*:refs/remotes/origin/*'
if (isPr()) {
    refspec += ' +refs/pull-requests/*/merge:refs/remotes/origin/PR-*'
}
checkout([$class: 'GitSCM',
    doGenerateSubmoduleConfigurations: false,
    extensions: [[$class: 'PreBuildMerge', options: [mergeRemote: "refs/remotes/origin", mergeTarget: env.BRANCH_NAME]]],
    submoduleCfg: [],
    userRemoteConfigs: [[
        refspec: refspec,
        url: '<repo URL>'
    ]]
])
Run Code Online (Sandbox Code Playgroud)

条件合并

def isPr() {
    env.CHANGE_ID != null
}
def extensions = []
if (isPr()) {
    extensions = [[$class: 'PreBuildMerge', options: [mergeRemote: "refs/remotes/origin/pull-requests", mergeTarget: "${env.CHANGE_ID}/from"]]]
}
checkout([$class: 'GitSCM',
    doGenerateSubmoduleConfigurations: false,
    extensions: extensions,
    submoduleCfg: [],
    userRemoteConfigs: [[
        refspec: '+refs/heads/*:refs/remotes/origin/* +refs/pull-requests/*:refs/remotes/origin/pull-requests/*',
        url: '<repo URL>'
    ]]
])
Run Code Online (Sandbox Code Playgroud)

  • 我只能假设这与git版本有关。我想错误消息也没有用。 (2认同)