mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-09-02 22:49:40 +00:00
Change pipeline config path resolution (#299)
# Config resolution - pipeline-config setting empty / not specified (default): `.woodpecker/` => `.woodpecker.yml` => `.drone.yml` - pipeline-config setting defined by user: try that file / folder and no fallback (if a user sets some special value that is normally done for some reason) # Changes - pipeline-config setting will be empty by default - remove fallback setting for config loading (simplifies config) --- closes #133 --- * adjust config fetching mechanism * default path empty * remove fallback flag from ui and db
This commit is contained in:
@@ -89,12 +89,6 @@ var flags = []cli.Flag{
|
|||||||
Name: "open",
|
Name: "open",
|
||||||
Usage: "enable open user registration",
|
Usage: "enable open user registration",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
EnvVar: "DRONE_REPO_CONFIG,WOODPECKER_REPO_CONFIG",
|
|
||||||
Name: "repo-config",
|
|
||||||
Usage: "file path for the drone config",
|
|
||||||
Value: ".drone.yml",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
EnvVar: "DRONE_DOCS,WOODPECKER_DOCS",
|
EnvVar: "DRONE_DOCS,WOODPECKER_DOCS",
|
||||||
Name: "docs",
|
Name: "docs",
|
||||||
|
@@ -20,11 +20,9 @@ When you activate your repository Woodpecker automatically add webhooks to your
|
|||||||
|
|
||||||
Webhooks are used to trigger pipeline executions. When you push code to your repository, open a pull request, or create a tag, your version control system will automatically send a webhook to Woodpecker which will in turn trigger pipeline execution.
|
Webhooks are used to trigger pipeline executions. When you push code to your repository, open a pull request, or create a tag, your version control system will automatically send a webhook to Woodpecker which will in turn trigger pipeline execution.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
To configure you pipeline you should place a `.woodpecker.yml` file in the root of your repository. The .woodpecker.yml file is used to define your pipeline steps. It is a superset of the widely used docker-compose file format.
|
To configure your pipeline you should place a `.woodpecker.yml` file in the root of your repository. The .woodpecker.yml file is used to define your pipeline steps. It is a superset of the widely used docker-compose file format.
|
||||||
|
|
||||||
Example pipeline configuration:
|
Example pipeline configuration:
|
||||||
|
|
||||||
|
@@ -6,9 +6,7 @@ As the owner of a project in Woodpecker you can change some project related sett
|
|||||||
|
|
||||||
## Pipeline path
|
## Pipeline path
|
||||||
|
|
||||||
The path to the pipeline file or folder. By default it point `.woodpecker.yml`. To use a [multi pipeline](/docs/usage/multi-pipeline) you have to change it to a folder path ending with `/` like `.woodpecker/`.
|
The path to the pipeline config file or folder. By default it is left empty which will use the following configuration resolution `.woodpecker/*.yml` -> `.woodpecker.yml` -> `.drone.yml`. If you set a custom path Woodpecker tries to load your configuration or fails if no configuration could be found at the specified location. To use a [multi pipeline](/docs/usage/multi-pipeline) you have to change it to a folder path ending with a `/` like `.woodpecker/`.
|
||||||
|
|
||||||
If you enable the fallback check, Woodpecker will first try to load the configuration from the defined path and if it fails to find that file it will try to use `.drone.yml`.
|
|
||||||
|
|
||||||
## Repository hooks
|
## Repository hooks
|
||||||
|
|
||||||
|
@@ -4,11 +4,14 @@ Some versions need some changes to the server configuration or the pipeline conf
|
|||||||
|
|
||||||
## 0.15.0
|
## 0.15.0
|
||||||
|
|
||||||
- Default pipeline path changed to `.woodpecker/`
|
- Default value for custom pipeline path is now empty / un-set which results in following resolution:
|
||||||
|
|
||||||
**Solution:** Set configuration location via [project settings](/docs/usage/project-settings#pipeline-path).
|
`.woodpecker/*.yml` -> `.woodpecker.yml` -> `.drone.yml`
|
||||||
|
|
||||||
|
Only projects created after updating will have an empty value by default. Existing projects will stick to the current pipeline path which is `.drone.yml` in most cases.
|
||||||
|
|
||||||
|
Read more about it at the [Project Settings](/docs/usage/project-settings#pipeline-path)
|
||||||
|
|
||||||
There is still a default fallback mechanism in following order: `.woodpecker/*.yml` -> `.woodpecker.yml` -> `.drone.yml`
|
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
## 0.14.0
|
## 0.14.0
|
||||||
|
@@ -55,7 +55,6 @@ type Repo struct {
|
|||||||
Config string `json:"config_file" meddler:"repo_config_path"`
|
Config string `json:"config_file" meddler:"repo_config_path"`
|
||||||
Hash string `json:"-" meddler:"repo_hash"`
|
Hash string `json:"-" meddler:"repo_hash"`
|
||||||
Perm *Perm `json:"-" meddler:"-"`
|
Perm *Perm `json:"-" meddler:"-"`
|
||||||
Fallback bool `json:"fallback" meddler:"repo_fallback"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repo) ResetVisibility() {
|
func (r *Repo) ResetVisibility() {
|
||||||
@@ -106,5 +105,4 @@ type RepoPatch struct {
|
|||||||
AllowDeploy *bool `json:"allow_deploy,omitempty"`
|
AllowDeploy *bool `json:"allow_deploy,omitempty"`
|
||||||
AllowTag *bool `json:"allow_tag,omitempty"`
|
AllowTag *bool `json:"allow_tag,omitempty"`
|
||||||
BuildCounter *int `json:"build_counter,omitempty"`
|
BuildCounter *int `json:"build_counter,omitempty"`
|
||||||
Fallback *bool `json:"fallback,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
@@ -429,7 +429,7 @@ func PostBuild(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch the .drone.yml file from the database
|
// fetch the pipeline config from database
|
||||||
configs, err := Config.Storage.Config.ConfigsForBuild(build.ID)
|
configs, err := Config.Storage.Config.ConfigsForBuild(build.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("failure to get build config for %s. %s", repo.FullName, err)
|
logrus.Errorf("failure to get build config for %s. %s", repo.FullName, err)
|
||||||
|
@@ -30,7 +30,7 @@ func (cf *configFetcher) Fetch() (files []*remote.FileMeta, err error) {
|
|||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
select {
|
select {
|
||||||
case <-time.After(time.Second * time.Duration(i)):
|
case <-time.After(time.Second * time.Duration(i)):
|
||||||
|
if len(cf.repo.Config) > 0 {
|
||||||
// either a file
|
// either a file
|
||||||
if !strings.HasSuffix(cf.repo.Config, "/") {
|
if !strings.HasSuffix(cf.repo.Config, "/") {
|
||||||
file, err = cf.remote_.File(cf.user, cf.repo, cf.build, cf.repo.Config)
|
file, err = cf.remote_.File(cf.user, cf.repo, cf.build, cf.repo.Config)
|
||||||
@@ -49,9 +49,24 @@ func (cf *configFetcher) Fetch() (files []*remote.FileMeta, err error) {
|
|||||||
return filterPipelineFiles(files), nil
|
return filterPipelineFiles(files), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// no user defined config so try .woodpecker/*.yml -> .woodpecker.yml -> .drone.yml
|
||||||
|
|
||||||
|
// test .woodpecker/ folder
|
||||||
|
// if folder is not supported we will get a "Not implemented" error and continue
|
||||||
|
files, err = cf.remote_.Dir(cf.user, cf.repo, cf.build, ".woodpecker")
|
||||||
|
if err == nil {
|
||||||
|
return filterPipelineFiles(files), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err = cf.remote_.File(cf.user, cf.repo, cf.build, ".woodpecker.yml")
|
||||||
|
if err == nil {
|
||||||
|
return []*remote.FileMeta{{
|
||||||
|
Name: ".woodpecker.yml",
|
||||||
|
Data: file,
|
||||||
|
}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// or fallback
|
|
||||||
if cf.repo.Fallback {
|
|
||||||
file, err = cf.remote_.File(cf.user, cf.repo, cf.build, ".drone.yml")
|
file, err = cf.remote_.File(cf.user, cf.repo, cf.build, ".drone.yml")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return []*remote.FileMeta{{
|
return []*remote.FileMeta{{
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
package server_test
|
package server_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
@@ -17,59 +18,17 @@ func TestFetch(t *testing.T) {
|
|||||||
testTable := []struct {
|
testTable := []struct {
|
||||||
name string
|
name string
|
||||||
repoConfig string
|
repoConfig string
|
||||||
repoFallback bool
|
files []string
|
||||||
fileMocks []struct {
|
|
||||||
file []byte
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
dirMock struct {
|
|
||||||
files []*remote.FileMeta
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
expectedFileNames []string
|
expectedFileNames []string
|
||||||
expectedError bool
|
expectedError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Single .woodpecker.yml file",
|
name: "Default config - .woodpecker/",
|
||||||
repoConfig: ".woodpecker.yml",
|
repoConfig: "",
|
||||||
repoFallback: false,
|
files: []string{
|
||||||
fileMocks: []struct {
|
".woodpecker/text.txt",
|
||||||
file []byte
|
".woodpecker/release.yml",
|
||||||
err error
|
".woodpecker/image.png",
|
||||||
}{
|
|
||||||
{
|
|
||||||
file: []byte{},
|
|
||||||
err: nil,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedFileNames: []string{
|
|
||||||
".woodpecker.yml",
|
|
||||||
},
|
|
||||||
expectedError: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Folder .woodpecker/",
|
|
||||||
repoConfig: ".woodpecker/",
|
|
||||||
repoFallback: false,
|
|
||||||
dirMock: struct {
|
|
||||||
files []*remote.FileMeta
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
files: []*remote.FileMeta{
|
|
||||||
{
|
|
||||||
Name: ".woodpecker/text.txt",
|
|
||||||
Data: []byte{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: ".woodpecker/release.yml",
|
|
||||||
Data: []byte{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: ".woodpecker/image.png",
|
|
||||||
Data: []byte{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
expectedFileNames: []string{
|
expectedFileNames: []string{
|
||||||
".woodpecker/release.yml",
|
".woodpecker/release.yml",
|
||||||
@@ -77,23 +36,21 @@ func TestFetch(t *testing.T) {
|
|||||||
expectedError: false,
|
expectedError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Requesting woodpecker-file but using fallback",
|
name: "Default config - .woodpecker.yml",
|
||||||
repoConfig: ".woodpecker.yml",
|
repoConfig: "",
|
||||||
repoFallback: true,
|
files: []string{
|
||||||
fileMocks: []struct {
|
".woodpecker.yml",
|
||||||
file []byte
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
// first call requesting regular woodpecker.yml
|
|
||||||
{
|
|
||||||
file: nil,
|
|
||||||
err: errors.New("File not found"),
|
|
||||||
},
|
},
|
||||||
// fallback file call
|
expectedFileNames: []string{
|
||||||
{
|
".woodpecker.yml",
|
||||||
file: []byte{},
|
|
||||||
err: nil,
|
|
||||||
},
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Default config - .drone.yml",
|
||||||
|
repoConfig: "",
|
||||||
|
files: []string{
|
||||||
|
".drone.yml",
|
||||||
},
|
},
|
||||||
expectedFileNames: []string{
|
expectedFileNames: []string{
|
||||||
".drone.yml",
|
".drone.yml",
|
||||||
@@ -101,49 +58,99 @@ func TestFetch(t *testing.T) {
|
|||||||
expectedError: false,
|
expectedError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Requesting folder but using fallback",
|
name: "Default config - Empty repo",
|
||||||
repoConfig: ".woodpecker/",
|
repoConfig: "",
|
||||||
repoFallback: true,
|
files: []string{},
|
||||||
fileMocks: []struct {
|
expectedFileNames: []string{},
|
||||||
file []byte
|
expectedError: true,
|
||||||
err error
|
},
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
file: []byte{},
|
name: "Default config - Additional sub-folders",
|
||||||
err: nil,
|
repoConfig: "",
|
||||||
},
|
files: []string{
|
||||||
},
|
".woodpecker/test.yml",
|
||||||
dirMock: struct {
|
".woodpecker/sub-folder/config.yml",
|
||||||
files []*remote.FileMeta
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
files: []*remote.FileMeta{},
|
|
||||||
err: errors.New("Dir not found"),
|
|
||||||
},
|
},
|
||||||
expectedFileNames: []string{
|
expectedFileNames: []string{
|
||||||
".drone.yml",
|
".woodpecker/test.yml",
|
||||||
},
|
},
|
||||||
expectedError: false,
|
expectedError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Not found and disabled fallback",
|
name: "Default config - Additional none .yml files",
|
||||||
repoConfig: ".woodpecker.yml",
|
repoConfig: "",
|
||||||
repoFallback: false,
|
files: []string{
|
||||||
fileMocks: []struct {
|
".woodpecker/notes.txt",
|
||||||
file []byte
|
".woodpecker/image.png",
|
||||||
err error
|
".woodpecker/test.yml",
|
||||||
}{
|
},
|
||||||
// first call requesting regular woodpecker.yml
|
expectedFileNames: []string{
|
||||||
|
".woodpecker/test.yml",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
file: nil,
|
name: "Special config - folder (ignoring default files)",
|
||||||
err: errors.New("File not found"),
|
repoConfig: ".my-ci-folder/",
|
||||||
|
files: []string{
|
||||||
|
".woodpecker/test.yml",
|
||||||
|
".woodpecker.yml",
|
||||||
|
".drone.yml",
|
||||||
|
".my-ci-folder/test.yml",
|
||||||
|
},
|
||||||
|
expectedFileNames: []string{
|
||||||
|
".my-ci-folder/test.yml",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
},
|
},
|
||||||
// fallback file call
|
|
||||||
{
|
{
|
||||||
file: []byte{},
|
name: "Special config - folder",
|
||||||
err: errors.New("File not found"),
|
repoConfig: ".my-ci-folder/",
|
||||||
|
files: []string{
|
||||||
|
".my-ci-folder/test.yml",
|
||||||
},
|
},
|
||||||
|
expectedFileNames: []string{
|
||||||
|
".my-ci-folder/test.yml",
|
||||||
},
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Special config - subfolder",
|
||||||
|
repoConfig: ".my-ci-folder/my-config/",
|
||||||
|
files: []string{
|
||||||
|
".my-ci-folder/my-config/test.yml",
|
||||||
|
},
|
||||||
|
expectedFileNames: []string{
|
||||||
|
".my-ci-folder/my-config/test.yml",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Special config - file",
|
||||||
|
repoConfig: ".config.yml",
|
||||||
|
files: []string{
|
||||||
|
".config.yml",
|
||||||
|
},
|
||||||
|
expectedFileNames: []string{
|
||||||
|
".config.yml",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Special config - file inside subfolder",
|
||||||
|
repoConfig: ".my-ci-folder/sub-folder/config.yml",
|
||||||
|
files: []string{
|
||||||
|
".my-ci-folder/sub-folder/config.yml",
|
||||||
|
},
|
||||||
|
expectedFileNames: []string{
|
||||||
|
".my-ci-folder/sub-folder/config.yml",
|
||||||
|
},
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Special config - empty repo",
|
||||||
|
repoConfig: ".config.yml",
|
||||||
|
files: []string{},
|
||||||
expectedFileNames: []string{},
|
expectedFileNames: []string{},
|
||||||
expectedError: true,
|
expectedError: true,
|
||||||
},
|
},
|
||||||
@@ -151,13 +158,26 @@ func TestFetch(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range testTable {
|
for _, tt := range testTable {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
repo := &model.Repo{Owner: "laszlocph", Name: "drone-multipipeline", Config: tt.repoConfig, Fallback: tt.repoFallback}
|
repo := &model.Repo{Owner: "laszlocph", Name: "drone-multipipeline", Config: tt.repoConfig}
|
||||||
|
|
||||||
r := new(mocks.Remote)
|
r := new(mocks.Remote)
|
||||||
for _, fileMock := range tt.fileMocks {
|
dirs := map[string][]*remote.FileMeta{}
|
||||||
r.On("File", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(fileMock.file, fileMock.err).Once()
|
for _, file := range tt.files {
|
||||||
|
r.On("File", mock.Anything, mock.Anything, mock.Anything, file).Return([]byte{}, nil)
|
||||||
|
path := filepath.Dir(file)
|
||||||
|
dirs[path] = append(dirs[path], &remote.FileMeta{
|
||||||
|
Name: file,
|
||||||
|
Data: []byte{},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
r.On("Dir", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.dirMock.files, tt.dirMock.err)
|
|
||||||
|
for path, files := range dirs {
|
||||||
|
r.On("Dir", mock.Anything, mock.Anything, mock.Anything, path).Return(files, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the previous mocks do not match return not found errors
|
||||||
|
r.On("File", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("File not found"))
|
||||||
|
r.On("Dir", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("Directory not found"))
|
||||||
|
|
||||||
configFetcher := server.NewConfigFetcher(
|
configFetcher := server.NewConfigFetcher(
|
||||||
r,
|
r,
|
||||||
@@ -182,7 +202,11 @@ func TestFetch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if matchingFiles != len(tt.expectedFileNames) {
|
if matchingFiles != len(tt.expectedFileNames) {
|
||||||
t.Fatal("expected some other pipeline files", tt.expectedFileNames, files)
|
receivedFileNames := []string{}
|
||||||
|
for _, file := range files {
|
||||||
|
receivedFileNames = append(receivedFileNames, file.Name)
|
||||||
|
}
|
||||||
|
t.Fatal("expected some other pipeline files", tt.expectedFileNames, receivedFileNames)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -52,9 +52,6 @@ func PostRepo(c *gin.Context) {
|
|||||||
repo.Visibility = model.VisibilityPrivate
|
repo.Visibility = model.VisibilityPrivate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if repo.Config == "" {
|
|
||||||
repo.Config = Config.Server.RepoConfig
|
|
||||||
}
|
|
||||||
if repo.Timeout == 0 {
|
if repo.Timeout == 0 {
|
||||||
repo.Timeout = 60 // 1 hour default build time
|
repo.Timeout = 60 // 1 hour default build time
|
||||||
}
|
}
|
||||||
@@ -149,9 +146,6 @@ func PatchRepo(c *gin.Context) {
|
|||||||
if in.BuildCounter != nil {
|
if in.BuildCounter != nil {
|
||||||
repo.Counter = *in.BuildCounter
|
repo.Counter = *in.BuildCounter
|
||||||
}
|
}
|
||||||
if in.Fallback != nil {
|
|
||||||
repo.Fallback = *in.Fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
err := store.UpdateRepo(c, repo)
|
err := store.UpdateRepo(c, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -200,6 +200,10 @@ var migrations = []struct {
|
|||||||
name: "update-builds-set-changed_files",
|
name: "update-builds-set-changed_files",
|
||||||
stmt: updateBuildsSetChangedfiles,
|
stmt: updateBuildsSetChangedfiles,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "alter-table-drop-repo-fallback",
|
||||||
|
stmt: alterTableDropRepoFallback,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate performs the database migration. If the migration fails
|
// Migrate performs the database migration. If the migration fails
|
||||||
@@ -745,3 +749,11 @@ ALTER TABLE builds ADD COLUMN changed_files TEXT
|
|||||||
var updateBuildsSetChangedfiles = `
|
var updateBuildsSetChangedfiles = `
|
||||||
UPDATE builds SET changed_files='[]'
|
UPDATE builds SET changed_files='[]'
|
||||||
`
|
`
|
||||||
|
|
||||||
|
//
|
||||||
|
// 026_drop_repo_fallback_column.sql
|
||||||
|
//
|
||||||
|
|
||||||
|
var alterTableDropRepoFallback = `
|
||||||
|
ALTER TABLE repos DROP COLUMN repo_fallback
|
||||||
|
`
|
||||||
|
@@ -0,0 +1,2 @@
|
|||||||
|
-- name: alter-table-drop-repo-fallback
|
||||||
|
ALTER TABLE repos DROP COLUMN repo_fallback
|
@@ -200,6 +200,10 @@ var migrations = []struct {
|
|||||||
name: "update-builds-set-changed_files",
|
name: "update-builds-set-changed_files",
|
||||||
stmt: updateBuildsSetChangedfiles,
|
stmt: updateBuildsSetChangedfiles,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "alter-table-drop-repo-fallback",
|
||||||
|
stmt: alterTableDropRepoFallback,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate performs the database migration. If the migration fails
|
// Migrate performs the database migration. If the migration fails
|
||||||
@@ -747,3 +751,11 @@ ALTER TABLE builds ADD COLUMN changed_files TEXT;
|
|||||||
var updateBuildsSetChangedfiles = `
|
var updateBuildsSetChangedfiles = `
|
||||||
UPDATE builds SET changed_files='[]'
|
UPDATE builds SET changed_files='[]'
|
||||||
`
|
`
|
||||||
|
|
||||||
|
//
|
||||||
|
// 026_drop_repo_fallback_column.sql
|
||||||
|
//
|
||||||
|
|
||||||
|
var alterTableDropRepoFallback = `
|
||||||
|
ALTER TABLE repos DROP COLUMN repo_fallback
|
||||||
|
`
|
||||||
|
@@ -0,0 +1,2 @@
|
|||||||
|
-- name: alter-table-drop-repo-fallback
|
||||||
|
ALTER TABLE repos DROP COLUMN repo_fallback
|
@@ -204,6 +204,10 @@ var migrations = []struct {
|
|||||||
name: "update-builds-set-changed_files",
|
name: "update-builds-set-changed_files",
|
||||||
stmt: updateBuildsSetChangedfiles,
|
stmt: updateBuildsSetChangedfiles,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "alter-table-drop-repo-fallback",
|
||||||
|
stmt: alterTableDropRepoFallback,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate performs the database migration. If the migration fails
|
// Migrate performs the database migration. If the migration fails
|
||||||
@@ -746,3 +750,65 @@ ALTER TABLE builds ADD COLUMN changed_files TEXT
|
|||||||
var updateBuildsSetChangedfiles = `
|
var updateBuildsSetChangedfiles = `
|
||||||
UPDATE builds SET changed_files='[]'
|
UPDATE builds SET changed_files='[]'
|
||||||
`
|
`
|
||||||
|
|
||||||
|
//
|
||||||
|
// 026_drop_repo_fallback_column.sql
|
||||||
|
//
|
||||||
|
|
||||||
|
var alterTableDropRepoFallback = `
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
CREATE TABLE repos_new (
|
||||||
|
repo_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
repo_user_id INTEGER,
|
||||||
|
repo_owner TEXT,
|
||||||
|
repo_name TEXT,
|
||||||
|
repo_full_name TEXT,
|
||||||
|
repo_avatar TEXT,
|
||||||
|
repo_link TEXT,
|
||||||
|
repo_clone TEXT,
|
||||||
|
repo_branch TEXT,
|
||||||
|
repo_timeout INTEGER,
|
||||||
|
repo_private BOOLEAN,
|
||||||
|
repo_trusted BOOLEAN,
|
||||||
|
repo_active BOOLEAN,
|
||||||
|
repo_allow_pr BOOLEAN,
|
||||||
|
repo_allow_push BOOLEAN,
|
||||||
|
repo_allow_deploys BOOLEAN,
|
||||||
|
repo_allow_tags BOOLEAN,
|
||||||
|
repo_hash TEXT,
|
||||||
|
repo_scm TEXT,
|
||||||
|
repo_config_path TEXT,
|
||||||
|
repo_gated BOOLEAN,
|
||||||
|
repo_visibility TEXT,
|
||||||
|
repo_counter INTEGER,
|
||||||
|
UNIQUE(repo_full_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO repos_new SELECT repo_id
|
||||||
|
,repo_user_id
|
||||||
|
,repo_owner
|
||||||
|
,repo_name
|
||||||
|
,repo_full_name
|
||||||
|
,repo_avatar
|
||||||
|
,repo_link
|
||||||
|
,repo_clone
|
||||||
|
,repo_branch
|
||||||
|
,repo_timeout
|
||||||
|
,repo_private
|
||||||
|
,repo_trusted
|
||||||
|
,repo_active
|
||||||
|
,repo_allow_pr
|
||||||
|
,repo_allow_push
|
||||||
|
,repo_allow_deploys
|
||||||
|
,repo_allow_tags
|
||||||
|
,repo_hash
|
||||||
|
,repo_scm
|
||||||
|
,repo_config_path
|
||||||
|
,repo_gated
|
||||||
|
,repo_visibility
|
||||||
|
,repo_counter FROM repos;
|
||||||
|
DROP TABLE repos;
|
||||||
|
ALTER TABLE repos_new RENAME TO repos;
|
||||||
|
COMMIT;
|
||||||
|
`
|
||||||
|
@@ -0,0 +1,56 @@
|
|||||||
|
-- name: alter-table-drop-repo-fallback
|
||||||
|
BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
CREATE TABLE repos_new (
|
||||||
|
repo_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
repo_user_id INTEGER,
|
||||||
|
repo_owner TEXT,
|
||||||
|
repo_name TEXT,
|
||||||
|
repo_full_name TEXT,
|
||||||
|
repo_avatar TEXT,
|
||||||
|
repo_link TEXT,
|
||||||
|
repo_clone TEXT,
|
||||||
|
repo_branch TEXT,
|
||||||
|
repo_timeout INTEGER,
|
||||||
|
repo_private BOOLEAN,
|
||||||
|
repo_trusted BOOLEAN,
|
||||||
|
repo_active BOOLEAN,
|
||||||
|
repo_allow_pr BOOLEAN,
|
||||||
|
repo_allow_push BOOLEAN,
|
||||||
|
repo_allow_deploys BOOLEAN,
|
||||||
|
repo_allow_tags BOOLEAN,
|
||||||
|
repo_hash TEXT,
|
||||||
|
repo_scm TEXT,
|
||||||
|
repo_config_path TEXT,
|
||||||
|
repo_gated BOOLEAN,
|
||||||
|
repo_visibility TEXT,
|
||||||
|
repo_counter INTEGER,
|
||||||
|
UNIQUE(repo_full_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO repos_new SELECT repo_id
|
||||||
|
,repo_user_id
|
||||||
|
,repo_owner
|
||||||
|
,repo_name
|
||||||
|
,repo_full_name
|
||||||
|
,repo_avatar
|
||||||
|
,repo_link
|
||||||
|
,repo_clone
|
||||||
|
,repo_branch
|
||||||
|
,repo_timeout
|
||||||
|
,repo_private
|
||||||
|
,repo_trusted
|
||||||
|
,repo_active
|
||||||
|
,repo_allow_pr
|
||||||
|
,repo_allow_push
|
||||||
|
,repo_allow_deploys
|
||||||
|
,repo_allow_tags
|
||||||
|
,repo_hash
|
||||||
|
,repo_scm
|
||||||
|
,repo_config_path
|
||||||
|
,repo_gated
|
||||||
|
,repo_visibility
|
||||||
|
,repo_counter FROM repos;
|
||||||
|
DROP TABLE repos;
|
||||||
|
ALTER TABLE repos_new RENAME TO repos;
|
||||||
|
COMMIT;
|
@@ -93,7 +93,6 @@ func (db *datastore) RepoBatch(repos []*model.Repo) error {
|
|||||||
repo.IsGated,
|
repo.IsGated,
|
||||||
repo.Visibility,
|
repo.Visibility,
|
||||||
repo.Counter,
|
repo.Counter,
|
||||||
repo.Fallback,
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -30,7 +30,6 @@ SELECT
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
|
||||||
FROM repos
|
FROM repos
|
||||||
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
||||||
WHERE perms.perm_user_id = ?
|
WHERE perms.perm_user_id = ?
|
||||||
@@ -61,8 +60,7 @@ INSERT IGNORE INTO repos (
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
||||||
|
|
||||||
-- name: repo-delete
|
-- name: repo-delete
|
||||||
|
|
||||||
|
@@ -448,7 +448,6 @@ SELECT
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
|
||||||
FROM repos
|
FROM repos
|
||||||
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
||||||
WHERE perms.perm_user_id = ?
|
WHERE perms.perm_user_id = ?
|
||||||
@@ -479,8 +478,7 @@ INSERT IGNORE INTO repos (
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
||||||
`
|
`
|
||||||
|
|
||||||
var repoDelete = `
|
var repoDelete = `
|
||||||
|
@@ -30,7 +30,6 @@ SELECT
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
|
||||||
FROM repos
|
FROM repos
|
||||||
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
||||||
WHERE perms.perm_user_id = $1
|
WHERE perms.perm_user_id = $1
|
||||||
@@ -61,8 +60,7 @@ INSERT INTO repos (
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22)
|
||||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23)
|
|
||||||
ON CONFLICT (repo_full_name) DO NOTHING
|
ON CONFLICT (repo_full_name) DO NOTHING
|
||||||
|
|
||||||
-- name: repo-delete
|
-- name: repo-delete
|
||||||
|
@@ -451,7 +451,6 @@ SELECT
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
|
||||||
FROM repos
|
FROM repos
|
||||||
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
||||||
WHERE perms.perm_user_id = $1
|
WHERE perms.perm_user_id = $1
|
||||||
@@ -482,8 +481,7 @@ INSERT INTO repos (
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22)
|
||||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23)
|
|
||||||
ON CONFLICT (repo_full_name) DO NOTHING
|
ON CONFLICT (repo_full_name) DO NOTHING
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@@ -30,7 +30,6 @@ SELECT
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
|
||||||
FROM repos
|
FROM repos
|
||||||
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
||||||
WHERE perms.perm_user_id = ?
|
WHERE perms.perm_user_id = ?
|
||||||
@@ -61,8 +60,7 @@ INSERT OR IGNORE INTO repos (
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
||||||
|
|
||||||
-- name: repo-delete
|
-- name: repo-delete
|
||||||
|
|
||||||
|
@@ -448,7 +448,6 @@ SELECT
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
|
||||||
FROM repos
|
FROM repos
|
||||||
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
INNER JOIN perms ON perms.perm_repo_id = repos.repo_id
|
||||||
WHERE perms.perm_user_id = ?
|
WHERE perms.perm_user_id = ?
|
||||||
@@ -479,8 +478,7 @@ INSERT OR IGNORE INTO repos (
|
|||||||
,repo_gated
|
,repo_gated
|
||||||
,repo_visibility
|
,repo_visibility
|
||||||
,repo_counter
|
,repo_counter
|
||||||
,repo_fallback
|
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
||||||
`
|
`
|
||||||
|
|
||||||
var repoDelete = `
|
var repoDelete = `
|
||||||
|
@@ -41,7 +41,6 @@ export default class Settings extends Component {
|
|||||||
this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
|
this.handleVisibilityChange = this.handleVisibilityChange.bind(this);
|
||||||
this.handleTimeoutChange = this.handleTimeoutChange.bind(this);
|
this.handleTimeoutChange = this.handleTimeoutChange.bind(this);
|
||||||
this.handlePathChange = this.handlePathChange.bind(this);
|
this.handlePathChange = this.handlePathChange.bind(this);
|
||||||
this.handleFallbackChange = this.handleFallbackChange.bind(this);
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,14 +73,6 @@ export default class Settings extends Component {
|
|||||||
value={repo.config_file}
|
value={repo.config_file}
|
||||||
onBlur={this.handlePathChange}
|
onBlur={this.handlePathChange}
|
||||||
/>
|
/>
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={repo.fallback}
|
|
||||||
onChange={this.handleFallbackChange}
|
|
||||||
/>
|
|
||||||
<span>Fallback to .drone.yml if path not exists</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
@@ -231,10 +222,6 @@ export default class Settings extends Component {
|
|||||||
this.handleChange("config_file", e.target.value);
|
this.handleChange("config_file", e.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFallbackChange(e) {
|
|
||||||
this.handleChange("fallback", e.target.checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChange(prop, value) {
|
handleChange(prop, value) {
|
||||||
const { dispatch, drone, repo } = this.props;
|
const { dispatch, drone, repo } = this.props;
|
||||||
let data = {};
|
let data = {};
|
||||||
|
Reference in New Issue
Block a user