Cleanup server env settings (#3670)

Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
Co-authored-by: Robert Kaussow <xoxys@rknet.org>
This commit is contained in:
Anbraten 2024-05-15 15:45:08 +02:00 committed by GitHub
parent faf6b33140
commit 5527d9bf86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 70 additions and 39 deletions

View file

@ -4,6 +4,7 @@ tasks:
WOODPECKER_OPEN: true WOODPECKER_OPEN: true
WOODPECKER_ADMIN: woodpecker WOODPECKER_ADMIN: woodpecker
WOODPECKER_HOST: http://host.docker.internal:8000 WOODPECKER_HOST: http://host.docker.internal:8000
WOODPECKER_EXPERT_WEBHOOK_HOST: http://host.docker.internal:8000
WOODPECKER_AGENT_SECRET: '1234' WOODPECKER_AGENT_SECRET: '1234'
WOODPECKER_GITEA: true WOODPECKER_GITEA: true
WOODPECKER_DEV_WWW_PROXY: http://localhost:8010 WOODPECKER_DEV_WWW_PROXY: http://localhost:8010
@ -20,9 +21,9 @@ tasks:
grep "WOODPECKER_GITEA_URL=" .env \ grep "WOODPECKER_GITEA_URL=" .env \
&& sed "s,^WOODPECKER_GITEA_URL=.*,WOODPECKER_GITEA_URL=$(gp url 3000)," .env \ && sed "s,^WOODPECKER_GITEA_URL=.*,WOODPECKER_GITEA_URL=$(gp url 3000)," .env \
|| echo WOODPECKER_GITEA_URL=$(gp url 3000) >> .env || echo WOODPECKER_GITEA_URL=$(gp url 3000) >> .env
grep "WOODPECKER_DEV_OAUTH_HOST=" .env \ grep "WOODPECKER_HOST=" .env \
&& sed "s,^WOODPECKER_DEV_OAUTH_HOST=.*,WOODPECKER_DEV_OAUTH_HOST=$(gp url 8000)," .env \ && sed "s,^WOODPECKER_HOST=.*,WOODPECKER_HOST=$(gp url 8000)," .env \
|| echo WOODPECKER_DEV_OAUTH_HOST=$(gp url 8000) >> .env || echo WOODPECKER_HOST=$(gp url 8000) >> .env
gp sync-await gitea gp sync-await gitea
gp sync-done woodpecker-server gp sync-done woodpecker-server
go run go.woodpecker-ci.org/woodpecker/v2/cmd/server go run go.woodpecker-ci.org/woodpecker/v2/cmd/server

View file

@ -38,12 +38,7 @@ var flags = append([]cli.Flag{
&cli.StringFlag{ &cli.StringFlag{
EnvVars: []string{"WOODPECKER_HOST"}, EnvVars: []string{"WOODPECKER_HOST"},
Name: "server-host", Name: "server-host",
Usage: "server fully qualified url (<scheme>://<host>[/<prefixpath>])", Usage: "server fully qualified url. Format: <scheme>://<host>[/<prefixpath>]",
},
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_WEBHOOK_HOST"},
Name: "server-webhook-host",
Usage: "server fully qualified url for forge's Webhooks (<scheme>://<host>[/<prefixpath>])",
}, },
&cli.StringFlag{ &cli.StringFlag{
EnvVars: []string{"WOODPECKER_SERVER_ADDR"}, EnvVars: []string{"WOODPECKER_SERVER_ADDR"},
@ -330,6 +325,11 @@ var flags = append([]cli.Flag{
Usage: "skip ssl verification", Usage: "skip ssl verification",
EnvVars: []string{"WOODPECKER_FORGE_SKIP_VERIFY", "WOODPECKER_GITHUB_SKIP_VERIFY", "WOODPECKER_GITLAB_SKIP_VERIFY", "WOODPECKER_GITEA_SKIP_VERIFY", "WOODPECKER_BITBUCKET_SKIP_VERIFY"}, EnvVars: []string{"WOODPECKER_FORGE_SKIP_VERIFY", "WOODPECKER_GITHUB_SKIP_VERIFY", "WOODPECKER_GITLAB_SKIP_VERIFY", "WOODPECKER_GITEA_SKIP_VERIFY", "WOODPECKER_BITBUCKET_SKIP_VERIFY"},
}, },
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_EXPERT_FORGE_OAUTH_HOST", "WOODPECKER_DEV_GITEA_OAUTH_URL"}, // TODO: remove WOODPECKER_DEV_GITEA_OAUTH_URL in next major release
Name: "forge-oauth-host",
Usage: "!!!for experts!!! fully qualified public forge url. Use it if your forge url WOODPECKER_FORGE_URL or WOODPECKER_GITEA_URL, ... isn't a public url. Format: <scheme>://<host>[/<prefixpath>]",
},
// //
// Addon // Addon
// //
@ -366,11 +366,6 @@ var flags = append([]cli.Flag{
Name: "gitea", Name: "gitea",
Usage: "gitea driver is enabled", Usage: "gitea driver is enabled",
}, },
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_DEV_GITEA_OAUTH_URL"},
Name: "gitea-oauth-server",
Usage: "user-facing gitea server url for oauth",
},
// //
// Bitbucket // Bitbucket
// //
@ -416,10 +411,19 @@ var flags = append([]cli.Flag{
Usage: "serve the website by using a proxy (used for development)", Usage: "serve the website by using a proxy (used for development)",
Hidden: true, Hidden: true,
}, },
//
// expert flags
//
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_EXPERT_WEBHOOK_HOST", "WOODPECKER_WEBHOOK_HOST"}, // TODO: remove WOODPECKER_WEBHOOK_HOST in next major release
Name: "server-webhook-host",
Usage: "!!!for experts!!! fully qualified woodpecker server url called by forge's webhooks. Format: <scheme>://<host>[/<prefixpath>]",
},
// TODO: remove in next major release
&cli.StringFlag{ &cli.StringFlag{
EnvVars: []string{"WOODPECKER_DEV_OAUTH_HOST"}, EnvVars: []string{"WOODPECKER_DEV_OAUTH_HOST"},
Name: "server-dev-oauth-host", Name: "server-dev-oauth-host-deprecated",
Usage: "server fully qualified url (<scheme>://<host>[/<prefixpath>]) used for oauth redirect (used for development)", Usage: "DEPRECATED: use WOODPECKER_EXPERT_FORGE_OAUTH_HOST instead\nfully qualified url used for oauth redirects. Format: <scheme>://<host>[/<prefixpath>]",
Value: "", Value: "",
Hidden: true, Hidden: true,
}, },

View file

@ -317,8 +317,8 @@ func setupEvilGlobals(c *cli.Context, s store.Store) error {
} else { } else {
server.Config.Server.WebhookHost = serverHost server.Config.Server.WebhookHost = serverHost
} }
if c.IsSet("server-dev-oauth-host") { if c.IsSet("server-dev-oauth-host-deprecated") {
server.Config.Server.OAuthHost = c.String("server-dev-oauth-host") server.Config.Server.OAuthHost = c.String("server-dev-oauth-host-deprecated")
} else { } else {
server.Config.Server.OAuthHost = serverHost server.Config.Server.OAuthHost = serverHost
} }

