Skip to content

Commit abae0a7

Browse files
committed
allow downloading log directly from AV
1 parent bfc11fa commit abae0a7

File tree

1 file changed

+107
-22
lines changed

1 file changed

+107
-22
lines changed

misc/summarize-appveyor-log.go

Lines changed: 107 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,44 @@ package main
44

55
import (
66
"bufio"
7+
"encoding/json"
78
"fmt"
9+
"io"
10+
"net/http"
811
"os"
912
"regexp"
10-
"strings"
1113
"sort"
14+
"strings"
15+
)
16+
17+
const (
18+
headerKey = "Authorization"
19+
headerVal = "Bearer %s"
20+
projUrl = "https://ci.appveyor.com/api/projects/mpictor/stepcode"
21+
//"https://ci.appveyor.com/api/buildjobs/2rjxdv1rnb8jcg8y/log"
22+
logUrl = "https://ci.appveyor.com/api/buildjobs/%s/log"
1223
)
1324

1425
//uses stdin and stdout
1526
func main() {
16-
log := unwrap()
27+
rawlog, build, err := getLog()
28+
if err != nil {
29+
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
30+
return
31+
}
32+
defer rawlog.Close()
33+
log := unwrap(rawlog)
1734
warns, errs := countMessages(log)
18-
printMessages("error", errs)
19-
printMessages("warning", warns)
35+
fi, err := os.Create(fmt.Sprintf("appveyor-%d.smy", build))
36+
if err != nil {
37+
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
38+
return
39+
}
40+
printMessages("error", errs, fi)
41+
printMessages("warning", warns, fi)
42+
43+
fmt.Printf("done\n")
44+
2045
}
2146

