diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index b46ac462b7..19df26d2ea 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -10,6 +10,7 @@ import ( "flag" "fmt" "io" + "maps" "net/http" "os" "os/exec" @@ -31,7 +32,6 @@ import ( "github.com/databricks/cli/libs/auth" "github.com/databricks/cli/libs/testdiff" "github.com/databricks/cli/libs/testserver" - "github.com/databricks/cli/libs/utils" "github.com/stretchr/testify/require" ) @@ -817,7 +817,7 @@ func buildTestEnv(configEnv map[string]string, customEnv []string) []string { env := make([]string, 0, len(configEnv)+len(customEnv)) // Add config.Env first (but skip keys that exist in customEnv) - for _, key := range utils.SortedKeys(configEnv) { + for _, key := range slices.Sorted(maps.Keys(configEnv)) { if hasKey(customEnv, key) { continue } diff --git a/acceptance/internal/config.go b/acceptance/internal/config.go index 48bbd11c3f..10192524e0 100644 --- a/acceptance/internal/config.go +++ b/acceptance/internal/config.go @@ -2,6 +2,7 @@ package internal import ( "hash/fnv" + "maps" "os" "path/filepath" "reflect" @@ -345,11 +346,7 @@ func ExpandEnvMatrix(matrix, exclude map[string][]string, extraVars []string) [] return result } - keys := make([]string, 0, len(filteredMatrix)) - for key := range filteredMatrix { - keys = append(keys, key) - } - slices.Sort(keys) + keys := slices.Sorted(maps.Keys(filteredMatrix)) // Build an expansion of all combinations. // At each step we look at a given key and append each possible value to each diff --git a/bundle/artifacts/build.go b/bundle/artifacts/build.go index 6d89b8c07c..2d1b1e4d74 100644 --- a/bundle/artifacts/build.go +++ b/bundle/artifacts/build.go @@ -3,8 +3,10 @@ package artifacts import ( "context" "fmt" + "maps" "os" "path/filepath" + "slices" "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/config" @@ -15,7 +17,6 @@ import ( "github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/logdiag" "github.com/databricks/cli/libs/patchwheel" - "github.com/databricks/cli/libs/utils" ) func Build() bundle.Mutator { @@ -37,7 +38,7 @@ func (m *build) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { }) } - for _, artifactName := range utils.SortedKeys(b.Config.Artifacts) { + for _, artifactName := range slices.Sorted(maps.Keys(b.Config.Artifacts)) { a := b.Config.Artifacts[artifactName] if a.BuildCommand != "" { diff --git a/bundle/artifacts/prepare.go b/bundle/artifacts/prepare.go index 84e2eefd0e..041669ad11 100644 --- a/bundle/artifacts/prepare.go +++ b/bundle/artifacts/prepare.go @@ -3,8 +3,10 @@ package artifacts import ( "context" "errors" + "maps" "os" "path/filepath" + "slices" "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/config" @@ -15,7 +17,6 @@ import ( "github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/logdiag" "github.com/databricks/cli/libs/python" - "github.com/databricks/cli/libs/utils" ) func Prepare() bundle.Mutator { @@ -34,7 +35,7 @@ func (m *prepare) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics return diag.FromErr(err) } - for _, artifactName := range utils.SortedKeys(b.Config.Artifacts) { + for _, artifactName := range slices.Sorted(maps.Keys(b.Config.Artifacts)) { artifact := b.Config.Artifacts[artifactName] if artifact == nil { l := b.Config.GetLocation("artifacts." + artifactName) diff --git a/bundle/config/validate/scripts.go b/bundle/config/validate/scripts.go index 421ca593cb..04c6045bb4 100644 --- a/bundle/config/validate/scripts.go +++ b/bundle/config/validate/scripts.go @@ -3,12 +3,13 @@ package validate import ( "context" "fmt" + "maps" "regexp" + "slices" "github.com/databricks/cli/bundle" "github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/dyn" - "github.com/databricks/cli/libs/utils" ) type validateScripts struct{} @@ -28,7 +29,7 @@ func (f *validateScripts) Apply(ctx context.Context, b *bundle.Bundle) diag.Diag // Sort the scripts to have a deterministic order for the // generated diagnostics. - scriptKeys := utils.SortedKeys(b.Config.Scripts) + scriptKeys := slices.Sorted(maps.Keys(b.Config.Scripts)) for _, k := range scriptKeys { script := b.Config.Scripts[k] diff --git a/bundle/configsync/format.go b/bundle/configsync/format.go index 1ad54db5a1..c6b1278cd3 100644 --- a/bundle/configsync/format.go +++ b/bundle/configsync/format.go @@ -2,6 +2,7 @@ package configsync import ( "fmt" + "maps" "slices" "strings" ) @@ -17,21 +18,13 @@ func FormatTextOutput(changes Changes) string { output.WriteString(fmt.Sprintf("Detected changes in %d resource(s):\n\n", len(changes))) - resourceKeys := make([]string, 0, len(changes)) - for key := range changes { - resourceKeys = append(resourceKeys, key) - } - slices.Sort(resourceKeys) + resourceKeys := slices.Sorted(maps.Keys(changes)) for _, resourceKey := range resourceKeys { resourceChanges := changes[resourceKey] output.WriteString(fmt.Sprintf("Resource: %s\n", resourceKey)) - paths := make([]string, 0, len(resourceChanges)) - for path := range resourceChanges { - paths = append(paths, path) - } - slices.Sort(paths) + paths := slices.Sorted(maps.Keys(resourceChanges)) for _, path := range paths { configChange := resourceChanges[path] diff --git a/bundle/configsync/resolve.go b/bundle/configsync/resolve.go index f6c91a9dfa..ce065d6ca8 100644 --- a/bundle/configsync/resolve.go +++ b/bundle/configsync/resolve.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "io/fs" + "maps" "path/filepath" "slices" "strings" @@ -171,11 +172,7 @@ func ResolveChanges(ctx context.Context, b *bundle.Bundle, configChanges Changes var result []FieldChange targetName := b.Config.Bundle.Target - resourceKeys := make([]string, 0, len(configChanges)) - for resourceKey := range configChanges { - resourceKeys = append(resourceKeys, resourceKey) - } - slices.Sort(resourceKeys) + resourceKeys := slices.Sorted(maps.Keys(configChanges)) for _, resourceKey := range resourceKeys { resourceChanges := configChanges[resourceKey] diff --git a/bundle/direct/bundle_plan.go b/bundle/direct/bundle_plan.go index 10baf64d8a..15ccf2ac4e 100644 --- a/bundle/direct/bundle_plan.go +++ b/bundle/direct/bundle_plan.go @@ -23,7 +23,6 @@ import ( "github.com/databricks/cli/libs/structs/structdiff" "github.com/databricks/cli/libs/structs/structpath" "github.com/databricks/cli/libs/structs/structvar" - "github.com/databricks/cli/libs/utils" "github.com/databricks/databricks-sdk-go" ) @@ -968,7 +967,7 @@ func (b *DeploymentBundle) getAdapterForKey(resourceKey string) (*dresources.Ada adapter, ok := b.Adapters[group] if !ok { - return nil, fmt.Errorf("resource type %q not supported, available: %s", group, strings.Join(utils.SortedKeys(b.Adapters), ", ")) + return nil, fmt.Errorf("resource type %q not supported, available: %s", group, strings.Join(slices.Sorted(maps.Keys(b.Adapters)), ", ")) } return adapter, nil diff --git a/bundle/direct/graph.go b/bundle/direct/graph.go index 433eb8dc57..386c590f53 100644 --- a/bundle/direct/graph.go +++ b/bundle/direct/graph.go @@ -2,17 +2,18 @@ package direct import ( "fmt" + "maps" + "slices" "github.com/databricks/cli/bundle/deployplan" "github.com/databricks/cli/libs/dagrun" - "github.com/databricks/cli/libs/utils" ) func makeGraph(plan *deployplan.Plan) (*dagrun.Graph, error) { g := dagrun.NewGraph() // Add all nodes first - for _, resourceKey := range utils.SortedKeys(plan.Plan) { + for _, resourceKey := range slices.Sorted(maps.Keys(plan.Plan)) { g.AddNode(resourceKey) } diff --git a/bundle/internal/schema/annotations.go b/bundle/internal/schema/annotations.go index 689d75ae2e..c57926e131 100644 --- a/bundle/internal/schema/annotations.go +++ b/bundle/internal/schema/annotations.go @@ -3,6 +3,7 @@ package main import ( "bytes" "fmt" + "maps" "os" "reflect" "regexp" @@ -183,12 +184,7 @@ func saveYamlWithStyle(outputPath string, annotations annotation.File) error { } func getAlphabeticalOrder[T any](mapping map[string]T) *yamlsaver.Order { - var order []string - for k := range mapping { - order = append(order, k) - } - slices.Sort(order) - return yamlsaver.NewOrder(order) + return yamlsaver.NewOrder(slices.Sorted(maps.Keys(mapping))) } func convertLinksToAbsoluteUrl(s string) string { diff --git a/bundle/internal/tf/codegen/generator/generator.go b/bundle/internal/tf/codegen/generator/generator.go index 47af677c00..37d9a7b7f7 100644 --- a/bundle/internal/tf/codegen/generator/generator.go +++ b/bundle/internal/tf/codegen/generator/generator.go @@ -4,8 +4,10 @@ import ( "context" "fmt" "log" + "maps" "os" "path/filepath" + "slices" "strings" "text/template" @@ -56,7 +58,7 @@ func (r *root) Generate(path string) error { func Run(ctx context.Context, schema *tfjson.ProviderSchema, checksums *schemapkg.ProviderChecksums, path string) error { // Generate types for resources var resources []*namedBlock - for _, k := range sortKeys(schema.ResourceSchemas) { + for _, k := range slices.Sorted(maps.Keys(schema.ResourceSchemas)) { // Skipping all plugin framework struct generation. // TODO: This is a temporary fix, generation should be fixed in the future. if strings.HasSuffix(k, "_pluginframework") { @@ -87,7 +89,7 @@ func Run(ctx context.Context, schema *tfjson.ProviderSchema, checksums *schemapk // Generate types for data sources. var dataSources []*namedBlock - for _, k := range sortKeys(schema.DataSourceSchemas) { + for _, k := range slices.Sorted(maps.Keys(schema.DataSourceSchemas)) { // Skipping all plugin framework struct generation. // TODO: This is a temporary fix, generation should be fixed in the future. if strings.HasSuffix(k, "_pluginframework") { diff --git a/bundle/internal/tf/codegen/generator/util.go b/bundle/internal/tf/codegen/generator/util.go deleted file mode 100644 index 4844cd870e..0000000000 --- a/bundle/internal/tf/codegen/generator/util.go +++ /dev/null @@ -1,13 +0,0 @@ -package generator - -import ( - "maps" - "slices" -) - -// sortKeys returns a sorted copy of the keys in the specified map. -func sortKeys[M ~map[K]V, K string, V any](m M) []K { - keys := slices.Collect(maps.Keys(m)) - slices.Sort(keys) - return keys -} diff --git a/bundle/internal/tf/codegen/generator/walker.go b/bundle/internal/tf/codegen/generator/walker.go index e08490fe52..bdcb325bc3 100644 --- a/bundle/internal/tf/codegen/generator/walker.go +++ b/bundle/internal/tf/codegen/generator/walker.go @@ -2,6 +2,7 @@ package generator import ( "fmt" + "maps" "slices" "strings" @@ -117,7 +118,7 @@ func processAttributeType(typ cty.Type, resourceName, attributePath string) stri } func nestedBlockKeys(block *tfjson.SchemaBlock) []string { - keys := sortKeys(block.NestedBlocks) + keys := slices.Sorted(maps.Keys(block.NestedBlocks)) // Remove TF specific "timeouts" block. if i := slices.Index(keys, "timeouts"); i != -1 { @@ -163,7 +164,7 @@ func (w *walker) walk(block *tfjson.SchemaBlock, name []string) error { } // Declare attributes. - for _, k := range sortKeys(block.Attributes) { + for _, k := range slices.Sorted(maps.Keys(block.Attributes)) { v := block.Attributes[k] // Assert the attribute type is always set. diff --git a/bundle/internal/validation/enum.go b/bundle/internal/validation/enum.go index ca2e821da5..276a3847de 100644 --- a/bundle/internal/validation/enum.go +++ b/bundle/internal/validation/enum.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "go/format" + "maps" "os" "path/filepath" "reflect" @@ -182,11 +183,7 @@ func filterTargetsAndEnvironmentsEnum(patterns map[string][]EnumPatternInfo) map // sortGroupedPatterns sorts patterns within each group and returns them as a sorted slice func sortGroupedPatternsEnum(groupedPatterns map[string][]EnumPatternInfo) [][]EnumPatternInfo { // Get sorted group keys - groupKeys := make([]string, 0, len(groupedPatterns)) - for key := range groupedPatterns { - groupKeys = append(groupKeys, key) - } - slices.Sort(groupKeys) + groupKeys := slices.Sorted(maps.Keys(groupedPatterns)) // Build sorted result result := make([][]EnumPatternInfo, 0, len(groupKeys)) diff --git a/bundle/internal/validation/required.go b/bundle/internal/validation/required.go index 10c0c0eb5d..ee327b4f9c 100644 --- a/bundle/internal/validation/required.go +++ b/bundle/internal/validation/required.go @@ -5,6 +5,7 @@ import ( "cmp" "fmt" "go/format" + "maps" "os" "path/filepath" "reflect" @@ -138,11 +139,7 @@ func filterTargetsAndEnvironments(patterns map[string][]RequiredPatternInfo) map // sortGroupedPatterns sorts patterns within each group and returns them as a sorted slice func sortGroupedPatterns(groupedPatterns map[string][]RequiredPatternInfo) [][]RequiredPatternInfo { // Get sorted group keys - groupKeys := make([]string, 0, len(groupedPatterns)) - for key := range groupedPatterns { - groupKeys = append(groupKeys, key) - } - slices.Sort(groupKeys) + groupKeys := slices.Sorted(maps.Keys(groupedPatterns)) // Build sorted result result := make([][]RequiredPatternInfo, 0, len(groupKeys)) diff --git a/bundle/libraries/remote_path.go b/bundle/libraries/remote_path.go index d24387653a..22784a6335 100644 --- a/bundle/libraries/remote_path.go +++ b/bundle/libraries/remote_path.go @@ -3,13 +3,14 @@ package libraries import ( "context" "fmt" + "maps" "path" "path/filepath" + "slices" "github.com/databricks/cli/bundle" "github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/dyn" - "github.com/databricks/cli/libs/utils" ) // ReplaceWithRemotePath updates all the libraries paths to point to the remote location @@ -25,7 +26,7 @@ func ReplaceWithRemotePath(ctx context.Context, b *bundle.Bundle) (map[string][] return nil, diag.FromErr(err) } - sources := utils.SortedKeys(libs) + sources := slices.Sorted(maps.Keys(libs)) // Update all the config paths to point to the uploaded location err = b.Config.Mutate(func(v dyn.Value) (dyn.Value, error) { diff --git a/bundle/libraries/switch_to_patched_wheels.go b/bundle/libraries/switch_to_patched_wheels.go index d7f442bb58..0a9d184604 100644 --- a/bundle/libraries/switch_to_patched_wheels.go +++ b/bundle/libraries/switch_to_patched_wheels.go @@ -2,13 +2,14 @@ package libraries import ( "context" + "maps" "path/filepath" + "slices" "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/config" "github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/log" - "github.com/databricks/cli/libs/utils" ) type switchToPatchedWheels struct{} @@ -35,7 +36,7 @@ func (c switchToPatchedWheels) Apply(ctx context.Context, b *bundle.Bundle) diag log.Debugf(ctx, "Updating resources.jobs.%s.task[%d].libraries[%d].whl from %s to %s", jobName, taskInd, libInd, lib.Whl, repl) job.Tasks[taskInd].Libraries[libInd].Whl = repl } else { - log.Debugf(ctx, "Not updating resources.jobs.%s.task[%d].libraries[%d].whl from %s. Available replacements: %v", jobName, taskInd, libInd, lib.Whl, utils.SortedKeys(replacements)) + log.Debugf(ctx, "Not updating resources.jobs.%s.task[%d].libraries[%d].whl from %s. Available replacements: %v", jobName, taskInd, libInd, lib.Whl, slices.Sorted(maps.Keys(replacements))) } } @@ -49,7 +50,7 @@ func (c switchToPatchedWheels) Apply(ctx context.Context, b *bundle.Bundle) diag log.Debugf(ctx, "Updating resources.jobs.%s.task[%d].for_each_task.task.libraries[%d].whl from %s to %s", jobName, taskInd, libInd, lib.Whl, repl) foreachptr.Task.Libraries[libInd].Whl = repl } else { - log.Debugf(ctx, "Not updating resources.jobs.%s.task[%d].for_each_task.task.libraries[%d].whl from %s. Available replacements: %v", jobName, taskInd, libInd, lib.Whl, utils.SortedKeys(replacements)) + log.Debugf(ctx, "Not updating resources.jobs.%s.task[%d].for_each_task.task.libraries[%d].whl from %s. Available replacements: %v", jobName, taskInd, libInd, lib.Whl, slices.Sorted(maps.Keys(replacements))) } } } @@ -67,7 +68,7 @@ func (c switchToPatchedWheels) Apply(ctx context.Context, b *bundle.Bundle) diag log.Debugf(ctx, "Updating resources.jobs.%s.environments[%d].spec.dependencies[%d] from %s to %s", jobName, envInd, depInd, dep, repl) specptr.Dependencies[depInd] = repl } else { - log.Debugf(ctx, "Not updating resources.jobs.%s.environments[%d].spec.dependencies[%d] from %s. Available replacements: %v", jobName, envInd, depInd, dep, utils.SortedKeys(replacements)) + log.Debugf(ctx, "Not updating resources.jobs.%s.environments[%d].spec.dependencies[%d] from %s. Available replacements: %v", jobName, envInd, depInd, dep, slices.Sorted(maps.Keys(replacements))) } } } diff --git a/bundle/libraries/upload.go b/bundle/libraries/upload.go index 590adda4ff..cb3ff2faf0 100644 --- a/bundle/libraries/upload.go +++ b/bundle/libraries/upload.go @@ -4,8 +4,10 @@ import ( "context" "errors" "fmt" + "maps" "os" "path/filepath" + "slices" "github.com/databricks/cli/bundle" "github.com/databricks/cli/libs/cmdio" @@ -13,7 +15,6 @@ import ( "github.com/databricks/cli/libs/dyn" "github.com/databricks/cli/libs/filer" "github.com/databricks/cli/libs/log" - "github.com/databricks/cli/libs/utils" "golang.org/x/sync/errgroup" ) @@ -58,7 +59,7 @@ func (u *upload) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { u.client = client } - sources := utils.SortedKeys(u.libs) + sources := slices.Sorted(maps.Keys(u.libs)) errs, errCtx := errgroup.WithContext(ctx) errs.SetLimit(maxFilesRequestsInFlight) diff --git a/bundle/phases/bind.go b/bundle/phases/bind.go index 0435d19a6d..fbed0aaef1 100644 --- a/bundle/phases/bind.go +++ b/bundle/phases/bind.go @@ -5,6 +5,8 @@ import ( "encoding/json" "errors" "fmt" + "maps" + "slices" "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/config/engine" @@ -15,7 +17,6 @@ import ( "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/logdiag" - "github.com/databricks/cli/libs/utils" ) func Bind(ctx context.Context, b *bundle.Bundle, opts *terraform.BindOptions, engine engine.EngineType) { @@ -55,7 +56,7 @@ func Bind(ctx context.Context, b *bundle.Bundle, opts *terraform.BindOptions, en if result.Plan != nil { if entry, ok := result.Plan.Plan[resourceKey]; ok && entry != nil && len(entry.Changes) > 0 { cmdio.LogString(ctx, "\nChanges detected:") - for _, field := range utils.SortedKeys(entry.Changes) { + for _, field := range slices.Sorted(maps.Keys(entry.Changes)) { change := entry.Changes[field] if change.Action != deployplan.Skip { cmdio.LogString(ctx, fmt.Sprintf(" ~ %s: %v -> %v", field, jsonDump(ctx, change.Remote, field), jsonDump(ctx, change.New, field))) diff --git a/bundle/tests/include_test.go b/bundle/tests/include_test.go index c5ad2d58a1..50bf177fdf 100644 --- a/bundle/tests/include_test.go +++ b/bundle/tests/include_test.go @@ -1,13 +1,14 @@ package config_tests import ( + "maps" "path/filepath" + "slices" "testing" "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/phases" "github.com/databricks/cli/libs/logdiag" - "github.com/databricks/cli/libs/utils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -26,7 +27,7 @@ func TestIncludeInvalid(t *testing.T) { func TestIncludeWithGlob(t *testing.T) { b := load(t, "./include_with_glob") - keys := utils.SortedKeys(b.Config.Resources.Jobs) + keys := slices.Sorted(maps.Keys(b.Config.Resources.Jobs)) assert.Equal(t, []string{"my_job"}, keys) job := b.Config.Resources.Jobs["my_job"] @@ -46,7 +47,7 @@ func TestIncludeForMultipleMatches(t *testing.T) { b := load(t, "./include_multiple") // Test that both jobs were loaded. - keys := utils.SortedKeys(b.Config.Resources.Jobs) + keys := slices.Sorted(maps.Keys(b.Config.Resources.Jobs)) assert.Equal(t, []string{"my_first_job", "my_second_job"}, keys) first := b.Config.Resources.Jobs["my_first_job"] diff --git a/cmd/bundle/debug/refschema.go b/cmd/bundle/debug/refschema.go index 0b7b164e86..4ba1ae999f 100644 --- a/cmd/bundle/debug/refschema.go +++ b/cmd/bundle/debug/refschema.go @@ -3,6 +3,7 @@ package debug import ( "fmt" "io" + "maps" "reflect" "slices" "strings" @@ -11,7 +12,6 @@ import ( "github.com/databricks/cli/cmd/root" "github.com/databricks/cli/libs/structs/structpath" "github.com/databricks/cli/libs/structs/structwalk" - "github.com/databricks/cli/libs/utils" "github.com/spf13/cobra" ) @@ -42,7 +42,7 @@ func dumpRemoteSchemas(out io.Writer) error { return fmt.Errorf("failed to initialize adapters: %w", err) } - for _, resourceName := range utils.SortedKeys(adapters) { + for _, resourceName := range slices.Sorted(maps.Keys(adapters)) { adapter := adapters[resourceName] var resourcePrefix string @@ -100,9 +100,9 @@ func dumpRemoteSchemas(out io.Writer) error { } var lines []string - for _, p := range utils.SortedKeys(pathTypes) { + for _, p := range slices.Sorted(maps.Keys(pathTypes)) { byType := pathTypes[p] - for _, t := range utils.SortedKeys(byType) { + for _, t := range slices.Sorted(maps.Keys(byType)) { info := formatTags(byType[t]) sep := "." if strings.HasPrefix(p, "[") { @@ -125,5 +125,5 @@ func formatTags(sources map[string]struct{}) string { if len(sources) == 3 { return "ALL" } - return strings.Join(utils.SortedKeys(sources), "\t") + return strings.Join(slices.Sorted(maps.Keys(sources)), "\t") } diff --git a/cmd/pipelines/deploy.go b/cmd/pipelines/deploy.go index d966a962d3..2c8d27de14 100644 --- a/cmd/pipelines/deploy.go +++ b/cmd/pipelines/deploy.go @@ -4,6 +4,8 @@ package pipelines import ( "fmt" + "maps" + "slices" "github.com/databricks/cli/bundle" "github.com/databricks/cli/bundle/config/mutator" @@ -11,7 +13,6 @@ import ( "github.com/databricks/cli/cmd/root" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/logdiag" - libsutils "github.com/databricks/cli/libs/utils" "github.com/spf13/cobra" ) @@ -63,7 +64,7 @@ func deployCommand() *cobra.Command { } for _, group := range b.Config.Resources.AllResources() { - for _, resourceKey := range libsutils.SortedKeys(group.Resources) { + for _, resourceKey := range slices.Sorted(maps.Keys(group.Resources)) { resource := group.Resources[resourceKey] cmdio.LogString(ctx, fmt.Sprintf("View your %s %s here: %s", resource.ResourceDescription().SingularName, resourceKey, resource.GetURL())) } diff --git a/experimental/aitools/cmd/list.go b/experimental/aitools/cmd/list.go index 7c7144bd03..1be1538c9a 100644 --- a/experimental/aitools/cmd/list.go +++ b/experimental/aitools/cmd/list.go @@ -3,6 +3,7 @@ package aitools import ( "errors" "fmt" + "maps" "slices" "strings" "text/tabwriter" @@ -80,11 +81,7 @@ func defaultListSkills(cmd *cobra.Command, scope string) error { } // Build sorted list of skill names. - names := make([]string, 0, len(manifest.Skills)) - for name := range manifest.Skills { - names = append(names, name) - } - slices.Sort(names) + names := slices.Sorted(maps.Keys(manifest.Skills)) version := strings.TrimPrefix(ref, "v") cmdio.LogString(ctx, "Available skills (v"+version+"):") diff --git a/experimental/aitools/lib/installer/installer.go b/experimental/aitools/lib/installer/installer.go index 4a3f363254..8b10f0b9aa 100644 --- a/experimental/aitools/lib/installer/installer.go +++ b/experimental/aitools/lib/installer/installer.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "maps" "net/http" "os" "path/filepath" @@ -160,11 +161,7 @@ func InstallSkillsForAgents(ctx context.Context, src ManifestSource, targetAgent } // Install each skill in sorted order for determinism. - skillNames := make([]string, 0, len(targetSkills)) - for name := range targetSkills { - skillNames = append(skillNames, name) - } - slices.Sort(skillNames) + skillNames := slices.Sorted(maps.Keys(targetSkills)) for _, name := range skillNames { meta := targetSkills[name] diff --git a/experimental/aitools/lib/installer/update.go b/experimental/aitools/lib/installer/update.go index 9e5ea2ddaf..663ad5e908 100644 --- a/experimental/aitools/lib/installer/update.go +++ b/experimental/aitools/lib/installer/update.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "maps" "os" "path/filepath" "slices" @@ -84,7 +85,7 @@ func UpdateSkills(ctx context.Context, src ManifestSource, targetAgents []*agent if state.Release == latestTag && !opts.Force { cmdio.LogString(ctx, "Already up to date.") - return &UpdateResult{Unchanged: sortedKeys(state.Skills)}, nil + return &UpdateResult{Unchanged: slices.Sorted(maps.Keys(state.Skills))}, nil } manifest, err := src.FetchManifest(ctx, latestTag) @@ -105,7 +106,7 @@ func UpdateSkills(ctx context.Context, src ManifestSource, targetAgents []*agent isDev := strings.HasPrefix(cliVersion, build.DefaultSemver) // Sort skill names for deterministic output. - names := sortedKeys(skillSet) + names := slices.Sorted(maps.Keys(skillSet)) for _, name := range names { meta, inManifest := manifest.Skills[name] @@ -230,16 +231,6 @@ func hasLegacyInstall(ctx context.Context, globalDir string) bool { return hasSkillsOnDisk(filepath.Join(homeDir, ".databricks", "agent-skills")) } -// sortedKeys returns the keys of a map sorted alphabetically. -func sortedKeys[V any](m map[string]V) []string { - keys := make([]string, 0, len(m)) - for k := range m { - keys = append(keys, k) - } - slices.Sort(keys) - return keys -} - // FormatUpdateResult returns a human-readable summary of the update result. // When check is true, output uses "Would update/add" instead of "Updated/Added". func FormatUpdateResult(result *UpdateResult, check bool) string { diff --git a/libs/apps/manifest/manifest.go b/libs/apps/manifest/manifest.go index 8d3cd12e27..54423ada2e 100644 --- a/libs/apps/manifest/manifest.go +++ b/libs/apps/manifest/manifest.go @@ -4,6 +4,7 @@ import ( "cmp" "encoding/json" "fmt" + "maps" "os" "path/filepath" "slices" @@ -55,12 +56,7 @@ func (r Resource) HasFields() bool { // FieldNames returns the field names in sorted order for deterministic iteration. func (r Resource) FieldNames() []string { - names := make([]string, 0, len(r.Fields)) - for k := range r.Fields { - names = append(names, k) - } - slices.Sort(names) - return names + return slices.Sorted(maps.Keys(r.Fields)) } // Resources defines the required and optional resources for a plugin. @@ -171,12 +167,7 @@ func (m *Manifest) GetPluginByName(name string) *Plugin { // GetPluginNames returns a list of all plugin names. func (m *Manifest) GetPluginNames() []string { - names := make([]string, 0, len(m.Plugins)) - for name := range m.Plugins { - names = append(names, name) - } - slices.Sort(names) - return names + return slices.Sorted(maps.Keys(m.Plugins)) } // ValidatePluginNames checks that all provided plugin names exist in the manifest. diff --git a/libs/dyn/dynloc/locations.go b/libs/dyn/dynloc/locations.go index ec0d7e7c95..5c8e22f093 100644 --- a/libs/dyn/dynloc/locations.go +++ b/libs/dyn/dynloc/locations.go @@ -92,8 +92,7 @@ func (l *Locations) registerFileNames(locs []dyn.Location) error { cache[loc.File] = out } - l.Files = slices.Collect(maps.Values(cache)) - slices.Sort(l.Files) + l.Files = slices.Sorted(maps.Values(cache)) // Build the file-to-index map. for i, file := range l.Files { diff --git a/libs/dyn/dynvar/resolve.go b/libs/dyn/dynvar/resolve.go index b1366d93bb..1cfcc028b7 100644 --- a/libs/dyn/dynvar/resolve.go +++ b/libs/dyn/dynvar/resolve.go @@ -3,11 +3,11 @@ package dynvar import ( "errors" "fmt" + "maps" "slices" "strings" "github.com/databricks/cli/libs/dyn" - "github.com/databricks/cli/libs/utils" ) // Resolve resolves variable references in the given input value using the provided lookup function. @@ -101,7 +101,7 @@ func (r *resolver) resolveVariableReferences() (err error) { // We sort the keys here to ensure that we always resolve the same variable reference first. // This is done such that the cycle detection error is deterministic. If we did not do this, // we could enter the cycle at any point in the cycle and return varying errors. - keys := utils.SortedKeys(r.refs) + keys := slices.Sorted(maps.Keys(r.refs)) for _, key := range keys { v, err := r.resolveRef(r.refs[key], []string{key}) if err != nil { diff --git a/libs/structs/structdiff/diff.go b/libs/structs/structdiff/diff.go index c63c845563..61c909dfd1 100644 --- a/libs/structs/structdiff/diff.go +++ b/libs/structs/structdiff/diff.go @@ -2,6 +2,7 @@ package structdiff import ( "fmt" + "maps" "reflect" "slices" "strings" @@ -267,11 +268,7 @@ func diffMapStringKey(ctx *diffContext, path *structpath.PathNode, m1, m2 reflec keySet[ks] = k } - var keys []string - for s := range keySet { - keys = append(keys, s) - } - slices.Sort(keys) + keys := slices.Sorted(maps.Keys(keySet)) for _, ks := range keys { k := keySet[ks] diff --git a/libs/sync/diff_test.go b/libs/sync/diff_test.go index 94b6cc3754..d48223f775 100644 --- a/libs/sync/diff_test.go +++ b/libs/sync/diff_test.go @@ -87,7 +87,7 @@ func TestDiffComputationForRemovedFiles(t *testing.T) { expected := diff{ delete: []string{"foo/a/b/c"}, rmdir: []string{"foo", "foo/a", "foo/a/b"}, - mkdir: []string{}, + mkdir: nil, put: []string{}, } assert.Equal(t, expected, computeDiff(after, before)) @@ -121,8 +121,8 @@ func TestDiffComputationWhenRemoteNameIsChanged(t *testing.T) { expected := diff{ delete: []string{"foo/a/b/c"}, - rmdir: []string{}, - mkdir: []string{}, + rmdir: nil, + mkdir: nil, put: []string{"foo/a/b/c.py"}, } assert.Equal(t, expected, computeDiff(after, before)) @@ -143,7 +143,7 @@ func TestDiffComputationForNewFiles(t *testing.T) { expected := diff{ delete: []string{}, - rmdir: []string{}, + rmdir: nil, mkdir: []string{"foo", "foo/a", "foo/a/b"}, put: []string{"foo/a/b/c.py"}, } @@ -178,8 +178,8 @@ func TestDiffComputationForUpdatedFiles(t *testing.T) { expected := diff{ delete: []string{}, - rmdir: []string{}, - mkdir: []string{}, + rmdir: nil, + mkdir: nil, put: []string{"foo/a/b/c"}, } assert.Equal(t, expected, computeDiff(after, before)) diff --git a/libs/sync/dirset.go b/libs/sync/dirset.go index dc1b819cf5..c6d6622f41 100644 --- a/libs/sync/dirset.go +++ b/libs/sync/dirset.go @@ -1,6 +1,7 @@ package sync import ( + "maps" "path" "slices" ) @@ -33,12 +34,7 @@ func MakeDirSet(files []string) DirSet { // Slice returns a sorted copy of the dirset elements as a slice. func (dirset DirSet) Slice() []string { - out := make([]string, 0, len(dirset)) - for dir := range dirset { - out = append(out, dir) - } - slices.Sort(out) - return out + return slices.Sorted(maps.Keys(dirset)) } // Remove returns the set difference of two DirSets. diff --git a/libs/testserver/serving_endpoints.go b/libs/testserver/serving_endpoints.go index 49e72d3df2..cfe59e448e 100644 --- a/libs/testserver/serving_endpoints.go +++ b/libs/testserver/serving_endpoints.go @@ -3,6 +3,7 @@ package testserver import ( "encoding/json" "fmt" + "maps" "slices" "github.com/databricks/databricks-sdk-go/service/serving" @@ -294,11 +295,7 @@ func (s *FakeWorkspace) ServingEndpointPatchTags(req Request, name string) Respo // Convert back to slice sorted by key for stable output tags := make([]serving.EndpointTag, 0, len(tagMap)) - keys := make([]string, 0, len(tagMap)) - for key := range tagMap { - keys = append(keys, key) - } - slices.Sort(keys) + keys := slices.Sorted(maps.Keys(tagMap)) for _, key := range keys { tags = append(tags, serving.EndpointTag{Key: key, Value: tagMap[key]}) } diff --git a/libs/utils/utils.go b/libs/utils/utils.go index 6f3d553157..5d4dc62df9 100644 --- a/libs/utils/utils.go +++ b/libs/utils/utils.go @@ -2,18 +2,8 @@ package utils import ( "reflect" - "slices" ) -func SortedKeys[T any](m map[string]T) []string { - keys := make([]string, 0, len(m)) - for k := range m { - keys = append(keys, k) - } - slices.Sort(keys) - return keys -} - // FilterFields creates a new slice with fields present only in the provided type, // excluding any fields specified in the excludeFields list. // We must use that when copying structs because JSON marshaller in SDK crashes if it sees unknown field.