Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set github commit status with Jenkinsfile NOT using a pull request builder

We have Jenkins 2 set to build every push to github, and we do not use the Pull Request builder (although commits that are part of a pull request obviously will get built, as well). The GitHub Integration Plugin says that it only works with the pull request builder, so this won't work for us.

I've also tried the github-notify plugin, but it seems not to work for our case (possibly because the repo is private and/or owned as part of an Organizaiton, rather than an individual user). I have tried letting it infer settings as well as manually specifying credentialsId, account, repo, and of course status arguments, all with no luck.

Here's an abbreviated version of my Jenkinsfile at the moment:

pipeline {
    agent { label "centos7" }

    stages {
        stage("github => pending") {
            steps {
                githubNotify status: "PENDING", credentialsId: "my-credentials-id", account: "my-account", repo: "my-repo"
            }
        }
        stage("build") {
            ...
        }
    }

    post {
        success {
            githubNotify status: "SUCCESS", credentialsId: "my-credentials-id", account: "my-account", repo: "my-repo"
        }
        failure {
            githubNotify status: "FAILURE", credentialsId: "my-credentials-id", account: "my-account", repo: "my-repo"
        }
    }
}

When I run the build, I get the following:

java.lang.IllegalArgumentException: The suplied credentials are invalid to login
    at org.jenkinsci.plugins.pipeline.githubstatusnotification.GitHubStatusNotificationStep.getGitHubIfValid(GitHubStatusNotificationStep.java:234)
    at org.jenkinsci.plugins.pipeline.githubstatusnotification.GitHubStatusNotificationStep.getRepoIfValid(GitHubStatusNotificationStep.java:239)
    at org.jenkinsci.plugins.pipeline.githubstatusnotification.GitHubStatusNotificationStep.access$100(GitHubStatusNotificationStep.java:75)
    at org.jenkinsci.plugins.pipeline.githubstatusnotification.GitHubStatusNotificationStep$Execution.run(GitHubStatusNotificationStep.java:344)
    at org.jenkinsci.plugins.pipeline.githubstatusnotification.GitHubStatusNotificationStep$Execution.run(GitHubStatusNotificationStep.java:326)
    at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1$1.call(AbstractSynchronousNonBlockingStepExecution.java:47)
    at hudson.security.ACL.impersonate(ACL.java:221)
    at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1.run(AbstractSynchronousNonBlockingStepExecution.java:44)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

I've tested the credentials both through Jenkins (in the Configure System area) and manually in a browser -- the username and password are correct, and have read/write access to the repo in question.

like image 948
dcrosta Avatar asked Apr 04 '17 18:04

dcrosta


People also ask

How do I add a Jenkins check in GitHub?

Step 1: go to your GitHub repository and click on 'Settings'. Step 2: Click on Webhooks and then click on 'Add webhook'. Step 3: In the 'Payload URL' field, paste your Jenkins environment URL.

When can we use GitHub plugin in Jenkins?

In order to integrate Jenkins with GitHub, all you require is a plugin. The GitHub plugin for Jenkins allows you to schedule your build and facilitates easy transfer of data from the GitHub repository to Jenkins machine. Moreover, it also triggers each build automatically after each commit.

What is PR in Jenkins?

Every time a developer updates the PR, a new PR build is triggered and Jenkins tries to do a new merge. Once the PR is validated, if the developer click on the Merge button, it'll try to merge the code on the target branch. You can set some merge options in this properties file.


5 Answers

Per the Jenkins GitHub plugin's own example:

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]] ]
  ]);
}

... 

pipeline {
  stages {
     ...
  }
  post {
    success {
        setBuildStatus("Build succeeded", "SUCCESS");
    }
    failure {
        setBuildStatus("Build failed", "FAILURE");
    }
  }
}

No superfluous plugins necessary. So long as you have the GitHub plugin installed and correctly configured, you shouldn't even need to do the above, it should happen automatically. We aren't using the Pull Request builder either but are instead using the Jenkins Multibranch Pipeline. We're merely using the above snippet for additional status granularity in our PR's.

like image 107
James Avatar answered Sep 24 '22 03:09

James


First, make sure those credentials are global ones, not folder credentials.
The latter is not yet supported and would generate a similar error message: see JENKINS-42955 (still in review)

Second, if those credentials works in a browser but not through a DSL config file lie a jenkinsfile, that might be due to special characters in the name or password: see if you don't have to percent encode reserved characters.

like image 38
VonC Avatar answered Sep 23 '22 03:09

VonC


It didn't occur to me that value in account parameter must not match user in credentials. In account you must specify repository owner. And in credentialsId you may use any user with push access to the repository:

credentialsId: The id of the github's credentials to use, must be of type UsernameAndPassword. Make sure the credentials have write access, as stated by doc: Users with push access can create commit statuses for a given ref

account: The account that owns the repository

like image 24
x-yuri Avatar answered Sep 26 '22 03:09

x-yuri


A better example from the docs:

def getRepoURL() {
  sh "git config --get remote.origin.url > .git/remote-url"
  return readFile(".git/remote-url").trim()
}

def getCommitSha() {
  sh "git rev-parse HEAD > .git/current-commit"
  return readFile(".git/current-commit").trim()
}

def updateGithubCommitStatus(build) {
  // workaround https://issues.jenkins-ci.org/browse/JENKINS-38674
  repoUrl = getRepoURL()
  commitSha = getCommitSha()

  step([
    $class: 'GitHubCommitStatusSetter',
    reposSource: [$class: "ManuallyEnteredRepositorySource", url: repoUrl],
    commitShaSource: [$class: "ManuallyEnteredShaSource", sha: commitSha],
    errorHandlers: [[$class: 'ShallowAnyErrorHandler']],
    statusResultSource: [
      $class: 'ConditionalStatusResultSource',
      results: [
        [$class: 'BetterThanOrEqualBuildResult', result: 'SUCCESS', state: 'SUCCESS', message: build.description],
        [$class: 'BetterThanOrEqualBuildResult', result: 'FAILURE', state: 'FAILURE', message: build.description],
        [$class: 'AnyBuildResult', state: 'FAILURE', message: 'Loophole']
      ]
    ]
  ])
}
like image 41
Clintm Avatar answered Sep 22 '22 03:09

Clintm


If you do not want to bother with the specialized plugins, here is an alternative using curl:

post {
  success {
    withCredentials([usernamePassword(credentialsId: 'your_credentials_id', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
      sh 'curl -X POST --user $USERNAME:$PASSWORD --data  "{\\"state\\": \\"success\\"}" --url $GITHUB_API_URL/statuses/$GIT_COMMIT'
    }
  }
  failure {
    withCredentials([usernamePassword(credentialsId: 'your_credentials_id', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
      sh 'curl -X POST --user $USERNAME:$PASSWORD --data  "{\\"state\\": \\"failure\\"}" --url $GITHUB_API_URL/statuses/$GIT_COMMIT'
    }
  }
}

Where the GITHUB_API_URL is usually constructed like so, for example in the environment directive:

environment {
   GITHUB_API_URL='https://api.github.com/repos/organization_name/repo_name'
}

The credentialsId can be created and obtained from Jenkins -> Credentials

like image 28
Jozef Avatar answered Sep 26 '22 03:09

Jozef