2247
/* categorizes warnings and errors based upon the MSVC message number (i.e. C4244)
@@ -28,17 +53,14 @@ func countMessages(log []string) (warns, errs map[string][]string) {
2853
warns = make(map[string][]string)
2954
errs = make(map[string][]string)
3055
tstamp := `\[\d\d:\d\d:\d\d\] `
31-
fname := " *(.*)" // $1
32-
fline := `(?:\((\d+)\)| ): ` // $2 - either line number in parenthesis or a space, followed by a colon
33-
msgNr := `([A-Z]+\d+): ` // $3 - C4251, LNK2005, etc
34-
msgTxt := `([^\[]*) ` // $4
56+
fname := " *(.*)" // $1
57+
fline := `(?:\((\d+)\)| ): ` // $2 - either line number in parenthesis or a space, followed by a colon
58+
msgNr := `([A-Z]+\d+): ` // $3 - C4251, LNK2005, etc
59+
msgTxt := `([^\[]*) ` // $4
3560
tail := `\[[^\[\]]*\]`
3661
warnRe := regexp.MustCompile(tstamp + fname + fline + `warning ` + msgNr + msgTxt + tail)
3762
errRe := regexp.MustCompile(tstamp + fname + fline + `(?:fatal )?error ` + msgNr + msgTxt + tail)
38-
//reScanner := bufio.NewScanner(strings.NewReader(...log))
39-
//for reScanner.Scan() {
40-
//line := reScanner.Text()
41-
for _,line := range log {
63+
for _, line := range log {
4264
if warnRe.MatchString(line) {
4365
key := warnRe.ReplaceAllString(line, "$3")
4466
path := strings.ToLower(warnRe.ReplaceAllString(line, "$1:$2"))
@@ -84,53 +106,116 @@ func countMessages(log []string) (warns, errs map[string][]string) {
84106
return
85107
}
86108

87-
func printMessages(typ string, m map[string][]string) {
109+
func printMessages(typ string, m map[string][]string, w io.Writer) {
88110
//sort keys
89111
keys := make([]string, 0, len(m))
90112
for key := range m {
91113
keys = append(keys, key)
92114
}
93115
sort.Strings(keys)
94-
//fmt.Println(keys)
95116
for _, k := range keys {
96117
for i, l := range m[k] {
97118
//first string is an example, not a location
98119
if i == 0 {
99-
fmt.Printf("%s %s (i.e. \"%s\")\n", typ, k, l)
120+
fmt.Fprintf(w, "%s %s (i.e. \"%s\")\n", typ, k, l)
100121
} else if len(l) > 1 { //not sure where blank lines are coming from...
101-
fmt.Printf(" >> %s\n", l)
122+
fmt.Fprintf(w, " >> %s\n", l)
102123
}
103124
}
104125
}
105126
}
106127

107128
//
108-
func unwrap() (log []string) {
129+
func unwrap(r io.Reader) (log []string) {
109130
startNewLine := true
110-
unwrapScanner := bufio.NewScanner(os.Stdin)
131+
unwrapScanner := bufio.NewScanner(r)
111132
var lineOut string
112133
for unwrapScanner.Scan() {
113134
lastNewline := startNewLine
114135
lineIn := unwrapScanner.Text()
115-
startNewLine = (len(lineIn) < 240) || strings.HasSuffix(lineIn,"vcxproj]")
136+
startNewLine = (len(lineIn) < 240) || strings.HasSuffix(lineIn, "vcxproj]")
116137
if !lastNewline {
117138
lineOut += lineIn[11:]
118139
} else {
119140
lineOut = lineIn
120141
}
121142
if startNewLine {
122-
log = append(log,lineOut)
143+
log = append(log, lineOut)
123144
lineOut = ""
124-
//log += fmt.Sprintf("\n")
125145
}
126146
}
127147
if len(lineOut) > 0 {
128-
log = append(log,lineOut)
148+
log = append(log, lineOut)
129149
}
130150
if err := unwrapScanner.Err(); err != nil {
131151
fmt.Fprintln(os.Stderr, "Error reading appveyor log:", err)
132152
}
133153
return
134154
}
135155

156+
//http://json2struct.mervine.net/
157+
type AppVeyorBuild struct {
158+
Build struct {
159+
BuildNumber int `json:"buildNumber"`
160+
Jobs []struct {
161+
JobID string `json:"jobId"`
162+
} `json:"jobs"`
163+
} `json:"build"`
164+
}
165+
166+
func getLog() (log io.ReadCloser, build int, err error) {
167+
client := &http.Client{}
168+
req, err := http.NewRequest("GET", projUrl, nil)
169+
if err != nil {
170+
return
171+
}
172+
apikey := os.Getenv("APPVEYOR_API_KEY")
173+
//api key isn't necessary for read-only queries on public projects
174+
//if len(apikey) < 1 {
175+
// fmt.Printf("Env var APPVEYOR_API_KEY is not set.")
176+
//}
177+
req.Header.Add(headerKey, fmt.Sprintf(headerVal,apikey))
178+
resp, err := client.Do(req)
179+
if err != nil {
180+
return
181+
}
182+
183+
build, job := decode(resp.Body)
184+
fmt.Printf("build #%d, jobId %s\n", build, job)
185+
resp, err = http.Get(fmt.Sprintf(logUrl, job))
186+
if err != nil {
187+
return
188+
}
189+
logName := fmt.Sprintf("appveyor-%d.log", build)
190+
fi, err := os.Create(logName)
191+
if err != nil {
192+
return
193+
}
194+
_, err = io.Copy(fi, resp.Body)
195+
if err != nil {
196+
return
197+
}
198+
log, err = os.Open(logName)
199+
if err != nil {
200+
log = nil
201+
}
202+
return
203+
}
204+
205+
func decode(r io.Reader) (num int, job string) {
206+
dec := json.NewDecoder(r)
207+
var av AppVeyorBuild
208+
err := dec.Decode(&av)
209+
if err != io.EOF && err != nil {
210+
fmt.Printf("err %s\n", err)
211+
return
212+
}
213+
if len(av.Build.Jobs) != 1 {
214+
return
215+
}
216+
num = av.Build.BuildNumber
217+
job = av.Build.Jobs[0].JobID
218+
return
219+
}
220+
136221
// kate: indent-width 8; space-indent off; replace-tabs off; replace-tabs-save off; replace-trailing-space-save on; remove-trailing-space on; tab-intent on; tab-width 8; show-tabs off;

0 commit comments

Comments
 (0)