diff --git a/.gitignore b/.gitignore index 22527af4a..e2cebad11 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ release/ cli/release/ server/swagger/files/*.json +server/swagger/swagger_gen.go .idea/ diff --git a/model/config.go b/model/config.go index e81a97242..5707d605d 100644 --- a/model/config.go +++ b/model/config.go @@ -16,7 +16,7 @@ package model // ConfigStore persists pipeline configuration to storage. type ConfigStore interface { - ConfigLoad(ID int64) (*Config, error) + ConfigLoad(buildID int64) ([]*Config, error) ConfigFind(repo *Repo, sha string) (*Config, error) ConfigFindApproved(*Config) (bool, error) ConfigCreate(*Config) error @@ -24,8 +24,10 @@ type ConfigStore interface { // Config represents a pipeline configuration. type Config struct { - ID int64 `json:"-" meddler:"config_id,pk"` - RepoID int64 `json:"-" meddler:"config_repo_id"` - Data string `json:"data" meddler:"config_data"` - Hash string `json:"hash" meddler:"config_hash"` + ID int64 `json:"-" meddler:"config_id,pk"` + RepoID int64 `json:"-" meddler:"config_repo_id"` + BuildID int64 `json:"-" meddler:"config_build_id"` + Data string `json:"data" meddler:"config_data"` + Hash string `json:"hash" meddler:"config_hash"` + Name string `json:"name" meddler:"config_name"` } diff --git a/server/build.go b/server/build.go index ed024938d..6e5082d11 100644 --- a/server/build.go +++ b/server/build.go @@ -268,7 +268,7 @@ func PostApproval(c *gin.Context) { build.Reviewer = user.Login // fetch the build file from the database - conf, err := Config.Storage.Config.ConfigLoad(build.ConfigID) + configs, err := Config.Storage.Config.ConfigLoad(build.ID) if err != nil { logrus.Errorf("failure to get build config for %s. %s", repo.FullName, err) c.AbortWithError(404, err) @@ -315,6 +315,11 @@ func PostApproval(c *gin.Context) { } }() + var yamls []string + for _, y := range configs { + yamls = append(yamls, string(y.Data)) + } + b := procBuilder{ Repo: repo, Curr: build, @@ -323,7 +328,7 @@ func PostApproval(c *gin.Context) { Secs: secs, Regs: regs, Link: httputil.GetURL(c.Request), - Yamls: []string{conf.Data}, + Yamls: yamls, Envs: envs, } buildItems, err := b.Build() @@ -435,7 +440,7 @@ func PostBuild(c *gin.Context) { } // fetch the .drone.yml file from the database - conf, err := Config.Storage.Config.ConfigLoad(build.ConfigID) + configs, err := Config.Storage.Config.ConfigLoad(build.ID) if err != nil { logrus.Errorf("failure to get build config for %s. %s", repo.FullName, err) c.AbortWithError(404, err) @@ -503,6 +508,11 @@ func PostBuild(c *gin.Context) { } } + var yamls []string + for _, y := range configs { + yamls = append(yamls, string(y.Data)) + } + b := procBuilder{ Repo: repo, Curr: build, @@ -511,7 +521,7 @@ func PostBuild(c *gin.Context) { Secs: secs, Regs: regs, Link: httputil.GetURL(c.Request), - Yamls: []string{conf.Data}, + Yamls: yamls, Envs: buildParams, } buildItems, err := b.Build() diff --git a/store/datastore/config.go b/store/datastore/config.go index 7ac585347..aea0a13e7 100644 --- a/store/datastore/config.go +++ b/store/datastore/config.go @@ -22,11 +22,11 @@ import ( "github.com/russross/meddler" ) -func (db *datastore) ConfigLoad(id int64) (*model.Config, error) { +func (db *datastore) ConfigLoad(buildID int64) ([]*model.Config, error) { stmt := sql.Lookup(db.driver, "config-find-id") - conf := new(model.Config) - err := meddler.QueryRow(db, conf, stmt, id) - return conf, err + var configs = []*model.Config{} + err := meddler.QueryAll(db, &configs, stmt, buildID) + return configs, err } func (db *datastore) ConfigFind(repo *model.Repo, hash string) (*model.Config, error) { diff --git a/store/datastore/config_test.go b/store/datastore/config_test.go index dedef4466..bc09a6293 100644 --- a/store/datastore/config_test.go +++ b/store/datastore/config_test.go @@ -28,15 +28,18 @@ func TestConfig(t *testing.T) { }() var ( - data = "pipeline: [ { image: golang, commands: [ go build, go test ] } ]" - hash = "8d8647c9aa90d893bfb79dddbe901f03e258588121e5202632f8ae5738590b26" + data = "pipeline: [ { image: golang, commands: [ go build, go test ] } ]" + hash = "8d8647c9aa90d893bfb79dddbe901f03e258588121e5202632f8ae5738590b26" + buildID = int64(1) ) if err := s.ConfigCreate( &model.Config{ - RepoID: 2, - Data: data, - Hash: hash, + RepoID: 2, + BuildID: 1, + Data: data, + Hash: hash, + Name: "default", }, ); err != nil { t.Errorf("Unexpected error: insert config: %s", err) @@ -54,19 +57,25 @@ func TestConfig(t *testing.T) { if got, want := config.RepoID, int64(2); got != want { t.Errorf("Want config repo id %d, got %d", want, got) } + if got, want := config.BuildID, buildID; got != want { + t.Errorf("Want config build id %d, got %d", want, got) + } if got, want := config.Data, data; got != want { t.Errorf("Want config data %s, got %s", want, got) } if got, want := config.Hash, hash; got != want { t.Errorf("Want config hash %s, got %s", want, got) } + if got, want := config.Name, "default"; got != want { + t.Errorf("Want config name %s, got %s", want, got) + } - loaded, err := s.ConfigLoad(config.ID) + loaded, err := s.ConfigLoad(buildID) if err != nil { t.Errorf("Want config by id, got error %q", err) return } - if got, want := loaded.ID, config.ID; got != want { + if got, want := loaded[0].ID, config.ID; got != want { t.Errorf("Want config by id %d, got %d", want, got) } } @@ -89,46 +98,57 @@ func TestConfigApproved(t *testing.T) { s.CreateRepo(repo) var ( - data = "pipeline: [ { image: golang, commands: [ go build, go test ] } ]" - hash = "8d8647c9aa90d893bfb79dddbe901f03e258588121e5202632f8ae5738590b26" - conf = &model.Config{ + data = "pipeline: [ { image: golang, commands: [ go build, go test ] } ]" + hash = "8d8647c9aa90d893bfb79dddbe901f03e258588121e5202632f8ae5738590b26" + buildBlocked = &model.Build{ RepoID: repo.ID, - Data: data, - Hash: hash, + Status: model.StatusBlocked, + Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", + } + buildPending = &model.Build{ + RepoID: repo.ID, + Status: model.StatusPending, + Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", + } + buildRunning = &model.Build{ + RepoID: repo.ID, + Status: model.StatusRunning, + Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", } ) + s.CreateBuild(buildBlocked) + s.CreateBuild(buildPending) + conf := &model.Config{ + RepoID: repo.ID, + BuildID: buildBlocked.ID, + Data: data, + Hash: hash, + } if err := s.ConfigCreate(conf); err != nil { t.Errorf("Unexpected error: insert config: %s", err) return } - s.CreateBuild(&model.Build{ - RepoID: repo.ID, - ConfigID: conf.ID, - Status: model.StatusBlocked, - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", - }) - s.CreateBuild(&model.Build{ - RepoID: repo.ID, - ConfigID: conf.ID, - Status: model.StatusPending, - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", - }) - if ok, _ := s.ConfigFindApproved(conf); ok == true { - t.Errorf("Want config not approved, when blocked or pending") + if approved, err := s.ConfigFindApproved(conf); approved != false || err != nil { + t.Errorf("Want config not approved, when blocked or pending. %v", err) return } - s.CreateBuild(&model.Build{ - RepoID: repo.ID, - ConfigID: conf.ID, - Status: model.StatusRunning, - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", - }) + s.CreateBuild(buildRunning) + conf2 := &model.Config{ + RepoID: repo.ID, + BuildID: buildRunning.ID, + Data: data, + Hash: "xxx", + } + if err := s.ConfigCreate(conf2); err != nil { + t.Errorf("Unexpected error: insert config: %s", err) + return + } - if ok, _ := s.ConfigFindApproved(conf); ok == false { - t.Errorf("Want config approved, when running.") + if approved, err := s.ConfigFindApproved(conf2); approved != true || err != nil { + t.Errorf("Want config approved, when running. %v", err) return } } diff --git a/store/datastore/ddl/sqlite/ddl_gen.go b/store/datastore/ddl/sqlite/ddl_gen.go index 3318a9358..136dd6d62 100644 --- a/store/datastore/ddl/sqlite/ddl_gen.go +++ b/store/datastore/ddl/sqlite/ddl_gen.go @@ -1,17 +1,3 @@ -// Copyright 2018 Drone.IO Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - package sqlite import ( @@ -174,6 +160,22 @@ var migrations = []struct { name: "alter-table-update-file-meta", stmt: alterTableUpdateFileMeta, }, + { + name: "alter-table-add-config-build-id", + stmt: alterTableAddConfigBuildId, + }, + { + name: "update-table-set-config-config-id", + stmt: updateTableSetConfigConfigId, + }, + { + name: "alter-table-add-config-name", + stmt: alterTableAddConfigName, + }, + { + name: "update-table-set-config-name", + stmt: updateTableSetConfigName, + }, } // Migrate performs the database migration. If the migration fails @@ -637,3 +639,27 @@ UPDATE files SET ,file_meta_failed=0 ,file_meta_skipped=0 ` + +// +// 019_add_column_config_build_id.sql +// + +var alterTableAddConfigBuildId = ` +ALTER TABLE config ADD COLUMN config_build_id INTEGER +` + +var updateTableSetConfigConfigId = ` +UPDATE config SET config_build_id = (SELECT builds.build_id FROM builds WHERE builds.build_config_id = config.config_id) +` + +// +// 020_add_column_config_name.sql +// + +var alterTableAddConfigName = ` +ALTER TABLE config ADD COLUMN config_name TEXT +` + +var updateTableSetConfigName = ` +UPDATE config SET config_name = "default" +` diff --git a/store/datastore/ddl/sqlite/files/019_add_column_config_build_id.sql b/store/datastore/ddl/sqlite/files/019_add_column_config_build_id.sql new file mode 100644 index 000000000..469ea8677 --- /dev/null +++ b/store/datastore/ddl/sqlite/files/019_add_column_config_build_id.sql @@ -0,0 +1,7 @@ +-- name: alter-table-add-config-build-id + +ALTER TABLE config ADD COLUMN config_build_id INTEGER + +-- name: update-table-set-config-config-id + +UPDATE config SET config_build_id = (SELECT builds.build_id FROM builds WHERE builds.build_config_id = config.config_id) diff --git a/store/datastore/ddl/sqlite/files/020_add_column_config_name.sql b/store/datastore/ddl/sqlite/files/020_add_column_config_name.sql new file mode 100644 index 000000000..4e364a7d8 --- /dev/null +++ b/store/datastore/ddl/sqlite/files/020_add_column_config_name.sql @@ -0,0 +1,7 @@ +-- name: alter-table-add-config-name + +ALTER TABLE config ADD COLUMN config_name TEXT + +-- name: update-table-set-config-name + +UPDATE config SET config_name = "default" \ No newline at end of file diff --git a/store/datastore/sql/sqlite/files/config.sql b/store/datastore/sql/sqlite/files/config.sql index 8f29bd5d1..8a358300a 100644 --- a/store/datastore/sql/sqlite/files/config.sql +++ b/store/datastore/sql/sqlite/files/config.sql @@ -3,18 +3,22 @@ SELECT config_id ,config_repo_id +,config_build_id ,config_hash ,config_data +,config_name FROM config -WHERE config_id = ? +WHERE config_build_id = ? -- name: config-find-repo-hash SELECT config_id ,config_repo_id +,config_build_id ,config_hash ,config_data +,config_name FROM config WHERE config_repo_id = ? AND config_hash = ? @@ -23,6 +27,6 @@ WHERE config_repo_id = ? SELECT build_id FROM builds WHERE build_repo_id = ? -AND build_config_id = ? +AND build_id in (SELECT config_build_id FROM config WHERE config.config_id = ?) AND build_status NOT IN ('blocked', 'pending') LIMIT 1 diff --git a/store/datastore/sql/sqlite/sql_gen.go b/store/datastore/sql/sqlite/sql_gen.go index e98d2e36e..c0418612d 100644 --- a/store/datastore/sql/sqlite/sql_gen.go +++ b/store/datastore/sql/sqlite/sql_gen.go @@ -57,18 +57,22 @@ var configFindId = ` SELECT config_id ,config_repo_id +,config_build_id ,config_hash ,config_data +,config_name FROM config -WHERE config_id = ? +WHERE config_build_id = ? ` var configFindRepoHash = ` SELECT config_id ,config_repo_id +,config_build_id ,config_hash ,config_data +,config_name FROM config WHERE config_repo_id = ? AND config_hash = ? @@ -77,7 +81,7 @@ WHERE config_repo_id = ? var configFindApproved = ` SELECT build_id FROM builds WHERE build_repo_id = ? -AND build_config_id = ? +AND build_id in (SELECT config_build_id FROM config WHERE config.config_id = ?) AND build_status NOT IN ('blocked', 'pending') LIMIT 1 ` diff --git a/store/store.go b/store/store.go index 0ffd47328..e1839cb4d 100644 --- a/store/store.go +++ b/store/store.go @@ -111,7 +111,7 @@ type Store interface { PermDelete(perm *model.Perm) error PermFlush(user *model.User, before int64) error - ConfigLoad(int64) (*model.Config, error) + ConfigLoad(int64) ([]*model.Config, error) ConfigFind(*model.Repo, string) (*model.Config, error) ConfigFindApproved(*model.Config) (bool, error) ConfigCreate(*model.Config) error