如何使用Job DSL配置Jenkins GitHubPullRequestBuilder插件

6
我正在设置私有GitHub仓库和Jenkins构建之间的Webhook集成。我使用Job DSL groovy脚本独占地配置作业(我可以考虑切换到另一个编程式作业配置机制,但是不接受任何要求我手动配置作业的答案)。我想根据构建状态设置提交状态上下文和一组自定义消息。
在Jenkins中嵌入的Job DSL API文档没有帮助,只给出了这个签名:githubPullRequest(Closure closure),但没有告诉我如何构造合适的闭包。
以下是我Job DSL的相关部分:
triggers {
    githubPush()
    githubPullRequest {
        useGitHubHooks()
        buildStatus {
            completedStatus('SUCCESS', 'Build succeeded!')
            completedStatus('FAILURE', 'Build failed. ')
            completedStatus('ERROR', 'Build errored. This is probably a problem with Jenkins or related infrastructure and not an issue with your code changes.')
        }
    }
}

(...)

scm {
    git {
        remote {
            github('privateorg/myrepo', 'ssh')
            credentials('my-credential-id')
            refspec('+refs/pull/*:refs/remotes/origin/pr/*')
        }
        branch('${sha1}')
    }
}

这个错误如下:

ERROR: (build.groovy, line 8) No signature of method: javaposse.jobdsl.dsl.helpers.triggers.TriggerContext.buildStatus() is applicable for argument types: 
(build$_run_closure1$_closure2$_closure10$_closure11) values: 
[build$_run_closure1$_closure2$_closure10$_closure11@602572cb]

第8行是:

