diff --git a/db.go b/db.go index e339a4e..11e005c 100644 --- a/db.go +++ b/db.go @@ -235,6 +235,7 @@ CREATE TABLE IF NOT EXISTS user_work_repositories( id_work INTEGER NOT NULL, uri VARCHAR(255) NOT NULL, last_check TIMESTAMP NULL DEFAULT NULL, + droneref VARCHAR(255) NOT NULL, FOREIGN KEY(id_user) REFERENCES users(id_user), FOREIGN KEY(id_work) REFERENCES works(id_work), UNIQUE one_repo_per_work (id_user, id_work) diff --git a/go.mod b/go.mod index 2df1a22..c96d8b6 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.16 require ( github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 github.com/coreos/go-oidc/v3 v3.2.0 + github.com/drone/drone-go v1.7.1 github.com/gin-gonic/gin v1.7.7 github.com/go-sql-driver/mysql v1.6.0 github.com/jcmturner/gokrb5/v8 v8.4.3 diff --git a/go.sum b/go.sum index 3720138..03b124e 100644 --- a/go.sum +++ b/go.sum @@ -54,6 +54,7 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -84,6 +85,8 @@ github.com/coreos/go-oidc/v3 v3.2.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpA github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/drone/drone-go v1.7.1 h1:ZX+3Rs8YHUSUQ5mkuMLmm1zr1ttiiE2YGNxF3AnyDKw= +github.com/drone/drone-go v1.7.1/go.mod h1:fxCf9jAnXDZV1yDr0ckTuWd1intvcQwfJmTRpTZ1mXg= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= diff --git a/main.go b/main.go index eea9b0b..f2a5576 100644 --- a/main.go +++ b/main.go @@ -97,6 +97,7 @@ func main() { go a.Start(*bind) initializeOIDC(a.router) + initializeDroneOauth() // Prepare graceful shutdown interrupt := make(chan os.Signal, 1) diff --git a/repositories.go b/repositories.go index 5ddb786..1d185de 100644 --- a/repositories.go +++ b/repositories.go @@ -1,15 +1,41 @@ package main import ( + "flag" "fmt" "log" "net/http" "strconv" "time" + "github.com/drone/drone-go/drone" "github.com/gin-gonic/gin" + "golang.org/x/oauth2" ) +var ( + droneToken = "" + droneConfig *http.Client + droneEndpoint string +) + +func init() { + flag.StringVar(&droneToken, "drone-token", droneToken, "Token for Drone Oauth") + flag.StringVar(&droneEndpoint, "drone-endpoint", droneEndpoint, "Drone Endpoint") +} + +func initializeDroneOauth() { + if droneToken != "" { + config := new(oauth2.Config) + droneConfig = config.Client( + oauth2.NoContext, + &oauth2.Token{ + AccessToken: droneToken, + }, + ) + } +} + func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) { router.GET("/repositories", func(c *gin.Context) { var u *User @@ -113,15 +139,41 @@ func declareAPIAuthRepositoriesRoutes(router *gin.RouterGroup) { }) repositoriesRoutes.POST("/trigger", func(c *gin.Context) { + var u *User + if user, ok := c.Get("user"); ok { + u = user.(*User) + } else { + u = c.MustGet("LoggedUser").(*User) + } 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 + + } now := time.Now() - if !repo.LastCheck.Before(now.Add(-5 * time.Minute)) { + if repo.LastCheck != nil && !repo.LastCheck.Before(now.Add(-5*time.Minute)) { c.AbortWithStatusJSON(http.StatusPaymentRequired, gin.H{"errmsg": "Please wait between two pulls."}) return } + client := drone.NewClient(droneEndpoint, droneConfig) + result, err := client.BuildCreate("srs", "atsebay.t-worker", "", "master", map[string]string{ + "REPO_URL": repo.URI, + "REPO_TAG": work.Tag, + "LOGIN": u.Login, + "DEST": fmt.Sprintf("%d", work.Id), + }) + 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 + } + + repo.DroneRef = fmt.Sprintf("%s/%s/%d", "srs", "atsebay.t-worker", result.Number) repo.LastCheck = &now repo.Update() @@ -163,17 +215,18 @@ type Repository struct { IdWork int64 `json:"id_work"` URI string `json:"uri"` LastCheck *time.Time `json:"last_check"` + DroneRef string `json:"drone_ref,omitempty"` } func (u *User) GetRepositories() (repositories []*Repository, err error) { - if rows, errr := DBQuery("SELECT id_repository, id_user, id_work, uri, last_check FROM user_work_repositories WHERE id_user=?", u.Id); errr != nil { + if rows, errr := DBQuery("SELECT id_repository, id_user, id_work, uri, last_check, droneref FROM user_work_repositories WHERE id_user=?", u.Id); errr != nil { return nil, errr } else { defer rows.Close() for rows.Next() { var repo Repository - if err = rows.Scan(&repo.Id, &repo.IdUser, &repo.IdWork, &repo.URI, &repo.LastCheck); err != nil { + if err = rows.Scan(&repo.Id, &repo.IdUser, &repo.IdWork, &repo.URI, &repo.LastCheck, &repo.DroneRef); err != nil { return } repositories = append(repositories, &repo) @@ -188,13 +241,13 @@ func (u *User) GetRepositories() (repositories []*Repository, err error) { func getRepository(id int) (r *Repository, err error) { r = new(Repository) - err = DBQueryRow("SELECT id_repository, id_user, id_work, uri, last_check FROM user_work_repositories WHERE id_repository=?", id).Scan(&r.Id, &r.IdUser, &r.IdWork, &r.URI, &r.LastCheck) + err = DBQueryRow("SELECT id_repository, id_user, id_work, uri, last_check, droneref FROM user_work_repositories WHERE id_repository=?", id).Scan(&r.Id, &r.IdUser, &r.IdWork, &r.URI, &r.LastCheck, &r.DroneRef) return } func (u *User) getRepository(id int) (r *Repository, err error) { r = new(Repository) - err = DBQueryRow("SELECT id_repository, id_user, id_work, uri, last_check FROM user_work_repositories WHERE id_repository=? AND id_user=?", id, u.Id).Scan(&r.Id, &r.IdUser, &r.IdWork, &r.URI, &r.LastCheck) + err = DBQueryRow("SELECT id_repository, id_user, id_work, uri, last_check, droneref FROM user_work_repositories WHERE id_repository=? AND id_user=?", id, u.Id).Scan(&r.Id, &r.IdUser, &r.IdWork, &r.URI, &r.LastCheck, &r.DroneRef) return } @@ -204,12 +257,12 @@ 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, nil}, nil + return &Repository{rid, u.Id, w.Id, uri, nil, ""}, nil } } func (r *Repository) Update() (*Repository, error) { - if _, err := DBExec("UPDATE user_work_repositories SET id_user = ?, id_work = ?, uri = ?, last_check = ? WHERE id_repository = ?", r.IdUser, r.IdWork, r.URI, r.LastCheck, r.Id); err != nil { + if _, err := DBExec("UPDATE user_work_repositories SET id_user = ?, id_work = ?, uri = ?, last_check = ?, droneref = ? WHERE id_repository = ?", r.IdUser, r.IdWork, r.URI, r.LastCheck, r.DroneRef, r.Id); err != nil { return nil, err } else { return r, err