[JIRA] (JENKINS-39482) GitHub commit status not working with GitHubCommitStatusSetter on first build of branch in multi-branch pipeline

887 views
Skip to first unread message

tony.arous@emc.com (JIRA)

unread,
Nov 3, 2016, 12:02:01 PM11/3/16
to jenkinsc...@googlegroups.com
Tony Arous created an issue
 
Jenkins / Bug JENKINS-39482
GitHub commit status not working with GitHubCommitStatusSetter on first build of branch in multi-branch pipeline
Issue Type: Bug Bug
Assignee: Kirill Merkushev
Components: github-plugin
Created: 2016/Nov/03 4:01 PM
Environment: Jenkins 2.19.2, GitHub plugin 1.22.3
Priority: Major Major
Reporter: Tony Arous

In a multi-branch pipeline, I am using the GitHubCommitStatusSetter step in several places to set custom commit status. These calls do not work the first time the branch is built by Jenkins. Subsequent builds work correctly.

Jenkinsfile

step([$class: 'GitHubCommitStatusSetter', contextSource: [$class: 'ManuallyEnteredCommitContextSource', context: 'pylint'], statusResultSource: [$class: 'ConditionalStatusResultSource', results: [[$class: 'AnyBuildResult', state: 'SUCCESS', message: "Succeeded"]]]])

First build log – failing:

[pylint] [Set GitHub commit status (universal)] SUCCESS on repos [] (sha:c119d83) with context:pylint

All future builds – working:

[pylint] [Set GitHub commit status (universal)] SUCCESS on repos [GHRepository@68adaba[description=RepoDescription,homepage=https://filtered,name=reponame,license=<null>,fork=false,watchers=1,forks=0,size=23027,milestones={},language=Python,commits={},source=<null>,parent=<null>,url=https://filtered,id=115]] (sha:c119d83) with context:pylint
[pylint] Setting commit status on GitHub for https://filtered/commit/c119d83bbab1635708c95e800a6eb4052d8a787c
Add Comment Add Comment
 
This message was sent by Atlassian JIRA (v7.1.7#71011-sha1:2526d7c)
Atlassian logo

lanwen@yandex.ru (JIRA)

unread,
Nov 4, 2016, 7:43:01 AM11/4/16
to jenkinsc...@googlegroups.com
Kirill Merkushev closed an issue as Won't Fix
 

Please read docs for pipeline plugin. On first run there is no information about git (pipeline doesn't provide it)

Change By: Kirill Merkushev
Status: Open Closed
Resolution: Won't Fix

kyleezhu@gmail.com (JIRA)

unread,
Nov 17, 2016, 10:30:02 PM11/17/16
to jenkinsc...@googlegroups.com
xianjun zhu commented on Bug JENKINS-39482
 
Re: GitHub commit status not working with GitHubCommitStatusSetter on first build of branch in multi-branch pipeline

One working example to set repo url like below.

void setBuildStatus(String message, String state)

{ step([ $class: "GitHubCommitStatusSetter", reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/my-org/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]] ] ]); }

setBuildStatus("Build complete", "SUCCESS");

kyleezhu@gmail.com (JIRA)

unread,
Nov 17, 2016, 10:32:02 PM11/17/16
to jenkinsc...@googlegroups.com
xianjun zhu edited a comment on Bug JENKINS-39482
One working example to set repo url like below.

{code:groovy}
void setBuildStatus(String message, String state) {
  step([
      $class: "GitHubCommitStatusSetter",
      reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/my-org/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]] ]
  ]);
}

setBuildStatus("Build complete", "SUCCESS"); {code}

kyleezhu@gmail.com (JIRA)

unread,
Nov 17, 2016, 10:32:02 PM11/17/16
to jenkinsc...@googlegroups.com
xianjun zhu edited a comment on Bug JENKINS-39482
One working example to set repo url like below.

{code: groovy java }

void setBuildStatus(String message, String state) {
  step([
      $class: "GitHubCommitStatusSetter",
      reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/my-org/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]] ]
  ]);
}

setBuildStatus("Build complete", "SUCCESS");{code}

lanwen@yandex.ru (JIRA)

unread,
Nov 18, 2016, 11:17:01 AM11/18/16
to jenkinsc...@googlegroups.com

