From 7835a632e445c8bbe286aed4f04975151f238fb5 Mon Sep 17 00:00:00 2001 From: Earl Warren <109468362+earl-warren@users.noreply.github.com> Date: Wed, 1 Feb 2023 18:53:19 +0100 Subject: [PATCH] Define WOODPECKER_FORGE_TIMEOUT server config (#1558) When a server such as Codeberg has unusually high response time, three seconds may not be enough to fetch the configuration. Signed-off-by: Earl Warren Co-authored-by: 6543 <6543@obermui.de> --- cmd/server/flags.go | 6 ++++++ cmd/server/server.go | 1 + docs/docs/30-administration/10-server-config.md | 7 +++++++ server/config.go | 1 + server/forge/configFetcher.go | 11 +++++------ server/forge/configFetcher_test.go | 3 +++ server/pipeline/create.go | 2 +- 7 files changed, 24 insertions(+), 7 deletions(-) diff --git a/cmd/server/flags.go b/cmd/server/flags.go index 9c5323beb..e447f5427 100644 --- a/cmd/server/flags.go +++ b/cmd/server/flags.go @@ -209,6 +209,12 @@ var flags = []cli.Flag{ // // resource limit parameters // + &cli.DurationFlag{ + EnvVars: []string{"WOODPECKER_FORGE_TIMEOUT"}, + Name: "forge-timeout", + Usage: "how many seconds before timeout when fetching the Woodpecker configuration from a Forge", + Value: time.Second * 3, + }, &cli.Int64Flag{ EnvVars: []string{"WOODPECKER_LIMIT_MEM_SWAP"}, Name: "limit-mem-swap", diff --git a/cmd/server/server.go b/cmd/server/server.go index 7a26b734d..c81a2cb66 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -269,6 +269,7 @@ func setupEvilGlobals(c *cli.Context, v store.Store, f forge.Forge) { // forge server.Config.Services.Forge = f + server.Config.Services.Timeout = c.Duration("forge-timeout") // services server.Config.Services.Queue = setupQueue(c, v) diff --git a/docs/docs/30-administration/10-server-config.md b/docs/docs/30-administration/10-server-config.md index 62cb9fe68..62a183709 100644 --- a/docs/docs/30-administration/10-server-config.md +++ b/docs/docs/30-administration/10-server-config.md @@ -377,6 +377,13 @@ Example: `WOODPECKER_LIMIT_CPU_SET=1,2` Specify a configuration service endpoint, see [Configuration Extension](./100-external-configuration-api.md) + +### `WOODPECKER_FORGE_TIMEOUT` +> Default: 3sec + +Specify how many seconds before timeout when fetching the Woodpecker configuration from a Forge + + --- ### `WOODPECKER_GITHUB_...` diff --git a/server/config.go b/server/config.go index 774f4ea0b..7bb7f1205 100644 --- a/server/config.go +++ b/server/config.go @@ -39,6 +39,7 @@ var Config = struct { Registries model.RegistryService Environ model.EnvironService Forge forge.Forge + Timeout time.Duration Membership cache.MembershipService ConfigService config.Extension SignaturePrivateKey crypto.PrivateKey diff --git a/server/forge/configFetcher.go b/server/forge/configFetcher.go index 24ee17f13..53c8656e0 100644 --- a/server/forge/configFetcher.go +++ b/server/forge/configFetcher.go @@ -39,28 +39,27 @@ type configFetcher struct { repo *model.Repo pipeline *model.Pipeline configExtension config.Extension + timeout time.Duration } -func NewConfigFetcher(forge Forge, configExtension config.Extension, user *model.User, repo *model.Repo, pipeline *model.Pipeline) ConfigFetcher { +func NewConfigFetcher(forge Forge, timeout time.Duration, configExtension config.Extension, user *model.User, repo *model.Repo, pipeline *model.Pipeline) ConfigFetcher { return &configFetcher{ forge: forge, user: user, repo: repo, pipeline: pipeline, configExtension: configExtension, + timeout: timeout, } } -// configFetchTimeout determine seconds the configFetcher wait until cancel fetch process -var configFetchTimeout = time.Second * 3 - // Fetch pipeline config from source forge func (cf *configFetcher) Fetch(ctx context.Context) (files []*types.FileMeta, err error) { log.Trace().Msgf("Start Fetching config for '%s'", cf.repo.FullName) // try to fetch 3 times for i := 0; i < 3; i++ { - files, err = cf.fetch(ctx, configFetchTimeout, strings.TrimSpace(cf.repo.Config)) + files, err = cf.fetch(ctx, time.Second*cf.timeout, strings.TrimSpace(cf.repo.Config)) if err != nil { log.Trace().Err(err).Msgf("%d. try failed", i+1) } @@ -69,7 +68,7 @@ func (cf *configFetcher) Fetch(ctx context.Context) (files []*types.FileMeta, er } if cf.configExtension != nil && cf.configExtension.IsConfigured() { - fetchCtx, cancel := context.WithTimeout(ctx, configFetchTimeout) + fetchCtx, cancel := context.WithTimeout(ctx, cf.timeout) defer cancel() // ok here as we only try http fetching once, returning on fail and success log.Trace().Msgf("ConfigFetch[%s]: getting config from external http service", cf.repo.FullName) diff --git a/server/forge/configFetcher_test.go b/server/forge/configFetcher_test.go index f6c4b101d..775455689 100644 --- a/server/forge/configFetcher_test.go +++ b/server/forge/configFetcher_test.go @@ -25,6 +25,7 @@ import ( "net/http/httptest" "path/filepath" "testing" + "time" "github.com/go-ap/httpsig" "github.com/stretchr/testify/assert" @@ -314,6 +315,7 @@ func TestFetch(t *testing.T) { configFetcher := forge.NewConfigFetcher( f, + time.Second*3, config.NewHTTP("", ""), &model.User{Token: "xxx"}, repo, @@ -519,6 +521,7 @@ func TestFetchFromConfigService(t *testing.T) { configFetcher := forge.NewConfigFetcher( f, + time.Second*3, configAPI, &model.User{Token: "xxx"}, repo, diff --git a/server/pipeline/create.go b/server/pipeline/create.go index 3dc227156..eca1ed2bc 100644 --- a/server/pipeline/create.go +++ b/server/pipeline/create.go @@ -60,7 +60,7 @@ func Create(ctx context.Context, _store store.Store, repo *model.Repo, pipeline ) // fetch the pipeline file from the forge - configFetcher := forge.NewConfigFetcher(server.Config.Services.Forge, server.Config.Services.ConfigService, repoUser, repo, pipeline) + configFetcher := forge.NewConfigFetcher(server.Config.Services.Forge, server.Config.Services.Timeout, server.Config.Services.ConfigService, repoUser, repo, pipeline) forgeYamlConfigs, configFetchErr = configFetcher.Fetch(ctx) if configFetchErr == nil { filtered, parseErr = checkIfFiltered(pipeline, forgeYamlConfigs)