refactor: add more linters and fix findings (#41)

This commit is contained in:
Robert Kaussow 2023-02-08 10:16:05 +01:00 committed by GitHub
parent 5b1ee2a1b7
commit db28a0858b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 208 additions and 110 deletions

View File

@ -8,7 +8,7 @@ platform:
steps: steps:
- name: deps - name: deps
image: golang:1.19 image: golang:1.20
commands: commands:
- make deps - make deps
volumes: volumes:
@ -16,7 +16,7 @@ steps:
path: /go path: /go
- name: lint - name: lint
image: golang:1.19 image: golang:1.20
commands: commands:
- make lint - make lint
volumes: volumes:
@ -24,7 +24,7 @@ steps:
path: /go path: /go
- name: test - name: test
image: golang:1.19 image: golang:1.20
commands: commands:
- make test - make test
volumes: volumes:
@ -51,7 +51,7 @@ platform:
steps: steps:
- name: build - name: build
image: techknowlogick/xgo:go-1.19.x image: techknowlogick/xgo:go-1.20.x
commands: commands:
- ln -s /drone/src /source - ln -s /drone/src /source
- make release - make release
@ -292,6 +292,6 @@ depends_on:
--- ---
kind: signature kind: signature
hmac: ccad191c33e8df2f7c7c51f10e2e2999e5e6f46a8a50de9aa1e8a5ae6c116600 hmac: ed52cf54615cff7806ee5d08c981a280bdd31d42bd1af00096686a60727a5526
... ...

View File

@ -1,25 +1,92 @@
linters: linters:
enable:
- gosimple
- deadcode
- typecheck
- govet
- errcheck
- staticcheck
- unused
- structcheck
- varcheck
- dupl
- gofmt
- misspell
- gocritic
- bidichk
- ineffassign
- revive
- gofumpt
- depguard
enable-all: false enable-all: false
disable-all: true disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- contextcheck
- decorder
- depguard
- dogsled
- dupl
- dupword
- durationcheck
- errchkjson
- errname
- errorlint
- execinquery
- exhaustive
- exportloopref
- forcetypeassert
- ginkgolinter
- gocheckcompilerdirectives
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- godox
- goerr113
- gofmt
- gofumpt
- goheader
- goimports
- gomnd
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- grouper
- importas
- interfacebloat
- ireturn
- lll
- loggercheck
- maintidx
- makezero
- misspell
- musttag
- nakedret
- nestif
- nilerr
- nilnil
- nlreturn
- noctx
- nolintlint
- nonamedreturns
- nosprintfhostport
- prealloc
- predeclared
- promlinter
- reassign
- revive
# - rowserrcheck
# - sqlclosecheck
# - structcheck
- stylecheck
- tagliatelle
- tenv
- testableexamples
- thelper
- tparallel
- unconvert
- unparam
- usestdlibvars
# - wastedassign
- whitespace
- wsl
fast: false fast: false
run: run:
@ -28,4 +95,11 @@ run:
linters-settings: linters-settings:
gofumpt: gofumpt:
extra-rules: true extra-rules: true
lang-version: "1.18" lang-version: "1.20"
ireturn:
allow:
- anon
- error
- empty
- stdlib
- drone.Client

View File

@ -1,7 +1,7 @@
# renovate: datasource=github-releases depName=mvdan/gofumpt # renovate: datasource=github-releases depName=mvdan/gofumpt
GOFUMPT_PACKAGE_VERSION := v0.4.0 GOFUMPT_PACKAGE_VERSION := v0.4.0
# renovate: datasource=github-releases depName=golangci/golangci-lint # renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_PACKAGE_VERSION := v1.50.1 GOLANGCI_LINT_PACKAGE_VERSION := v1.51.1
EXECUTABLE := drone-admin EXECUTABLE := drone-admin
@ -19,7 +19,7 @@ GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(G
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GENERATE ?= GENERATE ?=
XGO_VERSION := go-1.19.x XGO_VERSION := go-1.20.x
XGO_TARGETS ?= linux/amd64,linux/arm64,linux/arm-6,linux/arm-7 XGO_TARGETS ?= linux/amd64,linux/arm64,linux/arm-6,linux/arm-7
TARGETOS ?= linux TARGETOS ?= linux

View File

@ -2,10 +2,12 @@ package autoscaler
import "github.com/urfave/cli/v2" import "github.com/urfave/cli/v2"
var Command = &cli.Command{ func GetAutoscalerCmd() *cli.Command {
Name: "autoscaler", return &cli.Command{
Usage: "manage autoscaler", Name: "autoscaler",
Subcommands: []*cli.Command{ Usage: "manage autoscaler",
&autoscalerReaperCmd, Subcommands: []*cli.Command{
}, getReaperCmd(),
},
}
} }

View File

@ -11,24 +11,28 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var autoscalerReaperCmd = cli.Command{ func getReaperCmd() *cli.Command {
Name: "reaper", return &cli.Command{
Usage: "find and kill agents in error state", Name: "reaper",
Action: autoscalerReaper, Usage: "find and kill agents in error state",
Flags: []cli.Flag{ Action: reaper,
&cli.StringFlag{ Flags: []cli.Flag{
Name: "state-file", &cli.StringFlag{
Usage: "state file", Name: "state-file",
EnvVars: []string{"DRONE_ADMIN_AUTOSCALER_REAPER_STATE_FILE"}, Usage: "state file",
Value: "/tmp/droneclean.gob", EnvVars: []string{"DRONE_ADMIN_AUTOSCALER_REAPER_STATE_FILE"},
Value: "/tmp/droneclean.gob",
},
}, },
}, }
} }
func autoscalerReaper(c *cli.Context) error { func reaper(ctx *cli.Context) error {
statefile := c.String("state-file") const maxRetries = 3
scaler := c.StringSlice("server")
dry := c.Bool("dry-run") statefile := ctx.String("state-file")
scaler := ctx.StringSlice("server")
dry := ctx.Bool("dry-run")
state := map[string]int{} state := map[string]int{}
force := false force := false
@ -44,7 +48,7 @@ func autoscalerReaper(c *cli.Context) error {
} }
for _, scaler := range scaler { for _, scaler := range scaler {
client, err := client.New(scaler, c.String("token")) client, err := client.New(scaler, ctx.String("token"))
if err != nil { if err != nil {
return err return err
} }
@ -53,6 +57,7 @@ func autoscalerReaper(c *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
serversAll := len(servers) serversAll := len(servers)
servers = util.Filter(servers, func(s *drone.Server) bool { servers = util.Filter(servers, func(s *drone.Server) bool {
return s.State == "running" return s.State == "running"
@ -65,25 +70,26 @@ func autoscalerReaper(c *cli.Context) error {
} }
logrus.WithFields(searchFields).Infof("lookup agents in error state") logrus.WithFields(searchFields).Infof("lookup agents in error state")
for _, s := range servers { for _, server := range servers {
state[s.Name]++ state[server.Name]++
triage := state[s.Name] triage := state[server.Name]
if state[s.Name] == 3 { if state[server.Name] == maxRetries {
force = true force = true
delete(state, s.Name)
delete(state, server.Name)
} }
foundFields := logrus.Fields{ foundFields := logrus.Fields{
"server": scaler, "server": scaler,
"agent": s.Name, "agent": server.Name,
"triage": triage, "triage": triage,
"force": force, "force": force,
} }
logrus.WithFields(foundFields).Infof("destroy agent") logrus.WithFields(foundFields).Infof("destroy agent")
if !dry { if !dry {
err = serverDestroy(client, s.Name, force) err = serverDestroy(client, server.Name, force)
if err != nil && !strings.Contains(err.Error(), "client error 404") { if err != nil && !strings.Contains(err.Error(), "client error 404") {
return err return err
} }

View File

@ -2,10 +2,12 @@ package build
import "github.com/urfave/cli/v2" import "github.com/urfave/cli/v2"
var Command = &cli.Command{ func GetBuildCmd() *cli.Command {
Name: "build", return &cli.Command{
Usage: "manage build", Name: "build",
Subcommands: []*cli.Command{ Usage: "manage build",
&buidPruneCmd, Subcommands: []*cli.Command{
}, getPruneCmd(),
},
}
} }

View File

@ -11,29 +11,34 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var buidPruneCmd = cli.Command{ const DroneClientPageSize = 50
Name: "prune",
Usage: "prune builds", func getPruneCmd() *cli.Command {
ArgsUsage: "<repo/name>", return &cli.Command{
Action: buidPrune, Name: "prune",
Flags: []cli.Flag{ Usage: "prune builds",
&cli.StringFlag{ ArgsUsage: "<repo/name>",
Name: "older-than", Action: prune,
Usage: "remove builds older than the specified time limit", Flags: []cli.Flag{
EnvVars: []string{"DRONE_ADMIN_BUILD_PRUNE_OLDER_THAN"}, &cli.StringFlag{
Required: true, Name: "older-than",
Usage: "remove builds older than the specified time limit",
EnvVars: []string{"DRONE_ADMIN_BUILD_PRUNE_OLDER_THAN"},
Required: true,
},
&cli.IntFlag{
Name: "keep-min",
Usage: "minimum number of builds to keep",
EnvVars: []string{"DRONE_ADMIN_BUILD_PRUNE_KEEP_MIN"},
//nolint:gomnd
Value: 10,
},
}, },
&cli.IntFlag{ }
Name: "keep-min",
Usage: "minimum number of builds to keep",
EnvVars: []string{"DRONE_ADMIN_BUILD_PRUNE_KEEP_MIN"},
Value: 10,
},
},
} }
func buidPrune(c *cli.Context) error { func prune(ctx *cli.Context) error {
client, err := client.New(c.StringSlice("server")[0], c.String("token")) client, err := client.New(ctx.StringSlice("server")[0], ctx.String("token"))
if err != nil { if err != nil {
return err return err
} }
@ -43,11 +48,11 @@ func buidPrune(c *cli.Context) error {
return err return err
} }
dur := c.String("older-than") buildDuration := ctx.String("older-than")
keep := c.Int("keep-min") buildMin := ctx.Int("keep-min")
dry := c.Bool("dry-run") dry := ctx.Bool("dry-run")
duration, err := time.ParseDuration(dur) duration, err := time.ParseDuration(buildDuration)
if err != nil { if err != nil {
return err return err
} }
@ -56,10 +61,10 @@ func buidPrune(c *cli.Context) error {
logrus.Info("dry-run enabled, no data will be removed") logrus.Info("dry-run enabled, no data will be removed")
} }
logrus.Infof("prune builds older than %v, keep min %v", dur, keep) logrus.Infof("prune builds older than %v, keep min %v", buildDuration, buildMin)
for _, r := range repos { for _, repo := range repos {
builds, err := getBuilds(client, r) builds, err := getBuilds(client, repo)
if err != nil { if err != nil {
return err return err
} }
@ -68,24 +73,23 @@ func buidPrune(c *cli.Context) error {
return builds[i].Number > builds[j].Number return builds[i].Number > builds[j].Number
}) })
if bl := len(builds); bl > 0 && bl > keep { if buildCount := len(builds); buildCount > 0 && buildCount > buildMin {
builds = builds[keep:] builds = builds[buildMin:]
builds = util.Filter(builds, func(b *drone.Build) bool { builds = util.Filter(builds, func(b *drone.Build) bool {
return time.Since(time.Unix(b.Created, 0)) > duration return time.Since(time.Unix(b.Created, 0)) > duration
}) })
logrus.Infof("prune %v/%v builds from '%v'", len(builds), bl, r.Slug) logrus.Infof("prune %v/%v builds from '%v'", len(builds), buildCount, repo.Slug)
if !dry && len(builds) > 0 { if !dry && len(builds) > 0 {
err := client.BuildPurge(r.Namespace, r.Name, int(builds[0].Number+1)) err := client.BuildPurge(repo.Namespace, repo.Name, int(builds[0].Number+1))
if err != nil { if err != nil {
return err return err
} }
} }
} else { } else {
logrus.Infof("skip '%v', number of %v builds lower than min value", r.Slug, len(builds)) logrus.Infof("skip '%v', number of %v builds lower than min value", repo.Slug, len(builds))
} }
} }
return nil return nil
@ -96,21 +100,21 @@ func getRepos(client drone.Client) ([]*drone.Repo, error) {
repos := make([]*drone.Repo, 0) repos := make([]*drone.Repo, 0)
for { for {
r, err := client.RepoListAll(drone.ListOptions{Page: page, Size: 50}) repo, err := client.RepoListAll(drone.ListOptions{Page: page, Size: DroneClientPageSize})
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(r) == 0 { if len(repo) == 0 {
break break
} }
repos = append(repos, r...) repos = append(repos, repo...)
page++ page++
} }
repos = util.Filter(repos, func(r *drone.Repo) bool { repos = util.Filter(repos, func(repo *drone.Repo) bool {
return r.Active return repo.Active
}) })
return repos, nil return repos, nil
@ -121,17 +125,18 @@ func getBuilds(client drone.Client, repo *drone.Repo) ([]*drone.Build, error) {
builds := make([]*drone.Build, 0) builds := make([]*drone.Build, 0)
for { for {
b, err := client.BuildList(repo.Namespace, repo.Name, drone.ListOptions{Page: page, Size: 50}) build, err := client.BuildList(repo.Namespace, repo.Name, drone.ListOptions{Page: page, Size: DroneClientPageSize})
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(b) == 0 { if len(build) == 0 {
break break
} }
builds = append(builds, b...) builds = append(builds, build...)
page++ page++
} }
return builds, nil return builds, nil
} }

View File

@ -13,12 +13,13 @@ import (
) )
func New(server, token string) (drone.Client, error) { func New(server, token string) (drone.Client, error) {
s, err := url.Parse(server) serverURL, err := url.Parse(server)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(s.Scheme) == 0 {
s.Scheme = "http" if len(serverURL.Scheme) == 0 {
serverURL.Scheme = "http"
} }
// attempt to find system CA certs // attempt to find system CA certs
@ -26,6 +27,7 @@ func New(server, token string) (drone.Client, error) {
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
RootCAs: certs, RootCAs: certs,
InsecureSkipVerify: false, InsecureSkipVerify: false,
MinVersion: tls.VersionTLS12,
} }
oauth := new(oauth2.Config) oauth := new(oauth2.Config)
@ -44,5 +46,5 @@ func New(server, token string) (drone.Client, error) {
Proxy: http.ProxyFromEnvironment, Proxy: http.ProxyFromEnvironment,
} }
return drone.NewClient(s.String(), authenticator), nil return drone.NewClient(serverURL.String(), authenticator), nil
} }

View File

@ -7,11 +7,13 @@ import (
func Filter[T any](vs []T, f func(T) bool) []T { func Filter[T any](vs []T, f func(T) bool) []T {
filtered := make([]T, 0) filtered := make([]T, 0)
for _, v := range vs { for _, v := range vs {
if f(v) { if f(v) {
filtered = append(filtered, v) filtered = append(filtered, v)
} }
} }
return filtered return filtered
} }
@ -21,7 +23,9 @@ func WriteGob(filePath string, object interface{}) error {
encoder := gob.NewEncoder(file) encoder := gob.NewEncoder(file)
err = encoder.Encode(object) err = encoder.Encode(object)
} }
file.Close() file.Close()
return err return err
} }
@ -31,6 +35,8 @@ func ReadGob(filePath string, object interface{}) error {
decoder := gob.NewDecoder(file) decoder := gob.NewDecoder(file)
err = decoder.Decode(object) err = decoder.Decode(object)
} }
file.Close() file.Close()
return err return err
} }

View File

@ -13,6 +13,7 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
//nolint:gochecknoglobals
var ( var (
BuildVersion = "devel" BuildVersion = "devel"
BuildDate = "00000000" BuildDate = "00000000"
@ -69,8 +70,8 @@ func main() {
return nil return nil
}, },
Commands: []*cli.Command{ Commands: []*cli.Command{
build.Command, build.GetBuildCmd(),
autoscaler.Command, autoscaler.GetAutoscalerCmd(),
}, },
} }

2
go.mod
View File

@ -1,6 +1,6 @@
module github.com/thegeeklab/drone-admin module github.com/thegeeklab/drone-admin
go 1.19 go 1.20
require ( require (
github.com/drone/drone-go v1.7.1 github.com/drone/drone-go v1.7.1