How to Update Jenkins Build Status in GitHub Pull Requests
Publish Jenkins build results on GitHub pull requests with commit statuses or richer Checks, and fix the SHA and naming issues that hide results.
To show a Jenkins build result on a GitHub pull request, publish a commit status for the commit GitHub evaluates. Use the Jenkins GitHub plugin for a simple pending, success, failure, or error state with a link to the build. Use the Jenkins Checks API integration when you need richer check output, such as summaries or annotations. The most common reason a result is missing is that Jenkins reported it against a different commit SHA than the pull request head.
Choose commit status or GitHub Check
| Need | Use | What to expect |
|---|---|---|
| A pass/fail state and a link to the Jenkins build | Commit status | A status attached to a commit, with a description, target URL, and context such as continuous-integration/jenkins. |
| Structured check output, summaries, or annotations | GitHub Check | A check run created through the Checks API. Configure a GitHub App with Checks permissions and report against the right SHA. |
GitHub displays commit statuses on pull requests that involve the commit. A commit status accepts error, failure, pending, or success. For a basic CI signal, start with a commit status. Choose Checks when reviewers need detailed results in GitHub. See the [Jenkins GitHub plugin documentation](https://plugins.jenkins.io/github/) and [GitHub commit statuses API](https://docs.github.com/en/rest/commits/statuses).
Publish a simple commit status from Jenkins
1. Configure the Jenkins GitHub integration
- Install and configure the Jenkins GitHub plugin using its official instructions.
- Set up the repository connection and credentials Jenkins needs to report status to GitHub. Use a credential suitable for the reporting operation and limit its scope to the repository or organization required by your setup.
- Keep webhook setup separate from status publishing. Permissions for managing GitHub hooks, such as
admin:org_hook, are not a universal requirement for posting a commit status. - Make sure the job checks out the commit that GitHub evaluates for the pull request.
The GitHub plugin documents reporting a build status result as a commit status. The exact job configuration depends on whether the job is a Pipeline, a Multibranch Pipeline using GitHub Branch Source, or a Freestyle job. Use the plugin’s documented job configuration and credential setup for your job type rather than assuming one Pipeline snippet applies to every installation.
2. Report a useful status
For each build, GitHub should receive a state, a short description, a link to the Jenkins build, and a stable context identifying the job. For example:
state: pending
context: continuous-integration/jenkins
description: Jenkins build is running
target_url: https://jenkins.example.com/job/my-job/42/
When the build completes, publish success or failure (or error if the reporting operation itself encountered an error). Reuse the same context for updates to the same logical check so GitHub presents the lifecycle as one status. Give separate jobs distinct contexts when maintainers need to distinguish their results.
The values above explain the fields; they are not a Jenkinsfile DSL. Use the plugin’s supported configuration for your job. If you publish through GitHub’s REST API directly, use its [Create a commit status endpoint](https://docs.github.com/en/rest/commits/statuses#create-a-commit-status) and authenticate with credentials authorized for that repository.
Publish richer output with the Jenkins GitHub Checks plugin
GitHub Checks can present more structured review output than a basic commit status. Jenkins provides the Checks API plugin and a GitHub Checks implementation. The Checks API plugin documents a Pipeline step named publishChecks; consult the [Checks API plugin documentation](https://plugins.jenkins.io/checks-api/) and [GitHub Checks plugin documentation](https://plugins.jenkins.io/github-checks/) for the installed versions and step parameters.
1. Configure the required GitHub App
- Install the Jenkins Checks API plugin and its GitHub Checks implementation.
- Configure a GitHub App for Jenkins with Checks read and write permission. GitHub requires a GitHub App for Checks API writes, and creating or managing check runs requires
checks:write. - Install or authorize the app for the repository where Jenkins reports results, then configure its credentials in Jenkins as described by the plugin.
- Do not mistake hook-management permissions for Checks permissions. A token used to manage webhooks is a separate configuration concern.
2. Publish from a Pipeline
The documented Pipeline entry point is publishChecks. The exact arguments for names, summaries, details, and annotations depend on the Checks API plugin version. Use the plugin’s installed-version reference for a runnable step signature; avoid copying an example written for a different version. Configure a distinct check name for each concurrently running job that reports on the same commit.
// Pipeline placement and step name documented by the Jenkins Checks API plugin:
publishChecks(...)
The ellipsis is intentionally not a copy-paste argument list: the official step reference defines the accepted parameters and their types for your plugin version. Once configured, ensure the run completes with the intended conclusion and that the result is attached to the PR head SHA.
GitHub’s [Checks API documentation](https://docs.github.com/en/rest/checks) describes check runs, summaries, and annotations. Jenkins plugin versions can change their step parameters, so the plugin reference should be treated as authoritative for the installed version.
Make sure Jenkins reports against the pull request SHA
The SHA receiving a status or check must be the commit GitHub evaluates for the pull request. The Jenkins GitHub Checks plugin documents different behavior depending on how the job obtains source:
- With GitHub Branch Source, reporting is against the pull request head SHA.
- With plain GitSCM, reporting uses the last built revision. If the job builds
refs/pull/<id>/merge, this can be GitHub’s temporary merge commit rather than the PR head.
For a required check expected on the PR head, configure the checkout/reporting path to use the head ref, such as refs/pull/<id>/head, where appropriate for your job. Confirm the actual SHA in both Jenkins and GitHub before changing branch protection. The plugin documentation states: “Required status checks on a pull request only look at the PR head (refs/pull/<id>/head), not at GitHub’s temporary merge commit (refs/pull/<id>/merge).” See the [Jenkins GitHub Checks documentation](https://github.com/jenkinsci/github-checks-plugin) for its SHA behavior.
Names, concurrency, and branch protection
- Use stable names. A check name or status context is how maintainers identify the reporting job.
- Use distinct names for concurrent jobs. Jenkins warns that identical check names on the same SHA can overwrite one another. The plugin does not combine multiple jobs into one catch-all required check.
- Configure branch protection against the check that is actually reported. Confirm its name and, when relevant, the expected GitHub App before requiring it.
- Handle skipped jobs deliberately. If a job does not run for some PRs, a required check may remain pending. Ensure the required check is produced for every applicable change or adjust the protection rules.
Verify a report
- Open the pull request and identify its current head commit SHA.
- Open that commit’s status or Checks view in GitHub and find the Jenkins result.
- Compare the reported SHA with the PR head SHA.
- Check the context or check name, conclusion, and build target URL.
- If branch protection requires a check, verify the required name and expected GitHub App match the report.
For a direct API integration, GitHub’s [Create a commit status](https://docs.github.com/en/rest/commits/statuses#create-a-commit-status) endpoint accepts the repository, SHA, state, and optional description, target URL, and context. Use the API response and resulting commit page to confirm the report was accepted and attached to the intended revision.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| No status or check appears on the PR | Jenkins reported to a different SHA, often a merge ref instead of the PR head. | Compare the SHA in Jenkins with the PR head. Adjust GitSCM/ref selection or use the GitHub Branch Source behavior appropriate to the job. |
| A check appears on the commit but branch protection still blocks merging | The required name or expected app does not match the reported check, or the check is on the wrong SHA. | Inspect the exact check name, source app, and SHA; update the Jenkins configuration or protection rule to match the intended result. |
| One job appears to replace another | Both jobs reported the same check name on the same SHA. | Give each concurrent job a unique, stable name. For commit statuses, use distinct contexts when they represent separate jobs. |
| Checks API write fails | The integration lacks a GitHub App with Checks write permission, or the app is not installed for the repository. | Configure and install the GitHub App with the Checks permissions required by the Jenkins plugin; verify its repository access. |
| Build link is missing or unhelpful | The status omitted its target URL or points to a non-permalink. | Include a target URL that takes maintainers to the relevant Jenkins build. |
| Required result stays pending when a job is skipped | The required check was never reported for that change. | Ensure the check runs on applicable changes or revise branch protection so it does not require a result that cannot be produced. |
GitHub Actions and merge queue note
If GitHub Actions checks also participate in the required-check rules, troubleshoot their workflow triggers separately from Jenkins. GitHub documents that skipped workflows can leave required checks pending, and merge queues require Actions workflows to listen for the separate merge_group event. That event requirement is specific to GitHub Actions; it does not describe how Jenkins selects its reporting SHA. See [GitHub’s required status checks troubleshooting guide](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/troubleshooting-required-status-checks).
Performance, reliability, and cost
- Publish promptly. Report a pending state when a build begins and a final state when it finishes, so GitHub does not show stale results.
- Keep reporting independent of test success. A failed test should result in a failure status; a reporting failure should be visible in Jenkins logs and retried or surfaced rather than silently treated as a passed build.
- Make updates repeatable. Use a stable context or check name for the logical job, while keeping names unique across jobs on the same SHA.
- Keep credentials scoped. Use the appropriate repository access and GitHub App permissions; hook management, commit status publication, and Checks writes have distinct needs.
- Cost. The Jenkins plugins and GitHub status/check APIs are configuration and API integration components. Budget for the Jenkins infrastructure you operate and any GitHub plan or usage terms that apply to your organization; this research dossier does not establish specific pricing.
Or skip the browser setup
When a PR build needs a visual review of a web page, ScreenshotNeo can capture the target URL in one API call. It is separate from Jenkins status reporting: use Jenkins and GitHub to publish the build result, and use ScreenshotNeo when the build or review process also needs a page screenshot.
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo and sign up for 1,000 free screenshots a month, with no card.
FAQ
Does a commit status update the pull request itself?
The status belongs to a commit. GitHub reflects it on pull requests involving that commit when it is the relevant revision.
Do I need a GitHub App for a simple commit status?
The Checks API path requires a GitHub App with Checks permissions. Follow the Jenkins GitHub plugin’s credential guidance for commit statuses; do not apply the Checks permission requirement to every status integration.
Can one required check cover several Jenkins jobs?
The Jenkins GitHub Checks plugin does not combine same-name checks into one catch-all result. Give jobs distinct names and configure branch protection for the results you intend to require.
Why is an Actions check mentioned in a Jenkins guide?
Some repositories require results from both Jenkins and GitHub Actions. Actions trigger eligibility and merge queue events are separate from Jenkins plugin configuration, so diagnose those workflows independently.


