This seems to be one of the more important, but less understood and documented features of GH and Jenkins, which seems to defeat the purpose of CI entirely ...
I'm trying to setup a simple, "kick off a build when a pull request is opened" Job in Jenkins. I've scanned though dozens of posts, some several years old, but have yet to find a solution that actually works, start-to-finish. I'm using GH 2.15.4 and Jenkins 2.89.3 with the GH Pull Request Builder plug-in. I've tried setting up a pipeline job, and a freestyle project, following various "how to" posts and docs. Nothing works as expected. Not even close. I've managed to get some functionality working, but not without a lot of trial-and-error experimenting, which doesn't leave me with a warm-fuzzy in using it. Webhooks are equally worthless in accomplishing what is needed, as nothing seems to fire off a job in Jenkins, regardless of how it is configured.
For starters, are there any references or docs that explain what the following status checks are that are automatically created by Jenkins:
continuous-integration/jenkins/branch
continuous-integration/jenkins/pr-head
continuous-integration/jenkins/pr-merge
Apparently there is no way to delete or edit these ... they just "appear" courtesy of Jenkins. I've seen some discussions, but some explanations contradict one another, so they may just be outdated, inaccurate, etc. I want to know "what does what" so I know which should be 'required' as part of the PR status check.
Any pointers would be appreciated!
I agree, this problem is tricky because Jenkins and its plugins have changed so much throughout the years. Let me tell you how I accomplished what you're asking for. I will post all of my version numbers (mostly up to date).
Jenkins Version: 2.176.1 (java -jar /usr/share/jenkins/jenkins.war --version)
Plugins
github 1.29.4
github-api 1.9
github-branch-source 2.5.3
github-pullrequest 0.2.5
pipeline-github-lib 1.0
Also, I use the Blue Ocean interface, which might affect things (who knows)
blueocean 1.17.0
blueocean-git-pipeline 1.17.0
blueocean-github-pipeline 1.17.0
Github Webhooks
First off, set up webhooks for your system. This is a good guide for Github Webhooks
Go to your Github repository and click on the Settings tab. Then select 'Webhooks' in the left menu:
The URL of my Jenkins setup is https://jenkinsci.dorian.com. So, in the 'Payload URL' box, I put https://jenkinsci.dorian.com/github-webhook/
I left the settings as "application/json" and "send me everything" and "active"
The Webhooks area has a handy 'Recent Deliveries' section which can show you if your webhooks are making it to Jenkins. At first, I had the wrong URL so mine has red Xs next to them. Now, they're all green checkmarks.
Github Access Token
Many guides suggest that you provide Jenkins with a personal access token to communicate with your repo. To do that, go to your account avatar in the top right and select Settings -> Developer Settings -> Personal access tokens->Generate Token
Put whatever you want for the description. Under 'select scopes', if you just want it to work, select every checkbox in the list.
I selected:
repo:status
write:repo_hook
read:repo_hook
admin:org_hook
Click save and you'll be shown your secret key. Copy this somewhere safe (we'll use it soon).
Configuring Jenkins
Now for the hard part. Try and install all of the plugins I've listed above.
Go to Jenkins-Manage Jenkins->Configure System
Locate the Github section and click Add Github Server
Name: Github
Api URL: https://api.github.com
Manage Hooks: true
Under credentials, click "Add." You'll be brought to a menu. Select "Secret Text"
Scope: Global
Secret: paste your access token from earlier
ID: (I left this blank)
Description: DorianGithubCreds
Hit save. Then, select DorianGithubCreds from the credentials list.
To test, hit "Test Connection." Mine returns 'Credentials verified for user dnrahamim', rate limit: 4998
Now go down to Github Pull Request Builder
GitHub Server API URL: https://api.github.com
Jenkins URL override: (blank)
Shared Secret: (blank)
Credentials: DorianGithubCreds
Auto-manage webhooks: true
Everything else is blank
Configure Job
Go to the job that should be building your repo
Select 'Configure' in the left menu
Under Projects->Github Organization
Credentials: DorianGithubCreds
Owner: Dorian
Behaviors:
Discover branches
Strategy: Exclude branches that are also filed as PRs
Discover pull requests from origin
Strategy: Merging the pull request with the current target branch revision
Discover pull requests from forks
Strategy: Merging the pull request with the current target branch revision
Trust: From users with Admin or Write permission
Project Recognizers
Pipeline Jenkinsfile
Path: Jenkinsfile (my Jenkinsfile is in the project root)
Build Strategies: (intentionally blank)
Notifications
Now, when I do a pull request, or whenever I post a change to a pull request, Jenkins run a fresh build for that branch.
The Pull Request itself in Github also lists its "Status Checks" at the bottom. When the build is pending, the status check is yellow. If it succeeds it gets a green checkmark. If it fails, it gets a red X.
I initially had a problem because I had an old Jenkins box which was also configured to manage Github webhooks and build pull requests. Its builds were failing so its notifications were the ones getting through to my pull request. I fixed that problem by preventing that old Jenkins box from building my newest branches. Once the old Jenkins box stopped building, the notifications from the new Jenkins box made it through to Github.
Wrapping up
That's it! That's everything I intentionally configured. Please try out my configuration and see if it works for you. Let me know if I left anything out.
The hard part with configuring Jenkins with Github is that, although there are many guides, the suggestions often conflict with each other and very many are out of date (sometimes even official documentation is out of date).
Nonetheless, here are some Resources:
This is a good guide for Github Webhooks
Github's Whitepaper on CI with Jenkins (It doesn't explain much in detail but it gives a good overview)
Github pull request builder plugin
Semi-official SO post for showing build status on Github repo
GitHub has "add webhook" feature which is accessible in the repository settings --> Webhooks section. This has 4 inputs
1. Payload URl - Enter the Jenkins url
2. Content Type - application/json
3. Secret - this is optional if you want to configure secret
4. Which events would you like to trigger this webhook? - select the option "Let me select individual events"
Bunch of checkbox options are visible, check "Pull requests" option. This option will send a request to Jenkins when Pull request is opened
Next step is create a job in Jenkins which will listen to GitHub events and kick off the build
I am integrating Jenkins with GitHub and have successfully set Jenkins to build after a GitHub push. But another thing I would like to establish is the build status icons(green check, yellow circle for pending, red "x") on the Pull request page. How do I go about to show these icons?
Here's an example from apple's swift pull request page:
In order to do this, you need to add Jenkins plugins:
github-request-builder sets the build status of a given PR in GitHub. This post is a good guide for setting it up.
embeddable-build-status hosts a project-wide image showing your overall build status:
I know there were a lot of conversations to this topic but any of those was helpful to me. So what I'm doing is configuring Jenkins CI to work properly with Github.
We want next:
When someone creates new PR or add commit to existing PR, Github
triggers Jenkins build.
During build is processing we want to see status - pending
Merge button should be disabled till build is completed
After build is completed, we want to see what is the status of that build - successful or failed
Right now, only step 1 works correctly but we can't figure out what is the problem with Jenkins requests to Github!
Also in console output I see error:
ERROR: Build step failed with exception java.lang.IllegalStateException: Can't get remote GH repo for project1 build and don't know what is the problem.
Any help would be really appreciated !
Regards
If you are using GitHub Pull Request Builder , go to trigger setup -> Update commit status during build
I have a teamcity project running a build against github repo. On completion of the build, it uses a build feature of teamcity named "Report Change Status to Github" which reports the build status using - https://api.github.com
Now I would like to have another teamcity project run a build against the same github repo and report the build status to github.
How do I make github display the 2 status checks differently? Despite the 2 builds reporting status to github, github just displays "1 pending check" or "1 status check completed successfully"
Edit: I didn't realize you already have the plug in installed, but I am going to leave the steps for other users. I think you need separate build configurations and to make sure you customize the context setting.
I was playing with this today and you can't use JetBrains "Commit Status Reporter" to do this. You can use this plugin though: https://github.com/jonnyzzz/TeamCity.GitHub
It wasn't straightforward to install--
Go here (choose Log in as guest): https://teamcity.jetbrains.com/viewType.html?buildTypeId=bt398 and
Click the "View" link in the "Artifacts" column in the latest successful build.
Then you click teamcity.github.zip and it will download a zip file
Then you upload that zip to TeamCity in the plugins section
Once you do that, go to Build Features and click "Add Build Feature" and select "Report change status to GitHub".
Then fill the form out with something like this (Note: You will need this for each build configuration you want reported. I am also running each build on separate agents which might be necessary):
Statuses are created with something called a context:
https://developer.github.com/v3/repos/statuses/#create-a-status
For each commit, the latest status for each context is shown. And for the pull request overall (next to the merge button) the latest per-context statuses of the latest commit in the pull request are shown.
This means that if you want multiple status checks to show up -- those statuses need to be created with different contexts. And that's something defined by the application which is creating statuses, not GitHub. GitHub only displays the statuses.
Is there a way to show the Jenkins build status on my project's GitHub Readme.md?
I use Jenkins to run continuous integration builds. After each commit it ensures that everything compiles, as well as executes unit and integration tests, before finally producing documentation and release bundles.
There's still a risk of inadvertently committing something that breaks the build. It would be good for users visiting the GitHub project page to know the current master is in that state.
Ok, here's how you can set up Jenkins to set GitHub build statuses. This assumes you've already got Jenkins with the GitHub plugin configured to do builds on every push.
Go to GitHub, log in, go to Settings, Developer Settings, Personal access tokens and click on Generate new token.
Check repo:status (I'm not sure this is necessary, but I did it, and it worked for me).
Generate the token, copy it.
Make sure the GitHub user you're going to use is a repository collaborator (for private repos) or is a member of a team with push and pull access (for organization repos) to the repositories you want to build.
Go to your Jenkins server, log in.
Manage Jenkins → Configure System
Under GitHub Web Hook select Let Jenkins auto-manage hook URLs, then specify your GitHub username and the OAuth token you got in step 3.
Verify that it works with the Test Credential button. Save the settings.
Find the Jenkins job and add Set build status on GitHub commit to the post-build steps
That's it. Now do a test build and go to GitHub repository to see if it worked. Click on Branches in the main repository page to see build statuses.
You should see green checkmarks:
In the meanwhile the UI of Jenkins and GitHub has changed a bit and it took me a while to figure out how to configure Jenkins now correctly. The explanation here is based on Jenkins version 2.121.1.
I also assume that you have already configured your Jenkins Job be triggered by a webhook or by polling.
Those are the steps that I have taken to get it working:
Configure Github: Create Personal Access Token with OAuth Scope repo:status
Configure Jenkins: Configure System and add the OAuth Secret as a GitHub Server - use Secret Text as an authentication method to put the OAuth Secret in there.
Configure your Jenkins Job: Add Set GitHub commit status as Post-build action. Set the Status Result to One of the default messages and statuses.
Check your result on GitHub: Check if you get the build status and build execution duration on your GitHub commit.
Configure Github
Configure Jenkins
Configure Jenkins Job
Result
You will now see the status for your commits and branches:
What I did is quite simple:
Install the Hudson Post Task Plugin
Create a Personal Access Token here : https://github.com/settings/tokens
Add a Post Task Plugin that always put success
curl -XPOST -H "Authorization: token OAUTH TOKEN" https://api.github.com/repos/:organization/:repos/statuses/$(git rev-parse HEAD) -d "{
\"state\": \"success\",
\"target_url\": \"${BUILD_URL}\",
\"description\": \"The build has succeeded!\"
}"
Add a Post Task Plugin that will put failure if "marked build as failure"
curl -XPOST -H "Authorization: token OAUTH TOKEN" https://api.github.com/repos/:organization/:repos/statuses/$(git rev-parse HEAD) -d "{
\"state\": \"failure\",
\"target_url\": \"${BUILD_URL}\",
\"description\": \"The build has failed!\"
}"
You can also add a call to pending at the beginning of tests
curl -XPOST -H "Authorization: token OAUTH TOKEN" https://api.github.com/repos/:organization/:repos/statuses/$(git rev-parse HEAD) -d "{
\"state\": \"pending\",
\"target_url\": \"${BUILD_URL}\",
\"description\": \"The build is pending!\"
}"
This plugin should work: https://wiki.jenkins-ci.org/display/JENKINS/Embeddable+Build+Status+Plugin
You should be able to embed badges like this into your README.md file:
The Commit Status API allows you to see the "Repo Statuses API".
And since April 26th 2013, you now can see the build status on your GitHub repo branch page:
That means it is another way, by visiting the GitHub project page, to see those statuses instead of having only Jenkins.
Starting April 30th, 2013, the API endpoint for commit statuses has been extended to allow branch and tag names, as well as commit SHAs.
There's also the plugin Embeddable Build Status that will give you a badge URL that you can post in your README.md file, and it looks like this:
If you have the GitHub plugin installed on your Jenkins, you can do it in the Post build actions like this:
Add the below line in your README.md file and change both URLs according to your Jenkins project.
[![Build Status](https://jenkins../..project/lastBuild/buildStatus)](https://jenkins../..project/lastBuild/)
In regards with setting up Jenkins and GitHub's protected branch. I'm using Jenkins 2.6, and these are the steps I did to make it work:
On your repository's GitHub webpage:
Navigate to Settings > Branches.
Under Protect branches, click on
the Choose a branch drown down menu and select the branch you want
to set as a Protected branch.
Enable the options as needed.
On the Jenkins Server:
(Make sure you have the Git and GitHub Plugin installed)
Navigate to Manage Jenkins > Configure System.
Under GitHub, set the API URL to https://api.github.com. Though this is the default value.
Select your generated token for the Credentials. If you haven't generated a token yet, click on Advanced... then on Additional actions, you can convert your login and password to token and use it as your credential.
Also, make sure the GitHub account that your Jenkins is using is a collaborator for the repository. I've set it with write permission level.
Hope this helps.
I followed the directions from Alex and it worked.
But, for GitHub Enterprise you need to modify the API URL when adding the server to Jenkins.
For example, if your company is creditcard.com, your URL would be
https://github.creditcard.com/api/v3/
Edit:
I'm no longer using this approach, please use one of the other answers.
Update: what I ended up doing, for our specific case: (above answers were great - thanks!)
Because our build server is not on the internet, we have a script to publish the build status to the gh-pages branch in github.
Start of build stamps failing
End of build stamps success
Project runs after main project to publish results -> build-status, API docs, test reports and test coverage.
GitHub caches images, so we created .htaccess file, that instructs a short cache timeout for the build-status image.
Put this in the directory with the build-status image:
ExpiresByType image/png "access plus 2 minutes"
Here's the build script. The target that publishes to gh-pages is '--publish.site.dry.run'
With less than 400 lines of config, we have:
Compile checks
unit & integration tests
Test Reports
Code Coverage Reports
API Docs
Publishing to Github
. . and this script can be run in or outside of Jenkins, so that:
Developers can run this script before commit, reducing the chance of a broken build that impacts others.
A failure is easy to reproduce locally.
The Results:
Project main page has the build status, updated after each build, along with latest API Docs, test results and test coverage.
Jently updates your GitHub commit status (as described by vonc), but unfortunately they have yet to implement the Repo Status API.
For pipeline projects, you can use the post section like so:
void setBuildStatus(String message, String state) {
step([
$class: "GitHubCommitStatusSetter",
reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/my-user/my-repo"],
contextSource: [$class: "ManuallyEnteredCommitContextSource", context: "ci/jenkins/build-status"],
errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ]
]);
}
pipeline {
agent any
triggers {
githubPush()
}
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
post {
success {
setBuildStatus("Build succeeded", "SUCCESS");
}
failure {
setBuildStatus("Build failed", "FAILURE");
}
}
}
Just change "https://github.com/my-user/my-repo" to meet your GitHub repository.
Reference: How to set GitHub commit status with Jenkinsfile NOT using a pull request builder
I am adding to this answer, and also to this one. They have answered the question, but they didn't give us a proper intuition about the problem
So, here are my intuitions:
We need to add status to our GitHub commit. This status is based upon the results of our Jenkins build.
To do this, we need to give Jenkins access to the GitHub API, not to the repo. We do this through OAuth, and we can create the token going to the GitHub settings → Developer settings → Personal access tokens. Then for a public GitHub repository just check repo:status, and for a private repository, check the whole repository section
After creating your access token you need to add it to your Jenkins server:
Copy and paste the access token to the GitHub plugin section settings, under your Jenkins configurations
Create a GitHub server. It defaults to api.github.com. And add the access token as a secret text credentials.
The last step is to add a post build settings when you create your pipeline.
Resources:
Here is a section of a YouTube video in which he goes over the above steps.
Read about OAuth