forked from mislav/hub
/
ci_status.go
148 lines (122 loc) · 3.1 KB
/
ci_status.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package commands
import (
"fmt"
"os"
"github.com/github/hub/git"
"github.com/github/hub/github"
"github.com/github/hub/ui"
"github.com/github/hub/utils"
)
var cmdCiStatus = &Command{
Run: ciStatus,
Usage: "ci-status [-v] [COMMIT]",
Short: "Show CI status of a commit",
Long: `Looks up the SHA for <COMMIT> in GitHub Status API and displays the latest
status. Exits with one of:
success (0), error (1), failure (1), pending (2), no status (3)
If "-v" is given, additionally print detailed report of all checks and their URLs.
`,
}
var flagCiStatusVerbose bool
func init() {
cmdCiStatus.Flag.BoolVarP(&flagCiStatusVerbose, "verbose", "v", false, "VERBOSE")
CmdRunner.Use(cmdCiStatus)
}
/*
$ hub ci-status
> (prints CI state of HEAD and exits with appropriate code)
$ hub ci-status -v
> (prints CI states and URLs to CI build results for HEAD and exits with appropriate code)
$ hub ci-status BRANCH
> (prints CI state of BRANCH and exits with appropriate code)
$ hub ci-status SHA
> (prints CI state of SHA and exits with appropriate code)
*/
func ciStatus(cmd *Command, args *Args) {
ref := "HEAD"
if !args.IsParamsEmpty() {
ref = args.RemoveParam(0)
}
localRepo, err := github.LocalRepo()
utils.Check(err)
project, err := localRepo.MainProject()
utils.Check(err)
sha, err := git.Ref(ref)
if err != nil {
err = fmt.Errorf("Aborted: no revision could be determined from '%s'", ref)
}
utils.Check(err)
if args.Noop {
ui.Printf("Would request CI status for %s\n", sha)
} else {
gh := github.NewClient(project.Host)
response, err := gh.FetchCIStatus(project, sha)
utils.Check(err)
state := response.State
if len(response.Statuses) == 0 {
state = ""
}
var exitCode int
switch state {
case "success":
exitCode = 0
case "failure", "error":
exitCode = 1
case "pending":
exitCode = 2
default:
exitCode = 3
}
targetUrl := relevantTargetUrl(response.Statuses, state)
if flagCiStatusVerbose && targetUrl != "" {
ui.Printf("%s: %s\n", state, targetUrl)
} else {
if state != "" {
ui.Println(state)
} else {
ui.Println("no status")
}
}
os.Exit(exitCode)
}
}
func relevantTargetUrl(statuses []github.CIStatus, state string) string {
for _, status := range statuses {
if status.State == state {
return status.TargetUrl
}
}
return ""
}
func verboseFormat(statuses []github.CIStatus) {
colorize := ui.IsTerminal(os.Stdout)
contextWidth := 0
for _, status := range statuses {
if len(status.Context) > contextWidth {
contextWidth = len(status.Context)
}
}
for _, status := range statuses {
var color int
var stateMarker string
switch status.State {
case "success":
stateMarker = "✔︎"
color = 32
case "failure", "error":
stateMarker = "✖︎"
color = 31
case "pending":
stateMarker = "●"
color = 33
}
if colorize {
stateMarker = fmt.Sprintf("\033[%dm%s\033[0m", color, stateMarker)
}
if status.TargetUrl == "" {
ui.Printf("%s\t%s\n", stateMarker, status.Context)
} else {
ui.Printf("%s\t%-*s\t%s\n", stateMarker, contextWidth, status.Context, status.TargetUrl)
}
}
}