From 971a61961e1e3388cc558d863c7a05062f17ec0c Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 10:42:25 +0200 Subject: [PATCH 1/8] Add deadcode to tools/go.mod Co-authored-by: Isaac --- tools/go.mod | 2 ++ tools/go.sum | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tools/go.mod b/tools/go.mod index a961b14996..3755d674db 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -208,6 +208,7 @@ require ( golang.org/x/mod v0.28.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect + golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect golang.org/x/term v0.29.0 // indirect golang.org/x/text v0.29.0 // indirect golang.org/x/tools v0.37.0 // indirect @@ -224,5 +225,6 @@ require ( tool ( github.com/golangci/golangci-lint/v2/cmd/golangci-lint github.com/google/yamlfmt/cmd/yamlfmt + golang.org/x/tools/cmd/deadcode gotest.tools/gotestsum ) diff --git a/tools/go.sum b/tools/go.sum index 6c6b89daf9..43a76d00c4 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -814,6 +814,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= +golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= From bca03d68a676a7bf538eb58714ebd7e96983b84c Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 10:46:16 +0200 Subject: [PATCH 2/8] Add check_deadcode.py wrapper script Co-authored-by: Isaac --- tools/check_deadcode.py | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 tools/check_deadcode.py diff --git a/tools/check_deadcode.py b/tools/check_deadcode.py new file mode 100755 index 0000000000..199bcc7a1d --- /dev/null +++ b/tools/check_deadcode.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# /// script +# requires-python = ">=3.12" +# /// +""" +Deadcode checker for the Databricks CLI. + +Runs the 'deadcode' tool (golang.org/x/tools/cmd/deadcode) to find functions +that are unreachable from main() or test entry points. Since the CLI is a +product (not a library), any unreachable function is dead code. + +Suppression mechanisms +====================== + +1. Directory exclusions (EXCLUDED_DIRS below): + Entire directories can be excluded. Use this for directories where + everything is a false positive. Example: libs/gorules/ contains lint + rule definitions loaded by golangci-lint's ruleguard engine, not + through Go's call graph. + +2. Inline comments: + Add "//deadcode:allow " on the line directly above a function + to suppress a specific finding. Example: + + //deadcode:allow loaded by golangci-lint ruleguard, not via Go imports + func MyLintRule(m dsl.Matcher) { + + This matches the //nolint: pattern Go developers already know. +""" +import re +import subprocess +import sys + +# Directories to exclude entirely. Everything in these directories is a +# false positive. Each entry is matched as a prefix of the file path in +# deadcode output. +EXCLUDED_DIRS = [ + "libs/gorules/", +] + +ALLOW_COMMENT = "//deadcode:allow" + + +def main(): + result = subprocess.run( + ["go", "tool", "-modfile=tools/go.mod", "deadcode", "-test", "./..."], + capture_output=True, + text=True, + ) + output = result.stdout.strip() + if not output: + print("No dead code found.") + return + + lines = output.split("\n") + violations = [] + + for line in lines: + if any(line.startswith(d) or ("/" + d) in line for d in EXCLUDED_DIRS): + continue + + match = re.match(r"(.+?):(\d+):\d+:", line) + if not match: + violations.append(line) + continue + + filepath = match.group(1) + lineno = int(match.group(2)) + + try: + with open(filepath) as f: + file_lines = f.readlines() + if lineno >= 2 and ALLOW_COMMENT in file_lines[lineno - 2]: + continue + except (OSError, IndexError): + pass + + violations.append(line) + + if not violations: + print("No dead code found.") + return + + print("Dead code found:\n") + for v in violations: + print(f" {v}") + print(f"\n{len(violations)} unreachable function(s) found.") + print("\nTo suppress, add a comment on the line above the function:") + print(" //deadcode:allow ") + print("\nOr add a directory exclusion in tools/check_deadcode.py.") + sys.exit(1) + + +if __name__ == "__main__": + main() From 877f2a969f8512f06c6660610e2241ee089a3626 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 10:46:57 +0200 Subject: [PATCH 3/8] Add make deadcode target, wire into make checks Co-authored-by: Isaac --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b31bb73d08..4844d7a3c1 100644 --- a/Makefile +++ b/Makefile @@ -65,9 +65,13 @@ wsfix: links: ./tools/update_github_links.py +.PHONY: deadcode +deadcode: + ./tools/check_deadcode.py + # Checks other than 'fmt' and 'lint'; these are fast, so can be run first .PHONY: checks -checks: tidy ws links +checks: tidy ws links deadcode .PHONY: install-pythons From a20a6c8842694099370d2bdf6ade00e1f9b847df Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 11:34:43 +0200 Subject: [PATCH 4/8] Remove dead functions found by deadcode Co-authored-by: Isaac --- bundle/internal/schema/main_test.go | 22 --- bundle/internal/tf/schema/data_sources.go | 136 ------------------ bundle/libraries/upload.go | 7 - cmd/bundle/utils/utils.go | 85 ----------- .../aitools/lib/installer/installer.go | 21 --- experimental/ssh/internal/keys/secrets.go | 13 -- internal/testcli/golden.go | 24 ---- internal/testutil/helpers.go | 3 - libs/apps/prompt/listers.go | 22 --- libs/apps/prompt/prompt.go | 14 -- libs/calladapt/validate_test.go | 2 - libs/cmdio/io.go | 5 - libs/cmdio/render.go | 10 -- libs/dagrun/dagrun.go | 4 - libs/databrickscfg/profile/context.go | 4 - libs/dyn/dynassert/dump.go | 60 -------- libs/dyn/pattern.go | 11 -- libs/dyn/visit.go | 10 -- libs/fileset/fileset.go | 5 - libs/git/fileset.go | 8 -- libs/log/logger.go | 18 --- libs/process/opts.go | 18 --- libs/structs/structpath/path.go | 9 -- libs/testdiff/golden.go | 50 ------- 24 files changed, 561 deletions(-) delete mode 100644 internal/testcli/golden.go delete mode 100644 libs/dyn/dynassert/dump.go diff --git a/bundle/internal/schema/main_test.go b/bundle/internal/schema/main_test.go index 1b655d2e16..57287ada17 100644 --- a/bundle/internal/schema/main_test.go +++ b/bundle/internal/schema/main_test.go @@ -125,25 +125,3 @@ func getAnnotations(path string) (annotation.File, error) { return data, err } -func DisabledTestNoDuplicatedAnnotations(t *testing.T) { - // Check for duplicated annotations in annotation files - files := []string{ - "annotations_openapi_overrides.yml", - "annotations.yml", - } - - annotations := map[string]string{} - for _, file := range files { - annotationsFile, err := getAnnotations(file) - assert.NoError(t, err) - for typ, props := range annotationsFile { - for prop := range props { - key := typ + "_" + prop - if prevFile, ok := annotations[key]; ok { - t.Errorf("Annotation `%s` is duplicated in %s and %s", key, prevFile, file) - } - annotations[key] = file - } - } - } -} diff --git a/bundle/internal/tf/schema/data_sources.go b/bundle/internal/tf/schema/data_sources.go index 0aecdaed4e..8e989f0058 100644 --- a/bundle/internal/tf/schema/data_sources.go +++ b/bundle/internal/tf/schema/data_sources.go @@ -135,139 +135,3 @@ type DataSources struct { WorkspaceSettingV2 map[string]any `json:"databricks_workspace_setting_v2,omitempty"` Zones map[string]any `json:"databricks_zones,omitempty"` } - -func NewDataSources() *DataSources { - return &DataSources{ - AccountFederationPolicies: make(map[string]any), - AccountFederationPolicy: make(map[string]any), - AccountNetworkPolicies: make(map[string]any), - AccountNetworkPolicy: make(map[string]any), - AccountSettingUserPreferenceV2: make(map[string]any), - AccountSettingV2: make(map[string]any), - AlertV2: make(map[string]any), - AlertsV2: make(map[string]any), - App: make(map[string]any), - AppSpace: make(map[string]any), - AppSpaces: make(map[string]any), - Apps: make(map[string]any), - AppsSettingsCustomTemplate: make(map[string]any), - AppsSettingsCustomTemplates: make(map[string]any), - AwsAssumeRolePolicy: make(map[string]any), - AwsBucketPolicy: make(map[string]any), - AwsCrossaccountPolicy: make(map[string]any), - AwsUnityCatalogAssumeRolePolicy: make(map[string]any), - AwsUnityCatalogPolicy: make(map[string]any), - BudgetPolicies: make(map[string]any), - BudgetPolicy: make(map[string]any), - Catalog: make(map[string]any), - Catalogs: make(map[string]any), - Cluster: make(map[string]any), - ClusterPolicy: make(map[string]any), - Clusters: make(map[string]any), - CurrentConfig: make(map[string]any), - CurrentMetastore: make(map[string]any), - CurrentUser: make(map[string]any), - Dashboards: make(map[string]any), - DataClassificationCatalogConfig: make(map[string]any), - DataQualityMonitor: make(map[string]any), - DataQualityMonitors: make(map[string]any), - DataQualityRefresh: make(map[string]any), - DataQualityRefreshes: make(map[string]any), - DatabaseDatabaseCatalog: make(map[string]any), - DatabaseDatabaseCatalogs: make(map[string]any), - DatabaseInstance: make(map[string]any), - DatabaseInstances: make(map[string]any), - DatabaseSyncedDatabaseTable: make(map[string]any), - DatabaseSyncedDatabaseTables: make(map[string]any), - DbfsFile: make(map[string]any), - DbfsFilePaths: make(map[string]any), - Directory: make(map[string]any), - Endpoint: make(map[string]any), - Endpoints: make(map[string]any), - EntityTagAssignment: make(map[string]any), - EntityTagAssignments: make(map[string]any), - ExternalLocation: make(map[string]any), - ExternalLocations: make(map[string]any), - ExternalMetadata: make(map[string]any), - ExternalMetadatas: make(map[string]any), - FeatureEngineeringFeature: make(map[string]any), - FeatureEngineeringFeatures: make(map[string]any), - FeatureEngineeringKafkaConfig: make(map[string]any), - FeatureEngineeringKafkaConfigs: make(map[string]any), - FeatureEngineeringMaterializedFeature: make(map[string]any), - FeatureEngineeringMaterializedFeatures: make(map[string]any), - Functions: make(map[string]any), - Group: make(map[string]any), - InstancePool: make(map[string]any), - InstanceProfiles: make(map[string]any), - Job: make(map[string]any), - Jobs: make(map[string]any), - KnowledgeAssistant: make(map[string]any), - KnowledgeAssistantKnowledgeSource: make(map[string]any), - KnowledgeAssistantKnowledgeSources: make(map[string]any), - KnowledgeAssistants: make(map[string]any), - MaterializedFeaturesFeatureTag: make(map[string]any), - MaterializedFeaturesFeatureTags: make(map[string]any), - Metastore: make(map[string]any), - Metastores: make(map[string]any), - MlflowExperiment: make(map[string]any), - MlflowModel: make(map[string]any), - MlflowModels: make(map[string]any), - MwsCredentials: make(map[string]any), - MwsNetworkConnectivityConfig: make(map[string]any), - MwsNetworkConnectivityConfigs: make(map[string]any), - MwsWorkspaces: make(map[string]any), - NodeType: make(map[string]any), - Notebook: make(map[string]any), - NotebookPaths: make(map[string]any), - NotificationDestinations: make(map[string]any), - OnlineStore: make(map[string]any), - OnlineStores: make(map[string]any), - Pipelines: make(map[string]any), - PolicyInfo: make(map[string]any), - PolicyInfos: make(map[string]any), - PostgresBranch: make(map[string]any), - PostgresBranches: make(map[string]any), - PostgresDatabase: make(map[string]any), - PostgresDatabases: make(map[string]any), - PostgresEndpoint: make(map[string]any), - PostgresEndpoints: make(map[string]any), - PostgresProject: make(map[string]any), - PostgresProjects: make(map[string]any), - QualityMonitorV2: make(map[string]any), - QualityMonitorsV2: make(map[string]any), - RegisteredModel: make(map[string]any), - RegisteredModelVersions: make(map[string]any), - RfaAccessRequestDestinations: make(map[string]any), - Schema: make(map[string]any), - Schemas: make(map[string]any), - ServicePrincipal: make(map[string]any), - ServicePrincipalFederationPolicies: make(map[string]any), - ServicePrincipalFederationPolicy: make(map[string]any), - ServicePrincipals: make(map[string]any), - ServingEndpoints: make(map[string]any), - Share: make(map[string]any), - Shares: make(map[string]any), - SparkVersion: make(map[string]any), - SqlWarehouse: make(map[string]any), - SqlWarehouses: make(map[string]any), - StorageCredential: make(map[string]any), - StorageCredentials: make(map[string]any), - Table: make(map[string]any), - Tables: make(map[string]any), - TagPolicies: make(map[string]any), - TagPolicy: make(map[string]any), - User: make(map[string]any), - Users: make(map[string]any), - Views: make(map[string]any), - Volume: make(map[string]any), - Volumes: make(map[string]any), - WarehousesDefaultWarehouseOverride: make(map[string]any), - WarehousesDefaultWarehouseOverrides: make(map[string]any), - WorkspaceEntityTagAssignment: make(map[string]any), - WorkspaceEntityTagAssignments: make(map[string]any), - WorkspaceNetworkOption: make(map[string]any), - WorkspaceSettingV2: make(map[string]any), - Zones: make(map[string]any), - } -} diff --git a/bundle/libraries/upload.go b/bundle/libraries/upload.go index cb3ff2faf0..b292fe43b7 100644 --- a/bundle/libraries/upload.go +++ b/bundle/libraries/upload.go @@ -30,13 +30,6 @@ func Upload(libs map[string][]LocationToUpdate) bundle.Mutator { } } -func UploadWithClient(libs map[string][]LocationToUpdate, client filer.Filer) bundle.Mutator { - return &upload{ - libs: libs, - client: client, - } -} - type upload struct { client filer.Filer libs map[string][]LocationToUpdate diff --git a/cmd/bundle/utils/utils.go b/cmd/bundle/utils/utils.go index a7568b8f6e..7157139fc1 100644 --- a/cmd/bundle/utils/utils.go +++ b/cmd/bundle/utils/utils.go @@ -4,10 +4,6 @@ import ( "context" "github.com/databricks/cli/bundle" - bundleenv "github.com/databricks/cli/bundle/env" - "github.com/databricks/cli/bundle/phases" - "github.com/databricks/cli/libs/diag" - "github.com/databricks/cli/libs/env" "github.com/databricks/cli/libs/logdiag" "github.com/spf13/cobra" ) @@ -21,84 +17,3 @@ func configureVariables(cmd *cobra.Command, b *bundle.Bundle, variables []string }) } -// getTargetFromCmd returns the target name from command flags or environment. -func getTargetFromCmd(cmd *cobra.Command) string { - // Check command line flag first - if flag := cmd.Flag("target"); flag != nil { - if value := flag.Value.String(); value != "" { - return value - } - } - - // Check deprecated environment flag - if flag := cmd.Flag("environment"); flag != nil { - if value := flag.Value.String(); value != "" { - return value - } - } - - // Fall back to environment variable - target, _ := bundleenv.Target(cmd.Context()) - return target -} - -// ReloadBundle reloads the bundle configuration without modifying the command context. -// This is useful when you need to refresh the bundle configuration after changes -// without side effects like setting values on the context. -func ReloadBundle(cmd *cobra.Command) *bundle.Bundle { - ctx := cmd.Context() - - // Load the bundle configuration fresh from the filesystem - b := bundle.MustLoad(ctx) - if b == nil || logdiag.HasError(ctx) { - return b - } - - // Load the target configuration - if target := getTargetFromCmd(cmd); target == "" { - phases.LoadDefaultTarget(ctx, b) - } else { - phases.LoadNamedTarget(ctx, b, target) - } - - if logdiag.HasError(ctx) { - return b - } - - // Configure the workspace profile if provided - configureProfile(cmd, b) - - // Configure variables if provided - variables, err := cmd.Flags().GetStringSlice("var") - if err != nil { - logdiag.LogDiag(ctx, diag.FromErr(err)[0]) - return b - } - configureVariables(cmd, b, variables) - return b -} - -// configureProfile applies the profile flag to the bundle. -func configureProfile(cmd *cobra.Command, b *bundle.Bundle) { - profile := getProfileFromCmd(cmd) - if profile == "" { - return - } - - bundle.ApplyFuncContext(cmd.Context(), b, func(ctx context.Context, b *bundle.Bundle) { - b.Config.Workspace.Profile = profile - }) -} - -// getProfileFromCmd returns the profile from command flags or environment. -func getProfileFromCmd(cmd *cobra.Command) string { - // Check command line flag first - if flag := cmd.Flag("profile"); flag != nil { - if value := flag.Value.String(); value != "" { - return value - } - } - - // Fall back to environment variable - return env.Get(cmd.Context(), "DATABRICKS_CONFIG_PROFILE") -} diff --git a/experimental/aitools/lib/installer/installer.go b/experimental/aitools/lib/installer/installer.go index 912e895743..71fc59ebb8 100644 --- a/experimental/aitools/lib/installer/installer.go +++ b/experimental/aitools/lib/installer/installer.go @@ -67,14 +67,6 @@ type InstallOptions struct { Scope string // ScopeGlobal or ScopeProject (default: global) } -// FetchManifest fetches the skills manifest from the skills repo. -// This is a convenience wrapper that uses the default GitHubManifestSource. -func FetchManifest(ctx context.Context) (*Manifest, error) { - src := &GitHubManifestSource{} - ref := GetSkillsRef(ctx) - return src.FetchManifest(ctx, ref) -} - func fetchSkillFile(ctx context.Context, ref, skillName, filePath string) ([]byte, error) { url := fmt.Sprintf("https://raw.githubusercontent.com/%s/%s/%s/%s/%s/%s", skillsRepoOwner, skillsRepoName, ref, skillsRepoPath, skillName, filePath) @@ -303,19 +295,6 @@ func InstallAllSkills(ctx context.Context) error { return InstallSkillsForAgents(ctx, src, installed, InstallOptions{}) } -// InstallSkill installs a single skill by name for all detected agents. -func InstallSkill(ctx context.Context, skillName string) error { - installed := agents.DetectInstalled(ctx) - if len(installed) == 0 { - printNoAgentsDetected(ctx) - return nil - } - - PrintInstallingFor(ctx, installed) - src := &GitHubManifestSource{} - return InstallSkillsForAgents(ctx, src, installed, InstallOptions{SpecificSkills: []string{skillName}}) -} - // PrintInstallingFor prints the "Installing..." header with agent names. func PrintInstallingFor(ctx context.Context, targetAgents []*agents.Agent) { names := make([]string, len(targetAgents)) diff --git a/experimental/ssh/internal/keys/secrets.go b/experimental/ssh/internal/keys/secrets.go index d4e00d10ba..030eeddae7 100644 --- a/experimental/ssh/internal/keys/secrets.go +++ b/experimental/ssh/internal/keys/secrets.go @@ -68,16 +68,3 @@ func putSecret(ctx context.Context, client *databricks.WorkspaceClient, scope, k return nil } -// PutSecretInScope creates the secret scope if needed and stores the secret. -// sessionID is the unique identifier for the session (cluster ID for dedicated clusters, connection name for serverless). -func PutSecretInScope(ctx context.Context, client *databricks.WorkspaceClient, sessionID, key, value string) (string, error) { - scopeName, err := CreateKeysSecretScope(ctx, client, sessionID) - if err != nil { - return "", err - } - err = putSecret(ctx, client, scopeName, key, value) - if err != nil { - return "", err - } - return scopeName, nil -} diff --git a/internal/testcli/golden.go b/internal/testcli/golden.go deleted file mode 100644 index eca4c1390b..0000000000 --- a/internal/testcli/golden.go +++ /dev/null @@ -1,24 +0,0 @@ -package testcli - -import ( - "context" - "fmt" - - "github.com/databricks/cli/internal/testutil" - "github.com/databricks/cli/libs/testdiff" - "github.com/stretchr/testify/assert" -) - -func captureOutput(t testutil.TestingT, ctx context.Context, args []string) string { - t.Helper() - r := NewRunner(t, ctx, args...) - stdout, stderr, err := r.Run() - assert.NoError(t, err) - return stderr.String() + stdout.String() -} - -func AssertOutput(t testutil.TestingT, ctx context.Context, args []string, expectedPath string) { - t.Helper() - out := captureOutput(t, ctx, args) - testdiff.AssertOutput(t, ctx, out, fmt.Sprintf("Output from %v", args), expectedPath) -} diff --git a/internal/testutil/helpers.go b/internal/testutil/helpers.go index f5afb51fd5..21dfaecfd8 100644 --- a/internal/testutil/helpers.go +++ b/internal/testutil/helpers.go @@ -26,6 +26,3 @@ func RandomName(prefix ...string) string { return out } -func ReplaceWindowsLineEndings(s string) string { - return strings.ReplaceAll(s, "\r\n", "\n") -} diff --git a/libs/apps/prompt/listers.go b/libs/apps/prompt/listers.go index 2757539479..5052744eb5 100644 --- a/libs/apps/prompt/listers.go +++ b/libs/apps/prompt/listers.go @@ -88,28 +88,6 @@ func ListSecretKeys(ctx context.Context, scope string) ([]ListItem, error) { return out, nil } -// ListSQLWarehousesItems returns SQL warehouses as ListItems (reuses same API as ListSQLWarehouses). -func ListSQLWarehousesItems(ctx context.Context) ([]ListItem, error) { - w, err := workspaceClient(ctx) - if err != nil { - return nil, err - } - iter := w.Warehouses.List(ctx, sql.ListWarehousesRequest{}) - whs, err := listing.ToSlice(ctx, iter) - if err != nil { - return nil, err - } - out := make([]ListItem, 0, min(len(whs), maxListResults)) - for _, wh := range whs { - label := wh.Name - if wh.State != "" { - label = fmt.Sprintf("%s (%s)", wh.Name, wh.State) - } - out = append(out, ListItem{ID: wh.Id, Label: label}) - } - return capResults(out), nil -} - // ListSchemas returns UC schemas within a catalog as selectable items. func ListSchemas(ctx context.Context, catalogName string) ([]ListItem, error) { w, err := workspaceClient(ctx) diff --git a/libs/apps/prompt/prompt.go b/libs/apps/prompt/prompt.go index 4a32c2e861..1b10f15024 100644 --- a/libs/apps/prompt/prompt.go +++ b/libs/apps/prompt/prompt.go @@ -467,20 +467,6 @@ func promptForPagedResource(ctx context.Context, r manifest.Resource, required b return singleValueResult(r, value), nil } -// PromptForWarehouse shows a picker to select a SQL warehouse. -func PromptForWarehouse(ctx context.Context) (string, error) { - var items []ListItem - err := RunWithSpinnerCtx(ctx, "Fetching SQL warehouses...", func() error { - var fetchErr error - items, fetchErr = ListSQLWarehousesItems(ctx) - return fetchErr - }) - if err != nil { - return "", fmt.Errorf("failed to fetch SQL warehouses: %w", err) - } - return PromptFromList(ctx, "Select SQL Warehouse", "no SQL warehouses found. Create one in your workspace first", items, true) -} - // resourceTitle returns a prompt title for a resource, including the plugin name // for context when available (e.g. "Select SQL Warehouse for Analytics"). func resourceTitle(fallback string, r manifest.Resource) string { diff --git a/libs/calladapt/validate_test.go b/libs/calladapt/validate_test.go index e26466d20c..6a75512010 100644 --- a/libs/calladapt/validate_test.go +++ b/libs/calladapt/validate_test.go @@ -16,13 +16,11 @@ type testIface interface { type partialType struct{} func (*partialType) Foo() {} -func (*partialType) baz() {} //nolint:unused type goodType struct{} func (*goodType) Foo() {} func (*goodType) Bar() {} -func (*goodType) baz() {} //nolint:unused type badType struct{} diff --git a/libs/cmdio/io.go b/libs/cmdio/io.go index d54840d0f0..5477cd3512 100644 --- a/libs/cmdio/io.go +++ b/libs/cmdio/io.go @@ -53,11 +53,6 @@ func NewIO(ctx context.Context, outputFormat flags.Output, in io.Reader, out, er } } -func IsInteractive(ctx context.Context) bool { - c := fromContext(ctx) - return c.capabilities.SupportsInteractive() -} - func IsPromptSupported(ctx context.Context) bool { c := fromContext(ctx) return c.capabilities.SupportsPrompt() diff --git a/libs/cmdio/render.go b/libs/cmdio/render.go index c344c3d028..35f365277b 100644 --- a/libs/cmdio/render.go +++ b/libs/cmdio/render.go @@ -276,16 +276,6 @@ func RenderWithTemplate(ctx context.Context, v any, headerTemplate, template str return renderWithTemplate(ctx, newRenderer(v), c.outputFormat, c.out, headerTemplate, template) } -func RenderIteratorWithTemplate[T any](ctx context.Context, i listing.Iterator[T], headerTemplate, template string) error { - c := fromContext(ctx) - return renderWithTemplate(ctx, newIteratorRenderer(i), c.outputFormat, c.out, headerTemplate, template) -} - -func RenderIteratorJson[T any](ctx context.Context, i listing.Iterator[T]) error { - c := fromContext(ctx) - return renderWithTemplate(ctx, newIteratorRenderer(i), c.outputFormat, c.out, c.headerTemplate, c.template) -} - var renderFuncMap = template.FuncMap{ // we render colored output if stdout is TTY, otherwise we render text. // in the future we'll check if we can explicitly check for stderr being diff --git a/libs/dagrun/dagrun.go b/libs/dagrun/dagrun.go index 0ccefaa289..de2fa44b8e 100644 --- a/libs/dagrun/dagrun.go +++ b/libs/dagrun/dagrun.go @@ -23,8 +23,6 @@ func NewGraph() *Graph { } } -func (g *Graph) Size() int { return len(g.Nodes) } - func (g *Graph) AddNode(n string) { if _, ok := g.Adj[n]; !ok { g.Adj[n] = nil @@ -32,8 +30,6 @@ func (g *Graph) AddNode(n string) { } } -func (g *Graph) HasNode(n string) bool { _, ok := g.Adj[n]; return ok } - func (g *Graph) AddDirectedEdge(from, to, label string) { g.AddNode(from) g.AddNode(to) diff --git a/libs/databrickscfg/profile/context.go b/libs/databrickscfg/profile/context.go index fa4d2ad8ac..910e787669 100644 --- a/libs/databrickscfg/profile/context.go +++ b/libs/databrickscfg/profile/context.go @@ -4,10 +4,6 @@ import "context" var profiler int -func WithProfiler(ctx context.Context, p Profiler) context.Context { - return context.WithValue(ctx, &profiler, p) -} - func GetProfiler(ctx context.Context) Profiler { p, ok := ctx.Value(&profiler).(Profiler) if !ok { diff --git a/libs/dyn/dynassert/dump.go b/libs/dyn/dynassert/dump.go deleted file mode 100644 index 82b2c2b970..0000000000 --- a/libs/dyn/dynassert/dump.go +++ /dev/null @@ -1,60 +0,0 @@ -package dynassert - -import ( - "fmt" - "strings" - - "github.com/databricks/cli/libs/dyn" -) - -// Dump returns the Go code to recreate the given value. -func Dump(v dyn.Value) string { - var sb strings.Builder - dump(v, &sb) - return sb.String() -} - -func dump(v dyn.Value, sb *strings.Builder) { - sb.WriteString("dyn.NewValue(\n") - - switch v.Kind() { - case dyn.KindMap: - sb.WriteString("map[string]dyn.Value{") - m := v.MustMap() - for _, p := range m.Pairs() { - fmt.Fprintf(sb, "\n%q: ", p.Key.MustString()) - dump(p.Value, sb) - sb.WriteByte(',') - } - sb.WriteString("\n},\n") - case dyn.KindSequence: - sb.WriteString("[]dyn.Value{\n") - for _, e := range v.MustSequence() { - dump(e, sb) - sb.WriteByte(',') - } - sb.WriteString("},\n") - case dyn.KindString: - fmt.Fprintf(sb, "%q,\n", v.MustString()) - case dyn.KindBool: - fmt.Fprintf(sb, "%t,\n", v.MustBool()) - case dyn.KindInt: - fmt.Fprintf(sb, "%d,\n", v.MustInt()) - case dyn.KindFloat: - fmt.Fprintf(sb, "%f,\n", v.MustFloat()) - case dyn.KindTime: - fmt.Fprintf(sb, "dyn.NewTime(%q),\n", v.MustTime().String()) - case dyn.KindNil: - sb.WriteString("nil,\n") - default: - panic(fmt.Sprintf("unhandled kind: %v", v.Kind())) - } - - // Add location - sb.WriteString("[]dyn.Location{") - for _, l := range v.Locations() { - fmt.Fprintf(sb, "{File: %q, Line: %d, Column: %d},", l.File, l.Line, l.Column) - } - sb.WriteString("},\n") - sb.WriteString(")") -} diff --git a/libs/dyn/pattern.go b/libs/dyn/pattern.go index 2a15d12cc3..4aefb01542 100644 --- a/libs/dyn/pattern.go +++ b/libs/dyn/pattern.go @@ -1,7 +1,6 @@ package dyn import ( - "errors" "fmt" "slices" "strings" @@ -108,11 +107,6 @@ func (e expectedMapError) Error() string { return fmt.Sprintf("expected a map at %q, found %s", e.p, e.v.Kind()) } -func IsExpectedMapError(err error) bool { - var target expectedMapError - return errors.As(err, &target) -} - type expectedSequenceError struct { p Path v Value @@ -122,11 +116,6 @@ func (e expectedSequenceError) Error() string { return fmt.Sprintf("expected a sequence at %q, found %s", e.p, e.v.Kind()) } -func IsExpectedSequenceError(err error) bool { - var target expectedSequenceError - return errors.As(err, &target) -} - // This function implements the patternComponent interface. func (c anyKeyComponent) visit(v Value, prefix Path, suffix Pattern, opts visitOptions) (Value, error) { m, ok := v.AsMap() diff --git a/libs/dyn/visit.go b/libs/dyn/visit.go index 15ea0af5c7..1822c7db65 100644 --- a/libs/dyn/visit.go +++ b/libs/dyn/visit.go @@ -63,11 +63,6 @@ func (e expectedMapToIndexError) Error() string { return fmt.Sprintf("expected a map to index %q, found %s", e.p, e.v.Kind()) } -func IsExpectedMapToIndexError(err error) bool { - var target expectedMapToIndexError - return errors.As(err, &target) -} - type expectedSequenceToIndexError struct { p Path v Value @@ -77,11 +72,6 @@ func (e expectedSequenceToIndexError) Error() string { return fmt.Sprintf("expected a sequence to index %q, found %s", e.p, e.v.Kind()) } -func IsExpectedSequenceToIndexError(err error) bool { - var target expectedSequenceToIndexError - return errors.As(err, &target) -} - type visitOptions struct { // The function to apply to the value once found. // diff --git a/libs/fileset/fileset.go b/libs/fileset/fileset.go index 26ae2e8600..ec9dcdeb79 100644 --- a/libs/fileset/fileset.go +++ b/libs/fileset/fileset.go @@ -61,11 +61,6 @@ func Empty() *FileSet { return &FileSet{} } -// Ignorer returns the [FileSet]'s current ignorer. -func (w *FileSet) Ignorer() Ignorer { - return w.ignore -} - // SetIgnorer sets the [Ignorer] interface for this [FileSet]. func (w *FileSet) SetIgnorer(ignore Ignorer) { w.ignore = ignore diff --git a/libs/git/fileset.go b/libs/git/fileset.go index e6c6518931..da2a6cec78 100644 --- a/libs/git/fileset.go +++ b/libs/git/fileset.go @@ -33,14 +33,6 @@ func NewFileSetAtRoot(ctx context.Context, root vfs.Path, paths ...[]string) (*F return NewFileSet(ctx, root, root, paths...) } -func (f *FileSet) IgnoreFile(file string) (bool, error) { - return f.view.IgnoreFile(file) -} - -func (f *FileSet) IgnoreDirectory(dir string) (bool, error) { - return f.view.IgnoreDirectory(dir) -} - func (f *FileSet) Files() ([]fileset.File, error) { f.view.repo.taintIgnoreRules() return f.fileset.Files() diff --git a/libs/log/logger.go b/libs/log/logger.go index d77232f6c5..74347b1ab1 100644 --- a/libs/log/logger.go +++ b/libs/log/logger.go @@ -27,15 +27,6 @@ func log(ctx context.Context, logger *slog.Logger, level slog.Level, msg string) _ = logger.Handler().Handle(ctx, r) } -// Trace logs a string using the context-local or global logger. -func Trace(ctx context.Context, msg string) { - logger := GetLogger(ctx) - if !logger.Enabled(ctx, LevelTrace) { - return - } - log(ctx, logger, LevelTrace, msg) -} - // Debug logs a string using the context-local or global logger. func Debug(ctx context.Context, msg string) { logger := GetLogger(ctx) @@ -63,15 +54,6 @@ func Warn(ctx context.Context, msg string) { log(ctx, logger, LevelWarn, msg) } -// Error logs a string using the context-local or global logger. -func Error(ctx context.Context, msg string) { - logger := GetLogger(ctx) - if !logger.Enabled(ctx, LevelError) { - return - } - log(ctx, logger, LevelError, msg) -} - // Tracef logs a formatted string using the context-local or global logger. func Tracef(ctx context.Context, format string, v ...any) { logger := GetLogger(ctx) diff --git a/libs/process/opts.go b/libs/process/opts.go index dd06675168..a9848cebde 100644 --- a/libs/process/opts.go +++ b/libs/process/opts.go @@ -38,24 +38,6 @@ func WithDir(dir string) execOption { } } -func WithStdoutPipe(dst *io.ReadCloser) execOption { - return func(_ context.Context, c *exec.Cmd) error { - outPipe, err := c.StdoutPipe() - if err != nil { - return err - } - *dst = outPipe - return nil - } -} - -func WithStdinReader(src io.Reader) execOption { - return func(_ context.Context, c *exec.Cmd) error { - c.Stdin = src - return nil - } -} - func WithStderrWriter(dst io.Writer) execOption { return func(_ context.Context, c *exec.Cmd) error { c.Stderr = dst diff --git a/libs/structs/structpath/path.go b/libs/structs/structpath/path.go index 90d1fdb6c6..5ae81019ee 100644 --- a/libs/structs/structpath/path.go +++ b/libs/structs/structpath/path.go @@ -637,15 +637,6 @@ func MustParsePath(s string) *PathNode { return path } -// MustParsePattern parses a pattern string and panics on error. Wildcards are allowed. -func MustParsePattern(s string) *PatternNode { - pattern, err := ParsePattern(s) - if err != nil { - panic(err) - } - return pattern -} - // isReservedFieldChar checks if character is reserved and cannot be used in field names func isReservedFieldChar(ch byte) bool { switch ch { diff --git a/libs/testdiff/golden.go b/libs/testdiff/golden.go index f49a5a24be..1e7fe99f0f 100644 --- a/libs/testdiff/golden.go +++ b/libs/testdiff/golden.go @@ -1,15 +1,8 @@ package testdiff import ( - "context" - "errors" "flag" - "io/fs" - "os" "strings" - - "github.com/databricks/cli/internal/testutil" - "github.com/stretchr/testify/assert" ) var OverwriteMode = false @@ -18,49 +11,6 @@ func init() { flag.BoolVar(&OverwriteMode, "update", false, "Overwrite golden files") } -func ReadFile(t testutil.TestingT, ctx context.Context, filename string) string { - t.Helper() - data, err := os.ReadFile(filename) - if errors.Is(err, fs.ErrNotExist) { - return "" - } - assert.NoError(t, err, "Failed to read %s", filename) - // On CI, on Windows \n in the file somehow end up as \r\n - return NormalizeNewlines(string(data)) -} - -func WriteFile(t testutil.TestingT, filename, data string) { - t.Helper() - t.Logf("Overwriting %s", filename) - err := os.WriteFile(filename, []byte(data), 0o644) - assert.NoError(t, err, "Failed to write %s", filename) -} - -func AssertOutput(t testutil.TestingT, ctx context.Context, out, outTitle, expectedPath string) { - t.Helper() - expected := ReadFile(t, ctx, expectedPath) - - out = ReplaceOutput(t, ctx, out) - - if out != expected { - AssertEqualTexts(t, expectedPath, outTitle, expected, out) - - if OverwriteMode { - WriteFile(t, expectedPath, out) - } - } -} - -func ReplaceOutput(t testutil.TestingT, ctx context.Context, out string) string { - t.Helper() - out = NormalizeNewlines(out) - replacements := GetReplacementsMap(ctx) - if replacements == nil { - t.Fatal("WithReplacementsMap was not called") - } - return replacements.Replace(out) -} - func NormalizeNewlines(input string) string { output := strings.ReplaceAll(input, "\r\n", "\n") return strings.ReplaceAll(output, "\r", "\n") From d78c1d04d64a2603986f91cbe5cb1840a2ebb99a Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 11:38:07 +0200 Subject: [PATCH 5/8] Fix trailing whitespace after dead function removal Co-authored-by: Isaac --- bundle/internal/schema/main_test.go | 1 - cmd/bundle/utils/utils.go | 1 - experimental/ssh/internal/keys/secrets.go | 1 - internal/testutil/helpers.go | 1 - 4 files changed, 4 deletions(-) diff --git a/bundle/internal/schema/main_test.go b/bundle/internal/schema/main_test.go index 57287ada17..b41094ba4d 100644 --- a/bundle/internal/schema/main_test.go +++ b/bundle/internal/schema/main_test.go @@ -124,4 +124,3 @@ func getAnnotations(path string) (annotation.File, error) { err = yaml.Unmarshal(b, &data) return data, err } - diff --git a/cmd/bundle/utils/utils.go b/cmd/bundle/utils/utils.go index 7157139fc1..3c4bd1a5b9 100644 --- a/cmd/bundle/utils/utils.go +++ b/cmd/bundle/utils/utils.go @@ -16,4 +16,3 @@ func configureVariables(cmd *cobra.Command, b *bundle.Bundle, variables []string } }) } - diff --git a/experimental/ssh/internal/keys/secrets.go b/experimental/ssh/internal/keys/secrets.go index 030eeddae7..76d44da538 100644 --- a/experimental/ssh/internal/keys/secrets.go +++ b/experimental/ssh/internal/keys/secrets.go @@ -67,4 +67,3 @@ func putSecret(ctx context.Context, client *databricks.WorkspaceClient, scope, k } return nil } - diff --git a/internal/testutil/helpers.go b/internal/testutil/helpers.go index 21dfaecfd8..b5a257e2ff 100644 --- a/internal/testutil/helpers.go +++ b/internal/testutil/helpers.go @@ -25,4 +25,3 @@ func RandomName(prefix ...string) string { out += strings.ReplaceAll(uuid.New().String(), "-", "") return out } - From e8b383624af73fd4f4164e6b161140c20e2d975e Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 11:48:55 +0200 Subject: [PATCH 6/8] Address review feedback - check_deadcode.py: fail if deadcode itself exits non-zero with no stdout (e.g. package errors), instead of silently reporting success - render.go: update panic message to reference RenderIterator (the previously referenced RenderIteratorWithTemplate was removed) - data_sources.go.tmpl: remove NewDataSources from the codegen template so it won't be reintroduced on next generate Co-authored-by: Isaac --- bundle/internal/tf/codegen/templates/data_sources.go.tmpl | 8 -------- libs/cmdio/render.go | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/bundle/internal/tf/codegen/templates/data_sources.go.tmpl b/bundle/internal/tf/codegen/templates/data_sources.go.tmpl index 9d998d4973..06726f4bd6 100644 --- a/bundle/internal/tf/codegen/templates/data_sources.go.tmpl +++ b/bundle/internal/tf/codegen/templates/data_sources.go.tmpl @@ -7,11 +7,3 @@ type DataSources struct { {{ .FieldName }} map[string]any `json:"{{ .TerraformName }},omitempty"` {{- end }} } - -func NewDataSources() *DataSources { - return &DataSources{ - {{- range .Blocks }} - {{ .FieldName }}: make(map[string]any), - {{- end }} - } -} diff --git a/libs/cmdio/render.go b/libs/cmdio/render.go index 35f365277b..2dcaab7d00 100644 --- a/libs/cmdio/render.go +++ b/libs/cmdio/render.go @@ -271,7 +271,7 @@ func RenderIterator[T any](ctx context.Context, i listing.Iterator[T]) error { func RenderWithTemplate(ctx context.Context, v any, headerTemplate, template string) error { c := fromContext(ctx) if _, ok := v.(listingInterface); ok { - panic("use RenderIteratorWithTemplate instead") + panic("use RenderIterator instead") } return renderWithTemplate(ctx, newRenderer(v), c.outputFormat, c.out, headerTemplate, template) } From 41a0d3636181bbd33aea3139e153a4facfef2689 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 11:50:39 +0200 Subject: [PATCH 7/8] Exclude generated files from deadcode, revert template change Generated files (bundle/internal/tf/schema/) should be excluded from the deadcode check rather than modifying codegen templates. This avoids circular issues where the check and the generator fight over dead code in generated files. Also adds returncode checking to check_deadcode.py so it fails properly when deadcode itself errors out. Co-authored-by: Isaac --- .../tf/codegen/templates/data_sources.go.tmpl | 8 ++++++++ tools/check_deadcode.py | 13 +++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/bundle/internal/tf/codegen/templates/data_sources.go.tmpl b/bundle/internal/tf/codegen/templates/data_sources.go.tmpl index 06726f4bd6..9d998d4973 100644 --- a/bundle/internal/tf/codegen/templates/data_sources.go.tmpl +++ b/bundle/internal/tf/codegen/templates/data_sources.go.tmpl @@ -7,3 +7,11 @@ type DataSources struct { {{ .FieldName }} map[string]any `json:"{{ .TerraformName }},omitempty"` {{- end }} } + +func NewDataSources() *DataSources { + return &DataSources{ + {{- range .Blocks }} + {{ .FieldName }}: make(map[string]any), + {{- end }} + } +} diff --git a/tools/check_deadcode.py b/tools/check_deadcode.py index 199bcc7a1d..e350c986c3 100755 --- a/tools/check_deadcode.py +++ b/tools/check_deadcode.py @@ -31,11 +31,11 @@ import subprocess import sys -# Directories to exclude entirely. Everything in these directories is a -# false positive. Each entry is matched as a prefix of the file path in -# deadcode output. +# Directories to exclude entirely. Each entry is matched as a substring +# of the file path in deadcode output. EXCLUDED_DIRS = [ - "libs/gorules/", + "libs/gorules/", # Lint rule definitions loaded by golangci-lint's ruleguard + "bundle/internal/tf/schema/", # Generated from Terraform provider schema ] ALLOW_COMMENT = "//deadcode:allow" @@ -47,6 +47,11 @@ def main(): capture_output=True, text=True, ) + if result.returncode != 0 and not result.stdout.strip(): + print("deadcode failed:\n", file=sys.stderr) + print(result.stderr, file=sys.stderr) + sys.exit(1) + output = result.stdout.strip() if not output: print("No dead code found.") From f5922c56927ec396b0e8443f5c02acc995396639 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 15 Apr 2026 12:43:02 +0200 Subject: [PATCH 8/8] Address review findings: revert generated file edit, improve suppression scanning Revert the hand-edit to bundle/internal/tf/schema/data_sources.go since that directory is already excluded from deadcode. The codegen template still emits NewDataSources(), so the removal would be undone on the next regeneration. Fix the inline suppression logic in check_deadcode.py to scan a window of up to 5 lines above the reported function line (stopping at a blank line). This handles the common case where a doc comment sits between the allow comment and the func keyword. Update the panic message in RenderWithTemplate to be more descriptive. --- bundle/internal/tf/schema/data_sources.go | 136 ++++++++++++++++++++++ libs/cmdio/render.go | 2 +- tools/check_deadcode.py | 24 +++- 3 files changed, 158 insertions(+), 4 deletions(-) diff --git a/bundle/internal/tf/schema/data_sources.go b/bundle/internal/tf/schema/data_sources.go index 8e989f0058..0aecdaed4e 100644 --- a/bundle/internal/tf/schema/data_sources.go +++ b/bundle/internal/tf/schema/data_sources.go @@ -135,3 +135,139 @@ type DataSources struct { WorkspaceSettingV2 map[string]any `json:"databricks_workspace_setting_v2,omitempty"` Zones map[string]any `json:"databricks_zones,omitempty"` } + +func NewDataSources() *DataSources { + return &DataSources{ + AccountFederationPolicies: make(map[string]any), + AccountFederationPolicy: make(map[string]any), + AccountNetworkPolicies: make(map[string]any), + AccountNetworkPolicy: make(map[string]any), + AccountSettingUserPreferenceV2: make(map[string]any), + AccountSettingV2: make(map[string]any), + AlertV2: make(map[string]any), + AlertsV2: make(map[string]any), + App: make(map[string]any), + AppSpace: make(map[string]any), + AppSpaces: make(map[string]any), + Apps: make(map[string]any), + AppsSettingsCustomTemplate: make(map[string]any), + AppsSettingsCustomTemplates: make(map[string]any), + AwsAssumeRolePolicy: make(map[string]any), + AwsBucketPolicy: make(map[string]any), + AwsCrossaccountPolicy: make(map[string]any), + AwsUnityCatalogAssumeRolePolicy: make(map[string]any), + AwsUnityCatalogPolicy: make(map[string]any), + BudgetPolicies: make(map[string]any), + BudgetPolicy: make(map[string]any), + Catalog: make(map[string]any), + Catalogs: make(map[string]any), + Cluster: make(map[string]any), + ClusterPolicy: make(map[string]any), + Clusters: make(map[string]any), + CurrentConfig: make(map[string]any), + CurrentMetastore: make(map[string]any), + CurrentUser: make(map[string]any), + Dashboards: make(map[string]any), + DataClassificationCatalogConfig: make(map[string]any), + DataQualityMonitor: make(map[string]any), + DataQualityMonitors: make(map[string]any), + DataQualityRefresh: make(map[string]any), + DataQualityRefreshes: make(map[string]any), + DatabaseDatabaseCatalog: make(map[string]any), + DatabaseDatabaseCatalogs: make(map[string]any), + DatabaseInstance: make(map[string]any), + DatabaseInstances: make(map[string]any), + DatabaseSyncedDatabaseTable: make(map[string]any), + DatabaseSyncedDatabaseTables: make(map[string]any), + DbfsFile: make(map[string]any), + DbfsFilePaths: make(map[string]any), + Directory: make(map[string]any), + Endpoint: make(map[string]any), + Endpoints: make(map[string]any), + EntityTagAssignment: make(map[string]any), + EntityTagAssignments: make(map[string]any), + ExternalLocation: make(map[string]any), + ExternalLocations: make(map[string]any), + ExternalMetadata: make(map[string]any), + ExternalMetadatas: make(map[string]any), + FeatureEngineeringFeature: make(map[string]any), + FeatureEngineeringFeatures: make(map[string]any), + FeatureEngineeringKafkaConfig: make(map[string]any), + FeatureEngineeringKafkaConfigs: make(map[string]any), + FeatureEngineeringMaterializedFeature: make(map[string]any), + FeatureEngineeringMaterializedFeatures: make(map[string]any), + Functions: make(map[string]any), + Group: make(map[string]any), + InstancePool: make(map[string]any), + InstanceProfiles: make(map[string]any), + Job: make(map[string]any), + Jobs: make(map[string]any), + KnowledgeAssistant: make(map[string]any), + KnowledgeAssistantKnowledgeSource: make(map[string]any), + KnowledgeAssistantKnowledgeSources: make(map[string]any), + KnowledgeAssistants: make(map[string]any), + MaterializedFeaturesFeatureTag: make(map[string]any), + MaterializedFeaturesFeatureTags: make(map[string]any), + Metastore: make(map[string]any), + Metastores: make(map[string]any), + MlflowExperiment: make(map[string]any), + MlflowModel: make(map[string]any), + MlflowModels: make(map[string]any), + MwsCredentials: make(map[string]any), + MwsNetworkConnectivityConfig: make(map[string]any), + MwsNetworkConnectivityConfigs: make(map[string]any), + MwsWorkspaces: make(map[string]any), + NodeType: make(map[string]any), + Notebook: make(map[string]any), + NotebookPaths: make(map[string]any), + NotificationDestinations: make(map[string]any), + OnlineStore: make(map[string]any), + OnlineStores: make(map[string]any), + Pipelines: make(map[string]any), + PolicyInfo: make(map[string]any), + PolicyInfos: make(map[string]any), + PostgresBranch: make(map[string]any), + PostgresBranches: make(map[string]any), + PostgresDatabase: make(map[string]any), + PostgresDatabases: make(map[string]any), + PostgresEndpoint: make(map[string]any), + PostgresEndpoints: make(map[string]any), + PostgresProject: make(map[string]any), + PostgresProjects: make(map[string]any), + QualityMonitorV2: make(map[string]any), + QualityMonitorsV2: make(map[string]any), + RegisteredModel: make(map[string]any), + RegisteredModelVersions: make(map[string]any), + RfaAccessRequestDestinations: make(map[string]any), + Schema: make(map[string]any), + Schemas: make(map[string]any), + ServicePrincipal: make(map[string]any), + ServicePrincipalFederationPolicies: make(map[string]any), + ServicePrincipalFederationPolicy: make(map[string]any), + ServicePrincipals: make(map[string]any), + ServingEndpoints: make(map[string]any), + Share: make(map[string]any), + Shares: make(map[string]any), + SparkVersion: make(map[string]any), + SqlWarehouse: make(map[string]any), + SqlWarehouses: make(map[string]any), + StorageCredential: make(map[string]any), + StorageCredentials: make(map[string]any), + Table: make(map[string]any), + Tables: make(map[string]any), + TagPolicies: make(map[string]any), + TagPolicy: make(map[string]any), + User: make(map[string]any), + Users: make(map[string]any), + Views: make(map[string]any), + Volume: make(map[string]any), + Volumes: make(map[string]any), + WarehousesDefaultWarehouseOverride: make(map[string]any), + WarehousesDefaultWarehouseOverrides: make(map[string]any), + WorkspaceEntityTagAssignment: make(map[string]any), + WorkspaceEntityTagAssignments: make(map[string]any), + WorkspaceNetworkOption: make(map[string]any), + WorkspaceSettingV2: make(map[string]any), + Zones: make(map[string]any), + } +} diff --git a/libs/cmdio/render.go b/libs/cmdio/render.go index 2dcaab7d00..d1c81eabed 100644 --- a/libs/cmdio/render.go +++ b/libs/cmdio/render.go @@ -271,7 +271,7 @@ func RenderIterator[T any](ctx context.Context, i listing.Iterator[T]) error { func RenderWithTemplate(ctx context.Context, v any, headerTemplate, template string) error { c := fromContext(ctx) if _, ok := v.(listingInterface); ok { - panic("use RenderIterator instead") + panic("listings must use RenderIterator, not RenderWithTemplate") } return renderWithTemplate(ctx, newRenderer(v), c.outputFormat, c.out, headerTemplate, template) } diff --git a/tools/check_deadcode.py b/tools/check_deadcode.py index e350c986c3..0cc97c8599 100755 --- a/tools/check_deadcode.py +++ b/tools/check_deadcode.py @@ -19,14 +19,20 @@ through Go's call graph. 2. Inline comments: - Add "//deadcode:allow " on the line directly above a function - to suppress a specific finding. Example: + Add "//deadcode:allow " above a function to suppress a + specific finding. The comment can appear on the line directly above + the func keyword, or above a doc comment block. The script scans + up to 5 lines above the reported line, stopping at a blank line. + + Example: //deadcode:allow loaded by golangci-lint ruleguard, not via Go imports + // ProcessRule applies a lint rule. func MyLintRule(m dsl.Matcher) { This matches the //nolint: pattern Go developers already know. """ + import re import subprocess import sys @@ -75,7 +81,19 @@ def main(): try: with open(filepath) as f: file_lines = f.readlines() - if lineno >= 2 and ALLOW_COMMENT in file_lines[lineno - 2]: + # Scan up to 5 lines above the reported line, stopping at a + # blank line. This handles doc comments between the allow + # comment and the func keyword. + suppressed = False + start = max(0, lineno - 6) + for check_line in file_lines[start : lineno - 1]: + stripped = check_line.strip() + if not stripped: + break + if ALLOW_COMMENT in stripped: + suppressed = True + break + if suppressed: continue except (OSError, IndexError): pass