未验证 提交 d293f544 编写于 作者: M Mislav Marohnić 提交者: GitHub

Merge pull request #1802 from github/checks-api

Have `ci-status` also query Checks API
......@@ -13,7 +13,7 @@ import (
var cmdCiStatus = &Command{
Run: ciStatus,
Usage: "ci-status [-v] [<COMMIT>]",
Long: `Display GitHub Status information for a commit.
Long: `Display status of GitHub checks for a commit.
## Options:
-v
......@@ -22,7 +22,11 @@ var cmdCiStatus = &Command{
<COMMIT>
A commit SHA or branch name (default: "HEAD").
Exits with one of: success (0), error (1), failure (1), pending (2), no status (3).
Possible outputs and exit statuses:
- success, neutral: 0
- failure, error, action_required, cancelled, timed_out: 1
- pending: 2
## See also:
......@@ -31,11 +35,32 @@ hub-pull-request(1), hub(1)
}
var flagCiStatusVerbose bool
var severityList []string
func init() {
cmdCiStatus.Flag.BoolVarP(&flagCiStatusVerbose, "verbose", "v", false, "VERBOSE")
CmdRunner.Use(cmdCiStatus)
severityList = []string{
"neutral",
"success",
"pending",
"cancelled",
"timed_out",
"action_required",
"failure",
"error",
}
}
func checkSeverity(targetState string) int {
for i, state := range severityList {
if state == targetState {
return i
}
}
return -1
}
func ciStatus(cmd *Command, args *Args) {
......@@ -64,15 +89,21 @@ func ciStatus(cmd *Command, args *Args) {
utils.Check(err)
state := response.State
if len(response.Statuses) == 0 {
if len(response.Statuses) > 0 {
for _, status := range response.Statuses {
if checkSeverity(status.State) > checkSeverity(state) {
state = status.State
}
}
} else if len(response.Statuses) == 0 {
state = ""
}
var exitCode int
switch state {
case "success":
case "success", "neutral":
exitCode = 0
case "failure", "error":
case "failure", "error", "action_required", "cancelled", "timed_out":
exitCode = 1
case "pending":
exitCode = 2
......@@ -111,9 +142,12 @@ func verboseFormat(statuses []github.CIStatus) {
case "success":
stateMarker = "✔︎"
color = 32
case "failure", "error":
case "failure", "error", "action_required", "cancelled", "timed_out":
stateMarker = "✖︎"
color = 31
case "neutral":
stateMarker = "◦"
color = 30
case "pending":
stateMarker = "●"
color = 33
......
......@@ -191,7 +191,7 @@ var helpText = `
These GitHub commands are provided by hub:
browse Open a GitHub page in the default browser
ci-status Show the CI status of a commit
ci-status Show the status of GitHub checks for a commit
compare Open a compare page on GitHub
create Create this repository on GitHub and add GitHub as origin
delete Delete a repository on GitHub
......
......@@ -92,7 +92,7 @@ __hub_setup_zsh_fns () {
delete:'delete a GitHub repo'
browse:'browse the project on GitHub'
compare:'open GitHub compare view'
ci-status:'lookup commit in GitHub Status API'
ci-status:'show status of GitHub checks for a commit'
sync:'update local branches from upstream'
)
_describe -t hub-commands 'hub command' hub_commands && ret=0
......
......@@ -25,7 +25,7 @@ Feature: hub ci-status
Given there is a commit named "the_sha"
Given the remote commit states of "michiels/pencilbox" "the_sha" are:
"""
{ :state => "pending",
{ :state => "error",
:statuses => [
{ :state => "success",
:context => "continuous-integration/travis-ci/push",
......@@ -49,7 +49,7 @@ Feature: hub ci-status
✖︎ GitHub CLA https://cla.github.com/michiels/pencilbox/accept/mislav
✖︎ whatevs!\n
"""
And the exit status should be 2
And the exit status should be 1
Scenario: Exit status 1 for 'error' and 'failure'
Given the remote commit state of "michiels/pencilbox" "HEAD" is "error"
......@@ -101,6 +101,36 @@ Feature: hub ci-status
Given there is a commit named "the_sha"
Given the remote commit state of "michiels/pencilbox" "the_sha" is "success"
When I successfully run `git config --global alias.ci-status "ci-status -v"`
When I run `hub ci-status the_sha`
And I successfully run `hub ci-status the_sha`
Then the output should contain exactly "success\n"
And the exit status should be 0
Scenario: Has Checks
Given there is a commit named "the_sha"
And the GitHub API server:
"""
get('/repos/michiels/pencilbox/commits/:sha/status') {
json({ :state => "success",
:statuses => [
{ :state => "success",
:context => "travis-ci",
:target_url => "the://url"}
]
})
}
get('/repos/michiels/pencilbox/commits/:sha/check-runs') {
json({ :check_runs => [
{ :status => "completed",
:conclusion => "action_required",
:name => "check 1",
:html_url => "the://url" },
{ :status => "queued",
:conclusion => "",
:name => "check 2",
:html_url => "the://url" },
]
})
}
"""
When I run `hub ci-status the_sha`
Then the output should contain exactly "action_required\n"
And the exit status should be 1
......@@ -259,6 +259,9 @@ Given(/^the remote commit states of "(.*?)" "(.*?)" are:$/) do |proj, ref, json_
get('#{'/api/v3' if host}/repos/#{owner}/#{repo}/commits/#{rev}/status'#{", :host_name => '#{host}'" if host}) {
json(#{json_value})
}
get('#{'/api/v3' if host}/repos/#{owner}/#{repo}/commits/#{rev}/check-runs'#{", :host_name => '#{host}'" if host}) {
status 422
}
EOS
step %{the GitHub API server:}, status_endpoint
end
......
......@@ -440,6 +440,17 @@ type CIStatus struct {
TargetUrl string `json:"target_url"`
}
type CheckRunsResponse struct {
CheckRuns []CheckRun `json:"check_runs"`
}
type CheckRun struct {
Status string `json:"status"`
Conclusion string `json:"conclusion"`
Name string `json:"name"`
HtmlUrl string `json:"html_url"`
}
func (client *Client) FetchCIStatus(project *Project, sha string) (status *CIStatusResponse, err error) {
api, err := client.simpleApi()
if err != nil {
......@@ -452,7 +463,35 @@ func (client *Client) FetchCIStatus(project *Project, sha string) (status *CISta
}
status = &CIStatusResponse{}
err = res.Unmarshal(status)
if err = res.Unmarshal(status); err != nil {
return
}
res, err = api.GetFile(fmt.Sprintf("repos/%s/%s/commits/%s/check-runs", project.Owner, project.Name, sha), checksType)
if err == nil && res.StatusCode == 422 {
return
}
if err = checkStatus(200, "fetching checks", res, err); err != nil {
return
}
checks := &CheckRunsResponse{}
if err = res.Unmarshal(checks); err != nil {
return
}
for _, checkRun := range checks.CheckRuns {
state := "pending"
if checkRun.Status == "completed" {
state = checkRun.Conclusion
}
checkStatus := CIStatus{
State: state,
Context: checkRun.Name,
TargetUrl: checkRun.HtmlUrl,
}
status.Statuses = append(status.Statuses, checkStatus)
}
return
}
......
......@@ -21,6 +21,7 @@ import (
const apiPayloadVersion = "application/vnd.github.v3+json;charset=utf-8"
const patchMediaType = "application/vnd.github.v3.patch;charset=utf-8"
const textMediaType = "text/plain;charset=utf-8"
const checksType = "application/vnd.github.antiope-preview+json;charset=utf-8"
var inspectHeaders = []string{
"Authorization",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册