I am setting up webhook integration between a private GitHub repository and a Jenkins build. I configure jobs exclusively using Job DSL groovy scripts (I'm open to switching to another programmatic job configuration mechanism, but I will not accept any answer that requires me to configure jobs manually). II would like to set up a commit status context and a set of custom messages based on build status.
The Job DSL API documentation embedded in Jenkins is not helpful, only giving me this signature: githubPullRequest(Closure closure)
, but not telling me how to construct a suitable closure.
Here are the relevant sections of my 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}')
}
}
This errors as follows:
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]
Line 8 is:
buildStatus {
If I remove the entire buildStatus
block, then Jenkins accepts the script and creates the job successfully. My push hooks work, but my pull request hooks don't.
I'm not a Groovy programmer, nor am I deeply familiar with any aspect of Jenkins. I understand that there is no method compatible with the DSL I've written, but I don't know where to look to find valid method signatures. I don't understand how the DSL maps to method calls well enough to find or even recognize an appropriate method and build DSL that is compatible.
Googling the error message led me to some people who had similar problems in 2016-2017: 1, 2, 3. Their issue seemed to stem from the deprecation of the Github Pull Request Builder plugin as a core, bundled plugin, and a corresponding change in syntax. That led me to discover a new syntax, given here:
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'
}
}
}
}
}
}
But that did not help either; the failure is essentially the same:
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]
Line 9 is:
'org.jenkinsci.plugins.ghprb.extensions.status.GhprbSimpleStatus' {
Amidst all of this, I'm struggling to understand the differences between a buildStatus, commitStatus, completedStatus, etc. What do these things mean?
Meanwhile, I reverted the DSL to the version without any buildStatus
and tried creating a PR to see if it would trigger a build. It did not. I checked the "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 -- [email protected]:privateorg/myrepo.git # timeout=10
Found 64 remote heads on [email protected]: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
Maybe the Hook Log isn't the right place to look, but the use of -h
in the call to git ls-remote
caused it to only list branches -- not PRs. If I use the same command locally but without -h
, PRs are listed that I am confident would match my refspec.
I originally encountered these problems using CloudBees Core Client Master version 2.204.3.7, revision 3. Upgrading to latest (2.235.2.3) did not help.
Plugin versions in use:
If there are other plugins in play that are relevant here, let me know and I'll add them.
Summary of my questions:
Job DSL was one of the first popular plugins for Jenkins which allows managing configuration as code and many other plugins dealing with this aspect have been created since then, most notably the Jenkins Pipeline and Configuration as Code plugins.
With Pipeline, you have features such as a parameterized manual input step, allowing you specify logic midstream within the pipeline. The logic that can be included in a Job DSL is limited to creating the jobs themselves; whereas with Pipeline you can include logic directly inside the job.
Install Github Pull Request Builder Plugin. Go to Manange Jenkins --> Manage Plugins. Click on the available tab at the top and search for Github Pull Request Builder. Select the plugin using the checkbox and click Install without restart as shown in the image below.
If any of them are not installed, go to your_jenkins_url /pluginManager/available and search for and select the plugins, then click Install without restart. Now that the required plugins are installed, let’s shift our focus to modifying your Job DSL script to include an additional pipeline job.
or if you want to use the actual commit in the pull request, use Under "Build Triggers", check "Github pull requests builder". Add admins for this specific job. If you want to use GitHub hooks for automatic testing, read the help for "Use github hooks for build triggering" in job configuration. Then you can check the checkbox.
Together, Docker, JCasC, Job DSL, and pipelines allow developers and administrators to deploy and configure Jenkins completely automatically, without any manual involvement.
Got it figured. There were several issues, but the crux of the problem was authentication: the various plugins and components accept and require different types of credentials. The setup I have working for me now uses a combination of personal access tokens and SSH keypairs to authenticate to GitHub.
Here's how to set up authentication:
Settings -> SSH and GPG keys
. (Note: that's the user's settings, not a repo's settings)Settings -> Developer settings -> Personal access tokens
Manage Jenkins -> Manage Credentials
.Manage Jenkins -> Configure System -> GitHub Pull Request Builder -> Credentials
, choose the token-based credential you created in step 9.Here's the Job DSL that worked for PRs, using the jenkins-ghprb
plugin:
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.')
}
}
}
}
Notes:
The webhook on the GitHub side is configured as follows:
Notes:
https://your-jenkins-host/ghprbhook/
Manage Jenkins -> Configure System -> GitHub Pull Request Builder -> Jenkins URL override
.application/json
.Manage Jenkins -> Configure System -> GitHub Pull Request Builder -> Shared secret
.The end result:
And this for pushes:
scm {
git {
remote {
github('privateorg/myrepo', 'ssh')
credentials('ssh-credential-id')
}
branch('refs/heads/*')
}
}
triggers {
githubPush()
}
Webhook:
Notes:
https://your-jenkins-host/github-webhook/
application/x-www-form-urlencoded
.branch
specifier.I was not able to have a single job that handled both PRs and pushes, due to differences in both branch
and refspec
params. I found some evidence that Git supports multiple refspecs, and was able to get that feature working with git
on the CLI, but was not successful in my attempts to configure Jenkins to do the same. I had no in creating a branch specifier that worked for both. I might be able to set up a single, parameterized build, and then have mini-jobs that use these triggers and then call the parameterized build, but at this time I don't see that being worth adding yet another job. Tangentially, I also set up a third job that runs nightly against our main development branch. We'll be building out an extensive (long-running) test suite for this build, while keeping the PR and push builders fast.
As for where I should have been looking for docs: I googled and googled, and pieced this together through trial and error with hints and bits and pieces of config found in dozens of places. I have gotten a bit better at reading the Job DSL plugin's API docs, but that was not enough by itself. Also useful: for the push-triggered job, the GitHub Hook Log, available on the Jenkins job summary page. For the PR-triggered job, the Jenkins System Log, available from Manage Jenkins -> System Log
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With