View file

@ -50,6 +50,7 @@ Sometimes there are multiple terms that can be used to describe something. This
- Environment variables `*_LINK` should be called `*_URL`. In the code use `URL()` instead of `Link()` - Environment variables `*_LINK` should be called `*_URL`. In the code use `URL()` instead of `Link()`
- Use the term **pipelines** instead of the previous **builds** - Use the term **pipelines** instead of the previous **builds**
- Use the term **steps** instead of the previous **jobs** - Use the term **steps** instead of the previous **jobs**
- Use the prefix `WOODPECKER_EXPERT_` for advanced environment variables that are normally not required to be set by users
<!-- References --> <!-- References -->

View file

@ -12,6 +12,8 @@ Some versions need some changes to the server configuration or the pipeline conf
- Deprecated alternative names for secrets, use `environment` with `from_secret` - Deprecated alternative names for secrets, use `environment` with `from_secret`
- Deprecated slice definition for env vars - Deprecated slice definition for env vars
- Deprecated `environment` filter, use `when.evaluate` - Deprecated `environment` filter, use `when.evaluate`
- Use `WOODPECKER_EXPERT_FORGE_OAUTH_HOST` instead of `WOODPECKER_DEV_GITEA_OAUTH_URL` or `WOODPECKER_DEV_OAUTH_HOST`
- Deprecated `WOODPECKER_WEBHOOK_HOST` in favor of `WOODPECKER_EXPERT_WEBHOOK_HOST`
## 2.0.0 ## 2.0.0