lanwen@yandex.ru (JIRA)

unread,
Nov 18, 2016, 11:17:01 AM11/18/16
to jenkinsc...@googlegroups.com

tony.arous@emc.com (JIRA)

unread,
Nov 20, 2016, 8:25:01 PM11/20/16
to jenkinsc...@googlegroups.com

kyleezhu@gmail.com (JIRA)

unread,
Nov 20, 2016, 8:30:01 PM11/20/16
to jenkinsc...@googlegroups.com

Hey Tony,
We are using Github Enterprise, I can verify it works for Github Enterprise. In my example above, I replace our GHE repo link with a github.com link.

staples4544@gmail.com (JIRA)

unread,
Feb 15, 2017, 6:59:01 PM2/15/17
to jenkinsc...@googlegroups.com

I am seeing the same general behavior as Tony's first run...for every run.

Tested on:

  • Jenkins: 2.19.1
  • – github-plugin: 1.26.0
  • Jenkins: 2.32.2
  • – github-plugin: 1.26.0
    Using:
  • Public & Enterprise GitHub
  • Webhooks, pull requests, manual builds

Since the default activity is to resolve any repos, I checked to see if it was picking up on any repos, which it was:
Picks up on multiple repos because of Global Shared Pipeline Library getting pulled from GitHub
Jenkins Log

Feb 15, 2017 10:51:18 PM FINEST org.jenkinsci.plugins.github.status.sources.AnyDefinedRepositorySource repos
repositories source=repo-name-contributor value=[GitHubRepositoryName[host=github.com,username=psprings,repository=jenkins-pipeline-helpers-lib], GitHubRepositoryName[host={{ENTERPRISEGITURL}},username={{ENTERPRISEGITORG}},repository={{ENTERPRISEGITREPO}}]]

But the output did not reflect any repos:
Pipeline Console Text

Unable to find source-code formatter for language: bash. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
[Pipeline] step
[Set GitHub commit status (universal)] PENDING on repos [] (sha:6f85cd0) with context:ci/jenkins/foo

So I tried manually setting the repo url as per xianju's suggestion, and got the same result (although overriding the sha worked just fine).
Jenkinsfile snippet

step([
        $class: "GitHubCommitStatusSetter",
        commitShaSource: [$class: "ManuallyEnteredShaSource", sha: gitCommit],
        //reposSource: [$class: "AnyDefinedRepositorySource"],
        reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://enterprisegithuburl.com/Org/Repo" ],
        contextSource: [$class: "ManuallyEnteredCommitContextSource", context: "ci/jenkins/foo" ],
        errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
        statusResultSource: [ $class: "ConditionalStatusResultSource", results: [
            [$class: "AnyBuildResult", message: message, state: state]] ]
      ]);

A status message is set by the GitHub Branch Source plugin if the build passes/fails, but would like more granular commit statuses.

Any thoughts/suggestions?

kyleezhu@gmail.com (JIRA)

unread,
Feb 15, 2017, 7:24:01 PM2/15/17
to jenkinsc...@googlegroups.com

@peter Not sure if I understand your granular commit status correct, in our build, we do set different status to github PR commit based on the progress of CI build.

So following my previous example, we wrapped each workflow step with `buildStep` function below, it will set the commit in PR as `PENDING` before each step, set it to `FAILURE` if fails. If the whole build is successful, then set the status to `SUCCESS`

node('a_node') {
    buildStep('Checkout'){
        checkout scm
    }

    buildStep('step 1'){
            sh '''echo "step 1"
            '''
    }

    setBuildStatus("Build complete", "SUCCESS");
}

void buildStep(String message, Closure closure) {
  stage(message);
  try {
    setBuildStatus(message, "PENDING");
    closure();
  } catch (Exception e) {
    setBuildStatus(message, "FAILURE");
  }
}

void setBuildStatus(String message, String state) {
  step([
      $class: "GitHubCommitStatusSetter",
      reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/my-org/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]] ]
  ]);
}

staples4544@gmail.com (JIRA)

unread,
Feb 15, 2017, 8:45:04 PM2/15/17
to jenkinsc...@googlegroups.com