buildStatus {

如果我删除整个buildStatus块,那么Jenkins将接受脚本并成功创建作业。我的推送挂钩有效,但我的拉取请求挂钩无效。
我不是Groovy程序员,也不太熟悉Jenkins的任何方面。我明白没有与我编写的DSL兼容的方法,但我不知道在哪里查找有效的方法签名。我不理解DSL如何映射到方法调用,以找到或甚至识别一个适当的方法和构建与其兼容的DSL。

通过谷歌搜索错误信息,我找到了一些在2016-2017年遇到类似问题的人:1, 2, 3。他们的问题似乎源自于Github Pull Request Builder插件作为核心捆绑插件的弃用及相应语法的更改。这使我发现了一种新的语法,可在此处找到:

triggers {
    githubPush()
    githubPullRequest {
        useGitHubHooks()
        extensions {
            'org.jenkinsci.plugins.ghprb.extensions.status.GhprbSimpleStatus' {
                buildStatus {
                    'org.jenkinsci.plugins.ghprb.extensions.comments.GhprbBuildResultMessage' {
                        message 'Build in progress...'
                        result 'PENDING'
                    }
                    'org.jenkinsci.plugins.ghprb.extensions.comments.GhprbBuildResultMessage' {
                        message 'Build succeeded! It is safe to merge ${ghprbSourceBranch} into ${ghprbTargetBranch}.'
                        result 'SUCCESS'
                    }
                    'org.jenkinsci.plugins.ghprb.extensions.comments.GhprbBuildResultMessage' {
                        message 'Build failed.'
                        result 'FAILURE'
                    }
                    'org.jenkinsci.plugins.ghprb.extensions.comments.GhprbBuildResultMessage' {
                        message 'Build errored. This is probably a problem with Jenkins or related infrastructure and not an issue with your code changes.'
                        result 'ERROR'
                    }
                }
            }
        }
    }
}

但这也没有帮助; 失败本质上是相同的:

ERROR: (build.groovy, line 9) No signature of method: javaposse.jobdsl.dsl.helpers.triggers.TriggerContext.org.jenkinsci.plugins.ghprb.extensions.status.GhprbSimpleStatus() is applicable for argument types: 
(build$_run_closure1$_closure2$_closure10$_closure11$_closure12) values: 
[build$_run_closure1$_closure2$_closure10$_closure11$_closure12@707221f0]

第9行是:

'org.jenkinsci.plugins.ghprb.extensions.status.GhprbSimpleStatus' {

在这一切之中,我很难理解buildStatus、commitStatus、completedStatus等之间的区别。这些东西是什么意思?
同时,我将DSL还原到没有任何buildStatus的版本,并尝试创建一个PR以查看是否会触发构建。但它没有。我检查了"GitHub Hook Log":
Started on Aug 4, 2020 6:16:47 PM
Started by event from 10.101.32.177 ⇒ https://my-jenkins-host.com/github-webhook/ on Tue Aug 04 18:16:47 UTC 2020
Using strategy: Default
[poll] Last Built Revision: Revision 91170fb44c40737a6410acfba820d6555a0475bb (refs/remotes/origin/dev)
using credential my-credential-id
 > git --version # timeout=10
using GIT_ASKPASS to set credentials 
 > git ls-remote -h -- git@github.com:privateorg/myrepo.git # timeout=10
Found 64 remote heads on git@github.com:privateorg/myrepo.git
Ignoring refs/heads/branch1 as it doesn't match any of the configured refspecs
Ignoring refs/heads/branch2 as it doesn't match any of the configured refspecs
...
Ignoring refs/heads/branch64 as it doesn't match any of the configured refspecs
Done. Took 0.71 sec
No changes

也许钩子日志不是查找的正确位置,但在调用git ls-remote时使用-h导致它只列出分支而不是PR。如果我在本地使用相同的命令但不带-h,则会列出我确信与我的refspec匹配的PR。
我最初在使用CloudBees Core Client Master版本2.204.3.7、修订版3时遇到了这些问题。升级到最新版本(2.235.2.3)没有帮助。
正在使用的插件版本:
Job DSL: 1.77
GHPRB: 1.42.1
如果还有其他相关的插件,请告诉我,我会添加它们。
我的问题总结:
1. 配置自定义状态消息以在GitHub中显示的正确语法是什么? 2. 我的配置除了轮询远程存储库忽略PR和打开新的PR不触发构建外,还有什么问题吗? 3. 还有其他地方可以查找这些内容的文档吗?或者其他资源可以帮助我学习我正在做的事情?
1个回答

4
我知道了。出现了几个问题,但问题的关键在于验证身份:各种插件和组件接受和需要不同类型的凭据。我现在使用个人访问令牌和SSH密钥对的组合进行验证,这是我正在使用的设置。
以下是如何设置身份验证的步骤:
  1. 生成新的公私钥对。我在本地机器上执行了此操作,但您可以在任何地方执行。私钥文件的内容将提供对您的 GitHub 帐户的访问权限,因此请在决定保存文件的位置时使用适当的注意,并相应地进行清理。
  2. 转到 GitHub 并以要用于验证到 GitHub 的 Jenkins 用户身份验证的用户身份登录。
  3. 导航到 设置 -> SSH 和 GPG 密钥。(注意:这是用户的设置,而不是存储库的设置)
  4. 创建一个新的 SSH 密钥。给它一个名称(我将其命名为 Jenkins 实例的名称),并粘贴第 1 步生成的 公共 密钥的内容。
  5. 导航到 设置 -> 开发人员设置 -> 个人访问令牌
  6. 生成新的令牌。授予其对“repo”的访问权限。确保您在某个安全的地方捕获令牌值--我将我的保存在密码管理器中。如果您丢失它,您将不得不重新执行所有这些步骤来创建一个新的令牌并配置 Jenkins 使用它。
    • 我们公司使用基于 SAML 的身份验证和 SSO 的私有 GitHub org。如果您也是这样,请确保为适当的 org 启用令牌上的 SSO。
  7. 在 Jenkins 中,转到 管理 Jenkins -> 管理凭据
  8. 在系统/全局域中创建一个新的“带有私钥的 SSH 用户名”凭据。在“用户名”字段中,输入 GitHub 用户名。对于私钥,选择“直接输入”,选择“添加”,并粘贴第 1 步生成的 私钥 文件的文本内容。
    • 您将在创建时为凭据分配 ID 和描述。ID 在 XML 配置文件中使用,描述在 Jenkins 配置 UI 中使用。我喜欢两者都使用相同的值,以便存储在 XML 配置文件中的值与我在用户界面中看到的值相同。ID 可以是大小写字母加分隔符字符。为了获得最佳可读性,我喜欢使用 kebab-case。
  9. 在系统/全局域中创建一个新的“秘密文本”凭据。在“秘密”字段中输入步骤 6 中 GitHub 生成的令牌值。同样,给它一个描述和 ID。
  10. 管理 Jenkins -> 配置系统 -> GitHub 拉取请求构建器 -> 凭据 中,选择您在步骤 9 中创建的基于令牌的凭据。
这是一个使用jenkins-ghprb插件的PRs工作DSL示例:
scm {
    git {
        remote {
            github('privateorg/myrepo', 'ssh')
            credentials('ssh-credential-id')
            refspec('+refs/pull/*:refs/remotes/origin/pr/*')
        }
        branch('${sha1}')
    }
}

triggers {
    githubPullRequest {
        useGitHubHooks()
        orgWhitelist('privateorg')
        allowMembersOfWhitelistedOrgsAsAdmin()
        extensions {
            commitStatus {
                context('Jenkins')
                completedStatus('SUCCESS', 'Build succeeded!')
                completedStatus('FAILURE', 'Build failed. ')
                completedStatus('ERROR', 'Build errored. This is probably a problem with Jenkins or related infrastructure and not an issue with your code changes.')
            }
        }
    }
}

备注:

  • 我们私有组织中的所有人都可以提交触发自动构建的PR。你的情况可能不同,如果是这样,你将需要配置一个不同的白名单(能够自动触发构建的PR的人)和/或不同的管理员(可以为非白名单贡献者触发构建的人)。

GitHub 上的 Webhook 配置如下: GitHub 拉取请求 webhook 配置的截图,如下所述

备注:

  • 负载URL:https://your-jenkins-host/ghprbhook/
    • 请注意,主机URL必须是公开可访问的。我的不是,但我们有一个面向公众的代理。我在此处使用了代理的主机名。我还需要在管理Jenkins -> 配置系统 -> GitHub拉取请求构建器 -> Jenkins URL覆盖中配置代理主机名。
  • Content-type 必须application/json
  • 此处使用的密钥是我使用密码管理器生成的随机字符串。这是可选的。如果提供,则需要在管理Jenkins -> 配置系统 -> GitHub拉取请求构建器 -> 共享密钥中输入相同的密钥。
  • Webhook应该在拉取请求和问题评论时触发。
    • 我已经裁剪了屏幕截图以隐藏不重要的事件。

最终结果: 显示在GitHub拉取请求中的成功Jenkins构建截图

对于推送,可以使用以下内容:

scm {
    git {
        remote {
            github('privateorg/myrepo', 'ssh')
            credentials('ssh-credential-id')
        }
        branch('refs/heads/*')
    }
}

triggers {
    githubPush()
}

Webhook: GitHub推送Webhook配置的截图,如下所述

注:

  • 有效载荷URL:https://your-jenkins-host/github-webhook/
    • 请注意,主机URL必须是公开可访问的。我的不是,但我们有一个面向公众的代理。我在这里使用了代理的主机名。
  • Content-type 必须application/x-www-form-urlencoded
  • 我没有配置密码。如果在Jenkins端配置密码的方法,请告诉我。
  • Webhook应该触发拉取请求和推送。
    • 我已经裁剪了截图以隐藏不重要的事件。
  • 此配置会导致每次推送都会构建,无论分支如何。这就是我想要的;可能不是你想要的。如果您想要其他内容,请更改branch指定器。

由于branchrefspec参数的差异,我无法找到一份工作既能处理PR又能处理push。我发现Git支持多个refspecs,并且能够在CLI上使用git实现该功能,但是我未能成功地配置Jenkins执行相同的操作。我无法创建适用于两者的分支指定器。我可能能够设置单个参数化构建,然后有小型作业使用这些触发器并调用参数化构建,但此时我认为这不值得再添加另一个作业。顺带提一下,我还设置了第三个作业,每晚针对我们的主要开发分支运行。我们将为此构建一个广泛(长时间运行)的测试套件,同时保持PR和push构建快速。

关于我应该在哪里寻找文档的问题:我搜索了许多次谷歌,并通过试错、提示和配置碎片在许多地方拼凑出这个结果。我现在更善于阅读Job DSL插件的API文档,但仅此还不够。另外有用的是:对于推送触发的作业,GitHub Hook日志,在Jenkins作业摘要页面上可用。对于PR触发的作业,Jenkins系统日志,在“管理Jenkins->系统日志”中可用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接