diff --git a/.golangci.yml b/.golangci.yml index 1b426fe75f..0f65428360 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -124,43 +124,49 @@ linters-settings: linters: disable-all: true enable: - - bidichk - - errcheck - - gofmt - - goimports - - gosimple - - govet - - ineffassign - - misspell - - revive - - staticcheck - - typecheck - - unused - - whitespace - - gofumpt - - errorlint - - forbidigo - - zerologlint - - depguard - asciicheck + - bidichk - bodyclose + - contextcheck + - depguard - dogsled - durationcheck + - errcheck - errchkjson + - errorlint + - forbidigo + - forcetypeassert - gochecknoinits + - goconst + - gocritic + - gofmt + - gofumpt - goheader + - goimports + - gomnd - gomoddirectives - gomodguard - goprintffuncname + - gosimple + - govet - importas + - ineffassign - makezero + - misspell + - nolintlint + - revive - rowserrcheck - sqlclosecheck + - staticcheck + - stylecheck - tenv + - typecheck - unconvert - unparam + - unused - wastedassign - whitespace + - zerologlint run: timeout: 15m @@ -168,7 +174,7 @@ run: issues: exclude-rules: # gin force us to use string as context key - - path: server/store/context.go + - path: 'server/store/context.go' linters: - staticcheck - revive @@ -186,3 +192,11 @@ issues: - path: '_test.go' linters: - forcetypeassert + + - path: 'cmd/agent/flags.go|cmd/server/flags.go|pipeline/backend/kubernetes/flags.go|_test.go' + linters: + - gomnd + + - path: '_test.go' + linters: + - goconst diff --git a/agent/rpc/auth_client_grpc.go b/agent/rpc/auth_client_grpc.go index 5f31e2803f..94a01151e2 100644 --- a/agent/rpc/auth_client_grpc.go +++ b/agent/rpc/auth_client_grpc.go @@ -18,9 +18,9 @@ import ( "context" "time" - "go.woodpecker-ci.org/woodpecker/v2/pipeline/rpc/proto" - "google.golang.org/grpc" + + "go.woodpecker-ci.org/woodpecker/v2/pipeline/rpc/proto" ) type AuthClient struct { @@ -40,7 +40,7 @@ func NewAuthGrpcClient(conn *grpc.ClientConn, agentToken string, agentID int64) } func (c *AuthClient) Auth() (string, int64, error) { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) //nolint: gomnd defer cancel() req := &proto.AuthRequest{ diff --git a/agent/rpc/client_grpc.go b/agent/rpc/client_grpc.go index 838bffd102..5866d3d68a 100644 --- a/agent/rpc/client_grpc.go +++ b/agent/rpc/client_grpc.go @@ -53,8 +53,8 @@ func (c *client) Close() error { func (c *client) newBackOff() backoff.BackOff { b := backoff.NewExponentialBackOff() - b.MaxInterval = 10 * time.Second - b.InitialInterval = 10 * time.Millisecond + b.MaxInterval = 10 * time.Second //nolint: gomnd + b.InitialInterval = 10 * time.Millisecond //nolint: gomnd return b } diff --git a/agent/runner.go b/agent/runner.go index 753785dcd1..b640d55803 100644 --- a/agent/runner.go +++ b/agent/runner.go @@ -133,12 +133,13 @@ func (r *Runner) Run(runnerCtx context.Context) error { state := rpc.State{} state.Started = time.Now().Unix() - err = r.client.Init(ctxmeta, work.ID, state) + err = r.client.Init(ctxmeta, work.ID, state) //nolint:contextcheck if err != nil { logger.Error().Err(err).Msg("pipeline initialization failed") } var uploads sync.WaitGroup + //nolint:contextcheck err = pipeline.New(work.Config, pipeline.WithContext(workflowCtx), pipeline.WithTaskUUID(fmt.Sprint(work.ID)), @@ -157,16 +158,17 @@ func (r *Runner) Run(runnerCtx context.Context) error { if canceled.IsSet() { state.Error = "" - state.ExitCode = 137 + state.ExitCode = pipeline.ExitCodeKilled } else if err != nil { pExitError := &pipeline.ExitError{} - if errors.As(err, &pExitError) { + switch { + case errors.As(err, &pExitError): state.ExitCode = pExitError.Code - } else if errors.Is(err, pipeline.ErrCancel) { + case errors.Is(err, pipeline.ErrCancel): state.Error = "" - state.ExitCode = 137 + state.ExitCode = pipeline.ExitCodeKilled canceled.SetTo(true) - } else { + default: state.ExitCode = 1 state.Error = err.Error() } @@ -187,7 +189,7 @@ func (r *Runner) Run(runnerCtx context.Context) error { Int("exit_code", state.ExitCode). Msg("updating pipeline status") - if err := r.client.Done(ctxmeta, work.ID, state); err != nil { + if err := r.client.Done(ctxmeta, work.ID, state); err != nil { //nolint:contextcheck logger.Error().Err(err).Msg("updating pipeline status failed") } else { logger.Debug().Msg("updating pipeline status complete") diff --git a/agent/tracer.go b/agent/tracer.go index eef207f4f6..0577bf9ebc 100644 --- a/agent/tracer.go +++ b/agent/tracer.go @@ -68,7 +68,7 @@ func (r *Runner) createTracer(ctxmeta context.Context, logger zerolog.Logger, wo // TODO: find better way to update this state and move it to pipeline to have the same env in cli-exec state.Pipeline.Step.Environment["CI_MACHINE"] = r.hostname - state.Pipeline.Step.Environment["CI_PIPELINE_STATUS"] = "success" + state.Pipeline.Step.Environment["CI_PIPELINE_STATUS"] = string(pipeline.StatusSuccess) state.Pipeline.Step.Environment["CI_PIPELINE_STARTED"] = strconv.FormatInt(state.Pipeline.Time, 10) state.Pipeline.Step.Environment["CI_PIPELINE_FINISHED"] = strconv.FormatInt(time.Now().Unix(), 10) @@ -79,8 +79,8 @@ func (r *Runner) createTracer(ctxmeta context.Context, logger zerolog.Logger, wo state.Pipeline.Step.Environment["CI_SYSTEM_PLATFORM"] = runtime.GOOS + "/" + runtime.GOARCH if state.Pipeline.Error != nil { - state.Pipeline.Step.Environment["CI_PIPELINE_STATUS"] = "failure" - state.Pipeline.Step.Environment["CI_STEP_STATUS"] = "failure" + state.Pipeline.Step.Environment["CI_PIPELINE_STATUS"] = string(pipeline.StatusFailure) + state.Pipeline.Step.Environment["CI_STEP_STATUS"] = string(pipeline.StatusFailure) } return nil diff --git a/cli/common/flags.go b/cli/common/flags.go index 5525624fa8..7898e7bad3 100644 --- a/cli/common/flags.go +++ b/cli/common/flags.go @@ -64,7 +64,7 @@ func FormatFlag(tmpl string, hidden ...bool) *cli.StringFlag { } } -// specify repository +// RepoFlag specifies repository var RepoFlag = &cli.StringFlag{ Name: "repository", Aliases: []string{"repo"}, diff --git a/cli/deploy/deploy.go b/cli/deploy/deploy.go index 0ed963e620..d4cdf5c878 100644 --- a/cli/deploy/deploy.go +++ b/cli/deploy/deploy.go @@ -97,7 +97,7 @@ func deploy(c *cli.Context) error { } } if number == 0 { - return fmt.Errorf("Cannot deploy failure pipeline") + return fmt.Errorf("cannot deploy failure pipeline") } } else { number, err = strconv.ParseInt(pipelineArg, 10, 64) @@ -106,9 +106,10 @@ func deploy(c *cli.Context) error { } } - env := c.Args().Get(2) + envArgIndex := 2 + env := c.Args().Get(envArgIndex) if env == "" { - return fmt.Errorf("Please specify the target environment (ie production)") + return fmt.Errorf("please specify the target environment (ie production)") } params := internal.ParseKeyPair(c.StringSlice("param")) diff --git a/cli/exec/exec.go b/cli/exec/exec.go index 9568316916..fbbf5dd399 100644 --- a/cli/exec/exec.go +++ b/cli/exec/exec.go @@ -123,13 +123,13 @@ func execWithAxis(c *cli.Context, file, repoPath string, axis matrix.Axis) error droneEnv := make(map[string]string) for _, env := range c.StringSlice("env") { - envs := strings.SplitN(env, "=", 2) - droneEnv[envs[0]] = envs[1] - if _, exists := environ[envs[0]]; exists { + before, after, _ := strings.Cut(env, "=") + droneEnv[before] = after + if _, exists := environ[before]; exists { // don't override existing values continue } - environ[envs[0]] = envs[1] + environ[before] = before } tmpl, err := envsubst.ParseFile(file) diff --git a/cli/internal/util.go b/cli/internal/util.go index e71b7558dd..921c1e7ec9 100644 --- a/cli/internal/util.go +++ b/cli/internal/util.go @@ -44,10 +44,10 @@ func NewClient(c *cli.Context) (woodpecker.Client, error) { // if no server url is provided we can default // to the hosted Woodpecker service. if len(server) == 0 { - return nil, fmt.Errorf("Error: you must provide the Woodpecker server address") + return nil, fmt.Errorf("you must provide the Woodpecker server address") } if len(token) == 0 { - return nil, fmt.Errorf("Error: you must provide your Woodpecker access token") + return nil, fmt.Errorf("you must provide your Woodpecker access token") } // attempt to find system CA certs @@ -107,11 +107,11 @@ func ParseRepo(client woodpecker.Client, str string) (repoID int64, err error) { func ParseKeyPair(p []string) map[string]string { params := map[string]string{} for _, i := range p { - parts := strings.SplitN(i, "=", 2) - if len(parts) != 2 { + before, after, ok := strings.Cut(i, "=") + if !ok || before == "" { continue } - params[parts[0]] = parts[1] + params[before] = after } return params } diff --git a/cli/pipeline/create.go b/cli/pipeline/create.go index b268622eb7..3db896a9f1 100644 --- a/cli/pipeline/create.go +++ b/cli/pipeline/create.go @@ -19,12 +19,11 @@ import ( "strings" "text/template" - "go.woodpecker-ci.org/woodpecker/v2/woodpecker-go/woodpecker" - "github.com/urfave/cli/v2" "go.woodpecker-ci.org/woodpecker/v2/cli/common" "go.woodpecker-ci.org/woodpecker/v2/cli/internal" + "go.woodpecker-ci.org/woodpecker/v2/woodpecker-go/woodpecker" ) var pipelineCreateCmd = &cli.Command{ @@ -61,9 +60,9 @@ func pipelineCreate(c *cli.Context) error { variables := make(map[string]string) for _, vaz := range c.StringSlice("var") { - sp := strings.SplitN(vaz, "=", 2) - if len(sp) == 2 { - variables[sp[0]] = sp[1] + before, after, _ := strings.Cut(vaz, "=") + if before != "" && after != "" { + variables[before] = after } } diff --git a/cli/pipeline/info.go b/cli/pipeline/info.go index 2b1e9103fc..51d7554438 100644 --- a/cli/pipeline/info.go +++ b/cli/pipeline/info.go @@ -46,7 +46,7 @@ func pipelineInfo(c *cli.Context) error { pipelineArg := c.Args().Get(1) var number int64 - if pipelineArg == "last" || len(pipelineArg) == 0 { + if pipelineArg == "last" || len(pipelineArg) == 0 { //nolint:goconst // Fetch the pipeline number from the last pipeline pipeline, err := client.PipelineLast(repoID, "") if err != nil { diff --git a/cli/pipeline/list.go b/cli/pipeline/list.go index 5a2fbaf92d..5cac3aa4d8 100644 --- a/cli/pipeline/list.go +++ b/cli/pipeline/list.go @@ -24,6 +24,7 @@ import ( "go.woodpecker-ci.org/woodpecker/v2/cli/internal" ) +//nolint:gomnd var pipelineListCmd = &cli.Command{ Name: "ls", Usage: "show pipeline history", diff --git a/cli/pipeline/logs.go b/cli/pipeline/logs.go index 8951b20521..116d68a4d2 100644 --- a/cli/pipeline/logs.go +++ b/cli/pipeline/logs.go @@ -41,12 +41,14 @@ func pipelineLogs(c *cli.Context) error { return err } - number, err := strconv.ParseInt(c.Args().Get(1), 10, 64) + numberArgIndex := 1 + number, err := strconv.ParseInt(c.Args().Get(numberArgIndex), 10, 64) if err != nil { return err } - step, err := strconv.ParseInt(c.Args().Get(2), 10, 64) + stepArgIndex := 2 + step, err := strconv.ParseInt(c.Args().Get(stepArgIndex), 10, 64) if err != nil { return err } diff --git a/cli/secret/secret_info.go b/cli/secret/secret_info.go index 138dbb28e1..02d1a5d5ea 100644 --- a/cli/secret/secret_info.go +++ b/cli/secret/secret_info.go @@ -61,17 +61,18 @@ func secretInfo(c *cli.Context) error { } var secret *woodpecker.Secret - if global { + switch { + case global: secret, err = client.GlobalSecret(secretName) if err != nil { return err } - } else if orgID != -1 { + case orgID != -1: secret, err = client.OrgSecret(orgID, secretName) if err != nil { return err } - } else { + default: secret, err = client.Secret(repoID, secretName) if err != nil { return err diff --git a/cli/secret/secret_list.go b/cli/secret/secret_list.go index 94a794f329..24d61fb0dd 100644 --- a/cli/secret/secret_list.go +++ b/cli/secret/secret_list.go @@ -56,17 +56,18 @@ func secretList(c *cli.Context) error { } var list []*woodpecker.Secret - if global { + switch { + case global: list, err = client.GlobalSecretList() if err != nil { return err } - } else if orgID != -1 { + case orgID != -1: list, err = client.OrgSecretList(orgID) if err != nil { return err } - } else { + default: list, err = client.SecretList(repoID) if err != nil { return err diff --git a/cli/user/user_info.go b/cli/user/user_info.go index f7c92abca2..62abe27130 100644 --- a/cli/user/user_info.go +++ b/cli/user/user_info.go @@ -41,7 +41,7 @@ func userInfo(c *cli.Context) error { login := c.Args().First() if len(login) == 0 { - return fmt.Errorf("Missing or invalid user login") + return fmt.Errorf("missing or invalid user login") } user, err := client.User(login) diff --git a/cmd/agent/agent.go b/cmd/agent/agent.go index fc9c6f0c28..5f2148c3c6 100644 --- a/cmd/agent/agent.go +++ b/cmd/agent/agent.go @@ -93,7 +93,7 @@ func run(c *cli.Context) error { agentToken := c.String("grpc-token") authClient := agentRpc.NewAuthGrpcClient(authConn, agentToken, agentConfig.AgentID) - authInterceptor, err := agentRpc.NewAuthInterceptor(authClient, 30*time.Minute) + authInterceptor, err := agentRpc.NewAuthInterceptor(authClient, 30*time.Minute) //nolint: gomnd if err != nil { return err } @@ -292,12 +292,12 @@ func stringSliceAddToMap(sl []string, m map[string]string) error { m = make(map[string]string) } for _, v := range sl { - parts := strings.SplitN(v, "=", 2) - switch len(parts) { - case 2: - m[parts[0]] = parts[1] - case 1: - return fmt.Errorf("key '%s' does not have a value assigned", parts[0]) + before, after, _ := strings.Cut(v, "=") + switch { + case before != "" && after != "": + m[before] = after + case after != "": + return fmt.Errorf("key '%s' does not have a value assigned", before) default: return fmt.Errorf("empty string in slice") } diff --git a/cmd/agent/health.go b/cmd/agent/health.go index 8c11589b61..d9d24ebf2e 100644 --- a/cmd/agent/health.go +++ b/cmd/agent/health.go @@ -39,14 +39,14 @@ func initHealth() { func handleHeartbeat(w http.ResponseWriter, _ *http.Request) { if counter.Healthy() { - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) } else { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) } } func handleVersion(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) w.Header().Add("Content-Type", "text/json") err := json.NewEncoder(w).Encode(versionResp{ Source: "https://github.com/woodpecker-ci/woodpecker", @@ -59,9 +59,9 @@ func handleVersion(w http.ResponseWriter, _ *http.Request) { func handleStats(w http.ResponseWriter, _ *http.Request) { if counter.Healthy() { - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) } else { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) } w.Header().Add("Content-Type", "text/json") if _, err := counter.WriteTo(w); err != nil { @@ -92,7 +92,7 @@ func pinger(c *cli.Context) error { return err } defer resp.Body.Close() - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { return fmt.Errorf("agent returned non-200 status code") } return nil diff --git a/cmd/server/main.go b/cmd/server/main.go index 72c1806c1a..4222e1911e 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -20,8 +20,8 @@ import ( _ "github.com/joho/godotenv/autoload" "github.com/urfave/cli/v2" - _ "go.woodpecker-ci.org/woodpecker/v2/cmd/server/docs" + _ "go.woodpecker-ci.org/woodpecker/v2/cmd/server/docs" "go.woodpecker-ci.org/woodpecker/v2/version" ) diff --git a/cmd/server/server.go b/cmd/server/server.go index 20478c892c..7fba220c77 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -50,8 +50,6 @@ import ( "go.woodpecker-ci.org/woodpecker/v2/shared/constant" "go.woodpecker-ci.org/woodpecker/v2/shared/logger" "go.woodpecker-ci.org/woodpecker/v2/version" - // "go.woodpecker-ci.org/woodpecker/v2/server/plugins/encryption" - // encryptedStore "go.woodpecker-ci.org/woodpecker/v2/server/plugins/encryption/wrapper/store" ) func run(c *cli.Context) error { @@ -180,7 +178,8 @@ func run(c *cli.Context) error { middleware.Store(c, _store), ) - if c.String("server-cert") != "" { + switch { + case c.String("server-cert") != "": // start the server with tls enabled g.Go(func() error { serve := &http.Server{ @@ -218,7 +217,7 @@ func run(c *cli.Context) error { } return err }) - } else if c.Bool("lets-encrypt") { + case c.Bool("lets-encrypt"): // start the server with lets-encrypt certmagic.DefaultACME.Email = c.String("lets-encrypt-email") certmagic.DefaultACME.Agreed = true @@ -234,7 +233,7 @@ func run(c *cli.Context) error { } return nil }) - } else { + default: // start the server without tls g.Go(func() error { err := http.ListenAndServe( diff --git a/pipeline/backend/common/script_win.go b/pipeline/backend/common/script_win.go index b311b0acb4..17d3b82797 100644 --- a/pipeline/backend/common/script_win.go +++ b/pipeline/backend/common/script_win.go @@ -24,7 +24,7 @@ func generateScriptWindows(commands []string) string { var buf bytes.Buffer for _, command := range commands { escaped := fmt.Sprintf("%q", command) - escaped = strings.Replace(escaped, "$", `\$`, -1) + escaped = strings.ReplaceAll(escaped, "$", `\$`) buf.WriteString(fmt.Sprintf( traceScriptWin, escaped, diff --git a/pipeline/backend/docker/docker.go b/pipeline/backend/docker/docker.go index 0e9c542948..2406910627 100644 --- a/pipeline/backend/docker/docker.go +++ b/pipeline/backend/docker/docker.go @@ -147,11 +147,11 @@ func (e *docker) Load(ctx context.Context) (*backend.BackendInfo, error) { }, nil } -func (e *docker) SetupWorkflow(_ context.Context, conf *backend.Config, taskUUID string) error { +func (e *docker) SetupWorkflow(ctx context.Context, conf *backend.Config, taskUUID string) error { log.Trace().Str("taskUUID", taskUUID).Msg("create workflow environment") for _, vol := range conf.Volumes { - _, err := e.client.VolumeCreate(noContext, volume.CreateOptions{ + _, err := e.client.VolumeCreate(ctx, volume.CreateOptions{ Name: vol.Name, Driver: volumeDriver, }) @@ -165,7 +165,7 @@ func (e *docker) SetupWorkflow(_ context.Context, conf *backend.Config, taskUUID networkDriver = networkDriverNAT } for _, n := range conf.Networks { - _, err := e.client.NetworkCreate(noContext, n.Name, types.NetworkCreate{ + _, err := e.client.NetworkCreate(ctx, n.Name, types.NetworkCreate{ Driver: networkDriver, EnableIPv6: e.enableIPv6, }) @@ -311,27 +311,27 @@ func (e *docker) DestroyStep(ctx context.Context, step *backend.Step, taskUUID s return nil } -func (e *docker) DestroyWorkflow(_ context.Context, conf *backend.Config, taskUUID string) error { +func (e *docker) DestroyWorkflow(ctx context.Context, conf *backend.Config, taskUUID string) error { log.Trace().Str("taskUUID", taskUUID).Msgf("delete workflow environment") for _, stage := range conf.Stages { for _, step := range stage.Steps { containerName := toContainerName(step) - if err := e.client.ContainerKill(noContext, containerName, "9"); err != nil && !isErrContainerNotFoundOrNotRunning(err) { + if err := e.client.ContainerKill(ctx, containerName, "9"); err != nil && !isErrContainerNotFoundOrNotRunning(err) { log.Error().Err(err).Msgf("could not kill container '%s'", step.Name) } - if err := e.client.ContainerRemove(noContext, containerName, removeOpts); err != nil && !isErrContainerNotFoundOrNotRunning(err) { + if err := e.client.ContainerRemove(ctx, containerName, removeOpts); err != nil && !isErrContainerNotFoundOrNotRunning(err) { log.Error().Err(err).Msgf("could not remove container '%s'", step.Name) } } } for _, v := range conf.Volumes { - if err := e.client.VolumeRemove(noContext, v.Name, true); err != nil { + if err := e.client.VolumeRemove(ctx, v.Name, true); err != nil { log.Error().Err(err).Msgf("could not remove volume '%s'", v.Name) } } for _, n := range conf.Networks { - if err := e.client.NetworkRemove(noContext, n.Name); err != nil { + if err := e.client.NetworkRemove(ctx, n.Name); err != nil { log.Error().Err(err).Msgf("could not remove network '%s'", n.Name) } } @@ -339,8 +339,6 @@ func (e *docker) DestroyWorkflow(_ context.Context, conf *backend.Config, taskUU } var ( - noContext = context.Background() - startOpts = types.ContainerStartOptions{} removeOpts = types.ContainerRemoveOptions{ diff --git a/pipeline/backend/kubernetes/utils.go b/pipeline/backend/kubernetes/utils.go index fd924f3570..c5802eab6d 100644 --- a/pipeline/backend/kubernetes/utils.go +++ b/pipeline/backend/kubernetes/utils.go @@ -32,7 +32,7 @@ var ( ) func dnsName(i string) (string, error) { - res := strings.Replace(i, "_", "-", -1) + res := strings.ReplaceAll(i, "_", "-") if found := dnsPattern.FindStringIndex(res); found == nil { return "", ErrDNSPatternInvalid diff --git a/pipeline/backend/local/clone.go b/pipeline/backend/local/clone.go index 8dd2bc8169..1bfd22dddf 100644 --- a/pipeline/backend/local/clone.go +++ b/pipeline/backend/local/clone.go @@ -26,9 +26,12 @@ import ( "strings" "github.com/rs/zerolog/log" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types" ) +const osWindows = "windows" + // checkGitCloneCap check if we have the git binary on hand func checkGitCloneCap() error { _, err := exec.LookPath("git") @@ -54,7 +57,7 @@ func (e *local) setupClone(state *workflowState) error { log.Info().Msg("no global 'plugin-git' installed, try to download for current workflow") state.pluginGitBinary = filepath.Join(state.homeDir, "plugin-git") - if e.os == "windows" { + if e.os == osWindows { state.pluginGitBinary += ".exe" } return e.downloadLatestGitPluginBinary(state.pluginGitBinary) @@ -87,7 +90,7 @@ func (e *local) execClone(ctx context.Context, step *types.Step, state *workflow var cmd *exec.Cmd if rmCmd != "" { // if we have a netrc injected we have to make sure it's deleted in any case after clone was attempted - if e.os == "windows" { + if e.os == osWindows { pwsh, err := exec.LookPath("powershell.exe") if err != nil { return err @@ -121,7 +124,7 @@ func (e *local) writeNetRC(step *types.Step, state *workflowState) (string, erro file := filepath.Join(state.homeDir, ".netrc") rmCmd := fmt.Sprintf("rm \"%s\"", file) - if e.os == "windows" { + if e.os == osWindows { file = filepath.Join(state.homeDir, "_netrc") rmCmd = fmt.Sprintf("del \"%s\"", file) } diff --git a/pipeline/backend/local/const.go b/pipeline/backend/local/const.go index 70594a7621..e84f5ed86d 100644 --- a/pipeline/backend/local/const.go +++ b/pipeline/backend/local/const.go @@ -31,8 +31,9 @@ var notAllowedEnvVarOverwrites = []string{ } var ( - ErrUnsupportedStepType = errors.New("unsupported step type") - ErrWorkflowStateNotFound = errors.New("workflow state not found") + ErrUnsupportedStepType = errors.New("unsupported step type") + ErrWorkflowStateNotFound = errors.New("workflow state not found") + ErrWorkflowStateMalformed = errors.New("workflow state malformed") ) const netrcFile = ` diff --git a/pipeline/backend/local/local.go b/pipeline/backend/local/local.go index 5eafe224e4..14b19b9634 100644 --- a/pipeline/backend/local/local.go +++ b/pipeline/backend/local/local.go @@ -257,7 +257,12 @@ func (e *local) getState(taskUUID string) (*workflowState, error) { if !ok { return nil, ErrWorkflowStateNotFound } - return state.(*workflowState), nil + + workflowState, ok := state.(*workflowState) + if !ok { + return nil, ErrWorkflowStateMalformed + } + return workflowState, nil } func (e *local) saveState(taskUUID string, state *workflowState) { diff --git a/pipeline/const.go b/pipeline/const.go new file mode 100644 index 0000000000..be0592f01f --- /dev/null +++ b/pipeline/const.go @@ -0,0 +1,33 @@ +// Copyright 2023 Woodpecker Authors +// +// 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 +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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. + +package pipeline + +// StatusValue represent pipeline states woodpecker know +type StatusValue string // @name StatusValue + +const ( + StatusSkipped StatusValue = "skipped" // skipped as another step failed + StatusPending StatusValue = "pending" // pending to be executed + StatusRunning StatusValue = "running" // currently running + StatusSuccess StatusValue = "success" // successfully finished + StatusFailure StatusValue = "failure" // failed to finish (exit code != 0) + StatusKilled StatusValue = "killed" // killed by user + StatusError StatusValue = "error" // error with the config / while parsing / some other system problem + StatusBlocked StatusValue = "blocked" // waiting for approval + StatusDeclined StatusValue = "declined" // blocked and declined + StatusCreated StatusValue = "created" // created / internal use only +) + +const ExitCodeKilled int = 137 diff --git a/pipeline/frontend/metadata/drone_compatibility_test.go b/pipeline/frontend/metadata/drone_compatibility_test.go index ff77135267..292d45e679 100644 --- a/pipeline/frontend/metadata/drone_compatibility_test.go +++ b/pipeline/frontend/metadata/drone_compatibility_test.go @@ -19,6 +19,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata" ) diff --git a/pipeline/frontend/metadata/environment.go b/pipeline/frontend/metadata/environment.go index b2629a9f7d..2d025c4ba9 100644 --- a/pipeline/frontend/metadata/environment.go +++ b/pipeline/frontend/metadata/environment.go @@ -38,7 +38,7 @@ func (m *Metadata) Environ() map[string]string { ) branchParts := strings.Split(m.Curr.Commit.Refspec, ":") - if len(branchParts) == 2 { + if len(branchParts) == 2 { //nolint: gomnd sourceBranch = branchParts[0] targetBranch = branchParts[1] } diff --git a/pipeline/frontend/yaml/compiler/cacher.go b/pipeline/frontend/yaml/compiler/cacher.go index 8e57f5f0fe..93c279f312 100644 --- a/pipeline/frontend/yaml/compiler/cacher.go +++ b/pipeline/frontend/yaml/compiler/cacher.go @@ -40,7 +40,7 @@ func (c *volumeCacher) Restore(repo, branch string, mounts []string) *yaml_types "mount": mounts, "path": "/cache", "restore": true, - "file": strings.Replace(branch, "/", "_", -1) + ".tar", + "file": strings.ReplaceAll(branch, "/", "_") + ".tar", "fallback_to": "main.tar", }, Volumes: yaml_types.Volumes{ @@ -64,7 +64,7 @@ func (c *volumeCacher) Rebuild(repo, branch string, mounts []string) *yaml_types "path": "/cache", "rebuild": true, "flush": true, - "file": strings.Replace(branch, "/", "_", -1) + ".tar", + "file": strings.ReplaceAll(branch, "/", "_") + ".tar", }, Volumes: yaml_types.Volumes{ Volumes: []*yaml_types.Volume{ diff --git a/pipeline/frontend/yaml/compiler/compiler.go b/pipeline/frontend/yaml/compiler/compiler.go index 3e82fcaaa1..fd980757e5 100644 --- a/pipeline/frontend/yaml/compiler/compiler.go +++ b/pipeline/frontend/yaml/compiler/compiler.go @@ -151,7 +151,7 @@ func (c *Compiler) Compile(conf *yaml_types.Workflow) (*backend_types.Config, er if !c.local && len(conf.Clone.ContainerList) == 0 && !conf.SkipClone { cloneSettings := map[string]any{"depth": "0"} if c.metadata.Curr.Event == metadata.EventTag { - cloneSettings["tags"] = "true" + cloneSettings["tags"] = "true" //nolint:goconst } container := &yaml_types.Container{ Name: defaultCloneName, diff --git a/pipeline/frontend/yaml/constraint/constraint.go b/pipeline/frontend/yaml/constraint/constraint.go index 582753a1df..2fa89e7bd0 100644 --- a/pipeline/frontend/yaml/constraint/constraint.go +++ b/pipeline/frontend/yaml/constraint/constraint.go @@ -195,7 +195,11 @@ func (c *Constraint) Match(m metadata.Metadata, global bool, env map[string]stri if err != nil { return false, err } - match = match && result.(bool) + bresult, ok := result.(bool) + if !ok { + return false, fmt.Errorf("could not parse result: %v", result) + } + match = match && bresult } return match, nil @@ -254,6 +258,7 @@ func (c *List) UnmarshalYAML(value *yaml.Node) error { err2 := value.Decode(&out2) c.Exclude = out1.Exclude + //nolint:gocritic c.Include = append( out1.Include, out2..., @@ -261,7 +266,7 @@ func (c *List) UnmarshalYAML(value *yaml.Node) error { if err1 != nil && err2 != nil { y, _ := yaml.Marshal(value) - return fmt.Errorf("Could not parse condition: %s: %w", y, multierr.Append(err1, err2)) + return fmt.Errorf("could not parse condition: %s: %w", y, multierr.Append(err1, err2)) } return nil @@ -335,6 +340,7 @@ func (c *Path) UnmarshalYAML(value *yaml.Node) error { c.Exclude = out1.Exclude c.IgnoreMessage = out1.IgnoreMessage + //nolint:gocritic c.Include = append( out1.Include, out2..., @@ -342,7 +348,7 @@ func (c *Path) UnmarshalYAML(value *yaml.Node) error { if err1 != nil && err2 != nil { y, _ := yaml.Marshal(value) - return fmt.Errorf("Could not parse condition: %s", y) + return fmt.Errorf("could not parse condition: %s", y) } return nil diff --git a/pipeline/frontend/yaml/linter/schema/schema.go b/pipeline/frontend/yaml/linter/schema/schema.go index da24cab37b..fae8636279 100644 --- a/pipeline/frontend/yaml/linter/schema/schema.go +++ b/pipeline/frontend/yaml/linter/schema/schema.go @@ -36,29 +36,29 @@ func Lint(r io.Reader) ([]gojsonschema.ResultError, error) { // read yaml config rBytes, err := io.ReadAll(r) if err != nil { - return nil, fmt.Errorf("Failed to load yml file %w", err) + return nil, fmt.Errorf("failed to load yml file %w", err) } // resolve sequence merges yamlDoc := new(yaml.Node) if err := xyaml.Unmarshal(rBytes, yamlDoc); err != nil { - return nil, fmt.Errorf("Failed to parse yml file %w", err) + return nil, fmt.Errorf("failed to parse yml file %w", err) } // convert to json jsonDoc, err := yaml2json.ConvertNode(yamlDoc) if err != nil { - return nil, fmt.Errorf("Failed to convert yaml %w", err) + return nil, fmt.Errorf("failed to convert yaml %w", err) } documentLoader := gojsonschema.NewBytesLoader(jsonDoc) result, err := gojsonschema.Validate(schemaLoader, documentLoader) if err != nil { - return nil, fmt.Errorf("Validation failed %w", err) + return nil, fmt.Errorf("validation failed %w", err) } if !result.Valid() { - return result.Errors(), fmt.Errorf("Config not valid") + return result.Errors(), fmt.Errorf("config not valid") } return nil, nil diff --git a/pipeline/frontend/yaml/matrix/matrix.go b/pipeline/frontend/yaml/matrix/matrix.go index 9abf3bd1af..b89dfc5d93 100644 --- a/pipeline/frontend/yaml/matrix/matrix.go +++ b/pipeline/frontend/yaml/matrix/matrix.go @@ -17,9 +17,9 @@ package matrix import ( "strings" - "go.woodpecker-ci.org/woodpecker/v2/pipeline/errors" - "codeberg.org/6543/xyaml" + + "go.woodpecker-ci.org/woodpecker/v2/pipeline/errors" ) const ( @@ -89,7 +89,7 @@ func calc(matrix Matrix) []Axis { decr := perm for i, tag := range tags { elems := matrix[tag] - decr = decr / len(elems) + decr /= len(elems) elem := p / decr % len(elems) axis[tag] = elems[elem] diff --git a/pipeline/frontend/yaml/parse.go b/pipeline/frontend/yaml/parse.go index e14b1bd1a6..2aaf6d940d 100644 --- a/pipeline/frontend/yaml/parse.go +++ b/pipeline/frontend/yaml/parse.go @@ -34,11 +34,12 @@ func ParseBytes(b []byte) (*types.Workflow, error) { // support deprecated branch filter if out.BranchesDontUseIt != nil { - if out.When.Constraints == nil { + switch { + case out.When.Constraints == nil: out.When.Constraints = []constraint.Constraint{{Branch: *out.BranchesDontUseIt}} - } else if len(out.When.Constraints) == 1 && out.When.Constraints[0].Branch.IsEmpty() { + case len(out.When.Constraints) == 1 && out.When.Constraints[0].Branch.IsEmpty(): out.When.Constraints[0].Branch = *out.BranchesDontUseIt - } else { + default: return nil, fmt.Errorf("could not apply deprecated branches filter into global when filter") } out.BranchesDontUseIt = nil diff --git a/pipeline/frontend/yaml/types/base/base_types_test.go b/pipeline/frontend/yaml/types/base/base_types_test.go index e21d68cdae..428b44f06b 100644 --- a/pipeline/frontend/yaml/types/base/base_types_test.go +++ b/pipeline/frontend/yaml/types/base/base_types_test.go @@ -104,7 +104,7 @@ bars: [] func TestUnmarshalSliceOrMap(t *testing.T) { s := StructSliceorMap{} err := yaml.Unmarshal([]byte(sampleStructSliceorMap), &s) - assert.Equal(t, fmt.Errorf("Cannot unmarshal 'true' of type bool into a string value"), err) + assert.Equal(t, fmt.Errorf("cannot unmarshal 'true' of type bool into a string value"), err) } func TestStr2SliceOrMapPtrMap(t *testing.T) { diff --git a/pipeline/frontend/yaml/types/base/int.go b/pipeline/frontend/yaml/types/base/int.go index e4ff93b792..26565f2d2e 100644 --- a/pipeline/frontend/yaml/types/base/int.go +++ b/pipeline/frontend/yaml/types/base/int.go @@ -42,7 +42,7 @@ func (s *StringOrInt) UnmarshalYAML(unmarshal func(any) error) error { return nil } - return errors.New("Failed to unmarshal StringOrInt") + return errors.New("failed to unmarshal StringOrInt") } // MemStringOrInt represents a string or an integer @@ -67,5 +67,5 @@ func (s *MemStringOrInt) UnmarshalYAML(unmarshal func(any) error) error { return nil } - return errors.New("Failed to unmarshal MemStringOrInt") + return errors.New("failed to unmarshal MemStringOrInt") } diff --git a/pipeline/frontend/yaml/types/base/map.go b/pipeline/frontend/yaml/types/base/map.go index 3102ef1b30..e25a65b04e 100644 --- a/pipeline/frontend/yaml/types/base/map.go +++ b/pipeline/frontend/yaml/types/base/map.go @@ -40,7 +40,7 @@ func (s *SliceOrMap) UnmarshalYAML(unmarshal func(any) error) error { } parts[key] = val } else { - return fmt.Errorf("Cannot unmarshal '%v' of type %T into a string value", s, s) + return fmt.Errorf("cannot unmarshal '%v' of type %T into a string value", s, s) } } *s = parts @@ -55,15 +55,15 @@ func (s *SliceOrMap) UnmarshalYAML(unmarshal func(any) error) error { if sv, ok := v.(string); ok { parts[sk] = sv } else { - return fmt.Errorf("Cannot unmarshal '%v' of type %T into a string value", v, v) + return fmt.Errorf("cannot unmarshal '%v' of type %T into a string value", v, v) } } else { - return fmt.Errorf("Cannot unmarshal '%v' of type %T into a string value", k, k) + return fmt.Errorf("cannot unmarshal '%v' of type %T into a string value", k, k) } } *s = parts return nil } - return errors.New("Failed to unmarshal SliceOrMap") + return errors.New("failed to unmarshal SliceOrMap") } diff --git a/pipeline/frontend/yaml/types/base/slice.go b/pipeline/frontend/yaml/types/base/slice.go index 0d2685f555..6203cbe1e6 100644 --- a/pipeline/frontend/yaml/types/base/slice.go +++ b/pipeline/frontend/yaml/types/base/slice.go @@ -41,7 +41,7 @@ func (s *StringOrSlice) UnmarshalYAML(unmarshal func(any) error) error { return nil } - return errors.New("Failed to unmarshal StringOrSlice") + return errors.New("failed to unmarshal StringOrSlice") } func toStrings(s []any) ([]string, error) { @@ -53,7 +53,7 @@ func toStrings(s []any) ([]string, error) { if sv, ok := v.(string); ok { r[k] = sv } else { - return nil, fmt.Errorf("Cannot unmarshal '%v' of type %T into a string value", v, v) + return nil, fmt.Errorf("cannot unmarshal '%v' of type %T into a string value", v, v) } } return r, nil diff --git a/pipeline/frontend/yaml/types/network.go b/pipeline/frontend/yaml/types/network.go index fe2798f996..4d7660a4c2 100644 --- a/pipeline/frontend/yaml/types/network.go +++ b/pipeline/frontend/yaml/types/network.go @@ -50,7 +50,7 @@ func (n *Networks) UnmarshalYAML(unmarshal func(any) error) error { for _, network := range sliceType { name, ok := network.(string) if !ok { - return fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", name, name) + return fmt.Errorf("cannot unmarshal '%v' to type %T into a string value", name, name) } n.Networks = append(n.Networks, &Network{ Name: name, @@ -65,7 +65,7 @@ func (n *Networks) UnmarshalYAML(unmarshal func(any) error) error { for mapKey, mapValue := range mapType { name, ok := mapKey.(string) if !ok { - return fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", name, name) + return fmt.Errorf("cannot unmarshal '%v' to type %T into a string value", name, name) } network, err := handleNetwork(name, mapValue) if err != nil { @@ -76,7 +76,7 @@ func (n *Networks) UnmarshalYAML(unmarshal func(any) error) error { return nil } - return errors.New("Failed to unmarshal Networks") + return errors.New("failed to unmarshal Networks") } func handleNetwork(name string, value any) (*Network, error) { @@ -95,16 +95,17 @@ func handleNetwork(name string, value any) (*Network, error) { case "aliases": aliases, ok := mapValue.([]any) if !ok { - return &Network{}, fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", aliases, aliases) + return &Network{}, fmt.Errorf("cannot unmarshal '%v' to type %T into a string value", aliases, aliases) } network.Aliases = []string{} for _, alias := range aliases { - network.Aliases = append(network.Aliases, alias.(string)) + a, _ := alias.(string) + network.Aliases = append(network.Aliases, a) } case "ipv4_address": - network.IPv4Address = mapValue.(string) + network.IPv4Address, _ = mapValue.(string) case "ipv6_address": - network.IPv6Address = mapValue.(string) + network.IPv6Address, _ = mapValue.(string) default: // Ignorer unknown keys ? continue @@ -112,6 +113,6 @@ func handleNetwork(name string, value any) (*Network, error) { } return network, nil default: - return &Network{}, fmt.Errorf("Failed to unmarshal Network: %#v", value) + return &Network{}, fmt.Errorf("failed to unmarshal Network: %#v", value) } } diff --git a/pipeline/frontend/yaml/types/volume.go b/pipeline/frontend/yaml/types/volume.go index 7dc7ec2323..3d925e25b3 100644 --- a/pipeline/frontend/yaml/types/volume.go +++ b/pipeline/frontend/yaml/types/volume.go @@ -64,10 +64,11 @@ func (v *Volumes) UnmarshalYAML(unmarshal func(any) error) error { for _, volume := range sliceType { name, ok := volume.(string) if !ok { - return fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", name, name) + return fmt.Errorf("cannot unmarshal '%v' to type %T into a string value", name, name) } elts := strings.SplitN(name, ":", 3) var vol *Volume + //nolint: gomnd switch { case len(elts) == 1: vol = &Volume{ @@ -93,5 +94,5 @@ func (v *Volumes) UnmarshalYAML(unmarshal func(any) error) error { return nil } - return errors.New("Failed to unmarshal Volumes") + return errors.New("failed to unmarshal Volumes") } diff --git a/pipeline/tracer.go b/pipeline/tracer.go index 88db835868..e9ab17f730 100644 --- a/pipeline/tracer.go +++ b/pipeline/tracer.go @@ -43,17 +43,17 @@ var DefaultTracer = TraceFunc(func(state *State) error { if state.Pipeline.Step.Environment == nil { return nil } - state.Pipeline.Step.Environment["CI_PIPELINE_STATUS"] = "success" + state.Pipeline.Step.Environment["CI_PIPELINE_STATUS"] = string(StatusSuccess) state.Pipeline.Step.Environment["CI_PIPELINE_STARTED"] = strconv.FormatInt(state.Pipeline.Time, 10) state.Pipeline.Step.Environment["CI_PIPELINE_FINISHED"] = strconv.FormatInt(time.Now().Unix(), 10) - state.Pipeline.Step.Environment["CI_STEP_STATUS"] = "success" + state.Pipeline.Step.Environment["CI_STEP_STATUS"] = string(StatusSuccess) state.Pipeline.Step.Environment["CI_STEP_STARTED"] = strconv.FormatInt(state.Pipeline.Time, 10) state.Pipeline.Step.Environment["CI_STEP_FINISHED"] = strconv.FormatInt(time.Now().Unix(), 10) if state.Pipeline.Error != nil { - state.Pipeline.Step.Environment["CI_PIPELINE_STATUS"] = "failure" - state.Pipeline.Step.Environment["CI_STEP_STATUS"] = "failure" + state.Pipeline.Step.Environment["CI_PIPELINE_STATUS"] = string(StatusFailure) + state.Pipeline.Step.Environment["CI_STEP_STATUS"] = string(StatusFailure) } return nil }) diff --git a/server/api/agent.go b/server/api/agent.go index 8c5bc36f70..c327ffd702 100644 --- a/server/api/agent.go +++ b/server/api/agent.go @@ -65,7 +65,7 @@ func GetAgent(c *gin.Context) { agent, err := store.FromContext(c).AgentFind(agentID) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.JSON(http.StatusOK, agent) @@ -89,7 +89,7 @@ func GetAgentTasks(c *gin.Context) { agent, err := store.FromContext(c).AgentFind(agentID) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -132,7 +132,7 @@ func PatchAgent(c *gin.Context) { agent, err := _store.AgentFind(agentID) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } agent.Name = in.Name @@ -201,7 +201,7 @@ func DeleteAgent(c *gin.Context) { agent, err := _store.AgentFind(agentID) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } if err = _store.AgentDelete(agent); err != nil { diff --git a/server/api/badge.go b/server/api/badge.go index 7e3b9fdef6..6f4b491d96 100644 --- a/server/api/badge.go +++ b/server/api/badge.go @@ -62,7 +62,7 @@ func GetBadge(c *gin.Context) { } if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -116,7 +116,7 @@ func GetCC(c *gin.Context) { } if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } diff --git a/server/api/cron.go b/server/api/cron.go index e496b6d151..c7bcb6371d 100644 --- a/server/api/cron.go +++ b/server/api/cron.go @@ -49,7 +49,7 @@ func GetCron(c *gin.Context) { cron, err := store.FromContext(c).CronFind(repo, id) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.JSON(http.StatusOK, cron) @@ -76,7 +76,7 @@ func RunCron(c *gin.Context) { cron, err := _store.CronFind(repo, id) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -183,7 +183,7 @@ func PatchCron(c *gin.Context) { cron, err := _store.CronFind(repo, id) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } if in.Branch != "" { @@ -259,7 +259,7 @@ func DeleteCron(c *gin.Context) { return } if err := store.FromContext(c).CronDelete(repo, id); err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.Status(http.StatusNoContent) diff --git a/server/api/global_secret.go b/server/api/global_secret.go index 9c8a5e5c86..e2322035b7 100644 --- a/server/api/global_secret.go +++ b/server/api/global_secret.go @@ -19,10 +19,9 @@ import ( "github.com/gin-gonic/gin" - "go.woodpecker-ci.org/woodpecker/v2/server/router/middleware/session" - "go.woodpecker-ci.org/woodpecker/v2/server" "go.woodpecker-ci.org/woodpecker/v2/server/model" + "go.woodpecker-ci.org/woodpecker/v2/server/router/middleware/session" ) // GetGlobalSecretList @@ -62,7 +61,7 @@ func GetGlobalSecret(c *gin.Context) { name := c.Param("secret") secret, err := server.Config.Services.Secrets.GlobalSecretFind(name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.JSON(http.StatusOK, secret.Copy()) @@ -122,7 +121,7 @@ func PatchGlobalSecret(c *gin.Context) { secret, err := server.Config.Services.Secrets.GlobalSecretFind(name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } if in.Value != "" { @@ -158,7 +157,7 @@ func PatchGlobalSecret(c *gin.Context) { func DeleteGlobalSecret(c *gin.Context) { name := c.Param("secret") if err := server.Config.Services.Secrets.GlobalSecretDelete(name); err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.Status(http.StatusNoContent) diff --git a/server/api/helper.go b/server/api/helper.go index cfe409b9b6..51646e370d 100644 --- a/server/api/helper.go +++ b/server/api/helper.go @@ -29,20 +29,21 @@ import ( ) func handlePipelineErr(c *gin.Context, err error) { - if errors.Is(err, &pipeline.ErrNotFound{}) { + switch { + case errors.Is(err, &pipeline.ErrNotFound{}): c.String(http.StatusNotFound, "%s", err) - } else if errors.Is(err, &pipeline.ErrBadRequest{}) { + case errors.Is(err, &pipeline.ErrBadRequest{}): c.String(http.StatusBadRequest, "%s", err) - } else if errors.Is(err, pipeline.ErrFiltered) { + case errors.Is(err, pipeline.ErrFiltered): // for debugging purpose we add a header c.Writer.Header().Add("Pipeline-Filtered", "true") c.Status(http.StatusNoContent) - } else { + default: _ = c.AbortWithError(http.StatusInternalServerError, err) } } -func handleDbError(c *gin.Context, err error) { +func handleDBError(c *gin.Context, err error) { if errors.Is(err, types.RecordNotExist) { c.AbortWithStatus(http.StatusNotFound) return diff --git a/server/api/hook.go b/server/api/hook.go index 961ec79d5d..cc247bac86 100644 --- a/server/api/hook.go +++ b/server/api/hook.go @@ -144,7 +144,7 @@ func PostHook(c *gin.Context) { repo, err := _store.GetRepoNameFallback(tmpRepo.ForgeRemoteID, tmpRepo.FullName) if err != nil { log.Error().Err(err).Msgf("failure to get repo %s from store", tmpRepo.FullName) - handleDbError(c, err) + handleDBError(c, err) return } if !repo.IsActive { diff --git a/server/api/login.go b/server/api/login.go index 29d25d7b1a..5442f0fe6b 100644 --- a/server/api/login.go +++ b/server/api/login.go @@ -81,7 +81,7 @@ func HandleAuth(c *gin.Context) { teams, terr := _forge.Teams(c, tmpuser) if terr != nil || !server.Config.Permissions.Orgs.IsMember(teams) { log.Error().Err(terr).Msgf("cannot verify team membership for %s.", u.Login) - c.Redirect(303, server.Config.Server.RootPath+"/login?error=access_denied") + c.Redirect(http.StatusSeeOther, server.Config.Server.RootPath+"/login?error=access_denied") return } } @@ -208,7 +208,7 @@ func GetLoginToken(c *gin.Context) { user, err := _store.GetUserLogin(login) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } diff --git a/server/api/metrics/prometheus.go b/server/api/metrics/prometheus.go index a7a7793b5e..1b68f7151f 100644 --- a/server/api/metrics/prometheus.go +++ b/server/api/metrics/prometheus.go @@ -26,7 +26,7 @@ import ( ) // errInvalidToken is returned when the api request token is invalid. -var errInvalidToken = errors.New("Invalid or missing token") +var errInvalidToken = errors.New("invalid or missing token") // PromHandler will pass the call from /api/metrics/prometheus to prometheus func PromHandler() gin.HandlerFunc { diff --git a/server/api/org.go b/server/api/org.go index e3b5999990..4474b7193a 100644 --- a/server/api/org.go +++ b/server/api/org.go @@ -19,9 +19,8 @@ import ( "strconv" "strings" - "github.com/rs/zerolog/log" - "github.com/gin-gonic/gin" + "github.com/rs/zerolog/log" "go.woodpecker-ci.org/woodpecker/v2/server" "go.woodpecker-ci.org/woodpecker/v2/server/model" @@ -49,7 +48,7 @@ func GetOrg(c *gin.Context) { org, err := _store.OrgGet(orgID) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -122,7 +121,7 @@ func LookupOrg(c *gin.Context) { org, err := _store.OrgFindByName(orgFullName) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } diff --git a/server/api/org_secret.go b/server/api/org_secret.go index 59bbd1b16d..b598ef378b 100644 --- a/server/api/org_secret.go +++ b/server/api/org_secret.go @@ -20,10 +20,9 @@ import ( "github.com/gin-gonic/gin" - "go.woodpecker-ci.org/woodpecker/v2/server/router/middleware/session" - "go.woodpecker-ci.org/woodpecker/v2/server" "go.woodpecker-ci.org/woodpecker/v2/server/model" + "go.woodpecker-ci.org/woodpecker/v2/server/router/middleware/session" ) // GetOrgSecret @@ -47,7 +46,7 @@ func GetOrgSecret(c *gin.Context) { secret, err := server.Config.Services.Secrets.OrgSecretFind(orgID, name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.JSON(http.StatusOK, secret.Copy()) @@ -152,7 +151,7 @@ func PatchOrgSecret(c *gin.Context) { secret, err := server.Config.Services.Secrets.OrgSecretFind(orgID, name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } if in.Value != "" { @@ -195,7 +194,7 @@ func DeleteOrgSecret(c *gin.Context) { } if err := server.Config.Services.Secrets.OrgSecretDelete(orgID, name); err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.Status(http.StatusNoContent) diff --git a/server/api/orgs.go b/server/api/orgs.go index 3e82c060b6..80d00c0a99 100644 --- a/server/api/orgs.go +++ b/server/api/orgs.go @@ -65,7 +65,7 @@ func DeleteOrg(c *gin.Context) { err = _store.OrgDelete(orgID) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } diff --git a/server/api/pipeline.go b/server/api/pipeline.go index 4f6dce6814..d66ecea522 100644 --- a/server/api/pipeline.go +++ b/server/api/pipeline.go @@ -140,7 +140,7 @@ func GetPipeline(c *gin.Context) { pl, err := _store.GetPipelineNumber(repo, num) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } if pl.Workflows, err = _store.WorkflowGetTree(pl); err != nil { @@ -158,7 +158,7 @@ func GetPipelineLast(c *gin.Context) { pl, err := _store.GetPipelineLast(repo, branch) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -194,7 +194,7 @@ func GetStepLogs(c *gin.Context) { pl, err := _store.GetPipelineNumber(repo, num) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -206,7 +206,7 @@ func GetStepLogs(c *gin.Context) { step, err := _store.StepLoad(stepID) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -218,7 +218,7 @@ func GetStepLogs(c *gin.Context) { logs, err := _store.LogFind(step) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -246,7 +246,7 @@ func GetPipelineConfig(c *gin.Context) { pl, err := _store.GetPipelineNumber(repo, num) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -277,7 +277,7 @@ func CancelPipeline(c *gin.Context) { pl, err := _store.GetPipelineNumber(repo, num) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -308,7 +308,7 @@ func PostApproval(c *gin.Context) { pl, err := _store.GetPipelineNumber(repo, num) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -340,7 +340,7 @@ func PostDecline(c *gin.Context) { pl, err := _store.GetPipelineNumber(repo, num) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -394,13 +394,13 @@ func PostPipeline(c *gin.Context) { user, err := _store.GetUser(repo.UserID) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } pl, err := _store.GetPipelineNumber(repo, num) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -467,7 +467,7 @@ func DeletePipelineLogs(c *gin.Context) { pl, err := _store.GetPipelineNumber(repo, num) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } diff --git a/server/api/registry.go b/server/api/registry.go index d8eb1b5674..6712ba94dd 100644 --- a/server/api/registry.go +++ b/server/api/registry.go @@ -41,10 +41,10 @@ func GetRegistry(c *gin.Context) { ) registry, err := server.Config.Services.Registries.RegistryFind(repo, name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } - c.JSON(200, registry.Copy()) + c.JSON(http.StatusOK, registry.Copy()) } // PostRegistry @@ -110,7 +110,7 @@ func PatchRegistry(c *gin.Context) { registry, err := server.Config.Services.Registries.RegistryFind(repo, name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } if in.Username != "" { @@ -180,7 +180,7 @@ func DeleteRegistry(c *gin.Context) { ) err := server.Config.Services.Registries.RegistryDelete(repo, name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.Status(http.StatusNoContent) diff --git a/server/api/repo.go b/server/api/repo.go index db16a49d77..f97067d607 100644 --- a/server/api/repo.go +++ b/server/api/repo.go @@ -400,7 +400,7 @@ func DeleteRepo(c *gin.Context) { if remove { if err := _store.DeleteRepo(repo); err != nil { - handleDbError(c, err) + handleDBError(c, err) return } } diff --git a/server/api/repo_secret.go b/server/api/repo_secret.go index 534af7369d..c7ef9eb72d 100644 --- a/server/api/repo_secret.go +++ b/server/api/repo_secret.go @@ -42,7 +42,7 @@ func GetSecret(c *gin.Context) { ) secret, err := server.Config.Services.Secrets.SecretFind(repo, name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.JSON(http.StatusOK, secret.Copy()) @@ -110,7 +110,7 @@ func PatchSecret(c *gin.Context) { secret, err := server.Config.Services.Secrets.SecretFind(repo, name) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } if in.Value != "" { @@ -176,7 +176,7 @@ func DeleteSecret(c *gin.Context) { name = c.Param("secret") ) if err := server.Config.Services.Secrets.SecretDelete(repo, name); err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.Status(http.StatusNoContent) diff --git a/server/api/signature_public_key.go b/server/api/signature_public_key.go index 0846f0c968..937f900247 100644 --- a/server/api/signature_public_key.go +++ b/server/api/signature_public_key.go @@ -21,6 +21,7 @@ import ( "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" + "go.woodpecker-ci.org/woodpecker/v2/server" ) diff --git a/server/api/user.go b/server/api/user.go index 4bd15ed34e..f33d4d32e6 100644 --- a/server/api/user.go +++ b/server/api/user.go @@ -117,11 +117,9 @@ func GetRepos(c *gin.Context) { existingRepo.Update(r) existingRepo.IsActive = active[r.ForgeRemoteID].IsActive repos = append(repos, existingRepo) - } else { - if r.Perm.Admin { - // you must be admin to enable the repo - repos = append(repos, r) - } + } else if r.Perm.Admin { + // you must be admin to enable the repo + repos = append(repos, r) } } } diff --git a/server/api/users.go b/server/api/users.go index b94e53043b..30fd8278fd 100644 --- a/server/api/users.go +++ b/server/api/users.go @@ -59,7 +59,7 @@ func GetUsers(c *gin.Context) { func GetUser(c *gin.Context) { user, err := store.FromContext(c).GetUserLogin(c.Param("login")) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.JSON(http.StatusOK, user) @@ -89,7 +89,7 @@ func PatchUser(c *gin.Context) { user, err := _store.GetUserLogin(c.Param("login")) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } @@ -159,11 +159,11 @@ func DeleteUser(c *gin.Context) { user, err := _store.GetUserLogin(c.Param("login")) if err != nil { - handleDbError(c, err) + handleDBError(c, err) return } if err = _store.DeleteUser(user); err != nil { - handleDbError(c, err) + handleDBError(c, err) return } c.Status(http.StatusNoContent) diff --git a/server/cache/membership.go b/server/cache/membership.go index 233d7fd080..3c73c12e03 100644 --- a/server/cache/membership.go +++ b/server/cache/membership.go @@ -19,10 +19,10 @@ import ( "fmt" "time" + "github.com/jellydator/ttlcache/v3" + "go.woodpecker-ci.org/woodpecker/v2/server/forge" "go.woodpecker-ci.org/woodpecker/v2/server/model" - - "github.com/jellydator/ttlcache/v3" ) // MembershipService is a service to check for user membership. diff --git a/server/forge/bitbucket/bitbucket.go b/server/forge/bitbucket/bitbucket.go index 3415ae6cb3..348ac35153 100644 --- a/server/forge/bitbucket/bitbucket.go +++ b/server/forge/bitbucket/bitbucket.go @@ -38,6 +38,7 @@ import ( const ( DefaultAPI = "https://api.bitbucket.org" DefaultURL = "https://bitbucket.org" + pageSize = 100 ) // Opts are forge options for bitbucket @@ -142,7 +143,7 @@ func (c *config) Refresh(ctx context.Context, user *model.User) (bool, error) { func (c *config) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { return shared_utils.Paginate(func(page int) ([]*model.Team, error) { opts := &internal.ListWorkspacesOpts{ - PageLen: 100, + PageLen: pageSize, Page: page, Role: "member", } @@ -191,7 +192,7 @@ func (c *config) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error workspaces, err := shared_utils.Paginate(func(page int) ([]*internal.Workspace, error) { resp, err := client.ListWorkspaces(&internal.ListWorkspacesOpts{ Page: page, - PageLen: 100, + PageLen: pageSize, Role: "member", }) if err != nil { diff --git a/server/forge/bitbucket/fixtures/handler.go b/server/forge/bitbucket/fixtures/handler.go index 707a6dd732..dffa9a5891 100644 --- a/server/forge/bitbucket/fixtures/handler.go +++ b/server/forge/bitbucket/fixtures/handler.go @@ -44,28 +44,27 @@ func Handler() http.Handler { } func getOauth(c *gin.Context) { - switch c.PostForm("error") { - case "invalid_scope": - c.String(500, "") + if c.PostForm("error") == "invalid_scope" { + c.String(http.StatusInternalServerError, "") } switch c.PostForm("code") { case "code_bad_request": - c.String(500, "") + c.String(http.StatusInternalServerError, "") return case "code_user_not_found": - c.String(200, tokenNotFoundPayload) + c.String(http.StatusOK, tokenNotFoundPayload) return } switch c.PostForm("refresh_token") { case "refresh_token_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") case "refresh_token_is_empty": c.Header("Content-Type", "application/json") - c.String(200, "{}") + c.String(http.StatusOK, "{}") default: c.Header("Content-Type", "application/json") - c.String(200, tokenPayload) + c.String(http.StatusOK, tokenPayload) } } @@ -75,12 +74,12 @@ func getWorkspaces(c *gin.Context) { switch c.Request.Header.Get("Authorization") { case "Bearer teams_not_found", "Bearer c81e728d": - c.String(404, "") + c.String(http.StatusNotFound, "") default: if c.Query("page") == "" || c.Query("page") == "1" { - c.String(200, workspacesPayload) + c.String(http.StatusOK, workspacesPayload) } else { - c.String(200, "{\"values\":[]}") + c.String(http.StatusOK, "{\"values\":[]}") } } } @@ -88,25 +87,25 @@ func getWorkspaces(c *gin.Context) { func getRepo(c *gin.Context) { switch c.Param("name") { case "not_found", "repo_unknown", "repo_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") case "permission_read", "permission_write", "permission_admin": - c.String(200, fmt.Sprintf(permissionRepoPayload, c.Param("name"))) + c.String(http.StatusOK, fmt.Sprintf(permissionRepoPayload, c.Param("name"))) default: - c.String(200, repoPayload) + c.String(http.StatusOK, repoPayload) } } func getRepoHooks(c *gin.Context) { switch c.Param("name") { case "hooks_not_found", "repo_no_hooks": - c.String(404, "") + c.String(http.StatusNotFound, "") case "hook_empty": - c.String(200, "{}") + c.String(http.StatusOK, "{}") default: if c.Query("page") == "" || c.Query("page") == "1" { - c.String(200, repoHookPayload) + c.String(http.StatusOK, repoHookPayload) } else { - c.String(200, "{\"values\":[]}") + c.String(http.StatusOK, "{\"values\":[]}") } } } @@ -114,74 +113,74 @@ func getRepoHooks(c *gin.Context) { func getRepoFile(c *gin.Context) { switch c.Param("file") { case "dir": - c.String(200, repoDirPayload) + c.String(http.StatusOK, repoDirPayload) case "dir_not_found/": - c.String(404, "") + c.String(http.StatusNotFound, "") case "file_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") default: - c.String(200, repoFilePayload) + c.String(http.StatusOK, repoFilePayload) } } func getBranchHead(c *gin.Context) { switch c.Param("commit") { case "branch_name": - c.String(200, branchCommitsPayload) + c.String(http.StatusOK, branchCommitsPayload) default: - c.String(404, "") + c.String(http.StatusNotFound, "") } } func getPullRequests(c *gin.Context) { switch c.Param("name") { case "repo_name": - c.String(200, pullRequestsPayload) + c.String(http.StatusOK, pullRequestsPayload) default: - c.String(404, "") + c.String(http.StatusNotFound, "") } } func createRepoStatus(c *gin.Context) { switch c.Param("name") { case "repo_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") default: - c.String(200, "") + c.String(http.StatusOK, "") } } func createRepoHook(c *gin.Context) { - c.String(200, "") + c.String(http.StatusOK, "") } func deleteRepoHook(c *gin.Context) { switch c.Param("name") { case "hook_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") default: - c.String(200, "") + c.String(http.StatusOK, "") } } func getUser(c *gin.Context) { switch c.Request.Header.Get("Authorization") { case "Bearer user_not_found", "Bearer a87ff679": - c.String(404, "") + c.String(http.StatusNotFound, "") default: - c.String(200, userPayload) + c.String(http.StatusOK, userPayload) } } func getUserRepos(c *gin.Context) { switch c.Request.Header.Get("Authorization") { case "Bearer repos_not_found", "Bearer 70efdf2e": - c.String(404, "") + c.String(http.StatusNotFound, "") default: if c.Query("page") == "" || c.Query("page") == "1" { - c.String(200, userRepoPayload) + c.String(http.StatusOK, userRepoPayload) } else { - c.String(200, "{\"values\":[]}") + c.String(http.StatusOK, "{\"values\":[]}") } } } @@ -194,13 +193,13 @@ func getPermissions(c *gin.Context) { query := c.Request.URL.Query()["q"][0] switch query { case `repository.full_name="test_name/permission_read"`: - c.String(200, permission("read")) + c.String(http.StatusOK, permission("read")) case `repository.full_name="test_name/permission_write"`: - c.String(200, permission("write")) + c.String(http.StatusOK, permission("write")) case `repository.full_name="test_name/permission_admin"`: - c.String(200, permission("admin")) + c.String(http.StatusOK, permission("admin")) default: - c.String(200, permission("read")) + c.String(http.StatusOK, permission("read")) } } diff --git a/server/forge/bitbucket/internal/client.go b/server/forge/bitbucket/internal/client.go index 8d832e8c16..949334dcb3 100644 --- a/server/forge/bitbucket/internal/client.go +++ b/server/forge/bitbucket/internal/client.go @@ -23,10 +23,10 @@ import ( "net/http" "net/url" - shared_utils "go.woodpecker-ci.org/woodpecker/v2/shared/utils" - "golang.org/x/oauth2" "golang.org/x/oauth2/bitbucket" + + shared_utils "go.woodpecker-ci.org/woodpecker/v2/shared/utils" ) const ( @@ -52,6 +52,7 @@ const ( pathPullRequests = "%s/2.0/repositories/%s/%s/pullrequests" pathBranchCommits = "%s/2.0/repositories/%s/%s/commits/%s" pathDir = "%s/2.0/repositories/%s/%s/src/%s%s" + pageSize = 100 ) type Client struct { @@ -114,7 +115,7 @@ func (c *Client) ListRepos(workspace string, opts *ListOpts) (*RepoResp, error) func (c *Client) ListReposAll(workspace string) ([]*Repo, error) { return shared_utils.Paginate(func(page int) ([]*Repo, error) { - resp, err := c.ListRepos(workspace, &ListOpts{Page: page, PageLen: 100}) + resp, err := c.ListRepos(workspace, &ListOpts{Page: page, PageLen: pageSize}) if err != nil { return nil, err } @@ -195,7 +196,7 @@ func (c *Client) GetBranchHead(owner, name, branch string) (string, error) { func (c *Client) GetUserWorkspaceMembership(workspace, user string) (string, error) { out := new(WorkspaceMembershipResp) - opts := &ListOpts{Page: 1, PageLen: 100} + opts := &ListOpts{Page: 1, PageLen: pageSize} for { uri := fmt.Sprintf(pathOrgPerms, c.base, workspace, opts.Encode()) _, err := c.do(uri, get, nil, out) diff --git a/server/forge/common/status.go b/server/forge/common/status.go index 27fa3f93fe..845edc2bf9 100644 --- a/server/forge/common/status.go +++ b/server/forge/common/status.go @@ -27,8 +27,7 @@ import ( func GetPipelineStatusContext(repo *model.Repo, pipeline *model.Pipeline, workflow *model.Workflow) string { event := string(pipeline.Event) - switch pipeline.Event { - case model.EventPull: + if pipeline.Event == model.EventPull { event = "pr" } diff --git a/server/forge/gitea/fixtures/handler.go b/server/forge/gitea/fixtures/handler.go index d6ff48fa1a..7bc2bbb42a 100644 --- a/server/forge/gitea/fixtures/handler.go +++ b/server/forge/gitea/fixtures/handler.go @@ -43,35 +43,35 @@ func Handler() http.Handler { func listRepoHooks(c *gin.Context) { page := c.Query("page") if page != "" && page != "1" { - c.String(200, "[]") + c.String(http.StatusOK, "[]") } else { - c.String(200, listRepoHookPayloads) + c.String(http.StatusOK, listRepoHookPayloads) } } func getRepo(c *gin.Context) { switch c.Param("name") { case "repo_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") default: - c.String(200, repoPayload) + c.String(http.StatusOK, repoPayload) } } func getRepoByID(c *gin.Context) { switch c.Param("id") { case "repo_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") default: - c.String(200, repoPayload) + c.String(http.StatusOK, repoPayload) } } func createRepoCommitStatus(c *gin.Context) { if c.Param("commit") == "v1.0.0" || c.Param("commit") == "9ecad50" { - c.String(200, repoPayload) + c.String(http.StatusOK, repoPayload) } - c.String(404, "") + c.String(http.StatusNotFound, "") } func getRepoFile(c *gin.Context) { @@ -79,12 +79,12 @@ func getRepoFile(c *gin.Context) { ref := c.Query("ref") if file == "file_not_found" { - c.String(404, "") + c.String(http.StatusNotFound, "") } if ref == "v1.0.0" || ref == "9ecad50" { - c.String(200, repoFilePayload) + c.String(http.StatusOK, repoFilePayload) } - c.String(404, "") + c.String(http.StatusNotFound, "") } func createRepoHook(c *gin.Context) { @@ -99,41 +99,41 @@ func createRepoHook(c *gin.Context) { if in.Type != "gitea" || in.Conf.Type != "json" || in.Conf.URL != "http://localhost" { - c.String(500, "") + c.String(http.StatusInternalServerError, "") return } - c.String(200, "{}") + c.String(http.StatusOK, "{}") } func deleteRepoHook(c *gin.Context) { - c.String(200, "{}") + c.String(http.StatusOK, "{}") } func getUserRepos(c *gin.Context) { switch c.Request.Header.Get("Authorization") { case "token repos_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") default: page := c.Query("page") if page != "" && page != "1" { - c.String(200, "[]") + c.String(http.StatusOK, "[]") } else { - c.String(200, userRepoPayload) + c.String(http.StatusOK, userRepoPayload) } } } func getVersion(c *gin.Context) { - c.JSON(200, map[string]any{"version": "1.18.0"}) + c.JSON(http.StatusOK, map[string]any{"version": "1.18.0"}) } func getPRFiles(c *gin.Context) { page := c.Query("page") if page == "1" { - c.String(200, prFilesPayload) + c.String(http.StatusOK, prFilesPayload) } else { - c.String(200, "[]") + c.String(http.StatusOK, "[]") } } diff --git a/server/forge/gitea/gitea.go b/server/forge/gitea/gitea.go index d198d1ecb2..3d60642b89 100644 --- a/server/forge/gitea/gitea.go +++ b/server/forge/gitea/gitea.go @@ -401,11 +401,11 @@ func (c *Gitea) Activate(ctx context.Context, u *model.User, r *model.Repo, link _, response, err := client.CreateRepoHook(r.Owner, r.Name, hook) if err != nil { if response != nil { - if response.StatusCode == 404 { - return fmt.Errorf("Could not find repository") + if response.StatusCode == http.StatusNotFound { + return fmt.Errorf("could not find repository") } - if response.StatusCode == 200 { - return fmt.Errorf("Could not find repository, repository was probably renamed") + if response.StatusCode == http.StatusOK { + return fmt.Errorf("could not find repository, repository was probably renamed") } } return err diff --git a/server/forge/gitea/helper.go b/server/forge/gitea/helper.go index 1f68bdc62d..44dcde56aa 100644 --- a/server/forge/gitea/helper.go +++ b/server/forge/gitea/helper.go @@ -197,7 +197,7 @@ func fixMalformedAvatar(url string) string { } index = strings.Index(url, "//avatars/") if index != -1 { - return strings.Replace(url, "//avatars/", "/avatars/", -1) + return strings.ReplaceAll(url, "//avatars/", "/avatars/") } return url } diff --git a/server/forge/github/fixtures/handler.go b/server/forge/github/fixtures/handler.go index 320805a517..0f02557053 100644 --- a/server/forge/github/fixtures/handler.go +++ b/server/forge/github/fixtures/handler.go @@ -37,29 +37,29 @@ func Handler() http.Handler { func getRepo(c *gin.Context) { switch c.Param("name") { case "repo_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") default: - c.String(200, repoPayload) + c.String(http.StatusOK, repoPayload) } } func getRepoByID(c *gin.Context) { switch c.Param("id") { case "repo_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") default: - c.String(200, repoPayload) + c.String(http.StatusOK, repoPayload) } } func getMembership(c *gin.Context) { switch c.Param("org") { case "org_not_found": - c.String(404, "") + c.String(http.StatusNotFound, "") case "github": - c.String(200, membershipIsMemberPayload) + c.String(http.StatusOK, membershipIsMemberPayload) default: - c.String(200, membershipIsOwnerPayload) + c.String(http.StatusOK, membershipIsOwnerPayload) } } diff --git a/server/forge/github/github.go b/server/forge/github/github.go index 197afc73b4..de30a01e51 100644 --- a/server/forge/github/github.go +++ b/server/forge/github/github.go @@ -132,7 +132,7 @@ func (c *client) Login(ctx context.Context, res http.ResponseWriter, req *http.R } email := matchingEmail(emails, c.API) if email == nil { - return nil, fmt.Errorf("No verified Email address for GitHub account") + return nil, fmt.Errorf("no verified Email address for GitHub account") } return &model.User{ @@ -435,7 +435,8 @@ func (c *client) newClientToken(ctx context.Context, token string) *github.Clien ) tc := oauth2.NewClient(ctx, ts) if c.SkipVerify { - tc.Transport.(*oauth2.Transport).Base = &http.Transport{ + tp, _ := tc.Transport.(*oauth2.Transport) + tp.Base = &http.Transport{ Proxy: http.ProxyFromEnvironment, TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, diff --git a/server/forge/github/parse.go b/server/forge/github/parse.go index 6df51b242e..df5b97c2d5 100644 --- a/server/forge/github/parse.go +++ b/server/forge/github/parse.go @@ -85,7 +85,7 @@ func parsePushHook(hook *github.PushEvent) (*model.Repo, *model.Pipeline) { Commit: hook.GetHeadCommit().GetID(), Ref: hook.GetRef(), ForgeURL: hook.GetHeadCommit().GetURL(), - Branch: strings.Replace(hook.GetRef(), "refs/heads/", "", -1), + Branch: strings.ReplaceAll(hook.GetRef(), "refs/heads/", ""), Message: hook.GetHeadCommit().GetMessage(), Email: hook.GetHeadCommit().GetAuthor().GetEmail(), Avatar: hook.GetSender().GetAvatarURL(), @@ -106,7 +106,7 @@ func parsePushHook(hook *github.PushEvent) (*model.Repo, *model.Pipeline) { // For tags, if the base_ref (tag's base branch) is set, we're using it // as pipeline's branch so that we can filter events base on it if strings.HasPrefix(hook.GetBaseRef(), "refs/heads/") { - pipeline.Branch = strings.Replace(hook.GetBaseRef(), "refs/heads/", "", -1) + pipeline.Branch = strings.ReplaceAll(hook.GetBaseRef(), "refs/heads/", "") } } diff --git a/server/forge/gitlab/convert.go b/server/forge/gitlab/convert.go index 0641d43d48..d376e26229 100644 --- a/server/forge/gitlab/convert.go +++ b/server/forge/gitlab/convert.go @@ -70,11 +70,12 @@ func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (int, * source := hook.ObjectAttributes.Source obj := hook.ObjectAttributes - if target == nil && source == nil { + switch { + case target == nil && source == nil: return 0, nil, nil, fmt.Errorf("target and source keys expected in merge request hook") - } else if target == nil { + case target == nil: return 0, nil, nil, fmt.Errorf("target key expected in merge request hook") - } else if source == nil { + case source == nil: return 0, nil, nil, fmt.Errorf("source key expected in merge request hook") } @@ -255,7 +256,7 @@ func getUserAvatar(email string) string { func extractFromPath(str string) (string, string, error) { s := strings.Split(str, "/") if len(s) < 2 { - return "", "", fmt.Errorf("Minimum match not found") + return "", "", fmt.Errorf("minimum match not found") } return s[0], s[1], nil } diff --git a/server/forge/gitlab/gitlab.go b/server/forge/gitlab/gitlab.go index 30292b4ccd..1261705fda 100644 --- a/server/forge/gitlab/gitlab.go +++ b/server/forge/gitlab/gitlab.go @@ -127,7 +127,7 @@ func (g *GitLab) Login(ctx context.Context, res http.ResponseWriter, req *http.R token, err := config.Exchange(oauth2Ctx, code) if err != nil { - return nil, fmt.Errorf("Error exchanging token. %w", err) + return nil, fmt.Errorf("error exchanging token: %w", err) } client, err := newClient(g.url, token.AccessToken, g.SkipVerify) @@ -513,7 +513,7 @@ func (g *GitLab) Deactivate(ctx context.Context, user *model.User, repo *model.R hookID := -1 listProjectHooksOptions := &gitlab.ListProjectHooksOptions{ - PerPage: 10, + PerPage: perPage, Page: 1, } for { @@ -642,7 +642,7 @@ func (g *GitLab) OrgMembership(ctx context.Context, u *model.User, owner string) groups, _, err := client.Groups.ListGroups(&gitlab.ListGroupsOptions{ ListOptions: gitlab.ListOptions{ Page: 1, - PerPage: 100, + PerPage: perPage, }, Search: gitlab.Ptr(owner), }, gitlab.WithContext(ctx)) @@ -663,7 +663,7 @@ func (g *GitLab) OrgMembership(ctx context.Context, u *model.User, owner string) opts := &gitlab.ListGroupMembersOptions{ ListOptions: gitlab.ListOptions{ Page: 1, - PerPage: 100, + PerPage: perPage, }, } diff --git a/server/forge/refresh.go b/server/forge/refresh.go index dd904c91f5..f650eb1af2 100644 --- a/server/forge/refresh.go +++ b/server/forge/refresh.go @@ -32,11 +32,13 @@ type Refresher interface { } func Refresh(c context.Context, forge Forge, _store store.Store, user *model.User) { + // Remaining ttl of 30 minutes (1800 seconds) until a token is refreshed. + const tokenMinTTL = 1800 + if refresher, ok := forge.(Refresher); ok { - // Check to see if the user token is expired or - // will expire within the next 30 minutes (1800 seconds). + // Check to see if the user token is expired or will expire soon. // If not, there is nothing we really need to do here. - if time.Now().UTC().Unix() < (user.Expiry - 1800) { + if time.Now().UTC().Unix() < (user.Expiry - tokenMinTTL) { return } diff --git a/server/grpc/auth_server.go b/server/grpc/auth_server.go index 362e74b4c2..88ef145313 100644 --- a/server/grpc/auth_server.go +++ b/server/grpc/auth_server.go @@ -41,7 +41,7 @@ func NewWoodpeckerAuthServer(jwtManager *JWTManager, agentMasterToken string, st func (s *WoodpeckerAuthServer) Auth(_ context.Context, req *proto.AuthRequest) (*proto.AuthResponse, error) { agent, err := s.getAgent(req.AgentId, req.AgentToken) if err != nil { - return nil, fmt.Errorf("Agent could not auth: %w", err) + return nil, fmt.Errorf("agent could not auth: %w", err) } accessToken, err := s.jwtManager.Generate(agent.ID) diff --git a/server/grpc/rpc.go b/server/grpc/rpc.go index ea1e9ae151..a59ad07be8 100644 --- a/server/grpc/rpc.go +++ b/server/grpc/rpc.go @@ -269,7 +269,7 @@ func (s *RPC) Done(c context.Context, id string, state rpc.State) error { var queueErr error if workflow.Failing() { - queueErr = s.queue.Error(c, id, fmt.Errorf("Step finished with exit code %d, %s", state.ExitCode, state.Error)) + queueErr = s.queue.Error(c, id, fmt.Errorf("step finished with exit code %d, %s", state.ExitCode, state.Error)) } else { queueErr = s.queue.Done(c, id, workflow.State) } @@ -388,7 +388,7 @@ func (s *RPC) ReportHealth(ctx context.Context, status string) error { } if status != "I am alive!" { - return errors.New("Are you alive?") + return errors.New("are you alive?") } agent.LastContact = time.Now().Unix() diff --git a/server/logging/log_test.go b/server/logging/log_test.go index ffa4166d3f..3ca442e2a3 100644 --- a/server/logging/log_test.go +++ b/server/logging/log_test.go @@ -21,6 +21,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "go.woodpecker-ci.org/woodpecker/v2/server/model" ) diff --git a/server/model/registry.go b/server/model/registry.go index cd93dc7dfd..875cd2d9c0 100644 --- a/server/model/registry.go +++ b/server/model/registry.go @@ -21,9 +21,9 @@ import ( ) var ( - errRegistryAddressInvalid = errors.New("Invalid Registry Address") - errRegistryUsernameInvalid = errors.New("Invalid Registry Username") - errRegistryPasswordInvalid = errors.New("Invalid Registry Password") + errRegistryAddressInvalid = errors.New("invalid registry address") + errRegistryUsernameInvalid = errors.New("invalid registry username") + errRegistryPasswordInvalid = errors.New("invalid registry password") ) // RegistryService defines a service for managing registries. diff --git a/server/model/secret.go b/server/model/secret.go index 0594c1d918..956e06b0fe 100644 --- a/server/model/secret.go +++ b/server/model/secret.go @@ -23,10 +23,10 @@ import ( ) var ( - ErrSecretNameInvalid = errors.New("Invalid Secret Name") - ErrSecretImageInvalid = errors.New("Invalid Secret Image") - ErrSecretValueInvalid = errors.New("Invalid Secret Value") - ErrSecretEventInvalid = errors.New("Invalid Secret Event") + ErrSecretNameInvalid = errors.New("invalid secret name") + ErrSecretImageInvalid = errors.New("invalid secret image") + ErrSecretValueInvalid = errors.New("invalid secret value") + ErrSecretEventInvalid = errors.New("invalid secret event") ) // SecretService defines a service for managing secrets. diff --git a/server/model/user.go b/server/model/user.go index 73eca72634..46e6e5ed7f 100644 --- a/server/model/user.go +++ b/server/model/user.go @@ -20,6 +20,8 @@ import ( "regexp" ) +const maxLoginLen = 250 + // validate a username (e.g. from github) var reUsername = regexp.MustCompile("^[a-zA-Z0-9-_.]+$") @@ -79,7 +81,7 @@ func (u *User) Validate() error { switch { case len(u.Login) == 0: return errUserLoginInvalid - case len(u.Login) > 250: + case len(u.Login) > maxLoginLen: return errUserLoginInvalid case !reUsername.MatchString(u.Login): return errUserLoginInvalid diff --git a/server/pipeline/queue.go b/server/pipeline/queue.go index 9b845ce91c..c8b1fc77ee 100644 --- a/server/pipeline/queue.go +++ b/server/pipeline/queue.go @@ -25,7 +25,7 @@ import ( "go.woodpecker-ci.org/woodpecker/v2/server/pipeline/stepbuilder" ) -func queuePipeline(repo *model.Repo, pipelineItems []*stepbuilder.Item) error { +func queuePipeline(ctx context.Context, repo *model.Repo, pipelineItems []*stepbuilder.Item) error { var tasks []*model.Task for _, item := range pipelineItems { if item.Workflow.State == model.StatusSkipped { @@ -54,7 +54,7 @@ func queuePipeline(repo *model.Repo, pipelineItems []*stepbuilder.Item) error { tasks = append(tasks, task) } - return server.Config.Services.Queue.PushAtOnce(context.Background(), tasks) + return server.Config.Services.Queue.PushAtOnce(ctx, tasks) } func taskIds(dependsOn []string, pipelineItems []*stepbuilder.Item) (taskIds []string) { diff --git a/server/pipeline/start.go b/server/pipeline/start.go index 42d1e64056..d4db5d53ac 100644 --- a/server/pipeline/start.go +++ b/server/pipeline/start.go @@ -37,9 +37,11 @@ func start(ctx context.Context, store store.Store, activePipeline *model.Pipelin return nil, err } - publishPipeline(ctx, activePipeline, repo, user) + if err := publishPipeline(ctx, activePipeline, repo, user); err != nil { + return nil, err + } - if err := queuePipeline(repo, pipelineItems); err != nil { + if err := queuePipeline(ctx, repo, pipelineItems); err != nil { log.Error().Err(err).Msg("queuePipeline") return nil, err } @@ -47,7 +49,12 @@ func start(ctx context.Context, store store.Store, activePipeline *model.Pipelin return activePipeline, nil } -func publishPipeline(ctx context.Context, pipeline *model.Pipeline, repo *model.Repo, repoUser *model.User) { - publishToTopic(pipeline, repo) +func publishPipeline(ctx context.Context, pipeline *model.Pipeline, repo *model.Repo, repoUser *model.User) error { + if err := publishToTopic(pipeline, repo); err != nil { + return err + } + updatePipelineStatus(ctx, pipeline, repo, repoUser) + + return nil } diff --git a/server/pipeline/step_status.go b/server/pipeline/step_status.go index 3d7bc37677..3eaad08e21 100644 --- a/server/pipeline/step_status.go +++ b/server/pipeline/step_status.go @@ -18,6 +18,7 @@ package pipeline import ( "time" + "go.woodpecker-ci.org/woodpecker/v2/pipeline" "go.woodpecker-ci.org/woodpecker/v2/pipeline/rpc" "go.woodpecker-ci.org/woodpecker/v2/server/model" ) @@ -31,7 +32,7 @@ func UpdateStepStatus(store model.UpdateStepStore, step *model.Step, state rpc.S if state.ExitCode != 0 || state.Error != "" { step.State = model.StatusFailure } - if state.ExitCode == 137 { + if state.ExitCode == pipeline.ExitCodeKilled { step.State = model.StatusKilled } } else if step.Stopped == 0 { @@ -77,6 +78,6 @@ func UpdateStepToStatusKilled(store model.UpdateStepStore, step model.Step) (*mo if step.Started == 0 { step.Started = step.Stopped } - step.ExitCode = 137 + step.ExitCode = pipeline.ExitCodeKilled return &step, store.StepUpdate(&step) } diff --git a/server/pipeline/step_status_test.go b/server/pipeline/step_status_test.go index 7a996cabe6..de05f218e2 100644 --- a/server/pipeline/step_status_test.go +++ b/server/pipeline/step_status_test.go @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" + "go.woodpecker-ci.org/woodpecker/v2/pipeline" "go.woodpecker-ci.org/woodpecker/v2/pipeline/rpc" "go.woodpecker-ci.org/woodpecker/v2/server/model" ) @@ -42,7 +43,7 @@ func TestUpdateStepStatusNotExited(t *testing.T) { Exited: false, // Dummy data Finished: int64(1), - ExitCode: 137, + ExitCode: pipeline.ExitCodeKilled, Error: "not an error", } @@ -66,7 +67,7 @@ func TestUpdateStepStatusNotExitedButStopped(t *testing.T) { Exited: false, // Dummy data Finished: int64(1), - ExitCode: 137, + ExitCode: pipeline.ExitCodeKilled, Error: "not an error", } @@ -90,7 +91,7 @@ func TestUpdateStepStatusExited(t *testing.T) { Started: int64(42), Exited: true, Finished: int64(34), - ExitCode: 137, + ExitCode: pipeline.ExitCodeKilled, Error: "an error", } diff --git a/server/plugins/config/http.go b/server/plugins/config/http.go index ab3e662c22..9af77e80ce 100644 --- a/server/plugins/config/http.go +++ b/server/plugins/config/http.go @@ -18,6 +18,7 @@ import ( "context" "crypto" "fmt" + httpStatus "net/http" forge_types "go.woodpecker-ci.org/woodpecker/v2/server/forge/types" "go.woodpecker-ci.org/woodpecker/v2/server/model" @@ -66,11 +67,11 @@ func (cp *http) FetchConfig(ctx context.Context, repo *model.Repo, pipeline *mod status, err := utils.Send(ctx, "POST", cp.endpoint, cp.privateKey, body, response) if err != nil && status != 204 { - return nil, false, fmt.Errorf("Failed to fetch config via http (%d) %w", status, err) + return nil, false, fmt.Errorf("failed to fetch config via http (%d) %w", status, err) } var newFileMeta []*forge_types.FileMeta - if status != 200 { + if status != httpStatus.StatusOK { newFileMeta = make([]*forge_types.FileMeta, 0) } else { newFileMeta = make([]*forge_types.FileMeta, len(response.Configs)) @@ -79,5 +80,5 @@ func (cp *http) FetchConfig(ctx context.Context, repo *model.Repo, pipeline *mod } } - return newFileMeta, status == 204, nil + return newFileMeta, status == httpStatus.StatusNoContent, nil } diff --git a/server/plugins/encryption/aes_encryption.go b/server/plugins/encryption/aes_encryption.go index 7bf2dae522..b7b5016ffb 100644 --- a/server/plugins/encryption/aes_encryption.go +++ b/server/plugins/encryption/aes_encryption.go @@ -20,10 +20,10 @@ import ( "errors" "fmt" - "go.woodpecker-ci.org/woodpecker/v2/server/store/types" "golang.org/x/crypto/bcrypt" - "golang.org/x/crypto/sha3" + + "go.woodpecker-ci.org/woodpecker/v2/server/store/types" ) func (svc *aesEncryptionService) loadCipher(password string) error { diff --git a/server/plugins/encryption/encryption_builder.go b/server/plugins/encryption/encryption_builder.go index 93b9dff1f6..f14a8824a6 100644 --- a/server/plugins/encryption/encryption_builder.go +++ b/server/plugins/encryption/encryption_builder.go @@ -50,22 +50,24 @@ func (b builder) isEnabled() (bool, error) { func (b builder) detectKeyType() (string, error) { rawKeyPresent := b.ctx.IsSet(rawKeyConfigFlag) tinkKeysetPresent := b.ctx.IsSet(tinkKeysetFilepathConfigFlag) - if rawKeyPresent && tinkKeysetPresent { + switch { + case rawKeyPresent && tinkKeysetPresent: return "", errors.New(errMessageCantUseBothServices) - } else if rawKeyPresent { + case rawKeyPresent: return keyTypeRaw, nil - } else if tinkKeysetPresent { + case tinkKeysetPresent: return keyTypeTink, nil } return keyTypeNone, nil } func (b builder) serviceBuilder(keyType string) (model.EncryptionServiceBuilder, error) { - if keyType == keyTypeTink { + switch { + case keyType == keyTypeTink: return newTink(b.ctx, b.store), nil - } else if keyType == keyTypeRaw { + case keyType == keyTypeRaw: return newAES(b.ctx, b.store), nil - } else if keyType == keyTypeNone { + case keyType == keyTypeNone: return &noEncryptionBuilder{}, nil } return nil, fmt.Errorf(errMessageTemplateUnsupportedKeyType, keyType) diff --git a/server/plugins/permissions/repo_owners_test.go b/server/plugins/permissions/repo_owners_test.go index 4ecd363219..c348212552 100644 --- a/server/plugins/permissions/repo_owners_test.go +++ b/server/plugins/permissions/repo_owners_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "go.woodpecker-ci.org/woodpecker/v2/server/model" ) diff --git a/server/plugins/registry/filesystem.go b/server/plugins/registry/filesystem.go index 2b889f49d3..dab4e17f6a 100644 --- a/server/plugins/registry/filesystem.go +++ b/server/plugins/registry/filesystem.go @@ -111,12 +111,12 @@ func decodeAuth(authStr string) (string, string, error) { return "", "", err } if n > decLen { - return "", "", fmt.Errorf("Something went wrong decoding auth config") + return "", "", fmt.Errorf("something went wrong decoding auth config") } - arr := strings.SplitN(string(decoded), ":", 2) - if len(arr) != 2 { - return "", "", fmt.Errorf("Invalid auth configuration file") + before, after, _ := strings.Cut(string(decoded), ":") + if before == "" || after == "" { + return "", "", fmt.Errorf("invalid auth configuration file") } - password := strings.Trim(arr[1], "\x00") - return arr[0], password, nil + password := strings.Trim(after, "\x00") + return before, password, nil } diff --git a/server/plugins/secrets/builtin_test.go b/server/plugins/secrets/builtin_test.go index c2f2509ac9..6c35aebfd7 100644 --- a/server/plugins/secrets/builtin_test.go +++ b/server/plugins/secrets/builtin_test.go @@ -20,6 +20,7 @@ import ( "github.com/franela/goblin" "github.com/stretchr/testify/mock" + "go.woodpecker-ci.org/woodpecker/v2/server/model" "go.woodpecker-ci.org/woodpecker/v2/server/plugins/secrets" mocks_store "go.woodpecker-ci.org/woodpecker/v2/server/store/mocks" diff --git a/server/plugins/utils/http.go b/server/plugins/utils/http.go index 95e504a54f..f3a0891b00 100644 --- a/server/plugins/utils/http.go +++ b/server/plugins/utils/http.go @@ -65,13 +65,13 @@ func Send(ctx context.Context, method, path string, privateKey crypto.PrivateKey } defer resp.Body.Close() - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { body, err := io.ReadAll(resp.Body) if err != nil { return resp.StatusCode, err } - return resp.StatusCode, fmt.Errorf("Response: %s", string(body)) + return resp.StatusCode, fmt.Errorf("response: %s", string(body)) } // if no other errors parse and return the json response. diff --git a/server/plugins/utils/http_test.go b/server/plugins/utils/http_test.go index 4426e82ffa..150538b56e 100644 --- a/server/plugins/utils/http_test.go +++ b/server/plugins/utils/http_test.go @@ -24,6 +24,7 @@ import ( "github.com/go-ap/httpsig" "github.com/stretchr/testify/assert" + "go.woodpecker-ci.org/woodpecker/v2/server/plugins/utils" ) diff --git a/server/queue/fifo.go b/server/queue/fifo.go index f86c2a8664..f690352b12 100644 --- a/server/queue/fifo.go +++ b/server/queue/fifo.go @@ -21,9 +21,9 @@ import ( "sync" "time" - "go.woodpecker-ci.org/woodpecker/v2/server/model" - "github.com/rs/zerolog/log" + + "go.woodpecker-ci.org/woodpecker/v2/server/model" ) type entry struct { @@ -52,6 +52,7 @@ type fifo struct { // New returns a new fifo queue. func New(_ context.Context) Queue { + //nolint: gomnd return &fifo{ workers: map[*worker]struct{}{}, running: map[string]*entry{}, @@ -204,10 +205,12 @@ func (q *fifo) Info(_ context.Context) InfoT { stats.Stats.Complete = 0 // TODO: implement this for e := q.pending.Front(); e != nil; e = e.Next() { - stats.Pending = append(stats.Pending, e.Value.(*model.Task)) + task, _ := e.Value.(*model.Task) + stats.Pending = append(stats.Pending, task) } for e := q.waitingOnDeps.Front(); e != nil; e = e.Next() { - stats.WaitingOnDeps = append(stats.WaitingOnDeps, e.Value.(*model.Task)) + task, _ := e.Value.(*model.Task) + stats.WaitingOnDeps = append(stats.WaitingOnDeps, task) } for _, entry := range q.running { stats.Running = append(stats.Running, entry.item) @@ -255,7 +258,7 @@ func (q *fifo) process() { q.resubmitExpiredPipelines() q.filterWaiting() for pending, worker := q.assignToWorker(); pending != nil && worker != nil; pending, worker = q.assignToWorker() { - task := pending.Value.(*model.Task) + task, _ := pending.Value.(*model.Task) task.AgentID = worker.agentID delete(q.workers, worker) q.pending.Remove(pending) @@ -273,7 +276,7 @@ func (q *fifo) filterWaiting() { var nextWaiting *list.Element for e := q.waitingOnDeps.Front(); e != nil; e = nextWaiting { nextWaiting = e.Next() - task := e.Value.(*model.Task) + task, _ := e.Value.(*model.Task) q.pending.PushBack(task) } @@ -283,7 +286,7 @@ func (q *fifo) filterWaiting() { var nextPending *list.Element for e := q.pending.Front(); e != nil; e = nextPending { nextPending = e.Next() - task := e.Value.(*model.Task) + task, _ := e.Value.(*model.Task) if q.depsInQueue(task) { log.Debug().Msgf("queue: waiting due to unmet dependencies %v", task.ID) q.waitingOnDeps.PushBack(task) @@ -301,7 +304,7 @@ func (q *fifo) assignToWorker() (*list.Element, *worker) { var next *list.Element for e := q.pending.Front(); e != nil; e = next { next = e.Next() - task := e.Value.(*model.Task) + task, _ := e.Value.(*model.Task) log.Debug().Msgf("queue: trying to assign task: %v with deps %v", task.ID, task.Dependencies) for w := range q.workers { @@ -384,7 +387,7 @@ func (q *fifo) removeFromPending(taskID string) { var next *list.Element for e := q.pending.Front(); e != nil; e = next { next = e.Next() - task := e.Value.(*model.Task) + task, _ := e.Value.(*model.Task) if task.ID == taskID { log.Debug().Msgf("queue: %s is removed from pending", taskID) q.pending.Remove(e) diff --git a/server/queue/fifo_test.go b/server/queue/fifo_test.go index e36b417ed7..d06d4148de 100644 --- a/server/queue/fifo_test.go +++ b/server/queue/fifo_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "go.woodpecker-ci.org/woodpecker/v2/server/model" ) diff --git a/server/router/middleware/header/header.go b/server/router/middleware/header/header.go index 571354604f..663bf451db 100644 --- a/server/router/middleware/header/header.go +++ b/server/router/middleware/header/header.go @@ -42,7 +42,7 @@ func Options(c *gin.Context) { c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept") c.Header("Allow", "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS") c.Header("Content-Type", "application/json") - c.AbortWithStatus(200) + c.AbortWithStatus(http.StatusOK) } } diff --git a/server/router/middleware/session/agent.go b/server/router/middleware/session/agent.go index 3f8dda0603..c9014e5710 100644 --- a/server/router/middleware/session/agent.go +++ b/server/router/middleware/session/agent.go @@ -16,6 +16,8 @@ package session import ( + "net/http" + "github.com/gin-gonic/gin" "go.woodpecker-ci.org/woodpecker/v2/shared/token" @@ -23,22 +25,23 @@ import ( // AuthorizeAgent authorizes requests from agent to access the queue. func AuthorizeAgent(c *gin.Context) { - secret := c.MustGet("agent").(string) + secret, _ := c.MustGet("agent").(string) if secret == "" { - c.String(401, "invalid or empty token.") + c.String(http.StatusUnauthorized, "invalid or empty token.") return } parsed, err := token.ParseRequest(c.Request, func(t *token.Token) (string, error) { return secret, nil }) - if err != nil { - c.String(500, "invalid or empty token. %s", err) + switch { + case err != nil: + c.String(http.StatusInternalServerError, "invalid or empty token. %s", err) c.Abort() - } else if parsed.Kind != token.AgentToken { - c.String(403, "invalid token. please use an agent token") + case parsed.Kind != token.AgentToken: + c.String(http.StatusForbidden, "invalid token. please use an agent token") c.Abort() - } else { + default: c.Next() } } diff --git a/server/router/middleware/session/pagination.go b/server/router/middleware/session/pagination.go index a9021100c4..9bf4455c10 100644 --- a/server/router/middleware/session/pagination.go +++ b/server/router/middleware/session/pagination.go @@ -18,6 +18,7 @@ import ( "strconv" "github.com/gin-gonic/gin" + "go.woodpecker-ci.org/woodpecker/v2/server/model" ) diff --git a/server/router/middleware/session/repo.go b/server/router/middleware/session/repo.go index 93366887e3..e61120b641 100644 --- a/server/router/middleware/session/repo.go +++ b/server/router/middleware/session/repo.go @@ -23,8 +23,8 @@ import ( "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" - "go.woodpecker-ci.org/woodpecker/v2/server" + "go.woodpecker-ci.org/woodpecker/v2/server" "go.woodpecker-ci.org/woodpecker/v2/server/model" "go.woodpecker-ci.org/woodpecker/v2/server/store" "go.woodpecker-ci.org/woodpecker/v2/server/store/types" diff --git a/server/router/middleware/session/user.go b/server/router/middleware/session/user.go index 0e40bffff5..520fa40526 100644 --- a/server/router/middleware/session/user.go +++ b/server/router/middleware/session/user.go @@ -18,13 +18,13 @@ import ( "net/http" "strconv" + "github.com/gin-gonic/gin" + "github.com/rs/zerolog/log" + "go.woodpecker-ci.org/woodpecker/v2/server" "go.woodpecker-ci.org/woodpecker/v2/server/model" "go.woodpecker-ci.org/woodpecker/v2/server/store" "go.woodpecker-ci.org/woodpecker/v2/shared/token" - - "github.com/gin-gonic/gin" - "github.com/rs/zerolog/log" ) func User(c *gin.Context) *model.User { @@ -75,10 +75,10 @@ func MustAdmin() gin.HandlerFunc { user := User(c) switch { case user == nil: - c.String(401, "User not authorized") + c.String(http.StatusUnauthorized, "User not authorized") c.Abort() case !user.Admin: - c.String(403, "User not authorized") + c.String(http.StatusForbidden, "User not authorized") c.Abort() default: c.Next() @@ -92,10 +92,10 @@ func MustRepoAdmin() gin.HandlerFunc { perm := Perm(c) switch { case user == nil: - c.String(401, "User not authorized") + c.String(http.StatusUnauthorized, "User not authorized") c.Abort() case !perm.Admin: - c.String(403, "User not authorized") + c.String(http.StatusForbidden, "User not authorized") c.Abort() default: c.Next() @@ -108,7 +108,7 @@ func MustUser() gin.HandlerFunc { user := User(c) switch { case user == nil: - c.String(401, "User not authorized") + c.String(http.StatusUnauthorized, "User not authorized") c.Abort() default: c.Next() diff --git a/server/store/context.go b/server/store/context.go index 02381e5136..96214a04c1 100644 --- a/server/store/context.go +++ b/server/store/context.go @@ -27,7 +27,8 @@ type Setter interface { // FromContext returns the Store associated with this context. func FromContext(c context.Context) Store { - return c.Value(key).(Store) + store, _ := c.Value(key).(Store) + return store } // TryFromContext try to return the Store associated with this context. diff --git a/server/store/datastore/agent.go b/server/store/datastore/agent.go index 6c3051d861..383692289d 100644 --- a/server/store/datastore/agent.go +++ b/server/store/datastore/agent.go @@ -20,7 +20,7 @@ import ( "go.woodpecker-ci.org/woodpecker/v2/server/model" ) -var ErrNoTokenProvided = errors.New("Please provide a token") +var ErrNoTokenProvided = errors.New("please provide a token") func (s storage) AgentList(p *model.ListOptions) ([]*model.Agent, error) { var agents []*model.Agent diff --git a/server/store/datastore/cron.go b/server/store/datastore/cron.go index ed3e23f9be..c6c7713cb5 100644 --- a/server/store/datastore/cron.go +++ b/server/store/datastore/cron.go @@ -15,9 +15,9 @@ package datastore import ( - "go.woodpecker-ci.org/woodpecker/v2/server/model" - "xorm.io/builder" + + "go.woodpecker-ci.org/woodpecker/v2/server/model" ) func (s storage) CronCreate(cron *model.Cron) error { diff --git a/server/store/datastore/engine.go b/server/store/datastore/engine.go index fb5a5c082e..20b1b9b546 100644 --- a/server/store/datastore/engine.go +++ b/server/store/datastore/engine.go @@ -16,12 +16,11 @@ package datastore import ( "github.com/rs/zerolog" + "xorm.io/xorm" + xlog "xorm.io/xorm/log" "go.woodpecker-ci.org/woodpecker/v2/server/store" "go.woodpecker-ci.org/woodpecker/v2/server/store/datastore/migration" - - "xorm.io/xorm" - xlog "xorm.io/xorm/log" ) type storage struct { diff --git a/server/store/datastore/log_test.go b/server/store/datastore/log_test.go index 1aa02d2854..3e6729844d 100644 --- a/server/store/datastore/log_test.go +++ b/server/store/datastore/log_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "go.woodpecker-ci.org/woodpecker/v2/server/model" ) diff --git a/server/store/datastore/migration/008_secrets_add_user.go b/server/store/datastore/migration/008_secrets_add_user.go index b77208f750..0a5320e68a 100644 --- a/server/store/datastore/migration/008_secrets_add_user.go +++ b/server/store/datastore/migration/008_secrets_add_user.go @@ -19,6 +19,8 @@ import ( "xorm.io/xorm" ) +const secretsTableName = "secrets" + type SecretV008 struct { Owner string `json:"-" xorm:"NOT NULL DEFAULT '' UNIQUE(s) INDEX 'secret_owner'"` RepoID int64 `json:"-" xorm:"NOT NULL DEFAULT 0 UNIQUE(s) INDEX 'secret_repo_id'"` @@ -27,7 +29,7 @@ type SecretV008 struct { // TableName return database table name for xorm func (SecretV008) TableName() string { - return "secrets" + return secretsTableName } var alterTableSecretsAddUserCol = xormigrate.Migration{ @@ -36,12 +38,12 @@ var alterTableSecretsAddUserCol = xormigrate.Migration{ if err := sess.Sync(new(SecretV008)); err != nil { return err } - if err := alterColumnDefault(sess, "secrets", "secret_repo_id", "0"); err != nil { + if err := alterColumnDefault(sess, secretsTableName, "secret_repo_id", "0"); err != nil { return err } - if err := alterColumnNull(sess, "secrets", "secret_repo_id", false); err != nil { + if err := alterColumnNull(sess, secretsTableName, "secret_repo_id", false); err != nil { return err } - return alterColumnNull(sess, "secrets", "secret_name", false) + return alterColumnNull(sess, secretsTableName, "secret_name", false) }, } diff --git a/server/store/datastore/migration/013_rename_remote_to_forge.go b/server/store/datastore/migration/013_rename_remote_to_forge.go index 78eff328be..870f6000ea 100644 --- a/server/store/datastore/migration/013_rename_remote_to_forge.go +++ b/server/store/datastore/migration/013_rename_remote_to_forge.go @@ -19,13 +19,15 @@ import ( "xorm.io/xorm" ) +const reposTableName = "repos" + type oldRepo013 struct { ID int64 `xorm:"pk autoincr 'repo_id'"` RemoteID string `xorm:"remote_id"` } func (oldRepo013) TableName() string { - return "repos" + return reposTableName } var renameRemoteToForge = xormigrate.Migration{ @@ -40,6 +42,6 @@ var renameRemoteToForge = xormigrate.Migration{ return err } - return renameColumn(sess, "repos", "remote_id", "forge_id") + return renameColumn(sess, reposTableName, "remote_id", "forge_id") }, } diff --git a/server/store/datastore/migration/common.go b/server/store/datastore/migration/common.go index c0d0df2f03..e79e8979aa 100644 --- a/server/store/datastore/migration/common.go +++ b/server/store/datastore/migration/common.go @@ -85,7 +85,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin tableSQL := normalizeSQLiteTableSchema(string(res[0]["sql"])) // Separate out the column definitions - tableSQL = tableSQL[strings.Index(tableSQL, "("):] + tableSQL = tableSQL[strings.Index(tableSQL, "("):] //nolint:gocritic // Remove the required columnNames tableSQL = removeColumnFromSQLITETableSchema(tableSQL, columnNames...) diff --git a/server/store/datastore/migration/migration.go b/server/store/datastore/migration/migration.go index 218f7e4042..0da773bcfe 100644 --- a/server/store/datastore/migration/migration.go +++ b/server/store/datastore/migration/migration.go @@ -113,7 +113,7 @@ func Migrate(e *xorm.Engine, allowLong bool) error { func syncAll(sess *xorm.Engine) error { for _, bean := range allBeans { if err := sess.Sync(bean); err != nil { - return fmt.Errorf("Sync error '%s': %w", reflect.TypeOf(bean), err) + return fmt.Errorf("sync error '%s': %w", reflect.TypeOf(bean), err) } } return nil diff --git a/server/web/web.go b/server/web/web.go index 2eb9b1aa2e..0524cfed4a 100644 --- a/server/web/web.go +++ b/server/web/web.go @@ -72,11 +72,12 @@ func handleCustomFilesAndAssets(fs *prefixFS) func(ctx *gin.Context) { } } return func(ctx *gin.Context) { - if strings.HasSuffix(ctx.Request.RequestURI, "/assets/custom.js") { + switch { + case strings.HasSuffix(ctx.Request.RequestURI, "/assets/custom.js"): serveFileOrEmptyContent(ctx.Writer, ctx.Request, server.Config.Server.CustomJsFile, "file.js") - } else if strings.HasSuffix(ctx.Request.RequestURI, "/assets/custom.css") { + case strings.HasSuffix(ctx.Request.RequestURI, "/assets/custom.css"): serveFileOrEmptyContent(ctx.Writer, ctx.Request, server.Config.Server.CustomCSSFile, "file.css") - } else { + default: serveFile(fs)(ctx) } } diff --git a/server/web/web_test.go b/server/web/web_test.go index e09df0e710..52e7b255ed 100644 --- a/server/web/web_test.go +++ b/server/web/web_test.go @@ -22,6 +22,7 @@ import ( "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" + "go.woodpecker-ci.org/woodpecker/v2/server" ) diff --git a/shared/httputil/httputil.go b/shared/httputil/httputil.go index 11c9a3fe9c..ce44152d53 100644 --- a/shared/httputil/httputil.go +++ b/shared/httputil/httputil.go @@ -15,6 +15,7 @@ package httputil import ( + "math" "net/http" "strings" ) @@ -47,7 +48,7 @@ func SetCookie(w http.ResponseWriter, r *http.Request, name, value string) { Domain: r.URL.Host, HttpOnly: true, Secure: IsHTTPS(r), - MaxAge: 2147483647, // the cooke value (token) is responsible for expiration + MaxAge: math.MaxInt32, // the cookie value (token) is responsible for expiration } http.SetCookie(w, &cookie)