feat: add server side of things
commit
2783ec1d0b
@ -0,0 +1 @@
|
|||||||
|
coverage.db
|
@ -0,0 +1,10 @@
|
|||||||
|
FROM golang:1.16 AS build
|
||||||
|
WORKDIR /root/
|
||||||
|
COPY . .
|
||||||
|
RUN go build -o coverage .
|
||||||
|
|
||||||
|
FROM golang:1.16
|
||||||
|
WORKDIR /root/
|
||||||
|
COPY --from=build /root/coverage .
|
||||||
|
EXPOSE 8080
|
||||||
|
CMD ["./coverage"]
|
@ -0,0 +1,38 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
|
||||||
|
"gitea.teamortix.com/team-ortix/coverage/db"
|
||||||
|
"gitea.teamortix.com/team-ortix/coverage/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
port = os.Getenv("COVERAGE_PORT")
|
||||||
|
dbFile = os.Getenv("DB_FILE")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if port == "" {
|
||||||
|
port = "8080"
|
||||||
|
}
|
||||||
|
if dbFile == "" {
|
||||||
|
dbFile = "coverage.db"
|
||||||
|
}
|
||||||
|
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, os.Interrupt)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
db.OpenDatabase(dbFile)
|
||||||
|
server.StartServer(port)
|
||||||
|
}()
|
||||||
|
|
||||||
|
log.Printf("server starting. at http://0.0.0.0:%s", port)
|
||||||
|
|
||||||
|
<-c
|
||||||
|
fmt.Println("\nAborting...")
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
// Required to connect to database.
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var db *sql.DB
|
||||||
|
|
||||||
|
func OpenDatabase(fileLocation string) {
|
||||||
|
var err error
|
||||||
|
db, err = sql.Open("sqlite3", fileLocation)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("could not open database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initializes the table.
|
||||||
|
_, err = db.Exec(`CREATE TABLE IF NOT EXISTS badge (
|
||||||
|
namespace VARCHAR(64) NOT NULL,
|
||||||
|
project_name VARCHAR(64) NOT NULL,
|
||||||
|
coverage INTEGER NOT NULL,
|
||||||
|
html TEXT NOT NULL,
|
||||||
|
|
||||||
|
branch VARCHAR(64),
|
||||||
|
pull INTEGER
|
||||||
|
)`)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Could not create table: %v", err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrNoData = errors.New("no badge found with the provided data")
|
||||||
|
|
||||||
|
type CoverageData struct {
|
||||||
|
Namespace string
|
||||||
|
Project string
|
||||||
|
Coverage float64
|
||||||
|
HTML string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryByBranch returns CoverageData for the provided branch for the project.
|
||||||
|
// If there is no such data, it returns ErrNoData.
|
||||||
|
func QueryByBranch(namespace, project, branch string) (CoverageData, error) {
|
||||||
|
result, err := db.Query(`SELECT coverage,html FROM badge WHERE
|
||||||
|
namespace=? AND
|
||||||
|
project_name=? AND
|
||||||
|
branch=?`,
|
||||||
|
namespace, project, branch)
|
||||||
|
if err != nil {
|
||||||
|
return CoverageData{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseRows(result, namespace, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryByBranch returns CoverageData for the provided pull request of the project.
|
||||||
|
// If there is no such data, it returns ErrNoData.
|
||||||
|
func QueryByPull(namespace, project, pullStr string) (CoverageData, error) {
|
||||||
|
pull, err := strconv.Atoi(pullStr)
|
||||||
|
if err != nil {
|
||||||
|
return CoverageData{}, ErrNoData
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := db.Query(`SELECT coverage, html FROM badge WHERE
|
||||||
|
namespace=? AND
|
||||||
|
project_name=? AND
|
||||||
|
pull=?`,
|
||||||
|
namespace, project, pull)
|
||||||
|
if err != nil {
|
||||||
|
return CoverageData{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseRows(result, namespace, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRows(result *sql.Rows, namespace, project string) (CoverageData, error) {
|
||||||
|
if !result.Next() {
|
||||||
|
return CoverageData{}, ErrNoData
|
||||||
|
}
|
||||||
|
|
||||||
|
var coverage float64
|
||||||
|
var html string
|
||||||
|
err := result.Scan(&coverage, &html)
|
||||||
|
if err != nil {
|
||||||
|
return CoverageData{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = result.Close(); err != nil {
|
||||||
|
return CoverageData{}, ErrNoData
|
||||||
|
}
|
||||||
|
|
||||||
|
return CoverageData{
|
||||||
|
Namespace: namespace,
|
||||||
|
Project: project,
|
||||||
|
Coverage: coverage,
|
||||||
|
HTML: html,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UploadBranchData(namespace, project, branch, coverageStr, html string) error {
|
||||||
|
coverage, err := strconv.ParseFloat(coverageStr, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("coverage param must be valid float, instead got %s", coverageStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because we don't have have a primary key, we must do the upsert manually.
|
||||||
|
_, err = QueryByBranch(namespace, project, branch)
|
||||||
|
if err == ErrNoData {
|
||||||
|
_, err = db.Exec("INSERT INTO badge (namespace, project_name, branch, coverage, html) VALUES (?, ?, ?, ?, ?)",
|
||||||
|
namespace, project, branch, coverage, html)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not update database: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.Exec("UPDATE badge SET coverage=?, html=? WHERE namespace=? AND project_name=? AND branch=?",
|
||||||
|
coverage, html, namespace, project, branch)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not update database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UploadPullData(namespace, project, pullStr, coverageStr, html string) error {
|
||||||
|
pull, err := strconv.Atoi(pullStr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("pull param must be valid int, instead got %s", pullStr)
|
||||||
|
}
|
||||||
|
coverage, err := strconv.ParseFloat(coverageStr, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("coverage param must be valid float, instead got %s", coverageStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because we don't have have a primary key, we must do the upsert manually.
|
||||||
|
_, err = QueryByPull(namespace, project, pullStr)
|
||||||
|
if err == ErrNoData {
|
||||||
|
_, err = db.Exec("INSERT INTO badge (namespace, project_name, pull, coverage, html) VALUES (?, ?, ?, ?, ?)",
|
||||||
|
namespace, project, pull, coverage, html)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not update database: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.Exec("UPDATE badge SET coverage=?, html=? WHERE namespace=? AND project_name=? AND pull=?",
|
||||||
|
coverage, html, namespace, project, pull)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not update database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
module gitea.teamortix.com/team-ortix/coverage
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gorilla/mux v1.8.0
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.6
|
||||||
|
)
|
@ -0,0 +1,4 @@
|
|||||||
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
@ -0,0 +1 @@
|
|||||||
|
package pill
|
@ -0,0 +1,79 @@
|
|||||||
|
package pill
|
||||||
|
|
||||||
|
import (
|
||||||
|
// Used for embedding pill.
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed pill.svg
|
||||||
|
pill string
|
||||||
|
|
||||||
|
tmpl = template.New("svgTemplate")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
modifier = 0.2
|
||||||
|
max = 190
|
||||||
|
blue = 55
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pill is used to execute the pill.svg template.
|
||||||
|
// Width is dependent on whether the percentage is 2 digits or 3 digits.
|
||||||
|
type Pill struct {
|
||||||
|
Percentage string
|
||||||
|
Colour string
|
||||||
|
Width string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPill creates creates a Pill, automatically calculating the colour, width, and formatting the percentage.
|
||||||
|
// Note: %02.0f gives us a float with 0 decimals and 0 padding for 2 numbers less than 10.
|
||||||
|
func NewPill(percentDecimal float64) Pill {
|
||||||
|
square := math.Pow(percentDecimal, 2)
|
||||||
|
red := modifier + clamp(2-2*square, 0, 1)*(1-modifier)
|
||||||
|
green := modifier + clamp(2*square, 0, 1)*(1-modifier)
|
||||||
|
|
||||||
|
percentage := fmt.Sprintf("%.0f", percentDecimal*100)
|
||||||
|
colour := fmt.Sprintf("rgb(%.0f, %.0f, %d)", red*max, green*max, blue)
|
||||||
|
width := "250"
|
||||||
|
if len(percentage) == 1 {
|
||||||
|
percentage = " " + percentage
|
||||||
|
width = "220"
|
||||||
|
}
|
||||||
|
if len(percentage) == 3 {
|
||||||
|
width = "300"
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pill{
|
||||||
|
Percentage: percentage,
|
||||||
|
Colour: colour,
|
||||||
|
Width: width,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute runs the pill template with the data and writes the result to the writer given.
|
||||||
|
func (p Pill) Execute(w io.Writer) error {
|
||||||
|
var err error
|
||||||
|
tmpl, err = tmpl.Parse(pill)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tmpl.Execute(w, p)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func clamp(n, min, max float64) float64 {
|
||||||
|
switch {
|
||||||
|
case n > max:
|
||||||
|
return max
|
||||||
|
case n < min:
|
||||||
|
return min
|
||||||
|
default:
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96" height="20" role="img" aria-label="coverage: {{.Percentage}}%">
|
||||||
|
<title>coverage: {{.Percentage}}%</title>
|
||||||
|
<g shape-rendering="crispEdges">
|
||||||
|
<rect width="61" height="20" fill="#555"/>
|
||||||
|
<rect x="61" width="35" height="20" fill="{{.Colour}}"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
|
||||||
|
<text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text>
|
||||||
|
<text x="780" y="140" transform="scale(.1)" fill="#fff" textLength="{{.Width}}">{{.Percentage}}%</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 735 B |
@ -0,0 +1,116 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"gitea.teamortix.com/team-ortix/coverage/db"
|
||||||
|
"gitea.teamortix.com/team-ortix/coverage/pill"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
)
|
||||||
|
|
||||||
|
type endpointData struct {
|
||||||
|
thirdParam string
|
||||||
|
queryFunc func(string, string, string) (db.CoverageData, error)
|
||||||
|
handle func(db.CoverageData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d endpointData) run(w http.ResponseWriter, r *http.Request) {
|
||||||
|
params, ok := getAllParams(w, r, d.thirdParam)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := d.queryFunc(params[0], params[1], params[2])
|
||||||
|
if err == db.ErrNoData {
|
||||||
|
http.Error(w, "not found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("could not query from db: %v", err), http.StatusInternalServerError)
|
||||||
|
log.Printf("error occurred while querying data from db: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d.handle(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBranchReport(w http.ResponseWriter, r *http.Request) {
|
||||||
|
endpointData{
|
||||||
|
thirdParam: "branch",
|
||||||
|
queryFunc: db.QueryByBranch,
|
||||||
|
handle: func(cd db.CoverageData) {
|
||||||
|
w.Header().Set("Content-Type", "text/html")
|
||||||
|
fmt.Fprint(w, cd.HTML)
|
||||||
|
},
|
||||||
|
}.run(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBadgeBranch(w http.ResponseWriter, r *http.Request) {
|
||||||
|
endpointData{
|
||||||
|
thirdParam: "branch",
|
||||||
|
queryFunc: db.QueryByBranch,
|
||||||
|
handle: func(cd db.CoverageData) {
|
||||||
|
p := pill.NewPill(cd.Coverage)
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "image/svg+xml")
|
||||||
|
err := p.Execute(w)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("could not write pill: %v", err), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}.run(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePullReport(w http.ResponseWriter, r *http.Request) {
|
||||||
|
endpointData{
|
||||||
|
thirdParam: "pull",
|
||||||
|
queryFunc: db.QueryByPull,
|
||||||
|
handle: func(cd db.CoverageData) {
|
||||||
|
w.Header().Set("Content-Type", "text/html")
|
||||||
|
fmt.Fprint(w, cd.HTML)
|
||||||
|
},
|
||||||
|
}.run(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePullBadge(w http.ResponseWriter, r *http.Request) {
|
||||||
|
endpointData{
|
||||||
|
thirdParam: "pull",
|
||||||
|
queryFunc: db.QueryByPull,
|
||||||
|
handle: func(cd db.CoverageData) {
|
||||||
|
p := pill.NewPill(cd.Coverage)
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "image/svg+xml")
|
||||||
|
err := p.Execute(w)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("could not write pill: %v", err), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}.run(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllParams(w http.ResponseWriter, r *http.Request, thirdParam string) ([3]string, bool) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
namespace, ok := vars["namespace"]
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "Path 'namespace' not found", http.StatusBadRequest)
|
||||||
|
return [3]string{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
project, ok := vars["project"]
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "Path 'project' not found", http.StatusBadRequest)
|
||||||
|
return [3]string{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
third, ok := vars[thirdParam]
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, fmt.Sprintf("Path '%s' not found", thirdParam), http.StatusBadRequest)
|
||||||
|
return [3]string{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return [3]string{namespace, project, third}, true
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"gitea.teamortix.com/team-ortix/coverage/pill"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartServer(port string) {
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/badge/{percentage}", handleBadge)
|
||||||
|
|
||||||
|
r.HandleFunc("/report/branch/{namespace}/{project}/{branch}", handleBranchReport)
|
||||||
|
r.HandleFunc("/report/pulls/{namespace}/{project}/{pull}", handlePullReport)
|
||||||
|
r.HandleFunc("/badge/branch/{namespace}/{project}/{branch}", handleBadgeBranch)
|
||||||
|
r.HandleFunc("/badge/pulls/{namespace}/{project}/{pull}", handlePullBadge)
|
||||||
|
|
||||||
|
r.HandleFunc("/upload/branch/{namespace}/{project}/{branch}", uploadBranch)
|
||||||
|
r.HandleFunc("/upload/pulls/{namespace}/{project}/{branch}", uploadPull)
|
||||||
|
|
||||||
|
portStr := fmt.Sprintf(":%s", port)
|
||||||
|
err := http.ListenAndServe(portStr, r)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("could not start server: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBadge(w http.ResponseWriter, r *http.Request) {
|
||||||
|
percentString, ok := mux.Vars(r)["percentage"]
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "could not find percentage in path", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
percent, err := strconv.ParseFloat(percentString, 64)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("could not convert %s to a number", percentString), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p := pill.NewPill(percent / 100)
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "image/svg+xml")
|
||||||
|
err = p.Execute(w)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("could not write pill: %v", err), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gitea.teamortix.com/team-ortix/coverage/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
const coverageSecret = "COVERAGE_SECRET"
|
||||||
|
|
||||||
|
var secretEnv = os.Getenv(coverageSecret)
|
||||||
|
|
||||||
|
func uploadBranch(w http.ResponseWriter, r *http.Request) {
|
||||||
|
upload(w, r, "branch", db.UploadBranchData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func uploadPull(w http.ResponseWriter, r *http.Request) {
|
||||||
|
upload(w, r, "pull", db.UploadPullData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func upload(w http.ResponseWriter, r *http.Request,
|
||||||
|
uploadType string, uploadFunc func(string, string, string, string, string) error) {
|
||||||
|
if r.Method != "POST" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.ParseMultipartForm(5 << 20)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "file too large", http.StatusRequestEntityTooLarge)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "could not parse form", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
secret := r.Form.Get("secret")
|
||||||
|
namespace := r.Form.Get("namespace")
|
||||||
|
project := r.Form.Get("project")
|
||||||
|
uploadValue := r.Form.Get(uploadType)
|
||||||
|
coverage := r.Form.Get("coverage")
|
||||||
|
|
||||||
|
if secretEnv != secret && secretEnv != "" {
|
||||||
|
http.Error(w, "invalid secret provided", http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if namespace == "" || project == "" || uploadValue == "" || coverage == "" {
|
||||||
|
http.Error(w, fmt.Sprintf("request params [namespace project, %s, coverage] must all be present", uploadType),
|
||||||
|
http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
report, _, err := r.FormFile("report")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "could not parse report parameter", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bytes, err := io.ReadAll(report)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("could not read file: %v", err), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uploadFunc(namespace, project, uploadValue, coverage, string(bytes))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, fmt.Sprintf("could not upload data to database: %v", err), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(w, "uploaded")
|
||||||
|
}
|
Loading…
Reference in New Issue