Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 51 additions & 33 deletions tools/cli/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ linters-settings:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: defer
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: early-return
- name: errorf
- name: exported
- name: import-shadowing
- name: indent-error-flow
- name: if-return
- name: increment-decrement
Expand All @@ -42,6 +45,14 @@ linters-settings:
- name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id
- name: unused-receiver
- name: constant-logical-expr
- name: confusing-naming
- name: unnecessary-stmt
- name: use-any
- name: imports-blocklist
arguments:
- "github.com/pkg/errors"
misspell:
locale: US
lll:
Expand All @@ -52,42 +63,49 @@ linters-settings:
funlen:
lines: 360
statements: 120
gci:
sections:
- standard
- default
linters:
disable-all: true
enable:
- dogsled
- errcheck
- funlen
- gocritic
- gofmt
- goimports
- revive
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
- lll
- misspell
- nakedret
- nolintlint
- rowserrcheck
- copyloopvar
- staticcheck
- stylecheck
- typecheck
- unconvert
- unused
- whitespace
- thelper
- testifylint
- exhaustive
- makezero
- noctx
- tenv
- prealloc
- predeclared
- whitespace
- copyloopvar # copyloopvar is a linter detects places where loop variables are copied
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f())
- errcheck # errcheck is a program for checking for unchecked errors in Go code. These unchecked errors can be critical bugs in some cases
- errorlint # Errorlint is a linter that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13.
- exhaustive # check exhaustiveness of enum switch statements
- copyloopvar # copyloopvar is a linter detects places where loop variables are copied. Replaces exportloopref since Go1.22
- funlen # Tool for detection of long functions
- gci # Gci controls golang package import order and makes it always deterministic. [fast: true, auto-fix: false]
- gocritic # Provides diagnostics that check for bugs, performance and style issues.
- godot # Check if comments end in a period [fast: true, auto-fix: true]
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
- goimports # Check import statements are formatted according to the 'goimport' command. Reformat imports in autofix mode.
- goprintffuncname # Checks that printf-like functions are named with `f` at the end.
- gosec # Inspects source code for security problems
- gosimple # Linter for Go source code that specializes in simplifying code
- govet # Vet examines Go source code and reports suspicious constructs. It is roughly the same as 'go vet' and uses its passes.
- ineffassign # Detects when assignments to existing variables are not used
- lll # Reports long lines
- makezero # Finds slice declarations with non-zero initial length
- misspell # Finds commonly misspelled English words
- nakedret # Checks that functions with naked returns are not longer than a maximum size (can be zero).
- noctx # Finds sending http request without context.Context
- nolintlint # Reports ill-formed or insufficient nolint directives
- perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative.
- prealloc # Finds slice declarations that could potentially be pre-allocated
- predeclared # find code that shadows one of Go's predeclared identifiers
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.
- rowserrcheck # checks whether Rows.Err of rows is checked successfully
- staticcheck # It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint.
- stylecheck # Stylecheck is a replacement for golint
- tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17
- testifylint # Checks usage of github.com/stretchr/testify.
- thelper # thelper detects tests helpers which is not start with t.Helper() method.
- unconvert # Remove unnecessary type conversions
- unused # Checks Go code for unused constants, variables, functions and types
- whitespace # Whitespace is a linter that checks for unnecessary newlines at the start and end of functions, if, for, etc.

# don't enable:
# - deadcode
Expand Down
2 changes: 1 addition & 1 deletion tools/cli/internal/apiversion/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func FindLatestContentVersionMatched(op *openapi3.Operation, requestedVersion *A
return latestVersionMatch
}

