New route to run gradation tests
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
7340e10a7a
commit
0cc0ae3c7d
103
repositories.go
103
repositories.go
@ -8,10 +8,13 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/drone/drone-go/drone"
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/oauth2"
|
||||
@ -291,6 +294,29 @@ func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) {
|
||||
c.JSON(http.StatusOK, result)
|
||||
}
|
||||
})
|
||||
|
||||
repositoriesRoutes.POST("/gradation", func(c *gin.Context) {
|
||||
loggeduser := c.MustGet("LoggedUser").(*User)
|
||||
if !loggeduser.IsAdmin {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Permission denied."})
|
||||
return
|
||||
}
|
||||
|
||||
var u *User
|
||||
if user, ok := c.Get("user"); ok {
|
||||
u = user.(*User)
|
||||
} else {
|
||||
u = loggeduser
|
||||
}
|
||||
repo := c.MustGet("repository").(*Repository)
|
||||
work, err := getWork(int(repo.IdWork))
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to find related work."})
|
||||
return
|
||||
}
|
||||
|
||||
TriggerTests(c, work, repo, u)
|
||||
})
|
||||
}
|
||||
|
||||
type GitLabWebhook struct {
|
||||
@ -465,6 +491,79 @@ func TriggerTagUpdate(c *gin.Context, work *Work, repo *Repository, u *User, tag
|
||||
c.JSON(http.StatusOK, repo)
|
||||
}
|
||||
|
||||
func TriggerTests(c *gin.Context, work *Work, repo *Repository, u *User) {
|
||||
if work.GradationRepo == nil || len(*work.GradationRepo) == 0 {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "No tests defined for this work."})
|
||||
return
|
||||
}
|
||||
|
||||
slug := strings.SplitN(*work.GradationRepo, "/", 2)
|
||||
if len(slug) != 2 {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Graduation repository is invalid."})
|
||||
return
|
||||
}
|
||||
|
||||
login := u.Login
|
||||
groups := u.Groups
|
||||
if u.Id != repo.IdUser {
|
||||
user, _ := getUser(int(repo.IdUser))
|
||||
if user != nil {
|
||||
login = user.Login
|
||||
groups = user.Groups
|
||||
}
|
||||
}
|
||||
|
||||
branch := "master"
|
||||
if len(work.Tag) > 0 {
|
||||
branch = work.Tag
|
||||
}
|
||||
if branch[len(branch)-1] == '-' {
|
||||
branch += "grades"
|
||||
}
|
||||
|
||||
s, err := s3NewSession()
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Something goes wrong."})
|
||||
return
|
||||
}
|
||||
|
||||
req, _ := s3.New(s).GetObjectRequest(&s3.GetObjectInput{
|
||||
Bucket: aws.String(s3_bucket),
|
||||
Key: aws.String(filepath.Join(fmt.Sprintf("%d", work.Id), fmt.Sprintf("rendu-%s.tar.xz", u.Login))),
|
||||
})
|
||||
|
||||
url, err := req.Presign(SharingTime)
|
||||
if err != nil {
|
||||
log.Println("Unable to create presign URL:", err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Something goes wrong when creating the presigned URL."})
|
||||
return
|
||||
}
|
||||
|
||||
env := map[string]string{
|
||||
"SUBMISSION_URL": repo.URI,
|
||||
"META_URL": url,
|
||||
"LOGIN": login,
|
||||
"GROUPS": groups,
|
||||
"DEST": fmt.Sprintf("%d", work.Id),
|
||||
}
|
||||
|
||||
client := drone.NewClient(droneEndpoint, droneConfig)
|
||||
result, err := client.BuildCreate(slug[0], slug[1], "", branch, env)
|
||||
if err != nil {
|
||||
log.Println("Unable to communicate with Drone:", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to communication with the extraction service."})
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
repo.TestsRef = fmt.Sprintf("%s/%d", *work.GradationRepo, result.Number)
|
||||
repo.LastTests = &now
|
||||
repo.Update()
|
||||
|
||||
repo.Secret = []byte{}
|
||||
c.JSON(http.StatusOK, repo)
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
Id int64 `json:"id"`
|
||||
IdUser int64 `json:"id_user"`
|
||||
@ -474,7 +573,7 @@ type Repository struct {
|
||||
LastCheck *time.Time `json:"last_check"`
|
||||
DroneRef string `json:"drone_ref,omitempty"`
|
||||
LastTests *time.Time `json:"last_tests"`
|
||||
TestsRef string `json:"drone_ref,omitempty"`
|
||||
TestsRef string `json:"tests_ref,omitempty"`
|
||||
AlreadyUsed bool `json:"already_used,omitempty"`
|
||||
}
|
||||
|
||||
@ -544,7 +643,7 @@ func (u *User) NewRepository(w *Work, uri string) (*Repository, error) {
|
||||
} else if rid, err := res.LastInsertId(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &Repository{rid, u.Id, w.Id, uri, secret, nil, "", false}, nil
|
||||
return &Repository{rid, u.Id, w.Id, uri, secret, nil, "", nil, "", false}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,18 @@ export class Work {
|
||||
throw new Error((await res.json()).errmsg);
|
||||
}
|
||||
}
|
||||
|
||||
async runGradation(uid) {
|
||||
const res = await fetch(uid?`api/users/${uid}/works/${this.id}/gradation`:`api/works/${this.id}/gradation`, {
|
||||
method: 'POST',
|
||||
headers: {'Accept': 'application/json'},
|
||||
});
|
||||
if (res.status == 200) {
|
||||
return await res.json();
|
||||
} else {
|
||||
throw new Error((await res.json()).errmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getWorks() {
|
||||
|
@ -61,8 +61,8 @@
|
||||
<tbody>
|
||||
{#each users as user (user.id)}
|
||||
<tr>
|
||||
<td><a href="users/{user.login}">{user.login}</a></td>
|
||||
<td>
|
||||
<td><a href="users/{user.login}" class="text-truncate">{user.login}</a></td>
|
||||
<td class="text-center">
|
||||
<SubmissionStatus work={w} user={user} on:done={() => { nb_rendus += 1; show_dl_btn[user.id] = true; }} />
|
||||
</td>
|
||||
<td>
|
||||
@ -74,7 +74,7 @@
|
||||
<code class="text-truncate mx-1">
|
||||
{repo.uri}
|
||||
</code>
|
||||
<div class="mx-1">
|
||||
<div class="mx-1" style="white-space: nowrap">
|
||||
{#if repo.last_check}
|
||||
<DateFormat date={new Date(repo.last_check)} dateStyle="medium" timeStyle="medium" />
|
||||
<BuildState
|
||||
@ -118,7 +118,7 @@
|
||||
{/await}
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
<td class="d-flex gap-1">
|
||||
<a
|
||||
href="/api/users/{user.id}/works/{w.id}/download"
|
||||
class="btn btn-sm btn-dark"
|
||||
@ -127,6 +127,14 @@
|
||||
>
|
||||
<i class="bi bi-download"></i>
|
||||
</a>
|
||||
<button
|
||||
class="btn btn-sm btn-success mr-1"
|
||||
class:disabled={!show_dl_btn[user.id]}
|
||||
title="Relancer les tests"
|
||||
on:click={() => { w.runGradation(user.id); }}
|
||||
>
|
||||
<i class="bi bi-play"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
|
Reference in New Issue
Block a user