View file

@ -43,6 +43,7 @@ type Opts struct {
Password string // Git machine account password. Password string // Git machine account password.
ClientID string // OAuth 2.0 client id ClientID string // OAuth 2.0 client id
ClientSecret string // OAuth 2.0 client secret ClientSecret string // OAuth 2.0 client secret
OAuthHost string // OAuth 2.0 host
} }
type client struct { type client struct {
@ -50,6 +51,7 @@ type client struct {
urlAPI string urlAPI string
clientID string clientID string
clientSecret string clientSecret string
oauthHost string
username string username string
password string password string
} }
@ -62,6 +64,7 @@ func New(opts Opts) (forge.Forge, error) {
urlAPI: fmt.Sprintf("%s/rest", opts.URL), urlAPI: fmt.Sprintf("%s/rest", opts.URL),
clientID: opts.ClientID, clientID: opts.ClientID,
clientSecret: opts.ClientSecret, clientSecret: opts.ClientSecret,
oauthHost: opts.OAuthHost,
username: opts.Username, username: opts.Username,
password: opts.Password, password: opts.Password,
} }
@ -608,11 +611,16 @@ func (c *client) Org(_ context.Context, _ *model.User, owner string) (*model.Org
} }
func (c *client) newOAuth2Config() *oauth2.Config { func (c *client) newOAuth2Config() *oauth2.Config {
publicOAuthURL := c.oauthHost
if publicOAuthURL == "" {
publicOAuthURL = c.urlAPI
}
return &oauth2.Config{ return &oauth2.Config{
ClientID: c.clientID, ClientID: c.clientID,
ClientSecret: c.clientSecret, ClientSecret: c.clientSecret,
Endpoint: oauth2.Endpoint{ Endpoint: oauth2.Endpoint{
AuthURL: fmt.Sprintf("%s/oauth2/latest/authorize", c.urlAPI), AuthURL: fmt.Sprintf("%s/oauth2/latest/authorize", publicOAuthURL),
TokenURL: fmt.Sprintf("%s/oauth2/latest/token", c.urlAPI), TokenURL: fmt.Sprintf("%s/oauth2/latest/token", c.urlAPI),
}, },
Scopes: []string{string(bb.PermissionRepoRead), string(bb.PermissionRepoWrite), string(bb.PermissionRepoAdmin)}, Scopes: []string{string(bb.PermissionRepoRead), string(bb.PermissionRepoWrite), string(bb.PermissionRepoAdmin)},

View file

@ -50,9 +50,9 @@ const (
type Gitea struct { type Gitea struct {
url string url string
oauth2URL string
ClientID string ClientID string
ClientSecret string ClientSecret string
OAuthHost string
SkipVerify bool SkipVerify bool
pageSize int pageSize int
} }
@ -60,24 +60,20 @@ type Gitea struct {
// Opts defines configuration options. // Opts defines configuration options.
type Opts struct { type Opts struct {
URL string // Gitea server url. URL string // Gitea server url.
OAuth2URL string // User-facing Gitea server url for OAuth2.
Client string // OAuth2 Client ID Client string // OAuth2 Client ID
Secret string // OAuth2 Client Secret Secret string // OAuth2 Client Secret
OAuthHost string // OAuth2 Host
SkipVerify bool // Skip ssl verification. SkipVerify bool // Skip ssl verification.
} }
// New returns a Forge implementation that integrates with Gitea, // New returns a Forge implementation that integrates with Gitea,
// an open source Git service written in Go. See https://gitea.io/ // an open source Git service written in Go. See https://gitea.io/
func New(opts Opts) (forge.Forge, error) { func New(opts Opts) (forge.Forge, error) {
if opts.OAuth2URL == "" {
opts.OAuth2URL = opts.URL
}
return &Gitea{ return &Gitea{
url: opts.URL, url: opts.URL,
oauth2URL: opts.OAuth2URL,
ClientID: opts.Client, ClientID: opts.Client,
ClientSecret: opts.Secret, ClientSecret: opts.Secret,
OAuthHost: opts.OAuthHost,
SkipVerify: opts.SkipVerify, SkipVerify: opts.SkipVerify,
}, nil }, nil
} }
@ -93,12 +89,16 @@ func (c *Gitea) URL() string {
} }
func (c *Gitea) oauth2Config(ctx context.Context) (*oauth2.Config, context.Context) { func (c *Gitea) oauth2Config(ctx context.Context) (*oauth2.Config, context.Context) {
publicOAuthURL := c.OAuthHost
if publicOAuthURL == "" {
publicOAuthURL = c.url
}
return &oauth2.Config{ return &oauth2.Config{
ClientID: c.ClientID, ClientID: c.ClientID,
ClientSecret: c.ClientSecret, ClientSecret: c.ClientSecret,
Endpoint: oauth2.Endpoint{ Endpoint: oauth2.Endpoint{
AuthURL: fmt.Sprintf(authorizeTokenURL, c.oauth2URL), AuthURL: fmt.Sprintf(authorizeTokenURL, publicOAuthURL),
TokenURL: fmt.Sprintf(accessTokenURL, c.oauth2URL), TokenURL: fmt.Sprintf(accessTokenURL, c.url),
}, },
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost), RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost),
}, },

View file

@ -52,6 +52,7 @@ type Opts struct {
SkipVerify bool // Skip ssl verification. SkipVerify bool // Skip ssl verification.
MergeRef bool // Clone pull requests using the merge ref. MergeRef bool // Clone pull requests using the merge ref.
OnlyPublic bool // Only obtain OAuth tokens with access to public repos. OnlyPublic bool // Only obtain OAuth tokens with access to public repos.
OAuthHost string // Public url for oauth if different from url.
} }
// New returns a Forge implementation that integrates with a GitHub Cloud or // New returns a Forge implementation that integrates with a GitHub Cloud or
@ -62,6 +63,7 @@ func New(opts Opts) (forge.Forge, error) {
url: defaultURL, url: defaultURL,
Client: opts.Client, Client: opts.Client,
Secret: opts.Secret, Secret: opts.Secret,
oAuthHost: opts.OAuthHost,
SkipVerify: opts.SkipVerify, SkipVerify: opts.SkipVerify,
MergeRef: opts.MergeRef, MergeRef: opts.MergeRef,
OnlyPublic: opts.OnlyPublic, OnlyPublic: opts.OnlyPublic,
@ -82,6 +84,7 @@ type client struct {
SkipVerify bool SkipVerify bool
MergeRef bool MergeRef bool
OnlyPublic bool OnlyPublic bool
oAuthHost string
} }
// Name returns the string name of this driver. // Name returns the string name of this driver.
@ -415,12 +418,17 @@ func (c *client) newConfig() *oauth2.Config {
scopes = append(scopes, "repo") scopes = append(scopes, "repo")
} }
publicOAuthURL := c.oAuthHost
if publicOAuthURL == "" {
publicOAuthURL = c.url
}
return &oauth2.Config{ return &oauth2.Config{
ClientID: c.Client, ClientID: c.Client,
ClientSecret: c.Secret, ClientSecret: c.Secret,
Scopes: scopes, Scopes: scopes,
Endpoint: oauth2.Endpoint{ Endpoint: oauth2.Endpoint{
AuthURL: fmt.Sprintf("%s/login/oauth/authorize", c.url), AuthURL: fmt.Sprintf("%s/login/oauth/authorize", publicOAuthURL),
TokenURL: fmt.Sprintf("%s/login/oauth/access_token", c.url), TokenURL: fmt.Sprintf("%s/login/oauth/access_token", c.url),
}, },
RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost), RedirectURL: fmt.Sprintf("%s/authorize", server.Config.Server.OAuthHost),

View file

@ -51,6 +51,7 @@ type Opts struct {
ClientID string // Oauth2 client id. ClientID string // Oauth2 client id.
ClientSecret string // Oauth2 client secret. ClientSecret string // Oauth2 client secret.
SkipVerify bool // Skip ssl verification. SkipVerify bool // Skip ssl verification.
OAuthHost string // Public url for oauth if different from url.
} }
// Gitlab implements "Forge" interface. // Gitlab implements "Forge" interface.
@ -61,6 +62,7 @@ type GitLab struct {
SkipVerify bool SkipVerify bool
HideArchives bool HideArchives bool
Search bool Search bool
oAuthHost string
} }
// New returns a Forge implementation that integrates with Gitlab, an open // New returns a Forge implementation that integrates with Gitlab, an open
@ -70,6 +72,7 @@ func New(opts Opts) (forge.Forge, error) {
url: opts.URL, url: opts.URL,
ClientID: opts.ClientID, ClientID: opts.ClientID,
ClientSecret: opts.ClientSecret, ClientSecret: opts.ClientSecret,
oAuthHost: opts.OAuthHost,
SkipVerify: opts.SkipVerify, SkipVerify: opts.SkipVerify,
HideArchives: true, HideArchives: true,
}, nil }, nil
@ -86,11 +89,16 @@ func (g *GitLab) URL() string {
} }
func (g *GitLab) oauth2Config(ctx context.Context) (*oauth2.Config, context.Context) { func (g *GitLab) oauth2Config(ctx context.Context) (*oauth2.Config, context.Context) {
publicOAuthURL := g.oAuthHost
if publicOAuthURL == "" {
publicOAuthURL = g.url
}
return &oauth2.Config{ return &oauth2.Config{
ClientID: g.ClientID, ClientID: g.ClientID,
ClientSecret: g.ClientSecret, ClientSecret: g.ClientSecret,
Endpoint: oauth2.Endpoint{ Endpoint: oauth2.Endpoint{
AuthURL: fmt.Sprintf("%s/oauth/authorize", g.url), AuthURL: fmt.Sprintf("%s/oauth/authorize", publicOAuthURL),
TokenURL: fmt.Sprintf("%s/oauth/token", g.url), TokenURL: fmt.Sprintf("%s/oauth/token", g.url),
}, },
Scopes: []string{defaultScope}, Scopes: []string{defaultScope},

View file

@ -46,22 +46,17 @@ func setupBitbucket(forge *model.Forge) (forge.Forge, error) {
} }
func setupGitea(forge *model.Forge) (forge.Forge, error) { func setupGitea(forge *model.Forge) (forge.Forge, error) {
server, err := url.Parse(forge.URL) serverURL, err := url.Parse(forge.URL)
if err != nil { if err != nil {
return nil, err return nil, err
} }
oauthURL, ok := forge.AdditionalOptions["oauth-server"].(string)
if !ok {
return nil, fmt.Errorf("missing oauth-server")
}
opts := gitea.Opts{ opts := gitea.Opts{
URL: strings.TrimRight(server.String(), "/"), URL: strings.TrimRight(serverURL.String(), "/"),
Client: forge.Client, Client: forge.Client,
Secret: forge.ClientSecret, Secret: forge.ClientSecret,
SkipVerify: forge.SkipVerify, SkipVerify: forge.SkipVerify,
OAuth2URL: oauthURL, OAuthHost: forge.OAuthHost,
} }
if len(opts.URL) == 0 { if len(opts.URL) == 0 {
return nil, fmt.Errorf("WOODPECKER_GITEA_URL must be set") return nil, fmt.Errorf("WOODPECKER_GITEA_URL must be set")
@ -76,6 +71,7 @@ func setupGitLab(forge *model.Forge) (forge.Forge, error) {
ClientID: forge.Client, ClientID: forge.Client,
ClientSecret: forge.ClientSecret, ClientSecret: forge.ClientSecret,
SkipVerify: forge.SkipVerify, SkipVerify: forge.SkipVerify,
OAuthHost: forge.OAuthHost,
}) })
} }
@ -97,6 +93,7 @@ func setupGitHub(forge *model.Forge) (forge.Forge, error) {
SkipVerify: forge.SkipVerify, SkipVerify: forge.SkipVerify,
MergeRef: mergeRef, MergeRef: mergeRef,
OnlyPublic: publicOnly, OnlyPublic: publicOnly,
OAuthHost: forge.OAuthHost,
} }
log.Trace().Msgf("Forge (github) opts: %#v", opts) log.Trace().Msgf("Forge (github) opts: %#v", opts)
return github.New(opts) return github.New(opts)
@ -118,6 +115,7 @@ func setupBitbucketDatacenter(forge *model.Forge) (forge.Forge, error) {
ClientSecret: forge.ClientSecret, ClientSecret: forge.ClientSecret,
Username: gitUsername, Username: gitUsername,
Password: gitPassword, Password: gitPassword,
OAuthHost: forge.OAuthHost,
} }
log.Trace().Msgf("Forge (bitbucketdatacenter) opts: %#v", opts) log.Trace().Msgf("Forge (bitbucketdatacenter) opts: %#v", opts)
return bitbucketdatacenter.New(opts) return bitbucketdatacenter.New(opts)

