diff --git a/cli-plugins/manager/cobra.go b/cli-plugins/manager/cobra.go index 57ec4a7909ec..dd3f05baedbf 100644 --- a/cli-plugins/manager/cobra.go +++ b/cli-plugins/manager/cobra.go @@ -57,7 +57,7 @@ func AddPluginCommandStubs(dockerCLI config.Provider, rootCmd *cobra.Command) (e }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // Delegate completion to plugin - cargs := []string{p.Path, cobra.ShellCompRequestCmd, p.Name} + cargs := []string{p.Path, cobra.ShellCompRequestCmd, p.Name} //nolint:prealloc // no need to over-complicate things. cargs = append(cargs, args...) cargs = append(cargs, toComplete) os.Args = cargs diff --git a/cli/command/formatter/container.go b/cli/command/formatter/container.go index 979d3eb82d60..fafa6a56e0d9 100644 --- a/cli/command/formatter/container.go +++ b/cli/command/formatter/container.go @@ -350,7 +350,7 @@ func DisplayablePorts(ports []container.PortSummary) string { last uint16 } groupMap := make(map[string]*portGroup) - var result []string //nolint:prealloc + var result []string var hostMappings []string var groupMapKeys []string sort.Slice(ports, func(i, j int) bool { diff --git a/cli/command/image/build_test.go b/cli/command/image/build_test.go index 27884e3bd1ea..88d94d6cdec4 100644 --- a/cli/command/image/build_test.go +++ b/cli/command/image/build_test.go @@ -190,7 +190,7 @@ func (f *fakeBuild) build(_ context.Context, buildContext io.Reader, options cli func (f *fakeBuild) headers(t *testing.T) []*tar.Header { t.Helper() - headers := []*tar.Header{} + var headers []*tar.Header for { hdr, err := f.context.Next() switch err { @@ -206,8 +206,9 @@ func (f *fakeBuild) headers(t *testing.T) []*tar.Header { func (f *fakeBuild) filenames(t *testing.T) []string { t.Helper() - names := []string{} - for _, header := range f.headers(t) { + h := f.headers(t) + names := make([]string, 0, len(h)) + for _, header := range h { names = append(names, header.Name) } sort.Strings(names) diff --git a/cli/command/service/list_test.go b/cli/command/service/list_test.go index be60eb4f77d7..824806b449ee 100644 --- a/cli/command/service/list_test.go +++ b/cli/command/service/list_test.go @@ -108,7 +108,7 @@ func TestServiceListServiceStatus(t *testing.T) { }, } - matrix := make([]testCase, 0) + matrix := make([]testCase, 0, len(tests)) for _, quiet := range []bool{false, true} { for _, tc := range tests { if quiet { diff --git a/cli/command/service/progress/progress_test.go b/cli/command/service/progress/progress_test.go index 7cd7664e3545..1cc2d983f988 100644 --- a/cli/command/service/progress/progress_test.go +++ b/cli/command/service/progress/progress_test.go @@ -80,7 +80,7 @@ func TestReplicatedProgressUpdaterOneReplica(t *testing.T) { service: service, } - tasks := []swarm.Task{} + var tasks []swarm.Task //nolint:prealloc // no need to over-complicate things. ut.testUpdater(tasks, false, []progress.Progress{ @@ -193,7 +193,7 @@ func TestReplicatedProgressUpdaterManyReplicas(t *testing.T) { service: service, } - tasks := []swarm.Task{} + var tasks []swarm.Task // No per-task progress bars because there are too many replicas ut.testUpdater(tasks, false, @@ -248,7 +248,7 @@ func TestGlobalProgressUpdaterOneNode(t *testing.T) { service: service, } - tasks := []swarm.Task{} + var tasks []swarm.Task //nolint:prealloc // no need to over-complicate things. ut.testUpdater(tasks, false, []progress.Progress{ @@ -362,7 +362,7 @@ func TestGlobalProgressUpdaterManyNodes(t *testing.T) { ut.activeNodes[strconv.Itoa(i)] = struct{}{} } - tasks := []swarm.Task{} + var tasks []swarm.Task ut.testUpdater(tasks, false, []progress.Progress{ @@ -459,9 +459,8 @@ func TestReplicatedJobProgressUpdaterSmall(t *testing.T) { }) // wipe the old tasks out of the list - tasks = []swarm.Task{} - tasks = append(tasks, - swarm.Task{ + tasks = []swarm.Task{ //nolint:prealloc // no need to over-complicate things. + { ID: "task1", Slot: 0, NodeID: "", @@ -469,7 +468,7 @@ func TestReplicatedJobProgressUpdaterSmall(t *testing.T) { Status: swarm.TaskStatus{State: swarm.TaskStateNew}, JobIteration: &swarm.Version{Index: service.JobStatus.JobIteration.Index}, }, - swarm.Task{ + { ID: "task2", Slot: 1, NodeID: "", @@ -477,7 +476,7 @@ func TestReplicatedJobProgressUpdaterSmall(t *testing.T) { Status: swarm.TaskStatus{State: swarm.TaskStateNew}, JobIteration: &swarm.Version{Index: service.JobStatus.JobIteration.Index}, }, - ) + } ut.testUpdater(tasks, false, []progress.Progress{ {ID: "1/5", Action: "new ", Current: 1, Total: 10, HideCounts: true}, {ID: "2/5", Action: "new ", Current: 1, Total: 10, HideCounts: true}, @@ -644,7 +643,7 @@ func TestReplicatedJobProgressUpdaterLarge(t *testing.T) { service: service, } - tasks := []swarm.Task{} + var tasks []swarm.Task // see the comments in TestReplicatedJobProgressUpdaterSmall for why // we write this out twice. @@ -741,7 +740,7 @@ func TestGlobalJobProgressUpdaterSmall(t *testing.T) { service: service, } - tasks := []swarm.Task{ + tasks := []swarm.Task{ //nolint:prealloc // no need to over-complicate things. { ID: "oldtask1", DesiredState: swarm.TaskStateComplete, @@ -871,7 +870,7 @@ func TestGlobalJobProgressUpdaterLarge(t *testing.T) { service: service, } - tasks := []swarm.Task{} + var tasks []swarm.Task //nolint:prealloc // no need to over-complicate things. for nodeID := range activeNodes { tasks = append(tasks, swarm.Task{ ID: "task" + nodeID, diff --git a/cli/command/service/update.go b/cli/command/service/update.go index 54e83d442ea7..65ecb0b4dd9a 100644 --- a/cli/command/service/update.go +++ b/cli/command/service/update.go @@ -1333,7 +1333,7 @@ func updateNetworks(ctx context.Context, apiClient client.NetworkAPIClient, flag } existingNetworks := make(map[string]struct{}) - var newNetworks []swarm.NetworkAttachmentConfig //nolint:prealloc + var newNetworks []swarm.NetworkAttachmentConfig for _, nw := range specNetworks { if _, exists := idsToRemove[nw.Target]; exists { continue diff --git a/cli/command/stack/loader.go b/cli/command/stack/loader.go index 647a9f6b3c04..356e24dbc859 100644 --- a/cli/command/stack/loader.go +++ b/cli/command/stack/loader.go @@ -27,7 +27,6 @@ func loadComposeFile(streams command.Streams, opts deployOptions) (*composetypes return nil, err } - dicts := getDictsFrom(configDetails.ConfigFiles) config, err := loader.Load(configDetails) if err != nil { var fpe *loader.ForbiddenPropertiesError @@ -39,6 +38,7 @@ func loadComposeFile(streams command.Streams, opts deployOptions) (*composetypes return nil, err } + dicts := getDictsFrom(configDetails.ConfigFiles) unsupportedProperties := loader.GetUnsupportedProperties(dicts...) if len(unsupportedProperties) > 0 { _, _ = fmt.Fprintf(streams.Err(), "Ignoring unsupported options: %s\n\n", @@ -65,8 +65,7 @@ func loadComposeFile(streams command.Streams, opts deployOptions) (*composetypes } func getDictsFrom(configFiles []composetypes.ConfigFile) []map[string]any { - dicts := []map[string]any{} - + dicts := make([]map[string]any, 0, len(configFiles)) for _, configFile := range configFiles { dicts = append(dicts, configFile.Config) } diff --git a/cli/command/swarm/opts.go b/cli/command/swarm/opts.go index 57429ffb0904..1aa90e757bac 100644 --- a/cli/command/swarm/opts.go +++ b/cli/command/swarm/opts.go @@ -110,7 +110,7 @@ func (*ExternalCAOption) Type() string { // String returns a string repr of this option. func (m *ExternalCAOption) String() string { - externalCAs := []string{} + externalCAs := make([]string, 0, len(m.values)) for _, externalCA := range m.values { repr := fmt.Sprintf("%s: %s", externalCA.Protocol, externalCA.URL) externalCAs = append(externalCAs, repr) diff --git a/cli/command/system/events.go b/cli/command/system/events.go index 03f465fabd2f..eb77c6c6b2f9 100644 --- a/cli/command/system/events.go +++ b/cli/command/system/events.go @@ -133,12 +133,12 @@ func prettyPrintEvent(out io.Writer, event events.Message) error { _, _ = fmt.Fprintf(out, "%s %s %s", event.Type, event.Action, event.Actor.ID) if len(event.Actor.Attributes) > 0 { - var attrs []string - var keys []string + keys := make([]string, 0, len(event.Actor.Attributes)) for k := range event.Actor.Attributes { keys = append(keys, k) } sort.Strings(keys) + attrs := make([]string, 0, len(keys)) for _, k := range keys { v := event.Actor.Attributes[k] attrs = append(attrs, k+"="+v) diff --git a/cli/compose/convert/service.go b/cli/compose/convert/service.go index 5fbc289d830e..957ddb10a8d0 100644 --- a/cli/compose/convert/service.go +++ b/cli/compose/convert/service.go @@ -174,7 +174,11 @@ func Service( } func getPlacementPreference(preferences []composetypes.PlacementPreferences) []swarm.PlacementPreference { - result := []swarm.PlacementPreference{} + if len(preferences) == 0 { + return nil + } + + result := make([]swarm.PlacementPreference, 0, len(preferences)) for _, preference := range preferences { spreadDescriptor := preference.Spread result = append(result, swarm.PlacementPreference{ @@ -198,7 +202,7 @@ func convertServiceNetworks( } } - nets := []swarm.NetworkAttachmentConfig{} + nets := make([]swarm.NetworkAttachmentConfig, 0, len(networks)) for networkName, nw := range networks { networkConfig, ok := networkConfigs[networkName] if !ok && networkName != defaultNetwork { @@ -241,8 +245,6 @@ func convertServiceSecrets( secrets []composetypes.ServiceSecretConfig, secretSpecs map[string]composetypes.SecretConfig, ) ([]*swarm.SecretReference, error) { - refs := []*swarm.SecretReference{} - lookup := func(key string) (composetypes.FileObjectConfig, error) { secretSpec, exists := secretSpecs[key] if !exists { @@ -250,6 +252,8 @@ func convertServiceSecrets( } return composetypes.FileObjectConfig(secretSpec), nil } + + refs := make([]*swarm.SecretReference, 0, len(secrets)) for _, secret := range secrets { obj, err := convertFileObject(namespace, composetypes.FileReferenceConfig(secret), lookup) if err != nil { @@ -564,7 +568,7 @@ func convertResources(source composetypes.Resources) (*swarm.ResourceRequirement } func convertEndpointSpec(endpointMode string, source []composetypes.ServicePortConfig) *swarm.EndpointSpec { - portConfigs := []swarm.PortConfig{} + portConfigs := make([]swarm.PortConfig, 0, len(source)) for _, port := range source { portConfig := swarm.PortConfig{ Protocol: network.IPProtocol(port.Protocol), diff --git a/cli/compose/loader/merge.go b/cli/compose/loader/merge.go index 0aa61fad4673..950f9f8c01c8 100644 --- a/cli/compose/loader/merge.go +++ b/cli/compose/loader/merge.go @@ -134,7 +134,7 @@ func toServiceVolumeConfigsMap(s any) (map[any]any, error) { } func toServiceSecretConfigsSlice(dst reflect.Value, m map[any]any) error { - s := []types.ServiceSecretConfig{} + s := make([]types.ServiceSecretConfig, 0, len(m)) for _, v := range m { s = append(s, v.(types.ServiceSecretConfig)) } @@ -144,7 +144,7 @@ func toServiceSecretConfigsSlice(dst reflect.Value, m map[any]any) error { } func toSServiceConfigObjConfigsSlice(dst reflect.Value, m map[any]any) error { - s := []types.ServiceConfigObjConfig{} + s := make([]types.ServiceConfigObjConfig, 0, len(m)) for _, v := range m { s = append(s, v.(types.ServiceConfigObjConfig)) } @@ -154,7 +154,7 @@ func toSServiceConfigObjConfigsSlice(dst reflect.Value, m map[any]any) error { } func toServicePortConfigsSlice(dst reflect.Value, m map[any]any) error { - s := []types.ServicePortConfig{} + s := make([]types.ServicePortConfig, 0, len(m)) for _, v := range m { s = append(s, v.(types.ServicePortConfig)) } @@ -164,7 +164,7 @@ func toServicePortConfigsSlice(dst reflect.Value, m map[any]any) error { } func toServiceVolumeConfigsSlice(dst reflect.Value, m map[any]any) error { - s := []types.ServiceVolumeConfig{} + s := make([]types.ServiceVolumeConfig, 0, len(m)) for _, v := range m { s = append(s, v.(types.ServiceVolumeConfig)) } diff --git a/cli/connhelper/ssh/ssh.go b/cli/connhelper/ssh/ssh.go index 34ae267e20e4..2fcb54a98f68 100644 --- a/cli/connhelper/ssh/ssh.go +++ b/cli/connhelper/ssh/ssh.go @@ -175,7 +175,7 @@ func quoteCommand(commandAndArgs ...string) (string, error) { quotedCmd = a continue } - quotedCmd += " " + a //nolint:perfsprint // ignore "concat-loop"; no need to use a string-builder for this. + quotedCmd += " " + a } // each part is quoted appropriately, so now we'll have a full // shell command to pass off to "ssh" diff --git a/dockerfiles/Dockerfile.lint b/dockerfiles/Dockerfile.lint index 6c5008f2d55c..f017155b53d4 100644 --- a/dockerfiles/Dockerfile.lint +++ b/dockerfiles/Dockerfile.lint @@ -7,7 +7,7 @@ ARG GO_VERSION=1.25.7 # that's also available as alpine image variant for the Golang version used. ARG ALPINE_VERSION=3.22 # GOLANGCI_LINT_VERSION sets the version of the golangci/golangci-lint image to use. -ARG GOLANGCI_LINT_VERSION=v2.6.1 +ARG GOLANGCI_LINT_VERSION=v2.9.0 FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint diff --git a/internal/volumespec/volumespec.go b/internal/volumespec/volumespec.go index 791805edff38..ec7baf722f86 100644 --- a/internal/volumespec/volumespec.go +++ b/internal/volumespec/volumespec.go @@ -25,7 +25,7 @@ func Parse(spec string) (VolumeConfig, error) { return volume, nil } - var buffer []rune + buffer := make([]rune, 0, len(spec)) for _, char := range spec + string(endOfSpec) { switch { case isWindowsDrive(buffer, char): @@ -35,7 +35,7 @@ func Parse(spec string) (VolumeConfig, error) { populateType(&volume) return volume, fmt.Errorf("invalid spec: %s: %w", spec, err) } - buffer = []rune{} + buffer = buffer[:0] // reset, but reuse capacity default: buffer = append(buffer, char) } diff --git a/opts/gpus.go b/opts/gpus.go index b39a3f14e727..e68ede7a085f 100644 --- a/opts/gpus.go +++ b/opts/gpus.go @@ -105,7 +105,7 @@ func (*GpuOpts) Type() string { // String returns a string repr of this option func (o *GpuOpts) String() string { - gpus := []string{} + gpus := make([]string, 0, len(o.values)) for _, gpu := range o.values { gpus = append(gpus, fmt.Sprintf("%v", gpu)) } diff --git a/opts/mount.go b/opts/mount.go index 642f6500ab4c..2f252aaca5fe 100644 --- a/opts/mount.go +++ b/opts/mount.go @@ -151,7 +151,7 @@ func (*MountOpt) Type() string { // String returns a string repr of this option func (m *MountOpt) String() string { - mounts := []string{} + mounts := make([]string, 0, len(m.values)) for _, mount := range m.values { repr := fmt.Sprintf("%s %s %s", mount.Type, mount.Source, mount.Target) mounts = append(mounts, repr) diff --git a/opts/swarmopts/config.go b/opts/swarmopts/config.go index 78e8f886b649..4d98ed5257a3 100644 --- a/opts/swarmopts/config.go +++ b/opts/swarmopts/config.go @@ -86,7 +86,7 @@ func (*ConfigOpt) Type() string { // String returns a string repr of this option func (o *ConfigOpt) String() string { - configs := []string{} + configs := make([]string, 0, len(o.values)) for _, config := range o.values { repr := fmt.Sprintf("%s -> %s", config.ConfigName, config.File.Name) configs = append(configs, repr) diff --git a/opts/swarmopts/secret.go b/opts/swarmopts/secret.go index b28970af9ae8..834e8ae273fa 100644 --- a/opts/swarmopts/secret.go +++ b/opts/swarmopts/secret.go @@ -85,7 +85,7 @@ func (*SecretOpt) Type() string { // String returns a string repr of this option func (o *SecretOpt) String() string { - secrets := []string{} + secrets := make([]string, 0, len(o.values)) for _, secret := range o.values { repr := fmt.Sprintf("%s -> %s", secret.SecretName, secret.File.Name) secrets = append(secrets, repr)