Support for adding labels to github issues (#16)
This commit is contained in:
parent
530fcd69db
commit
bc292e4399
3 changed files with 53 additions and 10 deletions
|
@ -49,6 +49,11 @@ logs.)
|
||||||
|
|
||||||
* `version`: Application version. Included in the `details.log.gz` file.
|
* `version`: Application version. Included in the `details.log.gz` file.
|
||||||
|
|
||||||
|
* `label`: Label to attach to the github issue, and include in the details file.
|
||||||
|
|
||||||
|
If using the JSON upload encoding, this should be encoded as a `labels` field,
|
||||||
|
whose value should be a list of strings.
|
||||||
|
|
||||||
* `log`: a log file, with lines separated by newline characters. Multiple log
|
* `log`: a log file, with lines separated by newline characters. Multiple log
|
||||||
files can be included by including several `log` parts.
|
files can be included by including several `log` parts.
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ type payload struct {
|
||||||
UserAgent string `json:"user_agent"`
|
UserAgent string `json:"user_agent"`
|
||||||
Logs []logEntry `json:"logs"`
|
Logs []logEntry `json:"logs"`
|
||||||
Data map[string]string `json:"data"`
|
Data map[string]string `json:"data"`
|
||||||
|
Labels []string `json:"labels"`
|
||||||
Files []string
|
Files []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,6 +258,22 @@ func parseFormPart(part *multipart.Part, p *payload, reportDir string) error {
|
||||||
}
|
}
|
||||||
data := string(b)
|
data := string(b)
|
||||||
|
|
||||||
|
if field == "log" || field == "compressed-log" {
|
||||||
|
// todo: we could save the log directly rather than pointlessly
|
||||||
|
// unzipping and re-zipping.
|
||||||
|
p.Logs = append(p.Logs, logEntry{
|
||||||
|
ID: part.FileName(),
|
||||||
|
Lines: data,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
formPartToPayload(field, data, p)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// formPartToPayload updates the relevant part of *p from a name/value pair
|
||||||
|
// read from the form data.
|
||||||
|
func formPartToPayload(field, data string, p *payload) {
|
||||||
if field == "text" {
|
if field == "text" {
|
||||||
p.Text = data
|
p.Text = data
|
||||||
} else if field == "app" {
|
} else if field == "app" {
|
||||||
|
@ -265,17 +282,11 @@ func parseFormPart(part *multipart.Part, p *payload, reportDir string) error {
|
||||||
p.Version = data
|
p.Version = data
|
||||||
} else if field == "user_agent" {
|
} else if field == "user_agent" {
|
||||||
p.UserAgent = data
|
p.UserAgent = data
|
||||||
} else if field == "log" || field == "compressed-log" {
|
} else if field == "label" {
|
||||||
// todo: we could save the log directly rather than pointlessly
|
p.Labels = append(p.Labels, data)
|
||||||
// unzipping and re-zipping.
|
|
||||||
p.Logs = append(p.Logs, logEntry{
|
|
||||||
ID: part.FileName(),
|
|
||||||
Lines: data,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
p.Data[field] = data
|
p.Data[field] = data
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we use a quite restrictive regexp for the filenames; in particular:
|
// we use a quite restrictive regexp for the filenames; in particular:
|
||||||
|
@ -326,6 +337,7 @@ func (s *submitServer) saveReport(ctx context.Context, p payload, reportDir, lis
|
||||||
"%s\n\nNumber of logs: %d\nApplication: %s\nVersion: %s\nUser-Agent: %s\n",
|
"%s\n\nNumber of logs: %d\nApplication: %s\nVersion: %s\nUser-Agent: %s\n",
|
||||||
p.Text, len(p.Logs), p.AppName, p.Version, p.UserAgent,
|
p.Text, len(p.Logs), p.AppName, p.Version, p.UserAgent,
|
||||||
)
|
)
|
||||||
|
fmt.Fprintf(&summaryBuf, "Labels: %s\n", strings.Join(p.Labels, ", "))
|
||||||
for k, v := range p.Data {
|
for k, v := range p.Data {
|
||||||
fmt.Fprintf(&summaryBuf, "%s: %s\n", k, v)
|
fmt.Fprintf(&summaryBuf, "%s: %s\n", k, v)
|
||||||
}
|
}
|
||||||
|
@ -407,6 +419,7 @@ func buildGithubIssueRequest(p payload, listingURL string) github.IssueRequest {
|
||||||
return github.IssueRequest{
|
return github.IssueRequest{
|
||||||
Title: &title,
|
Title: &title,
|
||||||
Body: &body,
|
Body: &body,
|
||||||
|
Labels: &p.Labels,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,14 @@ Content-Disposition: form-data; name="user_agent"
|
||||||
|
|
||||||
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
|
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
|
||||||
------WebKitFormBoundarySsdgl8Nq9voFyhdO
|
------WebKitFormBoundarySsdgl8Nq9voFyhdO
|
||||||
|
Content-Disposition: form-data; name="label"
|
||||||
|
|
||||||
|
label1
|
||||||
|
------WebKitFormBoundarySsdgl8Nq9voFyhdO
|
||||||
|
Content-Disposition: form-data; name="label"
|
||||||
|
|
||||||
|
label2
|
||||||
|
------WebKitFormBoundarySsdgl8Nq9voFyhdO
|
||||||
Content-Disposition: form-data; name="test-field"
|
Content-Disposition: form-data; name="test-field"
|
||||||
|
|
||||||
Test data
|
Test data
|
||||||
|
@ -189,6 +197,10 @@ func checkParsedMultipartUpload(t *testing.T, p *payload) {
|
||||||
if len(p.Data) != 1 {
|
if len(p.Data) != 1 {
|
||||||
t.Errorf("Data length: got %d, want 1", len(p.Data))
|
t.Errorf("Data length: got %d, want 1", len(p.Data))
|
||||||
}
|
}
|
||||||
|
wantedLabels := []string{"label1", "label2"}
|
||||||
|
if !stringSlicesEqual(p.Labels, wantedLabels) {
|
||||||
|
t.Errorf("Labels: got %v, want %v", p.Labels, wantedLabels)
|
||||||
|
}
|
||||||
wanted = "Test data"
|
wanted = "Test data"
|
||||||
if p.Data["test-field"] != wanted {
|
if p.Data["test-field"] != wanted {
|
||||||
t.Errorf("test-field: got %s, want %s", p.Data["test-field"], wanted)
|
t.Errorf("test-field: got %s, want %s", p.Data["test-field"], wanted)
|
||||||
|
@ -215,6 +227,19 @@ func checkParsedMultipartUpload(t *testing.T, p *payload) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stringSlicesEqual(got, want []string) bool {
|
||||||
|
if len(got) != len(want) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range got {
|
||||||
|
if got[i] != want[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func TestEmptyFilename(t *testing.T) {
|
func TestEmptyFilename(t *testing.T) {
|
||||||
body := `------WebKitFormBoundarySsdgl8Nq9voFyhdO
|
body := `------WebKitFormBoundarySsdgl8Nq9voFyhdO
|
||||||
Content-Disposition: form-data; name="file"
|
Content-Disposition: form-data; name="file"
|
||||||
|
|
Reference in a new issue