8

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

工作截图

一直失败并出现以下错误

错误截图

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

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

4

1 回答 1

12

2019 年 3 月 22 日更新:

快速分析器

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

+refs/pull-requests/*/merge:refs/remotes/@{remote}/PR-*

完整答案

有一张关于此的公开票: 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 的来源,则可能需要进一步调整。

https://stackoverflow.com/a/36359706/4279361中所述,您可以省略“要构建的分支”选项,以免出现此错误。但是,根据您的 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
    ]]
])

比特桶

对于 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>'
    ]]
])

使用 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>'
    ]]
])

共享库

要将 PR 分支与全局共享库一起使用,最直接的方法似乎是在Discover other refs为库配置源代码控制时使用该选项。然而,这对我不起作用:(

在此处输入图像描述

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

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

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

    libBranch = env.BRANCH_NAME
    libId= "myLib@origin/${libBranch}"
    lib = library(libId)
    

使用 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>'
    ]]
])

条件分支名称

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>'
    ]]
])

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

条件参考规范

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>'
    ]]
])

条件合并

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>'
    ]]
])
于 2018-08-19T07:10:03.220 回答