【问题标题】:How to set github commit status with Jenkinsfile NOT using a pull request builder如何使用 Jenkinsfile 设置 github 提交状态而不使用拉取请求构建器
【发布时间】:2017-04-04 18:17:08
【问题描述】:

我们设置了 Jenkins 2 来构建对 github 的每次推送,并且我们不使用 Pull Request 构建器(尽管作为 pull request 的一部分的提交显然也会被构建)。 GitHub Integration Plugin 说它只适用于拉取请求构建器,所以这对我们不起作用。

我也尝试过github-notify plugin,但它似乎不适用于我们的案例(可能是因为回购是私有的和/或作为组织的一部分拥有,而不是个人用户)。我试过让它推断设置以及手动指定credentialsIdaccountrepo,当然还有status 参数,但都没有运气。

这是我的 Jenkinsfile 的缩写版本:

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"
        }
    }
}

当我运行构建时,我得到以下信息:

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)

我已经通过 Jenkins(在配置系统区域)和在浏览器中手动测试了凭据 -- 用户名和密码是正确的,并且具有对相关存储库的读/写访问权限。

【问题讨论】:

  • 您能否通过GitHub API 使用这些凭据手动设置状态?
  • @Jacob 是的——凭据正确(用户名与密码匹配等)并且对相关项目具有完全读/写权限。
  • 我仍然不清楚您是否能够通过 API 执行该操作。如果是,为什么不绕过插件并通过 API 自己调用 GitHub?
  • 是的,我可以——我只是使用凭据通过 Python 登录。我可以在 Jenkins UI 的配置系统部分做各种“测试凭据”;我无法让 githubNotify 插件正常工作,如此处所述。

标签: github jenkins jenkins-pipeline jenkins-2


【解决方案1】:

根据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");
    }
  }
}

不需要多余的插件。只要您安装并正确配置了 GitHub 插件,您甚至不需要执行上述操作,它应该会自动发生。我们也没有使用 Pull Request 构建器,而是使用 Jenkins Multibranch Pipeline。我们只是在 PR 中使用上述 sn-p 来获得额外的状态粒度。

【讨论】:

  • 很好,我尝试了很多方法来使 github-notify-plugin 正常工作,包括来自其他答案和 cmets 的所有建议。您的方法在大约 5 分钟内起作用:-D
  • 您好@James,当拉取请求开始构建时,您如何设置“待处理”状态?非常感谢。
  • @Ricardo 您只需在以“PENDING”状态运行管道后立即调用setBuildStatus。谷歌 GHCommitState 查看您的选项。
  • 存储库的硬编码URL可以替换为env.GIT_URL
  • @Flux 本身只会报告整体构建挂起/成功/失败。但是通过使用上面的 sn-p,您还可以添加粒度。 GitHub 支持显示多个状态检查,只需为每个使用不同的上下文。
【解决方案2】:

首先,确保这些凭据是全局凭据,而不是文件夹凭据。
后者尚不受支持,并且会生成类似的错误消息:请参阅JENKINS-42955(仍在审核中)

其次,如果这些凭据在浏览器中有效但不能通过 DSL 配置文件位于 jenkinsfile 中,这可能是由于名称或密码中的特殊字符:看看你是否不必percent encode reserved characters

【讨论】:

  • 凭证是全局凭证。唯一的特殊字符是连字符——否则都是字母数字。
  • 我遇到了同样的错误并尝试了所有这些但没有成功。我建议任何人按照 James 的回答使用 Jenkins Github 插件
【解决方案3】:

我没有想到account 参数中的值不能与凭据中的用户匹配。在account 中,您必须指定存储库所有者。在credentialsId 中,您可以使用push access 的任何用户到存储库:

credentialsId:要使用的 github 凭证的 id,必须是 UsernameAndPassword 类型。确保凭据具有写入权限,如 stated by doc:具有推送权限的用户可以为给定的 ref 创建提交状态

account: 拥有仓库的账户

【讨论】:

  • 请注意,文档继续声明(我已经测试过)您的帐户密码或访问令牌可用于UsernameAndPassword 凭据。
【解决方案4】:

文档中的一个更好的例子:

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】:

    如果您不想打扰专门的插件,这里是使用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'
        }
      }
    }
    

    GITHUB_API_URL 通常是这样构造的,例如在environment 指令中:

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

    credentialsId可以从Jenkins -> Credentials创建和获取

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-12
      • 2022-01-21
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-27
      • 1970-01-01
      相关资源
      最近更新 更多