Skip to content

Instantly share code, notes, and snippets.

@thinca
Created October 27, 2016 01:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thinca/ee3707b01a1aee1403dd511ec69d9aba to your computer and use it in GitHub Desktop.
Save thinca/ee3707b01a1aee1403dd511ec69d9aba to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"net/http"
"os"
"runtime"
"strconv"
"strings"
"golang.org/x/oauth2"
"github.com/google/go-github/github"
"github.com/haya14busa/errorformat"
"github.com/haya14busa/reviewdog"
)
type githubPR struct {
owner string
repo string
pr int
sha string
}
const usageMessage = `
run-your-lint | curl -X POST \
-F "owner=vim-jp" \
-F "repos=vital.vim" \
-F "pr_number=1" \
-F "sha=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-F "result=@-" \
-F "efm=%f:%l:%c:%m" \
review.example.com
`
func main() {
http.HandleFunc("/", mainHandler)
bind := fmt.Sprintf("%s:%s", os.Getenv("OPENSHIFT_GO_IP"), os.Getenv("OPENSHIFT_GO_PORT"))
fmt.Printf("listening on %s...", bind)
err := http.ListenAndServe(bind, nil)
if err != nil {
panic(err)
}
}
func mainHandler(res http.ResponseWriter, req *http.Request) {
switch req.Method {
case "GET":
fmt.Fprintf(res, "hello, world from %s", runtime.Version())
case "POST":
err := req.ParseMultipartForm(1024 * 1024)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(res, "Invalid form value %v", err)
return
}
fmt.Println(res, "MultipartForm: %+v\n", req.MultipartForm)
value := req.MultipartForm.Value
efms, ok := value["efm"]
if !ok {
res.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(res, "Requires efm parameter")
return
}
p, err := efmParser(efms)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(res, "Invalid efm: %v", efms)
return
}
gparam, err := getParameters(value)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(res, "Invalid parameter: %v", err)
return
}
ok = verifyParam(gparam)
if !ok {
res.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(res, "Not allowed: %v", gparam)
return
}
gs, err := githubService(gparam)
if err != nil {
res.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(res, "Invalid parameter: %v", gparam)
return
}
result, ok := req.MultipartForm.File["result"]
if !ok {
res.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(res, "Requires result parameter")
return
}
file, err := result[0].Open()
if err != nil {
res.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(res, "Fails on open result: %v", err)
return
}
defer file.Close()
app := reviewdog.NewReviewdog("", p, gs, gs)
if err := app.Run(file); err != nil {
res.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(res, "Error with run: %v", err)
return
}
for _, c := range gs.ListPostComments() {
fmt.Fprintln(res, strings.Join(c.Lines, "\n"))
}
gs.Flash()
}
}
func efmParser(efms []string) (reviewdog.Parser, error) {
efm, err := errorformat.NewErrorformat(efms)
if err != nil {
return nil, err
}
return reviewdog.NewErrorformatParser(efm), nil
}
func getParameters(value map[string][]string) (*githubPR, error) {
prs, ok := value["pr_number"]
if !ok {
return nil, fmt.Errorf("Requires pr_number parameter")
}
pr, err := strconv.Atoi(prs[0])
if err != nil {
return nil, fmt.Errorf("unexpected value (pr_number): %v", prs)
}
owner, ok := value["owner"]
if !ok {
return nil, fmt.Errorf("Requires pr_number parameter")
}
repo, ok := value["repos"]
if !ok {
return nil, fmt.Errorf("Requires repos parameter")
}
sha, ok := value["sha"]
if !ok {
return nil, fmt.Errorf("Requires sha parameter")
}
g := &githubPR{
owner: owner[0],
repo: repo[0],
pr: pr,
sha: sha[0],
}
return g, nil
}
func verifyParam(g *githubPR) bool {
// return g.owner == "vim-jp"
return true
}
func githubService(g *githubPR) (githubservice *reviewdog.GitHubPullRequest, err error) {
token, err := nonEmptyEnv("REVIEWDOG_GITHUB_API_TOKEN")
if err != nil {
return nil, err
}
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
tc := oauth2.NewClient(oauth2.NoContext, ts)
client := github.NewClient(tc)
githubservice = reviewdog.NewGitHubPullReqest(client, g.owner, g.repo, g.pr, g.sha)
return githubservice, nil
}
func nonEmptyEnv(env string) (string, error) {
v := os.Getenv(env)
if v == "" {
return "", fmt.Errorf("environment variable $%v is not set", env)
}
return v, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment