Make github issue a bit more useful (#7)

* include the text from the report and other useful info
* include a link to the report details
* Pick github repo based on submitted app name
This commit is contained in:
Richard van der Hoff 2017-04-12 15:06:40 +01:00 committed by GitHub
parent 112158fd47
commit 3b5b19cc90
4 changed files with 81 additions and 6 deletions

View file

@ -40,7 +40,9 @@ The body of the request should be a JSON object with the following fields:
* `user_agent`: Application user-agent. Included in the `details.log.gz` file.
* `app`: Identifier for the application (eg 'riot-web').
* `app`: Identifier for the application (eg 'riot-web'). Should correspond to a
mapping configured in the configuration file for github issue reporting to
work.
* `version`: Application version. Included in the `details.log.gz` file.

View file

@ -4,7 +4,15 @@
listings_auth_user: alice
listings_auth_pass: secret
# the external URL at which /api is accessible; it is used to add a link to the
# report to the GitHub issue. If unspecified, based on the listen address.
# api_prefix: https://riot.im/bugreports
# a GitHub personal access token (https://github.com/settings/tokens), which
# will be used to create a GitHub issue for each report. It requires
# `public_repo` scope. If omitted, no issues will be created.
github_token: secrettoken
# mappings from app name (as submitted in the API) to github repo for issue reporting.
github_project_mappings:
my-app: octocat/HelloWorld

View file

@ -25,8 +25,11 @@ import (
"golang.org/x/oauth2"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"strings"
"time"
yaml "gopkg.in/yaml.v2"
)
@ -39,8 +42,13 @@ type config struct {
BugsUser string `yaml:"listings_auth_user"`
BugsPass string `yaml:"listings_auth_pass"`
// External URI to /api
APIPrefix string `yaml:"api_prefix"`
// A GitHub personal access token, to create a GitHub issue for each report.
GithubToken string `yaml:"github_token"`
GithubProjectMappings map[string]string `yaml:"github_project_mappings"`
}
func basicAuth(handler http.Handler, username, password, realm string) http.Handler {
@ -77,10 +85,24 @@ func main() {
&oauth2.Token{AccessToken: cfg.GithubToken},
)
tc := oauth2.NewClient(ctx, ts)
tc.Timeout = time.Duration(5) * time.Minute
ghClient = github.NewClient(tc)
}
http.Handle("/api/submit", &submitServer{ghClient})
apiPrefix := cfg.APIPrefix
if apiPrefix == "" {
_, port, err := net.SplitHostPort(*bindAddr)
if err != nil {
log.Fatal(err)
}
apiPrefix = fmt.Sprintf("http://localhost:%s/api", port)
} else {
// remove trailing /
apiPrefix = strings.TrimRight(apiPrefix, "/")
}
log.Printf("Using %s/listing as public URI", apiPrefix)
http.Handle("/api/submit", &submitServer{ghClient, apiPrefix, cfg.GithubProjectMappings})
// Make sure bugs directory exists
_ = os.Mkdir("bugs", os.ModePerm)

View file

@ -29,6 +29,7 @@ import (
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
@ -38,6 +39,12 @@ type submitServer struct {
// github client for reporting bugs. may be nil, in which case,
// reporting is disabled.
ghClient *github.Client
// External URI to /api
apiPrefix string
// mappings from application to github owner/project
githubProjectMappings map[string]string
}
type payload struct {
@ -95,12 +102,17 @@ func (s *submitServer) saveReport(ctx context.Context, p payload) error {
// "bugreport-20170115-112233-N.log.gz" => oldest log
t := time.Now().UTC()
prefix := t.Format("2006-01-02/150405")
listingURL := s.apiPrefix + "/listing/" + prefix
log.Println("Handling report submission; listing URI will be %s", listingURL)
userText := strings.TrimSpace(p.Text)
var summaryBuf bytes.Buffer
fmt.Fprintf(
&summaryBuf,
"%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,
userText, len(p.Logs), p.AppName, p.Version, p.UserAgent,
)
for k, v := range p.Data {
fmt.Fprintf(&summaryBuf, "%s: %s\n", k, v)
@ -117,15 +129,46 @@ func (s *submitServer) saveReport(ctx context.Context, p payload) error {
if s.ghClient == nil {
// we're done here
log.Println("GH issue submission disabled")
return nil
}
// submit a github issue
owner := "richvdh"
repo := "test"
title := "Automated bug report"
ghProj := s.githubProjectMappings[p.AppName]
if ghProj == "" {
log.Println("Not creating GH issue for unknown app", p.AppName)
return nil
}
splits := strings.SplitN(ghProj, "/", 2)
if len(splits) < 2 {
log.Println("Can't create GH issue for invalid repo", ghProj)
}
owner, repo := splits[0], splits[1]
var title string
if userText == "" {
title = "Untitled report"
} else {
// set the title to the first line of the user's report
if i := strings.IndexAny(userText, "\r\n"); i < 0 {
title = userText
} else {
title = userText[0:i]
}
}
body := fmt.Sprintf(
"User message:\n```\n%s\n```\nVersion: %s\n[Details](%s) / [Logs](%s)",
userText,
p.Version,
listingURL+"/details.log.gz",
listingURL,
)
issueReq := github.IssueRequest{
Title: &title,
Body: &body,
}
issue, _, err := s.ghClient.Issues.Create(ctx, owner, repo, &issueReq)