Implement endpoints /badge/commit/{commit} and

/badge/{project_name}/{project_tag}, and show unknown coverage when
database record is missing, and formalize all commit messages in
/upload/go to json
pull/1/head
ALI Hamza 2019-08-13 16:23:23 +07:00
parent 99695a4c4d
commit 26d3508dc0
No known key found for this signature in database
GPG Key ID: 7C608266BF384ADC
6 changed files with 114 additions and 71 deletions

@ -1,57 +0,0 @@
package main
import (
"fmt"
"github.com/gorilla/mux"
"net/http"
"text/template"
)
var baseTemplate *template.Template
func init() {
baseTemplate = template.New("svgTemplate")
baseTemplate, _ = baseTemplate.Parse(svgTemplate)
}
func BadgeFromCommit(w http.ResponseWriter, r *http.Request) {
fmt.Println(mux.Vars(r))
commitID := mux.Vars(r)["commit"]
result, _ := db.Query("SELECT percentage FROM badge WHERE commit_hash=?", commitID)
defer result.Close()
w.Header().Set("Content-Type", "image/svg+xml")
if !result.Next() {
http.Error(w, "Request commit hash has no corresponding badge", 400)
//TODO send unknown svg instead
return
}
var percentage float64
result.Scan(&percentage)
fillColour := percentageToRGB(percentage)
template.New("svgConv")
pill := CoveragePill{
toOneDecimal(percentage * 100),
baseColour,
fillColour,
}
baseTemplate.Execute(w, pill)
}
func BadgeFromProject(w http.ResponseWriter, r *http.Request) {
projectName := mux.Vars(r)["project"]
tagName := mux.Vars(r)["tag"]
result, _ := db.Query("SELECT commit_hash FROM alias WHERE project_name=? AND project_tag=?", projectName, tagName)
defer result.Close()
var commit_hash string
result.Scan(&commit_hash)
fmt.Println(commit_hash)
mux.Vars(r)["commit"] = commit_hash
BadgeFromCommit(w, r)
}

@ -0,0 +1,74 @@
package main
import (
"bytes"
"fmt"
"net/http"
"text/template"
"github.com/gorilla/mux"
)
var baseTemplate *template.Template
func init() {
baseTemplate = template.New("svgTemplate")
baseTemplate, _ = baseTemplate.Parse(svgTemplate)
}
func badgeFromCommit(w http.ResponseWriter, r *http.Request) {
commitID := mux.Vars(r)["commit"]
result := svgFromHash(commitID)
w.Header().Set("Content-Type", "image/svg+xml")
fmt.Fprint(w, result)
}
func badgeFromProject(w http.ResponseWriter, r *http.Request) {
projectName := mux.Vars(r)["project"]
tagName := mux.Vars(r)["tag"]
commitRow, err := db.Query("SELECT commit_hash FROM alias WHERE project_name=? AND project_tag=?", projectName, tagName)
if err != nil {
panic(err)
}
if !commitRow.Next() {
fmt.Fprint(w, unknownCoveragePill())
return
}
var commitHash string
commitRow.Scan(&commitHash)
commitRow.Close()
result := svgFromHash(commitHash)
w.Header().Set("Content-Type", "image/svg+xml")
fmt.Fprint(w, result)
}
func svgFromHash(commit string) string {
result, err := db.Query("SELECT percentage FROM badge WHERE commit_hash=?", commit)
defer result.Close()
if err != nil {
panic(err)
}
if !result.Next() {
return unknownCoveragePill()
}
var percentage float64
result.Scan(&percentage)
fillColour := percentageToRGB(percentage)
pill := CoveragePill{
toOneDecimal(percentage*100) + "%",
baseColour,
fillColour,
}
buf := &bytes.Buffer{}
baseTemplate.Execute(buf, pill)
return buf.String()
}

Binary file not shown.

@ -2,17 +2,18 @@ package main
import ( import (
"fmt" "fmt"
"github.com/gorilla/mux"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"github.com/gorilla/mux"
) )
func main() { func main() {
r := mux.NewRouter() r := mux.NewRouter()
r.HandleFunc("/upload/go", uploadGo) r.HandleFunc("/upload/go", uploadGo)
r.HandleFunc("/badge/commit/{commit}.svg", BadgeFromCommit) r.HandleFunc("/badge/commit/{commit}.svg", badgeFromCommit)
r.HandleFunc("/badge/{project}/{tag}.svg", BadgeFromProject) r.HandleFunc("/badge/{project}/{tag}.svg", badgeFromProject)
_ = http.ListenAndServe(":8080", r) _ = http.ListenAndServe(":8080", r)
} }