xianjun zhu thanks for providing the code snippet. Let me clarify about the "granularity" comment. I mean tying stages to statuses for a given GitHub commit. Your example takes a similar approach to the GitHub Branch Source plugin's GitHubBuildStatusNotification class, whereby the final build status of the run (holistically) is tied to a single status for a given commit. What I would like to do is to tie each stage to a separate status.

So, your code snippet would be modified to be something like (untested pseudocode)

node('a_node') {
    buildStep('Checkout'){
        checkout scm
    }

    buildStep('step 1'){
            sh '''echo "step 1"
            '''
    }
}

void buildStep(String context, Closure closure) {
  stage(context);
  try {
    setBuildStatus(context, "In progress...", "PENDING");
    closure();
  } catch (Exception e) {
    setBuildStatus(context, e.take(140), "FAILURE");
  }
  setBuildStatus(context, "Success", "SUCCESS");
}


// Updated to account for context
void setBuildStatus(String context, String message, String state) {
  context = context ?: "ci/jenkins/build-status"
  step([
      $class: "GitHubCommitStatusSetter",
      reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/my-org/my-repo"],
      contextSource: [$class: "ManuallyEnteredCommitContextSource", context: context],
      errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
      statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ]
  ]);
}

So the resulting status array would be something like:
GET /repos/:owner/:repo/commits/:ref/statuses

Unable to find source-code formatter for language: bash. Available languages are: actionscript, html, java, javascript, none, sql, xhtml, xml
{
  "state": "failure",
  "statuses": [
    {
      "url": "https://...bfb1bf",
      "id": 899209,
      "state": "success",
      "description": "Success",
      "target_url": "http://...../job/PR-25/27/display/redirect",
      "context": "Checkout",
      "created_at": "2017-02-15T20:05:36Z",
      "updated_at": "2017-02-15T20:05:36Z"
    },
    {
      "url": "https://...bfb1bf",
      "id": 899210,
      "state": "failure",
      "description": "Error executing echo",
      "target_url": "http://...../job/PR-25/27/display/redirect",
      "context": "step 1",
      "created_at": "2017-02-15T20:05:36Z",
      "updated_at": "2017-02-15T20:05:36Z"
    }
  ],
  "sha": "...777bfb1bf",

I could facilitate this with direct API calls to GitHub, but would prefer a more Pipeline native approach.

staples4544@gmail.com (JIRA)

unread,
Feb 15, 2017, 8:46:01 PM2/15/17
to jenkinsc...@googlegroups.com
Peter Springsteen edited a comment on Bug JENKINS-39482
[~killuazhu] thanks for providing the code snippet. Let me clarify about the "granularity" comment. I mean tying stages to statuses for a given GitHub commit. Your example takes a similar approach to the GitHub Branch Source plugin's *GitHubBuildStatusNotification* class, whereby the final build status of the run (holistically) is tied to a single status for a given commit. What I would like to do is to tie each stage to a _separate_ status.


So, your code snippet would be modified to be something like (untested pseudocode)
{code:java}

node('a_node') {
    buildStep('Checkout'){
        checkout scm
    }

    buildStep('step 1'){
            sh '''echo "step 1"
            '''
    }
}

void buildStep(String context, Closure closure) {
  stage(context);
  try {
    setBuildStatus(context, "In progress...", "PENDING");
    closure();
  } catch (Exception e) {
    setBuildStatus(context, e.take(140), "FAILURE");
  }
  setBuildStatus(context, "Success", "SUCCESS");
}


// Updated to account for context
void setBuildStatus(String context, String message, String state) {
  context = context ?: "ci/jenkins/build-status"
  step([
      $class: "GitHubCommitStatusSetter",
      reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/my-org/my-repo"],
      contextSource: [$class: "ManuallyEnteredCommitContextSource", context: context],
      errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
      statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ]
  ]);
}
{code}


So the resulting status array would be something like:
*GET /repos/:owner/:repo/commits/:ref/statuses*
{code:
bash none }

