diff --git a/model/feed.go b/model/feed.go index c690ad9e3..2a2de5237 100644 --- a/model/feed.go +++ b/model/feed.go @@ -1,23 +1,24 @@ package model type Feed struct { - Owner string `json:"owner" meddler:"repo_owner"` - Name string `json:"name" meddler:"repo_name"` - FullName string `json:"full_name" meddler:"repo_full_name"` - Avatar string `json:"avatar_url" meddler:"repo_avatar"` + Owner string `json:"owner" meddler:"repo_owner"` + Name string `json:"name" meddler:"repo_name"` + FullName string `json:"full_name" meddler:"repo_full_name"` - Number int `json:"number" meddler:"build_number"` - Event string `json:"event" meddler:"build_event"` - Status string `json:"status" meddler:"build_status"` - Started int64 `json:"started_at" meddler:"build_started"` - Finished int64 `json:"finished_at" meddler:"build_finished"` - Commit string `json:"commit" meddler:"build_commit"` - Branch string `json:"branch" meddler:"build_branch"` - Ref string `json:"ref" meddler:"build_ref"` - Refspec string `json:"refspec" meddler:"build_refspec"` - Remote string `json:"remote" meddler:"build_remote"` - Title string `json:"title" meddler:"build_title"` - Message string `json:"message" meddler:"build_message"` - Author string `json:"author" meddler:"build_author"` - Email string `json:"author_email" meddler:"build_email"` + Number int `json:"number" meddler:"build_number"` + Event string `json:"event" meddler:"build_event"` + Status string `json:"status" meddler:"build_status"` + Created int64 `json:"created_at" meddler:"build_created"` + Started int64 `json:"started_at" meddler:"build_started"` + Finished int64 `json:"finished_at" meddler:"build_finished"` + Commit string `json:"commit" meddler:"build_commit"` + Branch string `json:"branch" meddler:"build_branch"` + Ref string `json:"ref" meddler:"build_ref"` + Refspec string `json:"refspec" meddler:"build_refspec"` + Remote string `json:"remote" meddler:"build_remote"` + Title string `json:"title" meddler:"build_title"` + Message string `json:"message" meddler:"build_message"` + Author string `json:"author" meddler:"build_author"` + Avatar string `json:"author_avatar" meddler:"build_avatar"` + Email string `json:"author_email" meddler:"build_email"` } diff --git a/model/repo.go b/model/repo.go index 78af7c1d9..36f5c3430 100644 --- a/model/repo.go +++ b/model/repo.go @@ -3,6 +3,7 @@ package model import ( "github.com/drone/drone/shared/database" "github.com/russross/meddler" + "strings" ) type RepoLite struct { @@ -40,14 +41,35 @@ func GetRepo(db meddler.DB, id int64) (*Repo, error) { } func GetRepoName(db meddler.DB, owner, name string) (*Repo, error) { + return GetRepoFullName(db, owner+"/"+name) +} + +func GetRepoFullName(db meddler.DB, name string) (*Repo, error) { var repo = new(Repo) - var err = meddler.QueryRow(db, repo, database.Rebind(repoNameQuery), owner, name) + var err = meddler.QueryRow(db, repo, database.Rebind(repoNameQuery), name) return repo, err } func GetRepoList(db meddler.DB, user *User) ([]*Repo, error) { + // we don't have real-time access to the intersection + // of github repos and drone repos. So we cheat by simply + // getting the distinct list of repos that the user + // has created builds for. var repos = []*Repo{} - var err = meddler.QueryAll(db, &repos, database.Rebind(repoListQuery), user.ID) + var err = meddler.QueryAll(db, &repos, database.Rebind(repoListQuery), user.Login) + return repos, err +} + +func GetRepoListOf(db meddler.DB, listof []string) ([]*Repo, error) { + var repos = []*Repo{} + var qs = make([]string, len(listof), len(listof)) + var in = make([]interface{}, len(listof), len(listof)) + for i, repo := range listof { + qs[i] = "?" + in[i] = repo + } + var stmt = "SELECT * FROM repos WHERE repo_id IN (" + strings.Join(qs, ",") + ")" + var err = meddler.QueryAll(db, &repos, database.Rebind(stmt), in...) return repos, err } @@ -69,12 +91,11 @@ const repoTable = "repos" const repoNameQuery = ` SELECT * FROM repos -WHERE repo_owner = ? -AND repo_name = ? +WHERE repo_full_name = ? LIMIT 1; ` -const repoListQuery = ` +const repoStarsQuery = ` SELECT r.* FROM repos r @@ -83,6 +104,16 @@ WHERE r.repo_id = s.star_repo_id AND s.star_user_id = ? ` +const repoListQuery = ` +SELECT * +FROM repos +WHERE repo_id IN ( + SELECT DISTINCT build_repo_id + FROM builds + WHERE build_author = ? +) +` + const repoDeleteStmt = ` DELETE FROM repos WHERE repo_id = ? diff --git a/model/repo_test.go b/model/repo_test.go index a823728bf..09270ba57 100644 --- a/model/repo_test.go +++ b/model/repo_test.go @@ -17,7 +17,7 @@ func TestRepostore(t *testing.T) { // before each test be sure to purge the package // table data from the database. g.BeforeEach(func() { - db.Exec("DELETE FROM stars") + db.Exec("DELETE FROM builds") db.Exec("DELETE FROM repos") db.Exec("DELETE FROM users") }) @@ -101,8 +101,9 @@ func TestRepostore(t *testing.T) { } CreateRepo(db, &repo1) CreateRepo(db, &repo2) - CreateStar(db, &User{ID: 1}, &repo1) - repos, err := GetRepoList(db, &User{ID: 1}) + CreateBuild(db, &Build{RepoID: repo1.ID, Author: "bradrydzewski"}) + CreateBuild(db, &Build{RepoID: repo1.ID, Author: "johnsmith"}) + repos, err := GetRepoList(db, &User{ID: 1, Login: "bradrydzewski"}) g.Assert(err == nil).IsTrue() g.Assert(len(repos)).Equal(1) g.Assert(repos[0].UserID).Equal(repo1.UserID) diff --git a/model/user.go b/model/user.go index eb398b1a1..0521f268a 100644 --- a/model/user.go +++ b/model/user.go @@ -37,7 +37,7 @@ func GetUserList(db meddler.DB) ([]*User, error) { func GetUserFeed(db meddler.DB, user *User, limit, offset int) ([]*Feed, error) { var feed = []*Feed{} - var err = meddler.QueryAll(db, &feed, database.Rebind(userFeedQuery), user.ID, limit, offset) + var err = meddler.QueryAll(db, &feed, database.Rebind(userFeedQuery), user.Login, limit, offset) return feed, err } @@ -85,15 +85,45 @@ DELETE FROM users WHERE user_id=? ` +// this query was referenced from +// http://stackoverflow.com/questions/2111384/sql-join-selecting-the-last-records-in-a-one-to-many-relationship/2111420#2111420 +// const userRepoLatestQuery = ` +// SELECT +// r.repo_owner +// ,r.repo_name +// ,r.repo_full_name +// ,r.repo_avatar +// ,b.build_number +// ,b.build_event +// ,b.build_status +// ,b.build_created +// ,b.build_started +// ,b.build_finished +// ,b.build_commit +// ,b.build_branch +// ,b.build_ref +// ,b.build_refspec +// ,b.build_remote +// ,b.build_title +// ,b.build_message +// ,b.build_author +// ,b.build_email +// FROM repos r +// JOIN builds b ON (r.repo_id = b.build_repo_id) +// LEFT OUTER JOIN builds bb ON (r.repo_id = bb.build_repo_id AND +// (b.build_number < bb.build_number OR b.build_number = bb.build_number AND b.build_id < bb.build_id AND b.build_author=?)) +// WHERE bb.build_id IS NULL; +// ` + const userFeedQuery = ` SELECT repo_owner ,repo_name ,repo_full_name -,repo_avatar ,build_number ,build_event ,build_status +,build_created ,build_started ,build_finished ,build_commit @@ -105,13 +135,12 @@ SELECT ,build_message ,build_author ,build_email +,build_avatar FROM builds b ,repos r -,stars s WHERE b.build_repo_id = r.repo_id - AND r.repo_id = s.star_repo_id - AND s.star_user_id = ? -ORDER BY b.build_number DESC + AND b.build_author = ? +ORDER BY b.build_id DESC LIMIT ? OFFSET ? ` diff --git a/model/user_test.go b/model/user_test.go index 0fa1a91e0..cca270ac1 100644 --- a/model/user_test.go +++ b/model/user_test.go @@ -179,25 +179,27 @@ func TestUserstore(t *testing.T) { } CreateRepo(db, repo1) CreateRepo(db, repo2) - CreateStar(db, &User{ID: 1}, repo1) build1 := &Build{ RepoID: repo1.ID, Status: StatusFailure, + Author: "bradrydzewski", } build2 := &Build{ RepoID: repo1.ID, Status: StatusSuccess, + Author: "bradrydzewski", } build3 := &Build{ RepoID: repo2.ID, Status: StatusSuccess, + Author: "octocat", } CreateBuild(db, build1) CreateBuild(db, build2) CreateBuild(db, build3) - builds, err := GetUserFeed(db, &User{ID: 1}, 20, 0) + builds, err := GetUserFeed(db, &User{ID: 1, Login: "bradrydzewski"}, 20, 0) g.Assert(err == nil).IsTrue() g.Assert(len(builds)).Equal(2) g.Assert(builds[0].Owner).Equal("bradrydzewski") diff --git a/router/router.go b/router/router.go index 86297f8ac..8740278a8 100644 --- a/router/router.go +++ b/router/router.go @@ -54,10 +54,10 @@ func Load(middleware ...gin.HandlerFunc) http.Handler { { user.Use(session.MustUser()) user.GET("", controller.GetSelf) - user.GET("/feed", controller.GetFeed) + user.GET("/builds", controller.GetFeed) user.GET("/repos", controller.GetRepos) - user.POST("/token", controller.PostToken) user.GET("/repos/remote", controller.GetRemoteRepos) + user.POST("/token", controller.PostToken) } users := e.Group("/api/users") diff --git a/shared/database/mysql/1_init.sql b/shared/database/mysql/1_init.sql index 87a752645..ca95d0232 100644 --- a/shared/database/mysql/1_init.sql +++ b/shared/database/mysql/1_init.sql @@ -33,7 +33,7 @@ CREATE TABLE repos ( ,repo_allow_tags BOOLEAN ,repo_hash VARCHAR(500) -,UNIQUE(repo_owner, repo_name) +,UNIQUE(repo_full_name) ); CREATE TABLE stars ( diff --git a/shared/database/postgres/1_init.sql b/shared/database/postgres/1_init.sql index 01955e673..44b1e9bda 100644 --- a/shared/database/postgres/1_init.sql +++ b/shared/database/postgres/1_init.sql @@ -33,7 +33,7 @@ CREATE TABLE repos ( ,repo_allow_tags BOOLEAN ,repo_hash VARCHAR(500) -,UNIQUE(repo_owner, repo_name) +,UNIQUE(repo_full_name) ); CREATE TABLE stars ( diff --git a/shared/database/sqlite3/1_init.sql b/shared/database/sqlite3/1_init.sql index 906d2f96f..3ee5490a3 100644 --- a/shared/database/sqlite3/1_init.sql +++ b/shared/database/sqlite3/1_init.sql @@ -33,7 +33,7 @@ CREATE TABLE repos ( ,repo_allow_tags BOOLEAN ,repo_hash TEXT -,UNIQUE(repo_owner, repo_name) +,UNIQUE(repo_full_name) ); CREATE TABLE stars (