Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions cmd/server/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,24 @@ var flags = append([]cli.Flag{
Name: "config-extension-netrc",
Usage: "whether global configuration extension should receive netrc data",
},
&cli.StringSliceFlag{
Sources: cli.EnvVars("WOODPECKER_DEFAULT_PIPELINE_CONFIGS"),
Name: "default-pipeline-configs",
Usage: "default pipeline config paths to check",
Value: constant.DefaultConfigOrder,
Config: cli.StringConfig{
TrimSpace: true,
},
},
&cli.StringSliceFlag{
Sources: cli.EnvVars("WOODPECKER_DEFAULT_PIPELINE_CONFIG_EXTENSIONS"),
Name: "default-pipeline-config-extensions",
Usage: "default pipeline config extensions when scanning a pipeline config directory",
Value: []string{".yaml", ".yml"},
Config: cli.StringConfig{
TrimSpace: true,
},
},
&cli.StringFlag{
Sources: cli.EnvVars("WOODPECKER_REGISTRY_EXTENSION_ENDPOINT"),
Name: "registry-extension-endpoint",
Expand Down
18 changes: 18 additions & 0 deletions docs/docs/30-administration/10-configuration/10-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,24 @@ Specify a configuration extension endpoint, see [Configuration Extension](../../

---

### DEFAULT_PIPELINE_CONFIGS

- Name: `WOODPECKER_DEFAULT_PIPELINE_CONFIGS`
- Default: `.woodpecker/`, `.woodpecker.yaml`, `.woodpecker.yml`

Specify the default pipeline config paths.

---

### DEFAULT_PIPELINE_CONFIG_EXTENSIONS

- Name: `WOODPECKER_DEFAULT_PIPELINE_CONFIG_EXTENSIONS`
- Default: `.yaml`, `.yml`

Specify the default pipeline config extensions when scanning a pipeline config directory.

---

### CONFIG_EXTENSION_EXCLUSIVE

- Name: `CONFIG_EXTENSION_EXCLUSIVE`
Expand Down
3 changes: 3 additions & 0 deletions e2e/setup/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"go.woodpecker-ci.org/woodpecker/v3/server/services"
"go.woodpecker-ci.org/woodpecker/v3/server/services/permissions"
"go.woodpecker-ci.org/woodpecker/v3/server/store"
"go.woodpecker-ci.org/woodpecker/v3/shared/constant"
)

const (
Expand Down Expand Up @@ -151,6 +152,8 @@ func newTestManager(s store.Store, mockForge *forge_mocks.MockForge) (services.M
// Forge flags — gitea=true satisfies setupForgeService's type switch.
&cli.BoolFlag{Name: string(TestForgeType), Value: true},
&cli.StringFlag{Name: "forge-url", Value: "https://forge.example.test"},
&cli.StringSliceFlag{Name: "default-pipeline-configs", Value: constant.DefaultConfigOrder},
&cli.StringSliceFlag{Name: "default-pipeline-config-extensions", Value: []string{".yaml", ".yml"}},
},
}

Expand Down
3 changes: 2 additions & 1 deletion server/services/config/combined_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/server/services/config"
"go.woodpecker-ci.org/woodpecker/v3/server/services/utils"
"go.woodpecker-ci.org/woodpecker/v3/shared/constant"
)

func TestFetchFromConfigService(t *testing.T) {
Expand Down Expand Up @@ -220,7 +221,7 @@ func TestFetchFromConfigService(t *testing.T) {

f.On("Netrc", mock.Anything, mock.Anything).Return(&model.Netrc{Machine: "mock", Login: "mock", Password: "mock"}, nil)

forgeFetcher := config.NewForge(time.Second*3, 3)
forgeFetcher := config.NewForge(time.Second*3, 3, constant.DefaultConfigOrder, []string{".yaml", ".yml"})
configFetcher := config.NewCombined(forgeFetcher, httpFetcher)
files, err := configFetcher.Fetch(
t.Context(),
Expand Down
49 changes: 29 additions & 20 deletions server/services/config/forge.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"context"
"errors"
"fmt"
"path/filepath"
"slices"
"strings"
"time"

Expand All @@ -26,18 +28,21 @@ import (
"go.woodpecker-ci.org/woodpecker/v3/server/forge"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/types"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/shared/constant"
)

type forgeFetcher struct {
timeout time.Duration
retryCount uint
timeout time.Duration
retryCount uint
configPaths []string
configExtensions []string
}

func NewForge(timeout time.Duration, retries uint) Service {
func NewForge(timeout time.Duration, retries uint, configPaths, configExtensions []string) Service {
return &forgeFetcher{
timeout: timeout,
retryCount: retries,
timeout: timeout,
retryCount: retries,
configPaths: configPaths,
configExtensions: configExtensions,
}
}

Expand All @@ -48,11 +53,13 @@ func (f *forgeFetcher) Fetch(ctx context.Context, forge forge.Forge, user *model
}

ffc := &forgeFetcherContext{
forge: forge,
user: user,
repo: repo,
pipeline: pipeline,
timeout: f.timeout,
forge: forge,
user: user,
repo: repo,
pipeline: pipeline,
timeout: f.timeout,
configPaths: f.configPaths,
configExtensions: f.configExtensions,
}

// try to fetch multiple times
Expand All @@ -69,11 +76,13 @@ func (f *forgeFetcher) Fetch(ctx context.Context, forge forge.Forge, user *model
}

type forgeFetcherContext struct {
forge forge.Forge
user *model.User
repo *model.Repo
pipeline *model.Pipeline
timeout time.Duration
forge forge.Forge
user *model.User
repo *model.Repo
pipeline *model.Pipeline
timeout time.Duration
configPaths []string
configExtensions []string
}

// fetch attempts to fetch the configuration file(s) for the given config string.
Expand All @@ -97,7 +106,7 @@ func (f *forgeFetcherContext) fetch(c context.Context, config string) ([]*types.

log.Trace().Msgf("configFetcher[%s]: user did not define own config, following default procedure", f.repo.FullName)
// for the order see shared/constants/constants.go
fileMetas, err := f.getFirstAvailableConfig(ctx, constant.DefaultConfigOrder[:])
fileMetas, err := f.getFirstAvailableConfig(ctx, f.configPaths)
if err == nil {
return fileMetas, nil
}
Expand All @@ -110,11 +119,11 @@ func (f *forgeFetcherContext) fetch(c context.Context, config string) ([]*types.
}
}

func filterPipelineFiles(files []*types.FileMeta) []*types.FileMeta {
func (f *forgeFetcherContext) filterPipelineFiles(files []*types.FileMeta) []*types.FileMeta {
var res []*types.FileMeta

for _, file := range files {
if strings.HasSuffix(file.Name, ".yml") || strings.HasSuffix(file.Name, ".yaml") {
if slices.Contains(f.configExtensions, filepath.Ext(file.Name)) {
res = append(res, file)
}
}
Expand Down Expand Up @@ -154,7 +163,7 @@ func (f *forgeFetcherContext) getFirstAvailableConfig(c context.Context, configs
}
continue
}
files = filterPipelineFiles(files)
files = f.filterPipelineFiles(files)
if len(files) != 0 {
log.Trace().Msgf("configFetcher[%s]: found %d files in '%s'", f.repo.FullName, len(files), fileOrFolder)
return files, nil
Expand Down
3 changes: 3 additions & 0 deletions server/services/config/forge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
forge_types "go.woodpecker-ci.org/woodpecker/v3/server/forge/types"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/server/services/config"
"go.woodpecker-ci.org/woodpecker/v3/shared/constant"
)

func TestFetch(t *testing.T) {
Expand Down Expand Up @@ -307,6 +308,8 @@ func TestFetch(t *testing.T) {
configFetcher := config.NewForge(
time.Second*3,
3,
constant.DefaultConfigOrder,
[]string{".yaml", ".yml"},
)
files, err := configFetcher.Fetch(
t.Context(),
Expand Down
2 changes: 1 addition & 1 deletion server/services/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func setupConfigService(c *cli.Command, client *utils.Client) (config.Service, e
if retries == 0 {
return nil, fmt.Errorf("WOODPECKER_FORGE_RETRY can not be 0")
}
configFetcher := config.NewForge(timeout, retries)
configFetcher := config.NewForge(timeout, retries, c.StringSlice("default-pipeline-configs"), c.StringSlice("default-pipeline-config-extensions"))

if endpoint := c.String("config-extension-endpoint"); endpoint != "" {
httpFetcher := config.NewHTTP(endpoint, client, c.Bool("config-extension-netrc"))
Expand Down
4 changes: 2 additions & 2 deletions shared/constant/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ package constant

import "time"

// DefaultConfigOrder represent the priority in witch woodpecker search for a pipeline config by default
// DefaultConfigOrder represent the priority in which woodpecker searches for a pipeline config by default
// folders are indicated by supplying a trailing slash.
var DefaultConfigOrder = [...]string{
var DefaultConfigOrder = []string{
".woodpecker/",
".woodpecker.yaml",
".woodpecker.yml",
Expand Down