// Sort versions
// Sort versions.
func Sort(versions []*APIVersion) {
for i := 0; i < len(versions); i++ {
for j := i + 1; j < len(versions); j++ {
Expand Down
3 changes: 2 additions & 1 deletion tools/cli/internal/apiversion/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func TestParseVersion(t *testing.T) {

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
match, err := Parse(tt.contentType)
if tt.wantErr {
assert.Error(t, err)
Expand Down Expand Up @@ -127,8 +128,8 @@ func TestNewAPIVersionFromContentType(t *testing.T) {

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
version, err := New(WithContent(tt.contentType))
t.Parallel()
version, err := New(WithContent(tt.contentType))
if tt.wantErr {
assert.Error(t, err)
} else {
Expand Down
23 changes: 12 additions & 11 deletions tools/cli/internal/breakingchanges/exemptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package breakingchanges

import (
"errors"
"fmt"
"log"
"strings"
Expand Down Expand Up @@ -57,7 +58,7 @@ func isWithinExpirationDate(exemption Exemption) bool {

func validateExemption(exemption Exemption) error {
if _, err := time.Parse("2006-01-02", exemption.ExemptUntil); err != nil {
return fmt.Errorf("validation error: %v. Exemption: %s", err, exemption)
return fmt.Errorf("validation error: %w. Exemption: %s", err, exemption)
}

if err := validateField(exemption.Reason, "reason", exemption); err != nil {
Expand All @@ -80,34 +81,34 @@ func validateField(fieldValue, fieldName string, exemption Exemption) error {

func transformComponentEntry(breakingChangeDescription string) string {
if strings.Contains(breakingChangeDescription, "api-schema-removed") && !strings.Contains(breakingChangeDescription, "in components") {
return fmt.Sprintf("in components %s", breakingChangeDescription)
return "in components " + breakingChangeDescription
}
return breakingChangeDescription
}

// GetValidExemptionsList returns a list of exemptions. If ignoreExpiration is set to true, it will return all exemptions.
func GetValidExemptionsList(exemptionsPath string, ignoreExpiration bool, fs afero.Fs) ([]Exemption, error) {
if exemptionsPath == "" {
return nil, fmt.Errorf("could not find exemptions file path")
return nil, errors.New("could not find exemptions file path")
}

log.Printf("Generating exemptions from file in %s", exemptionsPath)
exemptionsFile, err := fs.Open(exemptionsPath)
if err != nil {
return nil, fmt.Errorf("could not open exemptions file: %v", err)
return nil, fmt.Errorf("could not open exemptions file: %w", err)
}
defer exemptionsFile.Close()
data, err := afero.ReadAll(exemptionsFile)
if err != nil {
return nil, fmt.Errorf("could not read exemptions file: %v", err)
return nil, fmt.Errorf("could not read exemptions file: %w", err)
}

var exemptions []Exemption
if err := yaml.Unmarshal(data, &exemptions); err != nil {
return nil, fmt.Errorf("could not unmarshal exemptions: %v", err)
return nil, fmt.Errorf("could not unmarshal exemptions: %w", err)
}

var validExemptions []Exemption
validExemptions := make([]Exemption, 0, len(exemptions))
for _, exemption := range exemptions {
if err := validateExemption(exemption); err != nil {
return nil, err
Expand All @@ -126,10 +127,10 @@ func GetValidExemptionsList(exemptionsPath string, ignoreExpiration bool, fs afe
func CreateExemptionsFile(outputPath, exemptionsPath string, ignoreExpiration bool, fs afero.Fs) error {
validExemptions, err := GetValidExemptionsList(exemptionsPath, ignoreExpiration, fs)
if err != nil {
return fmt.Errorf("could not get valid exemptions list: %v", err)
return fmt.Errorf("could not get valid exemptions list: %w", err)
}

var transformedExemptions = []string{}
transformedExemptions := make([]string, 0, len(validExemptions))
for _, validExemption := range validExemptions {
exemptionLine := transformComponentEntry(validExemption.BreakingChangeDescription)
transformedExemptions = append(transformedExemptions, exemptionLine)
Expand All @@ -138,13 +139,13 @@ func CreateExemptionsFile(outputPath, exemptionsPath string, ignoreExpiration bo

file, err := fs.Create(outputPath)
if err != nil {
return fmt.Errorf("could not create exemptions file: %v", err)
return fmt.Errorf("could not create exemptions file: %w", err)
}
defer file.Close()

for _, exemption := range transformedExemptions {
if _, err := fmt.Fprintf(file, "%s\n", exemption); err != nil {
return fmt.Errorf("could not write to exemptions file: %v", err)
return fmt.Errorf("could not write to exemptions file: %w", err)
}
}
log.Printf("Exemptions file generated in %s\n", outputPath)
Expand Down
4 changes: 2 additions & 2 deletions tools/cli/internal/changelog/changelog.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ func findChangelogEntry(changelog []*Entry, date, operationID, version, changeCo
return nil
}

func newStringFromStruct(data interface{}) string {
func newStringFromStruct(data any) string {
bytes, err := json.MarshalIndent(data, "", " ")
if err != nil {
return ""
Expand All @@ -489,7 +489,7 @@ func newStringFromStruct(data interface{}) string {
// 1. Remove all entries with hideFromChangelog
// 2. Remove all empty versions
// 3. Remove all empty paths
// 4. Shift changelog entry if it turns out empty
// 4. Shift changelog entry if it turns out empty.
func NewNotHiddenEntries(changelog []*Entry) ([]*Entry, error) {
if len(changelog) == 0 {
return changelog, nil
Expand Down
2 changes: 1 addition & 1 deletion tools/cli/internal/changelog/manual_entry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestDetectManualEntriesAndMergeChangelog(t *testing.T) {
HTTPMethod: "POST",
Tag: "Multi-Cloud Clusters",
Sunset: "",
ManualChangelogEntries: map[string]interface{}{
ManualChangelogEntries: map[string]any{
previousRunDate: "change info 1", // Already in the changelog
runDate: "change info 2", // Should be added to the changelog
theDayAfterRunDate: "change info 3", // Should not be added to the changelog
Expand Down
18 changes: 9 additions & 9 deletions tools/cli/internal/changelog/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func newChangeTypeOverrides() map[string]string {
}
}

// NewEntriesFromSunsetAndManualEntry merges the base changelog with the new changes from manual entries and sunset endpoints
// NewEntriesFromSunsetAndManualEntry merges the base changelog with the new changes from manual entries and sunset endpoints.
func (m *Changelog) NewEntriesFromSunsetAndManualEntry() ([]*Entry, error) {
conf := outputfilter.NewOperationConfigs(nil, m.Revision)
if _, err := m.newEntriesFromSunsetEndpoints(conf); err != nil {
Expand Down Expand Up @@ -116,7 +116,7 @@ func (m *Changelog) newManualEntries(conf map[string]*outputfilter.OperationConf
return m.BaseChangelog, nil
}

// newEntryFromOasDiff merges the base changelog with the new changes from a Base and Revision OpenAPI specs
// newEntryFromOasDiff merges the base changelog with the new changes from a Base and Revision OpenAPI specs.
func (m *Changelog) newEntryFromOasDiff() ([]*Entry, error) {
changes, err := m.newOasDiffEntries()
if err != nil {
Expand All @@ -143,7 +143,7 @@ func (m *Changelog) newEntryFromOasDiff() ([]*Entry, error) {
// Logic:
// 1. If the entry already exists in the changelog for the Run Date, use that entry or create it (newEntryAtRunDate)
// 2. Get the paths from the changes and add them to the entry
// 3. Sort the changelog by date DESC, path + httpMethod ASC, version DESC
// 3. Sort the changelog by date DESC, path + httpMethod ASC, version DESC.
func (m *Changelog) mergeChangelog(
changeType string,
changes []*outputfilter.OasDiffEntry,
Expand All @@ -167,7 +167,7 @@ func (m *Changelog) mergeChangelog(
// 1. Get the deprecated paths from the changes
// 2. Get the updated paths with the deprecated changes from newPathsFromDeprecatedChanges
// 3. Get the revision paths from the changes
// 4. Get the updated paths with the revision changes from newPathsFromRevisionChanges
// 4. Get the updated paths with the revision changes from newPathsFromRevisionChanges.
func (m *Changelog) newPathsFromChanges(
changes []*outputfilter.OasDiffEntry,
changeType string, entry *Entry,
Expand All @@ -185,7 +185,7 @@ func (m *Changelog) newPathsFromChanges(
return paths, nil
}

// newPathsFromRevisionChanges creates new paths from revision changes
// newPathsFromRevisionChanges creates new paths from revision changes.
func (m *Changelog) newPathsFromRevisionChanges(
changes []*outputfilter.OasDiffEntry,
changeType string, changelogPath *[]*Path,
Expand All @@ -194,7 +194,7 @@ func (m *Changelog) newPathsFromRevisionChanges(
return newMergedChanges(revisionChanges, changeType, m.RevisionMetadata.ActiveVersion, changelogPath, conf)
}

// newPathsFromDeprecatedChanges creates new paths from deprecated changes
// newPathsFromDeprecatedChanges creates new paths from deprecated changes.
func (m *Changelog) newPathsFromDeprecatedChanges(
changes []*outputfilter.OasDiffEntry,
changelogPath *[]*Path,
Expand All @@ -219,7 +219,7 @@ func (m *Changelog) newOasDiffEntries() ([]*outputfilter.OasDiffEntry, error) {
return outputfilter.NewChangelogEntries(changes, diffResult.SpecInfoPair, m.ExemptionFilePath)
}

// sortChangelog sorts changelog by date DESC, path + httpMethod ASC, version DESC
// sortChangelog sorts changelog by date DESC, path + httpMethod ASC, version DESC.
func sortChangelog(changelog []*Entry) []*Entry {
sort.Slice(changelog, func(i, j int) bool {
return changelog[i].Date > changelog[j].Date
Expand All @@ -242,7 +242,7 @@ func sortChangelog(changelog []*Entry) []*Entry {
return changelog
}

// newMergedChanges merges the OasDiff changes into the changelog []paths
// newMergedChanges merges the OasDiff changes into the changelog []paths.
func newMergedChanges(changes []*outputfilter.OasDiffEntry,
changeType, version string, changelogPath *[]*Path,
operationConfig map[string]*outputfilter.OperationConfigs) ([]*Path, error) {
Expand Down Expand Up @@ -372,7 +372,7 @@ func newEntryVersion(versions *[]*Version, specVersion string) *Version {
}

// newPathEntry returns the index and the path entry if it already exists in the changelog
// otherwise it returns -1 and a new path entry
// otherwise it returns -1 and a new path entry.
func newPathEntry(paths *[]*Path, path, operation string) *Path {
for _, p := range *paths {
if p.URI == path && p.HTTPMethod == operation {
Expand Down
Loading
Loading