2018-02-19 22:24:10 +00:00
|
|
|
// Copyright 2018 Drone.IO Inc.
|
2018-03-21 13:02:17 +00:00
|
|
|
//
|
2018-02-19 22:24:10 +00:00
|
|
|
// 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
|
2018-03-21 13:02:17 +00:00
|
|
|
//
|
2018-02-19 22:24:10 +00:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2018-03-21 13:02:17 +00:00
|
|
|
//
|
2018-02-19 22:24:10 +00:00
|
|
|
// 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.
|
|
|
|
|
2017-06-29 22:51:22 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2017-07-24 23:15:25 +00:00
|
|
|
"crypto/tls"
|
2023-11-01 10:44:08 +00:00
|
|
|
"errors"
|
2017-06-29 22:51:22 +00:00
|
|
|
"net"
|
|
|
|
"net/http"
|
2021-09-26 22:22:23 +00:00
|
|
|
"net/http/httputil"
|
2017-06-29 22:51:22 +00:00
|
|
|
"net/url"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2022-09-04 01:24:42 +00:00
|
|
|
"github.com/caddyserver/certmagic"
|
2021-12-12 21:49:30 +00:00
|
|
|
"github.com/gin-gonic/gin"
|
2023-03-12 08:41:10 +00:00
|
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
2021-10-12 07:25:13 +00:00
|
|
|
"github.com/rs/zerolog"
|
|
|
|
"github.com/rs/zerolog/log"
|
2021-10-27 19:03:14 +00:00
|
|
|
"github.com/urfave/cli/v2"
|
2021-10-12 07:25:13 +00:00
|
|
|
"golang.org/x/sync/errgroup"
|
2017-06-29 22:51:22 +00:00
|
|
|
"google.golang.org/grpc"
|
2018-01-08 20:46:44 +00:00
|
|
|
"google.golang.org/grpc/keepalive"
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2023-11-07 07:04:33 +00:00
|
|
|
"go.woodpecker-ci.org/woodpecker/cmd/common"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/pipeline/rpc/proto"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/cron"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/forge"
|
|
|
|
woodpeckerGrpcServer "go.woodpecker-ci.org/woodpecker/server/grpc"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/logging"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/model"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/plugins/config"
|
2023-11-12 13:39:41 +00:00
|
|
|
"go.woodpecker-ci.org/woodpecker/server/plugins/permissions"
|
2023-11-07 07:04:33 +00:00
|
|
|
"go.woodpecker-ci.org/woodpecker/server/pubsub"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/router"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/router/middleware"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/store"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/server/web"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/shared/constant"
|
|
|
|
"go.woodpecker-ci.org/woodpecker/version"
|
|
|
|
// "go.woodpecker-ci.org/woodpecker/server/plugins/encryption"
|
|
|
|
// encryptedStore "go.woodpecker-ci.org/woodpecker/server/plugins/encryption/wrapper/store"
|
2017-06-29 22:51:22 +00:00
|
|
|
)
|
|
|
|
|
2021-11-23 14:36:52 +00:00
|
|
|
func run(c *cli.Context) error {
|
2023-10-24 10:23:42 +00:00
|
|
|
common.SetupGlobalLogger(c, true)
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2023-08-07 18:47:30 +00:00
|
|
|
// set gin mode based on log level
|
|
|
|
if zerolog.GlobalLevel() > zerolog.DebugLevel {
|
2021-12-12 21:49:30 +00:00
|
|
|
gin.SetMode(gin.ReleaseMode)
|
2021-12-08 22:40:00 +00:00
|
|
|
}
|
2021-10-16 22:41:36 +00:00
|
|
|
|
2017-07-12 18:48:56 +00:00
|
|
|
if c.String("server-host") == "" {
|
2021-10-12 07:25:13 +00:00
|
|
|
log.Fatal().Msg("WOODPECKER_HOST is not properly configured")
|
2017-07-12 18:48:56 +00:00
|
|
|
}
|
|
|
|
|
2017-12-20 02:08:55 +00:00
|
|
|
if !strings.Contains(c.String("server-host"), "://") {
|
2021-10-12 07:25:13 +00:00
|
|
|
log.Fatal().Msg(
|
Clean up config environment variables for server and agent (#218)
The goal here is to make consistent use of configuration environment variables prefixed `WOODPECKER_`. Where several variants existed, this PR aims to remove all but one option, leaving the most explicit.
This PR only changes server and agent code, but not documentation, in order to keep the PR digestible. Once we have consensus that this is correct, I'll change docs accordingly.
User (rather: admin) facing changes in this PR:
- In general, support for all server and agent config environment variables (env vars) starting with `DRONE_` is removed. The according `WOODPECKER_*` variables must be used instead.
- The env var `WOODPECKER_HOST` replaces `DRONE_HOST`, and `DRONE_SERVER_HOST`.
- The env var `WOODPECKER_AGENT_SECRET` is used to configure the shared secret which agents use to authenticate against the server. It replaces `WOODPECKER_SECRET`, `DRONE_SECRET`, `WOODPECKER_PASSWORD`, `DRONE_PASSWORD`, and `DRONE_AGENT_SECRET`.
- The env var `WOODPECKER_DATABASE_DRIVER` replaces `DRONE_DATABASE_DRIVER` and `DATABASE_DRIVER`.
- The env var `WOODPECKER_DATABASE_DATASOURCE` replaces `DRONE_DATABASE_DATASOURCE` and `DATABASE_CONFIG`.
2021-09-28 13:43:44 +00:00
|
|
|
"WOODPECKER_HOST must be <scheme>://<hostname> format",
|
2017-12-20 02:08:55 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-09-23 05:54:23 +00:00
|
|
|
if _, err := url.Parse(c.String("server-host")); err != nil {
|
|
|
|
log.Fatal().Err(err).Msg("could not parse WOODPECKER_HOST")
|
|
|
|
}
|
|
|
|
|
2021-08-20 14:32:52 +00:00
|
|
|
if strings.Contains(c.String("server-host"), "://localhost") {
|
2021-10-12 07:25:13 +00:00
|
|
|
log.Warn().Msg(
|
Clean up config environment variables for server and agent (#218)
The goal here is to make consistent use of configuration environment variables prefixed `WOODPECKER_`. Where several variants existed, this PR aims to remove all but one option, leaving the most explicit.
This PR only changes server and agent code, but not documentation, in order to keep the PR digestible. Once we have consensus that this is correct, I'll change docs accordingly.
User (rather: admin) facing changes in this PR:
- In general, support for all server and agent config environment variables (env vars) starting with `DRONE_` is removed. The according `WOODPECKER_*` variables must be used instead.
- The env var `WOODPECKER_HOST` replaces `DRONE_HOST`, and `DRONE_SERVER_HOST`.
- The env var `WOODPECKER_AGENT_SECRET` is used to configure the shared secret which agents use to authenticate against the server. It replaces `WOODPECKER_SECRET`, `DRONE_SECRET`, `WOODPECKER_PASSWORD`, `DRONE_PASSWORD`, and `DRONE_AGENT_SECRET`.
- The env var `WOODPECKER_DATABASE_DRIVER` replaces `DRONE_DATABASE_DRIVER` and `DATABASE_DRIVER`.
- The env var `WOODPECKER_DATABASE_DATASOURCE` replaces `DRONE_DATABASE_DATASOURCE` and `DATABASE_CONFIG`.
2021-09-28 13:43:44 +00:00
|
|
|
"WOODPECKER_HOST should probably be publicly accessible (not localhost)",
|
2021-08-20 14:32:52 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-11-04 23:35:06 +00:00
|
|
|
_forge, err := setupForge(c)
|
2017-06-29 22:51:22 +00:00
|
|
|
if err != nil {
|
2023-11-01 10:44:08 +00:00
|
|
|
log.Fatal().Err(err).Msg("can't setup forge")
|
2017-06-29 22:51:22 +00:00
|
|
|
}
|
|
|
|
|
2021-12-01 13:22:06 +00:00
|
|
|
_store, err := setupStore(c)
|
2021-10-19 09:44:49 +00:00
|
|
|
if err != nil {
|
2023-11-01 10:44:08 +00:00
|
|
|
log.Fatal().Err(err).Msg("cant't setup database store")
|
2021-10-19 09:44:49 +00:00
|
|
|
}
|
2021-11-13 19:18:06 +00:00
|
|
|
defer func() {
|
2021-12-01 13:22:06 +00:00
|
|
|
if err := _store.Close(); err != nil {
|
2021-11-13 19:18:06 +00:00
|
|
|
log.Error().Err(err).Msg("could not close store")
|
|
|
|
}
|
|
|
|
}()
|
2021-10-19 09:44:49 +00:00
|
|
|
|
2022-11-04 23:35:06 +00:00
|
|
|
setupEvilGlobals(c, _store, _forge)
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
var g errgroup.Group
|
2017-07-31 19:15:05 +00:00
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
setupMetrics(&g, _store)
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
g.Go(func() error {
|
2022-11-04 23:35:06 +00:00
|
|
|
return cron.Start(c.Context, _store, _forge)
|
2022-09-03 18:41:23 +00:00
|
|
|
})
|
2017-06-29 22:51:22 +00:00
|
|
|
|
|
|
|
// start the grpc server
|
|
|
|
g.Go(func() error {
|
2021-09-09 16:34:29 +00:00
|
|
|
lis, err := net.Listen("tcp", c.String("grpc-addr"))
|
2017-06-29 22:51:22 +00:00
|
|
|
if err != nil {
|
2023-11-01 10:44:08 +00:00
|
|
|
log.Fatal().Err(err).Msg("failed to listen on grpc-addr")
|
2017-06-29 22:51:22 +00:00
|
|
|
}
|
2023-01-28 13:13:04 +00:00
|
|
|
|
2023-03-19 19:24:43 +00:00
|
|
|
jwtSecret := c.String("grpc-secret")
|
2023-01-28 13:13:04 +00:00
|
|
|
jwtManager := woodpeckerGrpcServer.NewJWTManager(jwtSecret)
|
|
|
|
|
|
|
|
authorizer := woodpeckerGrpcServer.NewAuthorizer(jwtManager)
|
2019-06-28 12:23:52 +00:00
|
|
|
grpcServer := grpc.NewServer(
|
2023-01-28 13:13:04 +00:00
|
|
|
grpc.StreamInterceptor(authorizer.StreamInterceptor),
|
|
|
|
grpc.UnaryInterceptor(authorizer.UnaryInterceptor),
|
2018-01-08 20:46:44 +00:00
|
|
|
grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
|
|
|
|
MinTime: c.Duration("keepalive-min-time"),
|
|
|
|
}),
|
2017-06-29 23:35:38 +00:00
|
|
|
)
|
2023-01-28 13:13:04 +00:00
|
|
|
|
2021-09-29 00:10:09 +00:00
|
|
|
woodpeckerServer := woodpeckerGrpcServer.NewWoodpeckerServer(
|
2022-11-04 23:35:06 +00:00
|
|
|
_forge,
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Services.Queue,
|
|
|
|
server.Config.Services.Logs,
|
|
|
|
server.Config.Services.Pubsub,
|
2021-12-01 13:22:06 +00:00
|
|
|
_store,
|
2021-09-22 18:48:01 +00:00
|
|
|
)
|
2021-09-29 00:10:09 +00:00
|
|
|
proto.RegisterWoodpeckerServer(grpcServer, woodpeckerServer)
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2023-01-28 13:13:04 +00:00
|
|
|
woodpeckerAuthServer := woodpeckerGrpcServer.NewWoodpeckerAuthServer(
|
|
|
|
jwtManager,
|
|
|
|
server.Config.Server.AgentToken,
|
|
|
|
_store,
|
|
|
|
)
|
|
|
|
proto.RegisterWoodpeckerAuthServer(grpcServer, woodpeckerAuthServer)
|
|
|
|
|
2019-06-28 12:23:52 +00:00
|
|
|
err = grpcServer.Serve(lis)
|
2017-06-29 22:51:22 +00:00
|
|
|
if err != nil {
|
2023-11-01 10:44:08 +00:00
|
|
|
log.Fatal().Err(err).Msg("failed to serve grpc server")
|
2017-06-29 22:51:22 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
proxyWebUI := c.String("www-proxy")
|
|
|
|
var webUIServe func(w http.ResponseWriter, r *http.Request)
|
2019-05-30 10:15:29 +00:00
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
if proxyWebUI == "" {
|
2023-03-20 23:48:15 +00:00
|
|
|
webEngine, err := web.New()
|
|
|
|
if err != nil {
|
2023-11-01 10:44:08 +00:00
|
|
|
log.Fatal().Err(err).Msg("failed to create web engine")
|
2023-03-20 23:48:15 +00:00
|
|
|
}
|
|
|
|
webUIServe = webEngine.ServeHTTP
|
2022-09-03 18:41:23 +00:00
|
|
|
} else {
|
|
|
|
origin, _ := url.Parse(proxyWebUI)
|
|
|
|
|
|
|
|
director := func(req *http.Request) {
|
|
|
|
req.Header.Add("X-Forwarded-Host", req.Host)
|
|
|
|
req.Header.Add("X-Origin-Host", origin.Host)
|
|
|
|
req.URL.Scheme = origin.Scheme
|
|
|
|
req.URL.Host = origin.Host
|
|
|
|
}
|
|
|
|
|
|
|
|
proxy := &httputil.ReverseProxy{Director: director}
|
|
|
|
webUIServe = proxy.ServeHTTP
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup the server and start the listener
|
|
|
|
handler := router.Load(
|
|
|
|
webUIServe,
|
|
|
|
middleware.Logger(time.RFC3339, true),
|
|
|
|
middleware.Version,
|
|
|
|
middleware.Store(c, _store),
|
|
|
|
)
|
2022-08-31 22:36:32 +00:00
|
|
|
|
2017-06-29 22:51:22 +00:00
|
|
|
if c.String("server-cert") != "" {
|
2022-09-03 18:41:23 +00:00
|
|
|
// start the server with tls enabled
|
2017-07-26 14:44:38 +00:00
|
|
|
g.Go(func() error {
|
2017-09-19 22:30:31 +00:00
|
|
|
serve := &http.Server{
|
2023-05-11 04:11:10 +00:00
|
|
|
Addr: server.Config.Server.PortTLS,
|
2017-09-19 22:30:31 +00:00
|
|
|
Handler: handler,
|
|
|
|
TLSConfig: &tls.Config{
|
2021-10-19 09:44:49 +00:00
|
|
|
NextProtos: []string{"h2", "http/1.1"},
|
2017-09-19 22:30:31 +00:00
|
|
|
},
|
|
|
|
}
|
2023-11-01 10:44:08 +00:00
|
|
|
err = serve.ListenAndServeTLS(
|
2017-07-26 14:44:38 +00:00
|
|
|
c.String("server-cert"),
|
|
|
|
c.String("server-key"),
|
|
|
|
)
|
2023-11-01 10:44:08 +00:00
|
|
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
|
|
log.Fatal().Err(err).Msg("failed to start server with tls")
|
|
|
|
}
|
|
|
|
return err
|
2017-07-26 14:44:38 +00:00
|
|
|
})
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
// http to https redirect
|
2022-09-04 01:24:42 +00:00
|
|
|
redirect := func(w http.ResponseWriter, req *http.Request) {
|
2023-09-23 05:54:23 +00:00
|
|
|
serverURL, _ := url.Parse(server.Config.Server.Host)
|
2022-09-04 01:24:42 +00:00
|
|
|
req.URL.Scheme = "https"
|
2023-09-23 05:54:23 +00:00
|
|
|
req.URL.Host = serverURL.Host
|
2022-09-04 01:24:42 +00:00
|
|
|
|
|
|
|
w.Header().Set("Strict-Transport-Security", "max-age=31536000")
|
|
|
|
|
|
|
|
http.Redirect(w, req, req.URL.String(), http.StatusMovedPermanently)
|
|
|
|
}
|
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
g.Go(func() error {
|
2023-11-01 10:44:08 +00:00
|
|
|
err := http.ListenAndServe(server.Config.Server.Port, http.HandlerFunc(redirect))
|
|
|
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
|
|
log.Fatal().Err(err).Msg("unable to start server to redirect from http to https")
|
|
|
|
}
|
|
|
|
return err
|
2022-09-03 18:41:23 +00:00
|
|
|
})
|
|
|
|
} else if c.Bool("lets-encrypt") {
|
|
|
|
// start the server with lets-encrypt
|
2022-09-04 01:24:42 +00:00
|
|
|
certmagic.DefaultACME.Email = c.String("lets-encrypt-email")
|
|
|
|
certmagic.DefaultACME.Agreed = true
|
|
|
|
|
2023-10-07 13:39:19 +00:00
|
|
|
address, err := url.Parse(strings.TrimSuffix(c.String("server-host"), "/"))
|
2022-09-03 18:41:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
g.Go(func() error {
|
2022-09-04 01:24:42 +00:00
|
|
|
if err := certmagic.HTTPS([]string{address.Host}, handler); err != nil {
|
2023-11-01 10:44:08 +00:00
|
|
|
log.Fatal().Err(err).Msg("certmagic does not work")
|
2022-09-03 18:41:23 +00:00
|
|
|
}
|
2022-09-04 01:24:42 +00:00
|
|
|
return nil
|
2022-09-03 18:41:23 +00:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
// start the server without tls
|
|
|
|
g.Go(func() error {
|
2023-11-01 10:44:08 +00:00
|
|
|
err := http.ListenAndServe(
|
2022-09-03 18:41:23 +00:00
|
|
|
c.String("server-addr"),
|
|
|
|
handler,
|
|
|
|
)
|
2023-11-01 10:44:08 +00:00
|
|
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
|
|
log.Fatal().Err(err).Msg("could not start server")
|
|
|
|
}
|
|
|
|
return err
|
2022-09-03 18:41:23 +00:00
|
|
|
})
|
2018-01-13 04:54:49 +00:00
|
|
|
}
|
2022-09-03 18:41:23 +00:00
|
|
|
|
2023-03-12 08:41:10 +00:00
|
|
|
if metricsServerAddr := c.String("metrics-server-addr"); metricsServerAddr != "" {
|
|
|
|
g.Go(func() error {
|
|
|
|
metricsRouter := gin.New()
|
|
|
|
metricsRouter.GET("/metrics", gin.WrapH(promhttp.Handler()))
|
2023-11-01 10:44:08 +00:00
|
|
|
err := http.ListenAndServe(metricsServerAddr, metricsRouter)
|
|
|
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
|
|
log.Fatal().Err(err).Msg("could not start metrics server")
|
|
|
|
}
|
|
|
|
return err
|
2023-03-12 08:41:10 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-09-03 18:41:23 +00:00
|
|
|
log.Info().Msgf("Starting Woodpecker server with version '%s'", version.String())
|
2017-06-29 22:51:22 +00:00
|
|
|
|
|
|
|
return g.Wait()
|
|
|
|
}
|
|
|
|
|
2022-11-04 23:35:06 +00:00
|
|
|
func setupEvilGlobals(c *cli.Context, v store.Store, f forge.Forge) {
|
|
|
|
// forge
|
|
|
|
server.Config.Services.Forge = f
|
2023-02-01 17:53:19 +00:00
|
|
|
server.Config.Services.Timeout = c.Duration("forge-timeout")
|
2021-11-26 12:01:54 +00:00
|
|
|
|
2017-06-29 22:51:22 +00:00
|
|
|
// services
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Services.Queue = setupQueue(c, v)
|
|
|
|
server.Config.Services.Logs = logging.New()
|
|
|
|
server.Config.Services.Pubsub = pubsub.New()
|
|
|
|
server.Config.Services.Registries = setupRegistryService(c, v)
|
2023-01-15 19:12:18 +00:00
|
|
|
|
|
|
|
// TODO(1544): fix encrypted store
|
|
|
|
// // encryption
|
|
|
|
// encryptedSecretStore := encryptedStore.NewSecretStore(v)
|
|
|
|
// err := encryption.Encryption(c, v).WithClient(encryptedSecretStore).Build()
|
|
|
|
// if err != nil {
|
|
|
|
// log.Fatal().Err(err).Msg("could not create encryption service")
|
|
|
|
// }
|
|
|
|
// server.Config.Services.Secrets = setupSecretService(c, encryptedSecretStore)
|
|
|
|
server.Config.Services.Secrets = setupSecretService(c, v)
|
|
|
|
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Services.Environ = setupEnvironService(c, v)
|
2022-11-04 23:35:06 +00:00
|
|
|
server.Config.Services.Membership = setupMembershipService(c, f)
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2022-06-01 18:06:27 +00:00
|
|
|
server.Config.Services.SignaturePrivateKey, server.Config.Services.SignaturePublicKey = setupSignatureKeys(v)
|
|
|
|
|
2022-02-28 09:56:23 +00:00
|
|
|
if endpoint := c.String("config-service-endpoint"); endpoint != "" {
|
2022-06-01 18:06:27 +00:00
|
|
|
server.Config.Services.ConfigService = config.NewHTTP(endpoint, server.Config.Services.SignaturePrivateKey)
|
2022-02-28 09:56:23 +00:00
|
|
|
}
|
|
|
|
|
2022-02-08 16:55:08 +00:00
|
|
|
// authentication
|
|
|
|
server.Config.Pipeline.AuthenticatePublicRepos = c.Bool("authenticate-public-repos")
|
|
|
|
|
2022-02-10 16:05:19 +00:00
|
|
|
// Cloning
|
|
|
|
server.Config.Pipeline.DefaultCloneImage = c.String("default-clone-image")
|
2023-03-20 20:17:49 +00:00
|
|
|
constant.TrustedCloneImages = append(constant.TrustedCloneImages, server.Config.Pipeline.DefaultCloneImage)
|
2022-02-10 16:05:19 +00:00
|
|
|
|
2022-05-09 09:26:09 +00:00
|
|
|
// Execution
|
|
|
|
_events := c.StringSlice("default-cancel-previous-pipeline-events")
|
|
|
|
events := make([]model.WebhookEvent, len(_events))
|
|
|
|
for _, v := range _events {
|
|
|
|
events = append(events, model.WebhookEvent(v))
|
|
|
|
}
|
|
|
|
server.Config.Pipeline.DefaultCancelPreviousPipelineEvents = events
|
2023-03-19 19:24:43 +00:00
|
|
|
server.Config.Pipeline.DefaultTimeout = c.Int64("default-pipeline-timeout")
|
|
|
|
server.Config.Pipeline.MaxTimeout = c.Int64("max-pipeline-timeout")
|
2022-05-09 09:26:09 +00:00
|
|
|
|
2017-06-29 22:51:22 +00:00
|
|
|
// limits
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Pipeline.Limits.MemSwapLimit = c.Int64("limit-mem-swap")
|
|
|
|
server.Config.Pipeline.Limits.MemLimit = c.Int64("limit-mem")
|
|
|
|
server.Config.Pipeline.Limits.ShmSize = c.Int64("limit-shm-size")
|
|
|
|
server.Config.Pipeline.Limits.CPUQuota = c.Int64("limit-cpu-quota")
|
|
|
|
server.Config.Pipeline.Limits.CPUShares = c.Int64("limit-cpu-shares")
|
|
|
|
server.Config.Pipeline.Limits.CPUSet = c.String("limit-cpu-set")
|
2017-06-29 22:51:22 +00:00
|
|
|
|
2023-08-07 19:13:26 +00:00
|
|
|
// backend options for pipeline compiler
|
|
|
|
server.Config.Pipeline.Proxy.No = c.String("backend-no-proxy")
|
|
|
|
server.Config.Pipeline.Proxy.HTTP = c.String("backend-http-proxy")
|
|
|
|
server.Config.Pipeline.Proxy.HTTPS = c.String("backend-https-proxy")
|
|
|
|
|
2017-06-29 22:51:22 +00:00
|
|
|
// server configuration
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Server.Cert = c.String("server-cert")
|
|
|
|
server.Config.Server.Key = c.String("server-key")
|
2023-01-28 13:13:04 +00:00
|
|
|
server.Config.Server.AgentToken = c.String("agent-secret")
|
2023-10-07 13:39:19 +00:00
|
|
|
serverHost := strings.TrimSuffix(c.String("server-host"), "/")
|
2023-09-23 05:54:23 +00:00
|
|
|
server.Config.Server.Host = serverHost
|
2023-06-18 12:47:40 +00:00
|
|
|
if c.IsSet("server-webhook-host") {
|
|
|
|
server.Config.Server.WebhookHost = c.String("server-webhook-host")
|
|
|
|
} else {
|
2023-09-23 05:54:23 +00:00
|
|
|
server.Config.Server.WebhookHost = serverHost
|
2023-06-18 12:47:40 +00:00
|
|
|
}
|
2021-12-13 19:22:09 +00:00
|
|
|
if c.IsSet("server-dev-oauth-host") {
|
|
|
|
server.Config.Server.OAuthHost = c.String("server-dev-oauth-host")
|
|
|
|
} else {
|
2023-09-23 05:54:23 +00:00
|
|
|
server.Config.Server.OAuthHost = serverHost
|
2021-12-13 19:22:09 +00:00
|
|
|
}
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Server.Port = c.String("server-addr")
|
2023-05-11 04:11:10 +00:00
|
|
|
server.Config.Server.PortTLS = c.String("server-addr-tls")
|
2022-01-29 19:37:36 +00:00
|
|
|
server.Config.Server.StatusContext = c.String("status-context")
|
2022-05-12 17:07:33 +00:00
|
|
|
server.Config.Server.StatusContextFormat = c.String("status-context-format")
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Server.SessionExpires = c.Duration("session-expires")
|
2023-09-22 14:43:31 +00:00
|
|
|
rootPath := c.String("root-path")
|
|
|
|
if !c.IsSet("root-path") {
|
|
|
|
// Extract RootPath from Host...
|
|
|
|
u, _ := url.Parse(server.Config.Server.Host)
|
|
|
|
rootPath = u.Path
|
|
|
|
}
|
|
|
|
rootPath = strings.TrimSuffix(rootPath, "/")
|
2023-08-07 14:05:18 +00:00
|
|
|
if rootPath != "" && !strings.HasPrefix(rootPath, "/") {
|
|
|
|
rootPath = "/" + rootPath
|
|
|
|
}
|
|
|
|
server.Config.Server.RootPath = rootPath
|
support custom .JS and .CSS files for custom banner messages (white-labeling) (#1781)
This PR introduces two new server configuration options, for providing a
custom .JS and .CSS file.
These can be used to show custom banner messages, add
environment-dependent signals, or simply a corporate logo.
### Motivation (what problem I try to solve)
I'm operating Woodpecker in multiple k8s clusters for different
environments.
When having multiple browser tabs open, I prefer strong indicators for
each environment.
E.g. a red "PROD" banner, or just a blue "QA" banner.
Also, we sometimes need to have the chance for maintenance, and instead
of broadcasting emails,
I prefer a banner message, stating something like: "Heads-up: there's a
planned downtime, next Friday, blabla...".
Also, I like to have the firm's logo visible, which makes Woodpecker
look more like an integral part of our platform.
### Implementation notes
* Two new config options are introduced ```WOODPECKER_CUSTOM_CSS_FILE```
and ```WOODPECKER_CUSTOM_JS_FILE```
* I've piggy-bagged the existing handler for assets, as it seemed to me
a minimally invasive approach
* the option along with an example is documented
* a simple unit test for the Gin-handler ensures some regression safety
* no extra dependencies are introduced
### Visual example
The documented example will look like this.
![Screenshot 2023-05-27 at 17 00
44](https://github.com/woodpecker-ci/woodpecker/assets/1189394/8940392e-463c-4651-a1eb-f017cd3cd64d)
### Areas of uncertainty
This is my first contribution to Woodpecker and I tried my best to align
with your conventions.
That said, I found myself uncertain about these things and would be glad
about getting feedback.
* The handler tests are somewhat different than the other ones because I
wanted to keep them simple - I hope that still matches your coding
guidelines
* caching the page sometimes will let the browser not recognize changes
and a user must reload. I'm not fully into the details of how caching is
implemented and neither can judge if it's a real problem. Another pair
of eyes would be good.
2023-07-10 10:46:35 +00:00
|
|
|
server.Config.Server.CustomCSSFile = strings.TrimSpace(c.String("custom-css-file"))
|
|
|
|
server.Config.Server.CustomJsFile = strings.TrimSpace(c.String("custom-js-file"))
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Pipeline.Networks = c.StringSlice("network")
|
|
|
|
server.Config.Pipeline.Volumes = c.StringSlice("volume")
|
|
|
|
server.Config.Pipeline.Privileged = c.StringSlice("escalate")
|
2023-08-03 00:42:30 +00:00
|
|
|
server.Config.Server.EnableSwagger = c.Bool("enable-swagger")
|
2018-03-21 12:51:54 +00:00
|
|
|
|
|
|
|
// prometheus
|
2021-09-22 18:48:01 +00:00
|
|
|
server.Config.Prometheus.AuthToken = c.String("prometheus-auth-token")
|
2023-11-12 13:39:41 +00:00
|
|
|
|
|
|
|
// permissions
|
|
|
|
server.Config.Permissions.Open = c.Bool("open")
|
|
|
|
server.Config.Permissions.Admins = permissions.NewAdmins(c.StringSlice("admin"))
|
|
|
|
server.Config.Permissions.Orgs = permissions.NewOrgs(c.StringSlice("orgs"))
|
|
|
|
server.Config.Permissions.OwnersAllowlist = permissions.NewOwnersAllowlist(c.StringSlice("repo-owners"))
|
2017-06-29 22:51:22 +00:00
|
|
|
}
|