@ -1,6 +1,7 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"math" "math"
"strconv" "strconv"
@ -22,8 +23,8 @@ const svgTemplate string = `<?xml version="1.0" encoding="UTF-8"?>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"> <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="34" y="14" fill="#010101" fill-opacity="0.5">coverage</text> <text x="34" y="14" fill="#010101" fill-opacity="0.5">coverage</text>
<text x="34" y="13">coverage</text> <text x="34" y="13">coverage</text>
<text x="87" y="15" fill="#010101" fill-opacity=".5">{{.Percentage}}%</text> <text x="87" y="15" fill="#010101" fill-opacity=".5">{{.Percentage}}</text>
<text x="87" y="14">{{.Percentage}}%</text> <text x="87" y="14">{{.Percentage}}</text>
</g> </g>
</svg>` </svg>`
@ -34,12 +35,25 @@ const (
blue = 55 blue = 55
) )
//Pill used for template
type CoveragePill struct { type CoveragePill struct {
Percentage string Percentage string
BaseColour string BaseColour string
FillColour string FillColour string
} }
func unknownCoveragePill() string {
pill := CoveragePill{
"?",
baseColour,
baseColour, // Using the base colour for fill colour because unknown
}
buf := &bytes.Buffer{}
baseTemplate.Execute(buf, pill)
return buf.String()
}
func percentageToRGB(percentage float64) string { func percentageToRGB(percentage float64) string {
red := modifier + clamp(2-2*math.Pow(percentage, 2), 0, 1)*(1-modifier) red := modifier + clamp(2-2*math.Pow(percentage, 2), 0, 1)*(1-modifier)
green := modifier + clamp(2*math.Pow(percentage, 2), 0, 1)*(1-modifier) green := modifier + clamp(2*math.Pow(percentage, 2), 0, 1)*(1-modifier)

@ -1,6 +1,7 @@
package main package main
import ( import (
"database/sql"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -10,36 +11,46 @@ func uploadGo(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" { if r.Method != "POST" {
return return
} }
w.Header().Set("Content-Type", "application/json")
err := r.ParseForm() err := r.ParseForm()
if err != nil { if err != nil {
http.Error(w, "Request parameters not parsed", 500) http.Error(w, `{"success": false, "message": "Request parameters not parsed"}`, 500)
return return
} }
err = r.ParseMultipartForm(5 << 20) err = r.ParseMultipartForm(5 << 20)
if err != nil { if err != nil {
http.Error(w, "Request parameters not parsed", 500) http.Error(w, `{"success": false, "message": "Request parameters too large"}`, 500)
return return
} }
project := r.Form.Get("project") name := r.Form.Get("project-name")
tag := r.Form.Get("tag") tag := r.Form.Get("tag")
id := r.Form.Get("id") id := r.Form.Get("id")
if project == "" || tag == "" || id == "" { if name == "" || tag == "" || id == "" {
http.Error(w, "Request parameters [secret, project, tag, id] not found", 400) http.Error(w, `{"success": false, "message": "Request parameters [secret, name, tag, id] not found"}`, 400)
return return
} }
file, _, err := r.FormFile("file") file, _, err := r.FormFile("file")
if err != nil { if err != nil {
http.Error(w, "Request parameter file not found", 400) http.Error(w, `{"success": false, "message": "Request parameter file not found"}`, 400)
return return
} }
b, _ := ioutil.ReadAll(file) b, _ := ioutil.ReadAll(file)
coverage := parseCoverage(string(b)) coverage := parseCoverage(string(b))
db.Exec("INSERT INTO badge (commit_hash, percentage) VALUES (?, ?)", id, coverage) db.Exec("INSERT INTO badge (commit_hash, percentage) VALUES (?, ?)", id, coverage)
db.Exec("INSERT INTO alias (commit_hash, project_name, project_tag) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE commit=?", id, project, tag, id)
w.Header().Set("Content-Type", "application/json") _, err = db.Query("SELECT commit_hash FROM alias WHERE project_name=? AND project_tag=?", name, tag)
fmt.Fprintf(w, `{"success": "true", "coverage": `+toOneDecimal(coverage*100)+`}`)
if err == nil {
db.Exec("UPDATE ALIAS SET commit_hash=? WHERE project_name=? AND project_tag=?", id, name, tag)
} else if err == sql.ErrNoRows {
db.Exec("INSERT INTO alias (commit_hash, project_name, project_tag VALUES (?, ?, ?)", id, name, tag)
} else {
panic(err)
}
fmt.Fprintf(w, `{"success": "true", "coverage": %s%%}`, toOneDecimal(coverage*100))
} }