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

淺唱寂寞╮ 提交于 2019-11-27 12:58:23

问题


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.


回答1:


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.




回答2:


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.




回答3:


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




回答4:


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



回答5:


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



来源:https://stackoverflow.com/questions/43214730/how-to-set-github-commit-status-with-jenkinsfile-not-using-a-pull-request-builde

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!