coverage/db/upload.go

133 lines
3.8 KiB
Go

package db
import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strconv"
"time"
)
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)
}
createIssueMessage(namespace, project, pullStr, coverage)
return nil
}
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
}
const urlTemplate = "%s/api/v1/repos/%s/%s/issues/%s/comments"
const messageTemplate = `## Coverage Report Ready
[![Coverage %.01f%%](%s)](%s)
The coverage report can be found [here](%s). You can also click the badge above.
---
I am a bot and this was done automatically as part of CI.
The badge and report content will automatically stay up to date to the PR.`
type messageBody struct {
Body string `json:"body"`
}
func createIssueMessage(namespace, project, pull string, coverage float64) {
badgeURL := fmt.Sprintf("https://coverage.teamortix.com/badge/pulls/%s/%s/%s", namespace, project, pull)
reportURL := fmt.Sprintf("https://coverage.teamortix.com/report/pulls/%s/%s/%s", namespace, project, pull)
message := fmt.Sprintf(messageTemplate, coverage*100, badgeURL, reportURL, reportURL)
url := fmt.Sprintf(urlTemplate, os.Getenv("GITEA_HOST"), namespace, project, pull)
jsonBytes, err := json.Marshal(messageBody{message})
if err != nil {
log.Printf("Could not marshal json: %v\n", err)
}
body := bytes.NewReader(jsonBytes)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "POST", url, body)
if err != nil {
log.Printf("Could not make request: %v\n", err)
return
}
req.Header.Set("Authorization", "token "+os.Getenv("COVERAGE_TOKEN"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Printf("Issuecomment request error: %v\n", err)
return
}
err = res.Body.Close()
if err != nil {
log.Printf("Could not close request body: %v", err)
return
}
if res.StatusCode != 201 {
log.Printf("Issuecomment unexpected statuscode: %d\n", res.StatusCode)
return
}
}