diff --git a/Badge.go b/Badge.go new file mode 100644 index 0000000..d834aee --- /dev/null +++ b/Badge.go @@ -0,0 +1,57 @@ +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) +} diff --git a/connection.go b/connection.go new file mode 100644 index 0000000..fc2c978 --- /dev/null +++ b/connection.go @@ -0,0 +1,22 @@ +package main + +import ( + "database/sql" + _ "github.com/mattn/go-sqlite3" +) + +var db *sql.DB +var alreadyUsingMemory bool + +func init() { + openDatabase("./database.sqlite") +} + +func openDatabase(fileLocation string) { + db, _ = sql.Open("sqlite3", fileLocation) + db.SetMaxOpenConns(1) + + // Initializes the tables + db.Exec(`CREATE TABLE IF NOT EXISTS badge (commit_hash VARCHAR(32) NOT NULL UNIQUE PRIMARY KEY, percentage FLOAT NOT NULL)`) + db.Exec(`CREATE TABLE IF NOT EXISTS alias (commit_hash VARCHAR(32) NOT NULL UNIQUE PRIMARY KEY, project_name TEXT NOT NULL, project_tag TEXT NOT NULL)`) +} diff --git a/database.sqlite b/database.sqlite new file mode 100644 index 0000000..d427168 Binary files /dev/null and b/database.sqlite differ diff --git a/main.go b/main.go index 147bae0..87e2344 100644 --- a/main.go +++ b/main.go @@ -1,69 +1,36 @@ package main import ( - "bytes" "fmt" "github.com/gorilla/mux" - "io/ioutil" "net/http" -) - -const ( - baseColour = "#555" - modifier float64 = 0.2 - maxValue = 220 - blue = 55 + "strconv" + "strings" ) func main() { - //_ := template.New("svgConv") - - //percentage := 0.999 - //fill := percentageToRGB(percentage) - - //_ := CoveragePill{ - // fmt.Sprintf("%.1f", toFixed(percentage, 3)*100), - // baseColour, - // fill, - //} - r := mux.NewRouter() - r.HandleFunc("/upload/go", upload) + r.HandleFunc("/upload/go", uploadGo) + r.HandleFunc("/badge/commit/{commit}.svg", BadgeFromCommit) + r.HandleFunc("/badge/{project}/{tag}.svg", BadgeFromProject) _ = http.ListenAndServe(":8080", r) } -func upload(w http.ResponseWriter, r *http.Request) { - if r.Method != "POST" { - return - } - - err := r.ParseForm() - if err != nil { - http.Error(w, "Request parameters not parsed", 500) - return - } - err = r.ParseMultipartForm(5 << 20) - if err != nil { - http.Error(w, "Request parameters not parsed", 500) - return - } - - form := r.Form - - project := form.Get("project") - tag := form.Get("tag") - id := form.Get("id") - file, _, err := r.FormFile("file") - b, _ := ioutil.ReadAll(file) - n := bytes.Index(b, []byte{0}) - content := string(b[n]) +func parseCoverage(content string) float64 { + var totalStatements = 0 + var totalRun = 0 - fmt.Print(content) + lines := strings.Split(content, "\n") + for _, line := range lines[1 : len(lines)-1] { // Skip first line (which is not relevant) + sl := strings.Split(line, " ") + statements, _ := strconv.Atoi(sl[len(sl)-2]) + runCount, _ := strconv.Atoi(sl[len(sl)-1]) - if project == "" || tag == "" || id == "" { - http.Error(w, "Request parameters [secret, project, tag, id] not found", 400) - return + totalStatements += statements + if runCount != 0 { + totalRun += statements + } } - - _, _ = fmt.Fprintf(w, "project: '%s'\ntag: '%s'\nid: '%s'\n", project, tag, id) + fmt.Printf("DEBUG :: TotalStatements: %d, TotalRunCount: %d\n", totalStatements, totalRun) + return float64(totalRun) / float64(totalStatements) } diff --git a/pill.go b/pill.go index e1cf55c..027eb6e 100644 --- a/pill.go +++ b/pill.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "math" "strconv" ) @@ -26,6 +27,13 @@ const svgTemplate string = ` ` +const ( + baseColour = "#555" + modifier float64 = 0.2 + maxValue = 220 + blue = 55 +) + type CoveragePill struct { Percentage string BaseColour string @@ -57,7 +65,7 @@ func round(num float64) int { return int(num + math.Copysign(0.5, num)) } -func toFixed(num float64, precision int) float64 { - output := math.Pow(10, float64(precision)) - return float64(round(num*output)) / output +func toOneDecimal(num float64) string { + output := math.Pow(10, float64(5)) + return fmt.Sprintf("%.1f", float64(round(num*output))/output) } diff --git a/upload.go b/upload.go new file mode 100644 index 0000000..b20aa4f --- /dev/null +++ b/upload.go @@ -0,0 +1,45 @@ +package main + +import ( + "fmt" + "io/ioutil" + "net/http" +) + +func uploadGo(w http.ResponseWriter, r *http.Request) { + if r.Method != "POST" { + return + } + + err := r.ParseForm() + if err != nil { + http.Error(w, "Request parameters not parsed", 500) + return + } + err = r.ParseMultipartForm(5 << 20) + if err != nil { + http.Error(w, "Request parameters not parsed", 500) + return + } + + project := r.Form.Get("project") + tag := r.Form.Get("tag") + id := r.Form.Get("id") + + if project == "" || tag == "" || id == "" { + http.Error(w, "Request parameters [secret, project, tag, id] not found", 400) + return + } + file, _, err := r.FormFile("file") + if err != nil { + http.Error(w, "Request parameter file not found", 400) + return + } + b, _ := ioutil.ReadAll(file) + coverage := parseCoverage(string(b)) + + 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") + fmt.Fprintf(w, `{"success": "true", "coverage": `+toOneDecimal(coverage*100)+`}`) +}