Skip to content

Add deadcode CI check and remove unreachable functions#4974

Open
simonfaltum wants to merge 11 commits intomainfrom
simonfaltum/deadcode-check
Open

Add deadcode CI check and remove unreachable functions#4974
simonfaltum wants to merge 11 commits intomainfrom
simonfaltum/deadcode-check

Conversation

@simonfaltum
Copy link
Copy Markdown
Member

@simonfaltum simonfaltum commented Apr 15, 2026

Why

The CLI is its own application, not a library. Nobody imports it to use random functions. Any function not reachable from main() is dead code. The existing unused linter skips exported functions by default (it assumes external consumers might use them), leaving a gap. deadcode from golang.org/x/tools does whole-program reachability analysis and catches these.

Changes

Added deadcode as a CI check via make checks. A Python wrapper script (tools/check_deadcode.py) runs deadcode -test ./... and supports two suppression mechanisms:

  1. Directory exclusions for directories where everything is a false positive (e.g. libs/gorules/, which contains lint rule definitions loaded by golangci-lint's ruleguard engine, not through Go's call graph).
  2. Inline comments (//deadcode:allow <reason>) above a function, matching the //nolint: pattern.

The wrapper is needed because raw deadcode has no suppression mechanism. It reports every unreachable function with no way to exclude known false positives (code loaded via reflection, plugin systems, or code generators). Without the wrapper, the only options would be to either accept noisy output that developers learn to ignore, or not run the check at all. The wrapper keeps the check strict (zero tolerance, CI fails on any finding) while giving developers two escape hatches for legitimate exceptions.

Both mechanisms are documented in the script itself.

Removed 41 dead functions across 24 files found in the initial run.

Test plan

  • make deadcode passes clean ("No dead code found.")
  • make checks passes (includes deadcode)
  • make lintfull passes (0 issues, no unused imports)
  • go build ./... passes
  • Unit tests pass for all affected packages

This pull request was AI-assisted by Isaac.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 15, 2026

Approval status: pending

/bundle/ - needs approval

Files: bundle/internal/schema/main_test.go, bundle/libraries/upload.go
Suggested: @denik
Also eligible: @pietern, @shreyas-goenka, @andrewnester, @anton-107, @lennartkats-db, @janniklasrose

/cmd/bundle/ - needs approval

Files: cmd/bundle/utils/utils.go
Suggested: @denik
Also eligible: @pietern, @shreyas-goenka, @andrewnester, @anton-107, @lennartkats-db, @janniklasrose

/experimental/aitools/ - needs approval

Files: experimental/aitools/lib/installer/installer.go
Suggested: @pkosiec
Also eligible: @MarioCadenas, @arsenyinfo, @lennartkats-db, @fjakobs, @jamesbroadhead, @Shridhad, @atilafassina, @keugenek, @igrekun, @pffigueiredo, @ditadi, @calvarjorge

/internal/ - needs approval

Files: internal/testcli/golden.go, internal/testutil/helpers.go
Suggested: @tanmay-db
Also eligible: @mihaimitrea-db, @renaudhartert-db, @rauchy, @hectorcast-db, @parthban-db, @Divyansh-db, @tejaskochar-db, @chrisst

/libs/apps/ - needs approval

Files: libs/apps/prompt/listers.go, libs/apps/prompt/prompt.go
Suggested: @pkosiec
Also eligible: @MarioCadenas, @arsenyinfo, @fjakobs, @jamesbroadhead, @Shridhad, @atilafassina, @keugenek, @igrekun, @pffigueiredo, @ditadi, @calvarjorge

/libs/cmdio/ - needs approval

Files: libs/cmdio/io.go, libs/cmdio/render.go
Suggested: @tanmay-db
Also eligible: @mihaimitrea-db, @renaudhartert-db, @rauchy, @hectorcast-db, @parthban-db, @Divyansh-db, @tejaskochar-db, @chrisst

/libs/databrickscfg/ - needs approval

Files: libs/databrickscfg/profile/context.go
Suggested: @tanmay-db
Also eligible: @mihaimitrea-db, @renaudhartert-db, @rauchy, @hectorcast-db, @parthban-db, @Divyansh-db, @tejaskochar-db, @chrisst

/libs/git/ - needs approval

Files: libs/git/fileset.go
Suggested: @tanmay-db
Also eligible: @mihaimitrea-db, @renaudhartert-db, @rauchy, @hectorcast-db, @parthban-db, @Divyansh-db, @tejaskochar-db, @chrisst

/libs/log/ - needs approval

Files: libs/log/logger.go
Suggested: @tanmay-db
Also eligible: @mihaimitrea-db, @renaudhartert-db, @rauchy, @hectorcast-db, @parthban-db, @Divyansh-db, @tejaskochar-db, @chrisst

/libs/process/ - needs approval

Files: libs/process/opts.go
Suggested: @tanmay-db
Also eligible: @mihaimitrea-db, @renaudhartert-db, @rauchy, @hectorcast-db, @parthban-db, @Divyansh-db, @tejaskochar-db, @chrisst

General files (require maintainer)

Files: Makefile, experimental/ssh/internal/keys/secrets.go, libs/calladapt/validate_test.go, libs/dagrun/dagrun.go, libs/dyn/dynassert/dump.go, libs/dyn/pattern.go, libs/dyn/visit.go, libs/fileset/fileset.go, libs/structs/structpath/path.go, libs/testdiff/golden.go, tools/check_deadcode.py, tools/go.mod, tools/go.sum
Based on git history:

  • @denik -- recent work in libs/structs/structpath/, ./, tools/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @renaudhartert-db) can approve all areas.
See OWNERS for ownership rules.

simonfaltum and others added 5 commits April 15, 2026 11:48
- 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
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
…ion 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.
@simonfaltum simonfaltum requested a review from pietern April 15, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant