diff --git a/.golangci.yml b/.golangci.yml index 8e144ce8..ce5a02a9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,11 +9,25 @@ linters: - errorlint - gci - gocritic + - godot - goimports - misspell + - perfsprint - typecheck + - whitespace - wrapcheck + - unconvert + - unused + - usestdlibvars linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/release-argus/Argus) goimports: - local-prefixes: github.com/release-argus/Argus \ No newline at end of file + local-prefixes: github.com/release-argus/Argus + perfsprint: + # Optimises into `err.Error()` even if it is only equivalent for non-nil errors. + err-error: true \ No newline at end of file diff --git a/config/save.go b/config/save.go index 2430517e..6400c094 100644 --- a/config/save.go +++ b/config/save.go @@ -120,7 +120,6 @@ func (c *Config) Save() { if indents == 1 && strings.HasSuffix(line, ":") && parentKey[0] == "service" { - // First service will be on 1 because we remove items and decrement // currentOrderIndexEnd[currentServiceNumber]. So we want to know when the service // has started so that the decrements are direct to the service. @@ -278,7 +277,7 @@ func (c *Config) Save() { c.File, err), logutil.LogFrom{}, err != nil) logutil.Log.Info( - fmt.Sprintf("Saved service updates to %s", c.File), + "Saved service updates to "+c.File, logutil.LogFrom{}, true) } diff --git a/config/settings.go b/config/settings.go index 558ca599..ee4d6091 100644 --- a/config/settings.go +++ b/config/settings.go @@ -60,7 +60,7 @@ func (s *Settings) String(prefix string) string { // SettingsBase for the binary. // -// (Used in Defaults) +// (Used in Defaults). type SettingsBase struct { Log LogSettings `yaml:"log,omitempty"` // Log settings Data DataSettings `yaml:"data,omitempty"` // Data settings diff --git a/notify/shoutrrr/defaults.go b/notify/shoutrrr/defaults.go index feb33bac..6d91f849 100644 --- a/notify/shoutrrr/defaults.go +++ b/notify/shoutrrr/defaults.go @@ -15,6 +15,8 @@ // Package shoutrrr provides the shoutrrr notification service to services. package shoutrrr +import "net/http" + // notifyDefaultOptions are the default options for all notifiers. func notifyDefaultOptions() map[string]string { return map[string]string{ @@ -143,7 +145,7 @@ func (s *SliceDefaults) Default() { "contenttype": "application/json", "disabletls": "no", "messagekey": "message", - "requestmethod": "POST", + "requestmethod": http.MethodPost, "titlekey": "title"}) newSlice["shoutrrr"] = NewDefaults( "", diff --git a/notify/shoutrrr/new.go b/notify/shoutrrr/new.go index b55686a6..409f820a 100644 --- a/notify/shoutrrr/new.go +++ b/notify/shoutrrr/new.go @@ -16,6 +16,7 @@ package shoutrrr import ( + "errors" "fmt" "github.com/release-argus/Argus/notify/shoutrrr/types" @@ -50,7 +51,7 @@ func FromPayload( ) (*Shoutrrr, string, error) { // No `name` or `name_previous`. if payload.NamePrevious == "" && payload.Name == "" { - return nil, "", fmt.Errorf("name and/or name_previous are required") + return nil, "", errors.New("name and/or name_previous are required") } name := util.FirstNonDefault(payload.Name, payload.NamePrevious) diff --git a/notify/shoutrrr/shoutrrr.go b/notify/shoutrrr/shoutrrr.go index 5baf8019..997ea829 100644 --- a/notify/shoutrrr/shoutrrr.go +++ b/notify/shoutrrr/shoutrrr.go @@ -182,8 +182,7 @@ func (s *Shoutrrr) BuildURL() (url string) { case "googlechat": url = s.GetURLField("raw") // googlechat://url - url = fmt.Sprintf("googlechat://%s", - url) + url = "googlechat://" + url case "ifttt": // ifttt://webhookid/?events=event1,event2 url = fmt.Sprintf("ifttt://%s/?events=%s", @@ -448,7 +447,7 @@ func (s *Shoutrrr) send( func() error { err := sender.Send(message, params) if failed := s.parseSend(err, combinedErrs, serviceName, logFrom); failed { - return fmt.Errorf("send failed") + return errors.New("send failed") } return nil }, diff --git a/notify/shoutrrr/verify.go b/notify/shoutrrr/verify.go index f343b844..de9f071a 100644 --- a/notify/shoutrrr/verify.go +++ b/notify/shoutrrr/verify.go @@ -24,6 +24,7 @@ import ( "time" goshoutrrr "github.com/containrrr/shoutrrr" + "github.com/release-argus/Argus/util" ) diff --git a/service/deployed_version/query.go b/service/deployed_version/query.go index ebb9964e..c6df565d 100644 --- a/service/deployed_version/query.go +++ b/service/deployed_version/query.go @@ -17,6 +17,7 @@ package deployedver import ( "crypto/tls" + "errors" "fmt" "io" "net/http" @@ -213,7 +214,7 @@ func (l *Lookup) httpRequest(logFrom logutil.LogFrom) ([]byte, error) { if err != nil { // Don't crash on invalid certs. if strings.Contains(err.Error(), "x509") { - err = fmt.Errorf("x509 (certificate invalid)") + err = errors.New("x509 (certificate invalid)") logutil.Log.Warn(err, logFrom, true) return nil, err } diff --git a/service/deployed_version/refresh.go b/service/deployed_version/refresh.go index 0c6c61b6..8dd6f3a3 100644 --- a/service/deployed_version/refresh.go +++ b/service/deployed_version/refresh.go @@ -32,7 +32,7 @@ func (l *Lookup) Refresh( semanticVersioning *string, ) (string, error) { if l == nil { - return "", fmt.Errorf("lookup is nil") + return "", errors.New("lookup is nil") } logFrom := logutil.LogFrom{Primary: "deployed_version/refresh", Secondary: *serviceID} diff --git a/service/deployed_version/types.go b/service/deployed_version/types.go index 8cab7152..9ea5cfe3 100644 --- a/service/deployed_version/types.go +++ b/service/deployed_version/types.go @@ -18,6 +18,7 @@ package deployedver import ( "encoding/json" "fmt" + "net/http" opt "github.com/release-argus/Argus/service/option" "github.com/release-argus/Argus/service/status" @@ -25,7 +26,7 @@ import ( ) var ( - supportedTypes = []string{"GET", "POST"} + supportedTypes = []string{http.MethodGet, http.MethodPost} ) // Base is the base struct for the Lookup struct. diff --git a/service/deployed_version/verify.go b/service/deployed_version/verify.go index 57d78a74..9ecbc289 100644 --- a/service/deployed_version/verify.go +++ b/service/deployed_version/verify.go @@ -18,6 +18,7 @@ package deployedver import ( "errors" "fmt" + "net/http" "regexp" "strings" @@ -34,14 +35,14 @@ func (l *Lookup) CheckValues(prefix string) error { // Method l.Method = strings.ToUpper(l.Method) if l.Method == "" { - l.Method = "GET" + l.Method = http.MethodGet } else if !util.Contains(supportedTypes, l.Method) { errs = append(errs, fmt.Errorf("%smethod: %q (only [%s] are allowed)", prefix, l.Method, strings.Join(supportedTypes, ", "))) } // Body unused in GET, ensure it is empty. - if l.Method == "GET" { + if l.Method == http.MethodGet { l.Body = "" } diff --git a/service/deployed_version/verify_test.go b/service/deployed_version/verify_test.go index 077c720f..fffca029 100644 --- a/service/deployed_version/verify_test.go +++ b/service/deployed_version/verify_test.go @@ -17,6 +17,7 @@ package deployedver import ( + "net/http" "strings" "testing" @@ -40,7 +41,7 @@ func TestLookup_CheckValues(t *testing.T) { }, "valid service": { errRegex: `^$`, - method: "GET", + method: http.MethodGet, url: "https://example.com", regex: `[0-9.]+`, defaults: &Defaults{}, @@ -57,7 +58,7 @@ func TestLookup_CheckValues(t *testing.T) { }, "method - valid": { errRegex: `^$`, - method: "GET", + method: http.MethodGet, url: "https://example.com", }, "method - case insensitive": { @@ -67,38 +68,38 @@ func TestLookup_CheckValues(t *testing.T) { }, "url - empty string": { errRegex: `url: `, - method: "GET", + method: http.MethodGet, url: "", defaults: &Defaults{}, }, "body - removed for GET": { errRegex: `^$`, - method: "GET", + method: http.MethodGet, url: "https://example.com", body: "foo", defaults: &Defaults{}, }, "body - not removed for POST": { errRegex: `^$`, - method: "POST", + method: http.MethodPost, url: "https://example.com", body: "foo", defaults: &Defaults{}, }, "json - invalid, string in square brackets": { errRegex: `json: .* `, - method: "GET", + method: http.MethodGet, json: "foo[bar]", defaults: &Defaults{}, }, "regex - invalid": { errRegex: `regex: .* `, - method: "GET", + method: http.MethodGet, regex: `[0-`, defaults: &Defaults{}, }, "regexTemplate - with no regex": { - method: "GET", + method: http.MethodGet, url: "https://example.com", errRegex: `^$`, regexTemplate: "$1.$2.$3", @@ -106,14 +107,14 @@ func TestLookup_CheckValues(t *testing.T) { }, "all errs": { errRegex: `url: `, - method: "GET", + method: http.MethodGet, url: "", regex: `[0-`, defaults: &Defaults{}, }, "no url doesn't fail for Lookup Defaults": { errRegex: `^$`, - method: "GET", + method: http.MethodGet, url: "", defaults: nil, }, @@ -159,17 +160,17 @@ func TestLookup_CheckValues(t *testing.T) { t.Fatalf("RegexTemplate should be nil when Regex is empty") } // AND Body is empty when Method is GET - if lookup.Method == "GET" && lookup.Body != "" { + if lookup.Method == http.MethodGet && lookup.Body != "" { t.Fatalf("Body should be nil when Method is GET") } // AND Body is kept when Method is POST - if lookup.Method == "POST" && hadBody != "" && lookup.Body == "" { + if lookup.Method == http.MethodPost && hadBody != "" && lookup.Body == "" { t.Fatalf("Body should be kept when Method is POST") } // AND Method is uppercased wantMethod := strings.ToUpper(tc.method) if wantMethod == "" { - wantMethod = "GET" + wantMethod = http.MethodGet } if lookup.Method != wantMethod { t.Fatalf("Method should be uppercased:\nwant: %q\ngot: %q", diff --git a/service/init.go b/service/init.go index 9202255d..15c9b977 100644 --- a/service/init.go +++ b/service/init.go @@ -141,7 +141,6 @@ func (s *Service) Init( &s.Options, &s.Status, &s.Defaults.DeployedVersionLookup, &s.HardDefaults.DeployedVersionLookup) - } // initMetrics will initialise the Prometheus metrics for the Service. diff --git a/service/latest_version/filter/docker.go b/service/latest_version/filter/docker.go index 02b66d9f..64b7b125 100644 --- a/service/latest_version/filter/docker.go +++ b/service/latest_version/filter/docker.go @@ -295,7 +295,7 @@ func (d *DockerCheck) CheckValues(prefix string) error { prefix, d.Image)) // e.g. prometheus = library/prometheus on the docker hub api. case d.Type == "hub" && strings.Count(d.Image, "/") == 0: - d.Image = fmt.Sprintf("library/%s", d.Image) + d.Image = "library/" + d.Image } // Tag @@ -307,7 +307,7 @@ func (d *DockerCheck) CheckValues(prefix string) error { errs = append(errs, fmt.Errorf("%stag: %q (didn't pass templating)", prefix, d.Tag)) default: - if _, err := net_url.Parse(fmt.Sprintf("https://example.com/%s", d.Tag)); err != nil { + if _, err := net_url.Parse("https://example.com/" + d.Tag); err != nil { errs = append(errs, fmt.Errorf("%stag: %q (invalid for URL formatting)", prefix, d.Tag)) } @@ -339,7 +339,7 @@ func (d *DockerCheck) checkToken() error { return fmt.Errorf("token: (token for %s)", username) } else if username == "" && token != "" { - return fmt.Errorf("username: (token is for who?)") + return errors.New("username: (token is for who?)") } case "quay", "ghcr": // Token not required. @@ -392,7 +392,7 @@ func (d *DockerCheck) getToken() string { return util.EvalEnvVars(d.Defaults.getToken(d.GetType())) } -// getToken returns the token as is, +// getToken returns the token as is. func (d *DockerCheckDefaults) getToken(dType string) string { if d == nil { return "" diff --git a/service/latest_version/refresh.go b/service/latest_version/refresh.go index 4fc88fbf..3e02f021 100644 --- a/service/latest_version/refresh.go +++ b/service/latest_version/refresh.go @@ -17,6 +17,7 @@ package latestver import ( "encoding/json" + "errors" "fmt" "strings" @@ -33,7 +34,7 @@ func Refresh( semanticVersioning *string, // nil, "true", "false", "null" (unchanged, true, false, default). ) (string, bool, error) { if lookup == nil { - return "", false, fmt.Errorf("lookup is nil") + return "", false, errors.New("lookup is nil") } logFrom := logutil.LogFrom{Primary: "latest_version/refresh", Secondary: *lookup.GetStatus().ServiceID} diff --git a/service/latest_version/types/github/gets.go b/service/latest_version/types/github/gets.go index 93fd3c0f..499140ae 100644 --- a/service/latest_version/types/github/gets.go +++ b/service/latest_version/types/github/gets.go @@ -70,7 +70,7 @@ func (l *Lookup) ServiceURL(ignoreWebURL bool) (serviceURL string) { // GitHub service. Get the non-API URL. // If "owner/repo" rather than a full path. if strings.Count(serviceURL, "/") == 1 { - serviceURL = fmt.Sprintf("https://github.com/%s", serviceURL) + serviceURL = "https://github.com/" + serviceURL } return } diff --git a/service/latest_version/types/github/query.go b/service/latest_version/types/github/query.go index b1e9982b..bae99813 100644 --- a/service/latest_version/types/github/query.go +++ b/service/latest_version/types/github/query.go @@ -117,7 +117,7 @@ func (l *Lookup) createRequest(logFrom logutil.LogFrom) (*http.Request, error) { req.Header.Set("Connection", "close") // Access Token. if accessToken := l.accessToken(); accessToken != "" { - req.Header.Set("Authorization", fmt.Sprintf("token %s", accessToken)) + req.Header.Set("Authorization", "token "+accessToken) } // Conditional requests - https://docs.github.com/en/rest/overview/resources-in-the-rest-api#conditional-requests. if eTag := l.data.ETag(); eTag != "" { diff --git a/service/latest_version/types/github/query_test.go b/service/latest_version/types/github/query_test.go index f81302aa..1621ea34 100644 --- a/service/latest_version/types/github/query_test.go +++ b/service/latest_version/types/github/query_test.go @@ -398,7 +398,7 @@ func TestGetResponse_ReadError(t *testing.T) { t.Cleanup(func() { server.Close() }) // AND a request to the mock server's URL. - req, err := http.NewRequest("GET", server.URL, nil) + req, err := http.NewRequest(http.MethodGet, server.URL, nil) if err != nil { t.Fatalf("github.Lookup.getResponse() could not create request: %v", err) } diff --git a/service/latest_version/types/web/query.go b/service/latest_version/types/web/query.go index 28bf9580..8db7ce98 100644 --- a/service/latest_version/types/web/query.go +++ b/service/latest_version/types/web/query.go @@ -103,7 +103,7 @@ func (l *Lookup) httpRequest(logFrom logutil.LogFrom) ([]byte, error) { if err != nil { // Don't crash on invalid certs. if strings.Contains(err.Error(), "x509") { - err = fmt.Errorf("x509 (certificate invalid)") + err = errors.New("x509 (certificate invalid)") logutil.Log.Warn(err, logFrom, true) return nil, err } diff --git a/service/new.go b/service/new.go index cadee868..9cf7bc3a 100644 --- a/service/new.go +++ b/service/new.go @@ -99,7 +99,7 @@ func FromPayload( if err != nil { logutil.Log.Error(err, logFrom, true) logutil.Log.Verbose( - fmt.Sprintf("Payload: %s", buf.String()), + "Payload: "+buf.String(), logFrom, true) return nil, err //nolint:wrapcheck } diff --git a/service/status/fails.go b/service/status/fails.go index 7a342528..f23da395 100644 --- a/service/status/fails.go +++ b/service/status/fails.go @@ -17,6 +17,7 @@ package status import ( "fmt" + "strconv" "strings" "sync" @@ -107,7 +108,7 @@ func (f *failsBase) String(prefix string) string { for _, key := range keys { val := "nil" if f.fails[key] != nil { - val = fmt.Sprint(*f.fails[key]) + val = strconv.FormatBool(*f.fails[key]) } builder.WriteString(fmt.Sprintf("%s%s: %s\n", prefix, key, val)) @@ -192,7 +193,7 @@ func (f *FailsCommand) String(prefix string) string { for i, fail := range f.fails { val := "nil" if fail != nil { - val = fmt.Sprint(*fail) + val = strconv.FormatBool(*fail) } builder.WriteString(fmt.Sprintf("%s- %d: %s\n", diff --git a/service/types.go b/service/types.go index b8d7c7e2..5aba39e2 100644 --- a/service/types.go +++ b/service/types.go @@ -122,7 +122,7 @@ type Service struct { } // MarshalName returns whether the Name should be marshaled. -// (explicitly set in the config) +// (explicitly set in the config). func (s *Service) MarshalName() bool { return s.marshalName } diff --git a/service/types_test.go b/service/types_test.go index 12e91d7c..f9bd2c25 100644 --- a/service/types_test.go +++ b/service/types_test.go @@ -17,6 +17,7 @@ package service import ( + "net/http" "strings" "testing" @@ -1111,7 +1112,7 @@ func TestService_UnmarshalJSON(t *testing.T) { errRegex: `^$`, want: &Service{ DeployedVersionLookup: &deployedver.Lookup{ - Method: "GET", + Method: http.MethodGet, URL: "https://valid.release-argus.io/plain", }}, }, @@ -1576,7 +1577,7 @@ func TestService_UnmarshalYAML(t *testing.T) { errRegex: `^$`, want: &Service{ DeployedVersionLookup: &deployedver.Lookup{ - Method: "GET", + Method: http.MethodGet, URL: "https://valid.release-argus.io/plain", }}, }, diff --git a/util/json.go b/util/json.go index d762a8a2..3065199b 100644 --- a/util/json.go +++ b/util/json.go @@ -17,6 +17,7 @@ package util import ( "encoding/json" + "errors" "fmt" "strconv" "strings" @@ -78,7 +79,7 @@ func ToJSONString(input interface{}) string { // navigateJSON will navigate the JSON object to find the value of the key. func navigateJSON(jsonData *interface{}, fullKey string) (string, error) { if fullKey == "" { - return "", fmt.Errorf("no key was given to navigate the JSON") + return "", errors.New("no key was given to navigate the JSON") } //nolint:errcheck // Verify in deployed_version.verify.CheckValues. keys, _ := ParseKeys(fullKey) diff --git a/util/log/log.go b/util/log/log.go index d7910e3a..91b8ad7b 100644 --- a/util/log/log.go +++ b/util/log/log.go @@ -113,14 +113,12 @@ func (lf LogFrom) String() string { lf.Primary, lf.Secondary) } // Just Primary. - return fmt.Sprintf("%s, ", - lf.Primary) + return lf.Primary + ", " } // Just Secondary. if lf.Secondary != "" { - return fmt.Sprintf("%s, ", - lf.Secondary) + return lf.Secondary + ", " } // Neither Primary nor Secondary. @@ -153,7 +151,7 @@ func (l *JLog) Fatal(msg interface{}, from LogFrom, otherCondition bool) { // Error log the msg. // -// (if `otherCondition` true) +// (if `otherCondition` true). func (l *JLog) Error(msg interface{}, from LogFrom, otherCondition bool) { if !otherCondition { return @@ -167,7 +165,7 @@ func (l *JLog) Error(msg interface{}, from LogFrom, otherCondition bool) { // Warn log msg if l.Level > 0 (WARNING, INFO, VERBOSE or DEBUG). // -// (if otherCondition true) +// (if otherCondition true). func (l *JLog) Warn(msg interface{}, from LogFrom, otherCondition bool) { if l.Level == 0 || !otherCondition { return @@ -181,7 +179,7 @@ func (l *JLog) Warn(msg interface{}, from LogFrom, otherCondition bool) { // Info log msg if l.Level > 1 (INFO, VERBOSE or DEBUG). // -// (if otherCondition true) +// (if otherCondition true). func (l *JLog) Info(msg interface{}, from LogFrom, otherCondition bool) { if l.Level < 2 || !otherCondition { return @@ -195,7 +193,7 @@ func (l *JLog) Info(msg interface{}, from LogFrom, otherCondition bool) { // Verbose log msg if l.Level > 2 (VERBOSE or DEBUG). // -// (if otherCondition true) +// (if otherCondition true). func (l *JLog) Verbose(msg interface{}, from LogFrom, otherCondition bool) { if l.Level < 3 || !otherCondition { return @@ -210,7 +208,7 @@ func (l *JLog) Verbose(msg interface{}, from LogFrom, otherCondition bool) { // Debug log msg if l.Level 4 (DEBUG). // -// (if otherCondition true) +// (if otherCondition true). func (l *JLog) Debug(msg interface{}, from LogFrom, otherCondition bool) { if l.Level != 4 || !otherCondition { return diff --git a/web/api/types/argus.go b/web/api/types/argus.go index 7d437f85..3f6f35e6 100644 --- a/web/api/types/argus.go +++ b/web/api/types/argus.go @@ -16,7 +16,6 @@ package types import ( - "fmt" "strings" "time" @@ -124,7 +123,7 @@ func (s *ServiceSummary) RemoveUnchanged(oldData *ServiceSummary) { nilUnchanged(oldData.WebHook, &s.WebHook) } -// Helper function to handle "Removed" or "Unchanged" logic +// Helper function to handle "Removed" or "Unchanged" logic. func nilUnchanged[T comparable](oldValue *T, newValue **T) { // Removed: oldValue exists but newValue is nil. if oldValue != nil && *newValue == nil { @@ -232,21 +231,21 @@ func (d *Defaults) String() string { builder.WriteString("{") if serviceStr := util.ToJSONString(d.Service); !util.Contains([]string{"{}", "null"}, serviceStr) { - builder.WriteString(fmt.Sprintf(`"service":%s`, serviceStr)) + builder.WriteString(`"service":` + serviceStr) } if notifyStr := util.ToJSONString(d.Notify); !util.Contains([]string{"{}", "null"}, notifyStr) { if builder.Len() > 1 { builder.WriteString(",") } - builder.WriteString(fmt.Sprintf(`"notify":%s`, notifyStr)) + builder.WriteString(`"notify":` + notifyStr) } if webHookStr := util.ToJSONString(d.WebHook); !util.Contains([]string{"{}", "null"}, webHookStr) { if builder.Len() > 1 { builder.WriteString(",") } - builder.WriteString(fmt.Sprintf(`"webhook":%s`, webHookStr)) + builder.WriteString(`"webhook":` + webHookStr) } builder.WriteString("}") @@ -672,7 +671,7 @@ type CommandStatusUpdate struct { // # EDIT # // ################################################################################ -// CommandEdit for JSON react-hook-form +// CommandEdit for JSON react-hook-form. type CommandEdit struct { Arg string `json:"arg,omitempty" yaml:"arg,omitempty"` // Command argument. } diff --git a/web/api/types/argus_test.go b/web/api/types/argus_test.go index efb4f204..06121730 100644 --- a/web/api/types/argus_test.go +++ b/web/api/types/argus_test.go @@ -18,6 +18,7 @@ package types import ( "encoding/json" + "net/http" "strings" "testing" @@ -1234,7 +1235,7 @@ func TestDeployedVersionLookup_String(t *testing.T) { }, "all fields": { dvl: &DeployedVersionLookup{ - Method: "POST", + Method: http.MethodPost, URL: "https://release-argus.io", AllowInvalidCerts: test.BoolPtr(false), BasicAuth: &BasicAuth{ diff --git a/web/api/types/http.go b/web/api/types/http.go index b56cf0a6..55320658 100644 --- a/web/api/types/http.go +++ b/web/api/types/http.go @@ -17,14 +17,14 @@ package types import "time" -// VersionAPI used in /api/v1/version +// VersionAPI is the response given at the /api/v1/version endpoint. type VersionAPI struct { Version string `json:"version"` BuildDate string `json:"buildDate"` GoVersion string `json:"goVersion"` } -// RefreshAPI used in /api/v1/*_version/refresh +// RefreshAPI is the rsponse given at the /api/v1/*_version/refresh endpoint. type RefreshAPI struct { Version string `json:"version"` Date time.Time `json:"timestamp"` diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 536b5dde..4697c13a 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -50,7 +50,7 @@ func NewAPI(cfg *config.Config) *API { // In cases where routePrefix equals "/", trim to prevent "//". routePrefix = strings.TrimSuffix(routePrefix, "/") // On baseRouter as Router may have basicAuth. - baseRouter.Path(fmt.Sprintf("%s/api/v1/healthcheck", routePrefix)). + baseRouter.Path(routePrefix + "/api/v1/healthcheck"). Handler(loggerMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Connection", "close") fmt.Fprintf(w, "Alive") diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 26d00141..eb85ae8d 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -84,7 +84,7 @@ func TestNewAPI(t *testing.T) { api := NewAPI(cfg) // THEN the healthcheck endpoint is accessible - req, _ := http.NewRequest("GET", tc.routePrefix+"/api/v1/healthcheck", nil) + req, _ := http.NewRequest(http.MethodGet, tc.routePrefix+"/api/v1/healthcheck", nil) resp := httptest.NewRecorder() api.BaseRouter.ServeHTTP(resp, req) // 200 @@ -98,7 +98,7 @@ func TestNewAPI(t *testing.T) { "Alive", resp.Body.String()) } // AND the route prefix always has a trailing slash - req, _ = http.NewRequest("GET", tc.routePrefix, nil) + req, _ = http.NewRequest(http.MethodGet, tc.routePrefix, nil) resp = httptest.NewRecorder() api.BaseRouter.ServeHTTP(resp, req) // 308 @@ -118,9 +118,9 @@ func TestNewAPI(t *testing.T) { // AND basic auth middleware is added when set api.Router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) - }).Methods("GET") + }).Methods(http.MethodGet) authMiddlewareWanted := basicAuthTest.username != "" - req, _ = http.NewRequest("GET", tc.routePrefix+"/", nil) + req, _ = http.NewRequest(http.MethodGet, tc.routePrefix+"/", nil) resp = httptest.NewRecorder() api.BaseRouter.ServeHTTP(resp, req) middlewareUsed := resp.Body.String() != "OK" diff --git a/web/api/v1/convert_test.go b/web/api/v1/convert_test.go index c8ff1b7b..80e51e4d 100644 --- a/web/api/v1/convert_test.go +++ b/web/api/v1/convert_test.go @@ -18,6 +18,7 @@ package v1 import ( "encoding/json" + "net/http" "strings" "testing" "time" @@ -752,7 +753,7 @@ func TestConvertAndCensorDeployedVersionLookup(t *testing.T) { ServiceID: test.StringPtr("service-id"), WebURL: test.StringPtr("https://release-argus.io")}, want: &apitype.DeployedVersionLookup{ - Method: "POST", + Method: http.MethodPost, URL: "https://release-argus.io", AllowInvalidCerts: test.BoolPtr(true), BasicAuth: &apitype.BasicAuth{ diff --git a/web/api/v1/http.go b/web/api/v1/http.go index 57efa22a..0131061a 100644 --- a/web/api/v1/http.go +++ b/web/api/v1/http.go @@ -45,43 +45,43 @@ func (api *API) SetupRoutesAPI() { // /config // Apply the logging middleware globally. // GET, config. - v1Router.HandleFunc("/config", api.httpConfig).Methods("GET") + v1Router.HandleFunc("/config", api.httpConfig).Methods(http.MethodGet) // /status // GET, runtime info. - v1Router.HandleFunc("/status/runtime", api.httpRuntimeInfo).Methods("GET") + v1Router.HandleFunc("/status/runtime", api.httpRuntimeInfo).Methods(http.MethodGet) // GET, build info. - v1Router.HandleFunc("/version", api.httpVersion).Methods("GET") + v1Router.HandleFunc("/version", api.httpVersion).Methods(http.MethodGet) // /flags // GET, flags. - v1Router.HandleFunc("/flags", api.httpFlags).Methods("GET") + v1Router.HandleFunc("/flags", api.httpFlags).Methods(http.MethodGet) // /approvals // GET, service order. - v1Router.HandleFunc("/service/order", api.httpServiceOrder).Methods("GET") + v1Router.HandleFunc("/service/order", api.httpServiceOrder).Methods(http.MethodGet) // GET, service summary. - v1Router.HandleFunc("/service/summary/{service_id:.+}", api.httpServiceSummary).Methods("GET") + v1Router.HandleFunc("/service/summary/{service_id:.+}", api.httpServiceSummary).Methods(http.MethodGet) // GET, service actions (webhooks/commands). - v1Router.HandleFunc("/service/actions/{service_id:.+}", api.httpServiceGetActions).Methods("GET") + v1Router.HandleFunc("/service/actions/{service_id:.+}", api.httpServiceGetActions).Methods(http.MethodGet) // POST, service actions (disable=service_actions). - v1Router.HandleFunc("/service/actions/{service_id:.+}", api.httpServiceRunActions).Methods("POST") + v1Router.HandleFunc("/service/actions/{service_id:.+}", api.httpServiceRunActions).Methods(http.MethodPost) // GET, service-edit - get details. - v1Router.HandleFunc("/service/update", api.httpOtherServiceDetails).Methods("GET") - v1Router.HandleFunc("/service/update/{service_id:.+}", api.httpServiceDetail).Methods("GET") + v1Router.HandleFunc("/service/update", api.httpOtherServiceDetails).Methods(http.MethodGet) + v1Router.HandleFunc("/service/update/{service_id:.+}", api.httpServiceDetail).Methods(http.MethodGet) // GET, service-edit - refresh unsaved service (disable=[ld]v_refresh_new). - v1Router.HandleFunc("/latest_version/refresh", api.httpLatestVersionRefreshUncreated).Methods("GET") - v1Router.HandleFunc("/deployed_version/refresh", api.httpDeployedVersionRefreshUncreated).Methods("GET") + v1Router.HandleFunc("/latest_version/refresh", api.httpLatestVersionRefreshUncreated).Methods(http.MethodGet) + v1Router.HandleFunc("/deployed_version/refresh", api.httpDeployedVersionRefreshUncreated).Methods(http.MethodGet) // GET, service-edit - refresh service (disable=[ld]v_refresh). - v1Router.HandleFunc("/latest_version/refresh/{service_id:.+}", api.httpLatestVersionRefresh).Methods("GET") - v1Router.HandleFunc("/deployed_version/refresh/{service_id:.+}", api.httpDeployedVersionRefresh).Methods("GET") + v1Router.HandleFunc("/latest_version/refresh/{service_id:.+}", api.httpLatestVersionRefresh).Methods(http.MethodGet) + v1Router.HandleFunc("/deployed_version/refresh/{service_id:.+}", api.httpDeployedVersionRefresh).Methods(http.MethodGet) // POST, service-edit - test notify (disable=notify_test). - v1Router.HandleFunc("/notify/test", api.httpNotifyTest).Methods("POST") + v1Router.HandleFunc("/notify/test", api.httpNotifyTest).Methods(http.MethodPost) // PUT, service-edit - update details (disable=service_edit). - v1Router.HandleFunc("/service/update/{service_id:.+}", api.httpServiceEdit).Methods("PUT") + v1Router.HandleFunc("/service/update/{service_id:.+}", api.httpServiceEdit).Methods(http.MethodPut) // PUT, service-edit - new service (disable=service_create). - v1Router.HandleFunc("/service/new", api.httpServiceEdit).Methods("PUT") + v1Router.HandleFunc("/service/new", api.httpServiceEdit).Methods(http.MethodPut) // DELETE, service-edit - delete service (disable=service_delete). - v1Router.HandleFunc("/service/delete/{service_id:.+}", api.httpServiceDelete).Methods("DELETE") + v1Router.HandleFunc("/service/delete/{service_id:.+}", api.httpServiceDelete).Methods(http.MethodDelete) // GET, counts for Heimdall. - v1Router.HandleFunc("/counts", api.httpCounts).Methods("GET") + v1Router.HandleFunc("/counts", api.httpCounts).Methods(http.MethodGet) // Disable specified routes. api.DisableRoutesAPI() @@ -97,15 +97,15 @@ func (api *API) DisableRoutesAPI() { otherMethods map[string]func(w http.ResponseWriter, r *http.Request) disabled bool }{ - webRoutePrefix + "/api/v1/service/new": {name: "service_create", method: "PUT"}, - webRoutePrefix + "/api/v1/service/update/{service_id:.+}": {name: "service_update", method: "PUT"}, - webRoutePrefix + "/api/v1/service/delete/{service_id:.+}": {name: "service_delete", method: "DELETE"}, - webRoutePrefix + "/api/v1/notify/test": {name: "notify_test", method: "POST"}, - webRoutePrefix + "/api/v1/latest_version/refresh/{service_id:.+}": {name: "lv_refresh", method: "GET"}, - webRoutePrefix + "/api/v1/deployed_version/refresh/{service_id:.+}": {name: "dv_refresh", method: "GET"}, - webRoutePrefix + "/api/v1/latest_version/refresh": {name: "lv_refresh_new", method: "GET"}, - webRoutePrefix + "/api/v1/deployed_version/refresh": {name: "dv_refresh_new", method: "GET"}, - webRoutePrefix + "/api/v1/service/actions/{service_id:.+}": {name: "service_actions", method: "POST"}, + webRoutePrefix + "/api/v1/service/new": {name: "service_create", method: http.MethodPut}, + webRoutePrefix + "/api/v1/service/update/{service_id:.+}": {name: "service_update", method: http.MethodPut}, + webRoutePrefix + "/api/v1/service/delete/{service_id:.+}": {name: "service_delete", method: http.MethodDelete}, + webRoutePrefix + "/api/v1/notify/test": {name: "notify_test", method: http.MethodPost}, + webRoutePrefix + "/api/v1/latest_version/refresh/{service_id:.+}": {name: "lv_refresh", method: http.MethodGet}, + webRoutePrefix + "/api/v1/deployed_version/refresh/{service_id:.+}": {name: "dv_refresh", method: http.MethodGet}, + webRoutePrefix + "/api/v1/latest_version/refresh": {name: "lv_refresh_new", method: http.MethodGet}, + webRoutePrefix + "/api/v1/deployed_version/refresh": {name: "dv_refresh_new", method: http.MethodGet}, + webRoutePrefix + "/api/v1/service/actions/{service_id:.+}": {name: "service_actions", method: http.MethodPost}, } for _, r := range routes { r.disabled = util.Contains(api.Config.Settings.Web.DisabledRoutes, r.name) diff --git a/web/api/v1/http_test.go b/web/api/v1/http_test.go index e5fa1c73..6449ca3b 100644 --- a/web/api/v1/http_test.go +++ b/web/api/v1/http_test.go @@ -109,7 +109,7 @@ func TestHTTP_BasicAuth(t *testing.T) { // WHEN a HTTP request is made to this router client := http.Client{} - req, err := http.NewRequest("GET", ts.URL+"/test", nil) + req, err := http.NewRequest(http.MethodGet, ts.URL+"/test", nil) if err != nil { t.Fatal(err) } @@ -172,7 +172,7 @@ func TestHTTP_SetupRoutesFavicon(t *testing.T) { client := http.Client{} // WHEN a HTTP request is made to this router (apple-touch-icon.png) - req, err := http.NewRequest("GET", ts.URL+"/apple-touch-icon.png", nil) + req, err := http.NewRequest(http.MethodGet, ts.URL+"/apple-touch-icon.png", nil) if err != nil { t.Fatal(err) } @@ -196,7 +196,7 @@ func TestHTTP_SetupRoutesFavicon(t *testing.T) { } // WHEN a HTTP request is made to this router (favicon.svg) - req, err = http.NewRequest("GET", ts.URL+"/favicon.svg", nil) + req, err = http.NewRequest(http.MethodGet, ts.URL+"/favicon.svg", nil) if err != nil { t.Fatal(err) } @@ -537,7 +537,7 @@ func TestHTTP_SetupRoutesNodeJS(t *testing.T) { client := http.Client{} // WHEN a HTTP request is made to this router - req, err := http.NewRequest("GET", ts.URL+tc.route, nil) + req, err := http.NewRequest(http.MethodGet, ts.URL+tc.route, nil) if err != nil { t.Fatal(err) } diff --git a/web/api/v1/middleware.go b/web/api/v1/middleware.go index f0c6c069..7abe266c 100644 --- a/web/api/v1/middleware.go +++ b/web/api/v1/middleware.go @@ -70,6 +70,5 @@ func loggerMiddleware(next http.Handler) http.Handler { // Process request. next.ServeHTTP(w, r) - }) } diff --git a/web/api/v1/util_test.go b/web/api/v1/util_test.go index 5be17482..970bf59a 100644 --- a/web/api/v1/util_test.go +++ b/web/api/v1/util_test.go @@ -197,7 +197,7 @@ func TestAnnounceEdit(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { - t.Parallel() + // t.Parallel() - not parallel because we're using a shared channel tc.newData.Status = &apitype.Status{} if tc.oldData != nil { diff --git a/web/api/v1/websocket-hub.go b/web/api/v1/websocket-hub.go index fb17bd77..84e1cb3a 100644 --- a/web/api/v1/websocket-hub.go +++ b/web/api/v1/websocket-hub.go @@ -17,7 +17,6 @@ package v1 import ( "encoding/json" - "fmt" "time" logutil "github.com/release-argus/Argus/util/log" @@ -73,7 +72,7 @@ func (h *Hub) Run() { for n != 0 { if logutil.Log.IsLevel("DEBUG") { logutil.Log.Debug( - fmt.Sprintf("Broadcast %s", string(message)), + "Broadcast "+string(message), logutil.LogFrom{Primary: "WebSocket"}, len(h.clients) > 0) } diff --git a/web/web_test.go b/web/web_test.go index e336a82f..66bc734a 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -32,15 +32,15 @@ import ( var router *mux.Router func TestMainWithRoutePrefix(t *testing.T) { - // GIVEN a valid config with a Service + // GIVEN a valid config with a Service. cfg := testConfig("TestMainWithRoutePrefix.yml", t) cfg.Settings.Web.RoutePrefix = "/test" - // WHEN the Web UI is started with this Config + // WHEN the Web UI is started with this Config. go Run(cfg) time.Sleep(500 * time.Millisecond) - // THEN Web UI is accessible + // THEN Web UI is accessible. url := fmt.Sprintf("http://localhost:%s%s/metrics", cfg.Settings.Web.ListenPort, cfg.Settings.Web.RoutePrefix) req, _ := http.NewRequest(http.MethodGet, url, nil) @@ -56,7 +56,7 @@ func TestMainWithRoutePrefix(t *testing.T) { } func TestWebAccessible(t *testing.T) { - // GIVEN we have the Web UI Router from TestMain() + // GIVEN we have the Web UI Router from TestMain(), tests := map[string]struct { path string bodyRegex string @@ -79,12 +79,12 @@ func TestWebAccessible(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - // WHEN we make a request to path - req, _ := http.NewRequest("GET", tc.path, nil) + // WHEN we make a request to path. + req, _ := http.NewRequest(http.MethodGet, tc.path, nil) response := httptest.NewRecorder() router.ServeHTTP(response, req) - // THEN we get a Status OK + // THEN we get a Status OK. if response.Code != http.StatusOK { t.Errorf("Expected a 200, got %d", response.Code) @@ -101,7 +101,7 @@ func TestWebAccessible(t *testing.T) { } func TestAccessibleHTTPS(t *testing.T) { - // GIVEN a bunch of URLs to test and the webserver is running with HTTPS + // GIVEN a bunch of URLs to test and the webserver is running with HTTPS. tests := map[string]struct { path string bodyRegex string @@ -137,12 +137,12 @@ func TestAccessibleHTTPS(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - // WHEN we make a HTTPS request to path - req, _ := http.NewRequest("GET", address+tc.path, nil) + // WHEN we make a HTTPS request to path. + req, _ := http.NewRequest(http.MethodGet, address+tc.path, nil) response := httptest.NewRecorder() router.ServeHTTP(response, req) - // THEN we get a Status OK + // THEN we get a Status OK. if response.Code != http.StatusOK { t.Errorf("Expected a 200, got %d", response.Code) diff --git a/webhook/announce.go b/webhook/announce.go index dbd2282d..5102313d 100644 --- a/webhook/announce.go +++ b/webhook/announce.go @@ -23,7 +23,7 @@ import ( ) // AnnounceSend of the WebHook to the `w.Announce` channel. -// (Broadcast to all WebSocket clients) +// (Broadcast to all WebSocket clients). func (w *WebHook) AnnounceSend() { w.SetExecuting(false, false) webhookSummary := make(map[string]*apitype.WebHookSummary) diff --git a/webhook/github.go b/webhook/github.go index b2d76ac0..0860eff1 100644 --- a/webhook/github.go +++ b/webhook/github.go @@ -43,10 +43,10 @@ func SetGitHubHeaders(req *http.Request, payload []byte, secret string) { // X-Hub-Signature-256. hash := hmac.New(sha256.New, []byte(secret)) hash.Write(payload) - req.Header.Set("X-Hub-Signature-256", fmt.Sprintf("sha256=%s", hex.EncodeToString(hash.Sum(nil)))) + req.Header.Set("X-Hub-Signature-256", "sha256="+hex.EncodeToString(hash.Sum(nil))) // X-Hub-Signature. hash = hmac.New(sha1.New, []byte(secret)) hash.Write(payload) - req.Header.Set("X-Hub-Signature", fmt.Sprintf("sha1=%s", hex.EncodeToString(hash.Sum(nil)))) + req.Header.Set("X-Hub-Signature", "sha1="+hex.EncodeToString(hash.Sum(nil))) } diff --git a/webhook/send.go b/webhook/send.go index 83f300e0..b7bece39 100644 --- a/webhook/send.go +++ b/webhook/send.go @@ -113,7 +113,7 @@ func (w *WebHook) Send(serviceInfo util.ServiceInfo, useDelay bool) error { func (w *WebHook) try(logFrom logutil.LogFrom) error { req := w.BuildRequest() if req == nil { - err := fmt.Errorf("failed to get *http.request for WebHook") + err := errors.New("failed to get *http.request for WebHook") logutil.Log.Error(err, logFrom, true) return err } @@ -150,7 +150,7 @@ func (w *WebHook) try(logFrom logutil.LogFrom) error { // FAIL! // Pretty desiredStatusCode. - prettyStatusCode := fmt.Sprint(desiredStatusCode) + prettyStatusCode := strconv.FormatUint(uint64(desiredStatusCode), 10) if prettyStatusCode == "0" { prettyStatusCode = "2XX" }