{
  "state": "failure",
  "statuses": [
    {
      "url": "https://...bfb1bf",
      "id": 899209,
      "state": "success",
      "description": "Success",
      "target_url": "http://...../job/PR-25/27/display/redirect",
      "context": "Checkout",
      "created_at": "2017-02-15T20:05:36Z",
      "updated_at": "2017-02-15T20:05:36Z"
    },
    {
      "url": "https://...bfb1bf",
      "id": 899210,
      "state": "failure",
      "description": "Error executing echo",
      "target_url": "http://...../job/PR-25/27/display/redirect",
      "context": "step 1",
      "created_at": "2017-02-15T20:05:36Z",
      "updated_at": "2017-02-15T20:05:36Z"
    }
  ],
  "sha": "...777bfb1bf",
{code}


I could facilitate this with direct API calls to GitHub, but would prefer a more Pipeline native approach.

staples4544@gmail.com (JIRA)

unread,
Feb 15, 2017, 8:47:03 PM2/15/17
to jenkinsc...@googlegroups.com
Peter Springsteen edited a comment on Bug JENKINS-39482
I am seeing the same general behavior as Tony's first run...for every run.

Tested on:
* Jenkins: 2.19.1
* -- github-plugin: 1.26.0
* Jenkins: 2.32.2
* -- github-plugin: 1.26.0
Using:
* Public & Enterprise GitHub
* Webhooks, pull requests, manual builds


Since the default activity is to resolve any repos, I checked to see if it was picking up on any repos, which it was:
_Picks up on multiple repos because of Global Shared Pipeline Library getting pulled from GitHub_
*Jenkins Log*
{code:java}

Feb 15, 2017 10:51:18 PM FINEST org.jenkinsci.plugins.github.status.sources.AnyDefinedRepositorySource repos
repositories source=repo-name-contributor value=[GitHubRepositoryName[host=github.com,username=psprings,repository=jenkins-pipeline-helpers-lib], GitHubRepositoryName[host={{ENTERPRISEGITURL}},username={{ENTERPRISEGITORG}},repository={{ENTERPRISEGITREPO}}]]
{code}


But the output did not reflect any repos:
*Pipeline Console Text*
{code:
bash none }

[Pipeline] step
[Set GitHub commit status (universal)] PENDING on repos [] (sha:6f85cd0) with context:ci/jenkins/foo
{code}


So I tried manually setting the repo url as per xianju's suggestion, and got the same result (although overriding the sha worked just fine).
*Jenkinsfile snippet*
{code:java}

step([
        $class: "GitHubCommitStatusSetter",
        commitShaSource: [$class: "ManuallyEnteredShaSource", sha: gitCommit],
        //reposSource: [$class: "AnyDefinedRepositorySource"],
        reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://enterprisegithuburl.com/Org/Repo" ],
        contextSource: [$class: "ManuallyEnteredCommitContextSource", context: "ci/jenkins/foo" ],

        errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
        statusResultSource: [ $class: "ConditionalStatusResultSource", results: [
            [$class: "AnyBuildResult", message: message, state: state]] ]
      ]);
{code}

A status message _is_ set by the GitHub Branch Source plugin if the build passes/fails, but would like more granular commit statuses.

Any thoughts/suggestions?

jcarsique@java.net (JIRA)

unread,
Feb 17, 2017, 11:30:01 AM2/17/17
to jenkinsc...@googlegroups.com

Please read docs for pipeline plugin. On first run there is no information about git (pipeline doesn't provide it)

Hello Kirill Merkushev , I don't understand your sentence, nor why you closed the ticket as won't fix.
This is a major issue. In many cases, the branch will only be built once.
I understand that it's a Pipeline / SCM plugin issue at root, maybe already fixed. See for instance https://issues.jenkins-ci.org/browse/JENKINS-41795
So, won't the current issue require a fix to follow the API changes?
Thanks

lanwen@yandex.ru (JIRA)

unread,
Feb 25, 2017, 4:43:02 AM2/25/17
to jenkinsc...@googlegroups.com

JENKINS-41795 is not related to this issue.

How it works with defaults - pipeline is a just text for jenkins and jenkins knows nothing about content of the script before first evaluation.
Status step tries to find defined repos with dedicated jenkins api. But when jenkins dont know about script content - it can't provide info about repos to the status setter step.

As a workaround for short-living jobs you can define repo with manual provider (as in Peter Springsteen's example)

ddigtiar@cloudbees.com (JIRA)

unread,
Mar 29, 2017, 3:55:03 AM3/29/17
to jenkinsc...@googlegroups.com

jpstrydom8@gmail.com (JIRA)

unread,
Feb 4, 2019, 7:33:02 AM2/4/19
to jenkinsc...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages