Merge pull request #28 from Awesome-Technologies/slack
Add support for Slack notifications
This commit is contained in:
commit
de2fd6afb9
4 changed files with 116 additions and 26 deletions
12
main.go
12
main.go
|
@ -49,6 +49,8 @@ type config struct {
|
|||
GithubToken string `yaml:"github_token"`
|
||||
|
||||
GithubProjectMappings map[string]string `yaml:"github_project_mappings"`
|
||||
|
||||
SlackWebhookURL string `yaml:"slack_webhook_url"`
|
||||
}
|
||||
|
||||
func basicAuth(handler http.Handler, username, password, realm string) http.Handler {
|
||||
|
@ -89,6 +91,14 @@ func main() {
|
|||
ghClient = github.NewClient(tc)
|
||||
}
|
||||
|
||||
var slack *slackClient
|
||||
|
||||
if cfg.SlackWebhookURL == "" {
|
||||
fmt.Println("No slack_webhook_url configured. Reporting bugs to slack is disabled.")
|
||||
} else {
|
||||
slack = NewSlackClient(cfg.SlackWebhookURL)
|
||||
}
|
||||
|
||||
apiPrefix := cfg.APIPrefix
|
||||
if apiPrefix == "" {
|
||||
_, port, err := net.SplitHostPort(*bindAddr)
|
||||
|
@ -102,7 +112,7 @@ func main() {
|
|||
}
|
||||
log.Printf("Using %s/listing as public URI", apiPrefix)
|
||||
|
||||
http.Handle("/api/submit", &submitServer{ghClient, apiPrefix, cfg.GithubProjectMappings})
|
||||
http.Handle("/api/submit", &submitServer{ghClient, apiPrefix, cfg.GithubProjectMappings, slack})
|
||||
|
||||
// Make sure bugs directory exists
|
||||
_ = os.Mkdir("bugs", os.ModePerm)
|
||||
|
|
|
@ -16,3 +16,7 @@ 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
|
||||
|
||||
# a Slack personal webhook URL (https://api.slack.com/incoming-webhooks), which
|
||||
# will be used to post a notification on Slack for each report.
|
||||
slack_webhook_url: https://hooks.slack.com/services/TTTTTTT/XXXXXXXXXX/YYYYYYYYYYY
|
||||
|
|
48
slack.go
Normal file
48
slack.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type slackClient struct {
|
||||
webHook string
|
||||
name string
|
||||
face string
|
||||
}
|
||||
|
||||
func NewSlackClient(webHook string) *slackClient {
|
||||
return &slackClient{
|
||||
webHook: webHook,
|
||||
name: "Notifier",
|
||||
face: "robot_face"}
|
||||
}
|
||||
|
||||
func (slack *slackClient) Name(name string) {
|
||||
slack.name = name
|
||||
}
|
||||
|
||||
func (slack *slackClient) Face(face string) {
|
||||
slack.face = face
|
||||
}
|
||||
|
||||
func (slack slackClient) Notify(text string) error {
|
||||
json := buildRequest(text, slack)
|
||||
|
||||
req, err := http.NewRequest("POST", slack.webHook, strings.NewReader(json))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Can't connect to host %s: %s", slack.webHook, err.Error())
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
client := http.Client{}
|
||||
_, err = client.Do(req)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func buildRequest(text string, slack slackClient) string {
|
||||
return fmt.Sprintf(`{"text":"%s", "username": "%s", "icon_emoji": ":%s:"}`, text, slack.name, slack.face)
|
||||
}
|
78
submit.go
78
submit.go
|
@ -51,6 +51,8 @@ type submitServer struct {
|
|||
|
||||
// mappings from application to github owner/project
|
||||
githubProjectMappings map[string]string
|
||||
|
||||
slack *slackClient
|
||||
}
|
||||
|
||||
// the type of payload which can be uploaded as JSON to the submit endpoint
|
||||
|
@ -460,38 +462,64 @@ func (s *submitServer) saveReport(ctx context.Context, p parsedPayload, reportDi
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if s.ghClient == nil {
|
||||
// we're done here
|
||||
log.Println("GH issue submission disabled")
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// submit a github issue
|
||||
ghProj := s.githubProjectMappings[p.AppName]
|
||||
if ghProj == "" {
|
||||
log.Println("Not creating GH issue for unknown app", p.AppName)
|
||||
return &resp, 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]
|
||||
|
||||
issueReq := buildGithubIssueRequest(p, listingURL)
|
||||
|
||||
issue, _, err := s.ghClient.Issues.Create(ctx, owner, repo, &issueReq)
|
||||
if err != nil {
|
||||
if err := s.submitGithubIssue(ctx, p, listingURL, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Println("Created issue:", *issue.HTMLURL)
|
||||
|
||||
resp.ReportURL = *issue.HTMLURL
|
||||
if err := s.submitSlackNotification(p, listingURL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func (s *submitServer) submitGithubIssue(ctx context.Context, p parsedPayload, listingURL string, resp *submitResponse) error {
|
||||
if s.ghClient == nil {
|
||||
log.Println("GH issue submission disabled")
|
||||
} else {
|
||||
// submit a github issue
|
||||
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]
|
||||
|
||||
issueReq := buildGithubIssueRequest(p, listingURL)
|
||||
|
||||
issue, _, err := s.ghClient.Issues.Create(ctx, owner, repo, &issueReq)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("Created issue:", *issue.HTMLURL)
|
||||
|
||||
resp.ReportURL = *issue.HTMLURL
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *submitServer) submitSlackNotification(p parsedPayload, listingURL string) error {
|
||||
if s.slack == nil {
|
||||
log.Println("Slack notifications disabled")
|
||||
} else {
|
||||
slackBuf := fmt.Sprintf(
|
||||
"%s\nApplication: %s\nReport: %s",
|
||||
p.UserText, p.AppName, listingURL,
|
||||
)
|
||||
|
||||
err := s.slack.Notify(slackBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildGithubIssueRequest(p parsedPayload, listingURL string) github.IssueRequest {
|
||||
// set the title to the first (non-empty) line of the user's report, if any
|
||||
var title string
|
||||
|
|
Reference in a new issue