1
0
mirror of https://github.com/woodpecker-ci/woodpecker.git synced 2024-12-24 10:07:21 +02:00

1:n relationship for build-config

This commit is contained in:
Laszlo Fogas 2019-06-07 10:40:16 +02:00
parent 3f9356c6a7
commit 3fe710bbe4
11 changed files with 147 additions and 66 deletions

1
.gitignore vendored
View File

@ -8,4 +8,5 @@ release/
cli/release/
server/swagger/files/*.json
server/swagger/swagger_gen.go
.idea/

View File

@ -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"`
}

View File

@ -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()

View File

@ -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) {

View File

@ -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
}
}

View File

@ -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"
`

View File

@ -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)

View File

@ -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"

View File

@ -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

View File

@ -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
`

View File

@ -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