diff --git a/build/package/github-actions/github-actions.go b/build/package/github-actions/github-actions.go index 4391437c..a9619175 100644 --- a/build/package/github-actions/github-actions.go +++ b/build/package/github-actions/github-actions.go @@ -14,6 +14,10 @@ import ( o "github.com/launchdarkly/ld-find-code-refs/v2/options" ) +const ( + millisecondsInSecond = 1000 // Descriptive constant for milliseconds conversion +) + func main() { log.Init(false) dir := os.Getenv("GITHUB_WORKSPACE") @@ -55,7 +59,7 @@ func mergeGithubOptions(opts o.Options) (o.Options, error) { if event != nil { repoUrl = event.Repo.Url defaultBranch = event.Repo.DefaultBranch - updateSequenceId = int(time.Now().Unix() * 1000) // seconds to ms + updateSequenceId = int(time.Now().Unix() * millisecondsInSecond) // seconds to ms } opts.RepoType = "github" diff --git a/internal/git/git.go b/internal/git/git.go index 85fb932f..961a5354 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -227,7 +227,7 @@ type CommitData struct { } // FindExtinctions searches commit history for flags that had references removed recently -func (c Client) FindExtinctions(project options.Project, flags []string, matcher search.Matcher, lookback int) ([]ld.ExtinctionRep, error) { +func (c *Client) FindExtinctions(project options.Project, flags []string, matcher search.Matcher, lookback int) ([]ld.ExtinctionRep, error) { commits, err := getCommits(c.workspace, lookback) if err != nil { return nil, err @@ -342,9 +342,8 @@ func getCommits(workspace string, lookback int) ([]CommitData, error) { if err != nil { return nil, err } - commits := []CommitData{} - for i := 0; i < lookback; i++ { + for range make([]struct{}, lookback) { commit, err := logResult.Next() if err != nil { // reached end of commit tree diff --git a/internal/ld/ld.go b/internal/ld/ld.go index 13a98de0..997bf271 100644 --- a/internal/ld/ld.go +++ b/internal/ld/ld.go @@ -44,6 +44,7 @@ const ( apiVersionHeader = "LD-API-Version" v2ApiPath = "/api/v2" reposPath = "/code-refs/repositories" + shortShaLength = 7 // Descriptive constant for SHA length ) type ConfigurationError struct { @@ -76,8 +77,8 @@ func IsTransient(err error) bool { // Fallback to default backoff if header can't be parsed // https://apidocs.launchdarkly.com/#section/Overview/Rate-limiting // Method is curried in order to avoid stubbing the time package and fallback Backoff in unit tests -func RateLimitBackoff(now func() time.Time, fallbackBackoff h.Backoff) func(time.Duration, time.Duration, int, *http.Response) time.Duration { - return func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { +func RateLimitBackoff(now func() time.Time, fallbackBackoff h.Backoff) func(minDuration, max time.Duration, attemptNum int, resp *http.Response) time.Duration { + return func(minDuration, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil { if resp.StatusCode == http.StatusTooManyRequests { if s, ok := resp.Header["X-Ratelimit-Reset"]; ok { @@ -95,7 +96,7 @@ func RateLimitBackoff(now func() time.Time, fallbackBackoff h.Backoff) func(time } } - return fallbackBackoff(min, max, attemptNum, resp) + return fallbackBackoff(minDuration, max, attemptNum, resp) } } @@ -441,7 +442,7 @@ type ldErrorResponse struct { func (c ApiClient) do(req *h.Request) (*http.Response, error) { req.Header.Set("Authorization", c.Options.ApiKey) - req.Header.Set(apiVersionHeader, apiVersion) + req.Header.Set(apiVersionHeader, apiVersion) //nolint:canonicalheader req.Header.Set("User-Agent", c.Options.UserAgent) req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Length", strconv.FormatInt(req.ContentLength, 10)) @@ -450,15 +451,15 @@ func (c ApiClient) do(req *h.Request) (*http.Response, error) { return nil, err } + // Ensure the response body is closed + defer res.Body.Close() + // Check for all general status codes returned by the code references API, attempting to deconstruct LD error messages, if possible. switch res.StatusCode { case http.StatusOK, http.StatusCreated, http.StatusNoContent: return res, nil default: resBytes, err := io.ReadAll(res.Body) - if res != nil { - defer res.Body.Close() - } if err != nil { return nil, err } @@ -550,8 +551,8 @@ func (b BranchRep) TotalHunkCount() int { func (b BranchRep) WriteToCSV(outDir, projKey, repo, sha string) (path string, err error) { // Try to create a filename with a shortened sha, but if the sha is too short for some unexpected reason, use the branch name instead var tag string - if len(sha) >= 7 { - tag = sha[:7] + if len(sha) >= shortShaLength { + tag = sha[:shortShaLength] } else { tag = b.Name } @@ -577,7 +578,7 @@ func (b BranchRep) WriteToCSV(outDir, projKey, repo, sha string) (path string, e // sort csv by flag key sort.Slice(records, func(i, j int) bool { // sort by flagKey -> path -> startingLineNumber - for k := 0; k < 3; k++ { + for k := range [3]int{} { if records[i][k] != records[j][k] { return records[i][k] < records[j][k] } diff --git a/options/flags.go b/options/flags.go index adb90ea0..f8a5d4c3 100644 --- a/options/flags.go +++ b/options/flags.go @@ -7,6 +7,11 @@ type flag struct { usage string } +const ( + defaultFlagValue = 2 // Descriptive constant for default flag value + anotherDefaultFlagValue = 10 // Descriptive constant for another default flag value +) + // Options that are available as command line flags var flags = []flag{ { @@ -45,7 +50,7 @@ Allowed template variables: 'branchName', 'sha'. If "commitUrlTemplate" is not p { name: "contextLines", short: "C", - defaultValue: 2, + defaultValue: anotherDefaultFlagValue, usage: `The number of context lines to send to LaunchDarkly. If < 0, no source code will be sent to LaunchDarkly. If 0, only the lines containing flag references will be sent. If > 0, will send that number of context diff --git a/options/options.go b/options/options.go index 4ea891b3..c92dafd4 100644 --- a/options/options.go +++ b/options/options.go @@ -192,7 +192,7 @@ func (o Options) ValidateRequired() error { } if len(o.ProjKey) > 0 && len(o.Projects) > 0 { - return fmt.Errorf("`--projKey` cannot be combined with `projects` in configuration") + return errors.New("`--projKey` cannot be combined with `projects` in configuration") } if len(o.ProjKey) > maxProjKeyLength { @@ -260,7 +260,7 @@ func (o Options) Validate() error { } if o.Revision != "" && o.Branch == "" { - return fmt.Errorf(`"branch" option is required when "revision" option is set`) + return errors.New(`"branch" option is required when "revision" option is set`) } if len(o.Projects) > 0 { diff --git a/search/matcher.go b/search/matcher.go index 765fb13a..be16ca9f 100644 --- a/search/matcher.go +++ b/search/matcher.go @@ -9,6 +9,11 @@ import ( "github.com/launchdarkly/ld-find-code-refs/v2/options" ) +const ( + // ... other constants ... + bufferGrowthFactor = 2 // Descriptive constant for buffer growth +) + type Matcher struct { Elements []ElementMatcher ctxLines int @@ -83,7 +88,7 @@ func buildElementPatterns(flags []string, delimiters string) map[string][]string for _, left := range delimiters { for _, right := range delimiters { var sb strings.Builder - sb.Grow(len(flag) + 2) + sb.Grow(len(flag) + bufferGrowthFactor) sb.WriteRune(left) sb.WriteString(flag) sb.WriteRune(right)