View file

@ -32,5 +32,6 @@ type Forge struct {
Client string `xorm:"VARCHAR(250)"` Client string `xorm:"VARCHAR(250)"`
ClientSecret string `xorm:"VARCHAR(250)"` ClientSecret string `xorm:"VARCHAR(250)"`
SkipVerify bool `xorm:"bool"` SkipVerify bool `xorm:"bool"`
OAuthHost string `xorm:"VARCHAR(250) 'oauth_host'"` // public url for oauth if different from url
AdditionalOptions map[string]any `xorm:"json"` AdditionalOptions map[string]any `xorm:"json"`
} }

View file

@ -118,6 +118,7 @@ func setupForgeService(c *cli.Context, _store store.Store) error {
_forge.ClientSecret = c.String("forge-oauth-secret") _forge.ClientSecret = c.String("forge-oauth-secret")
_forge.URL = c.String("forge-url") _forge.URL = c.String("forge-url")
_forge.SkipVerify = c.Bool("forge-skip-verify") _forge.SkipVerify = c.Bool("forge-skip-verify")
_forge.OAuthHost = c.String("forge-oauth-host")
switch { switch {
case c.String("addon-forge") != "": case c.String("addon-forge") != "":
@ -137,7 +138,6 @@ func setupForgeService(c *cli.Context, _store store.Store) error {
} }
case c.Bool("gitea"): case c.Bool("gitea"):
_forge.Type = model.ForgeTypeGitea _forge.Type = model.ForgeTypeGitea
_forge.AdditionalOptions["oauth-server"] = c.String("gitea-oauth-server")
if _forge.URL == "" { if _forge.URL == "" {
_forge.URL = "https://try.gitea.com" _forge.URL = "https://try.gitea.com"
} }