chore(ci): add deadcode tooling to catch exported orphan funcs#2127
Open
schnie wants to merge 2 commits into
Open
chore(ci): add deadcode tooling to catch exported orphan funcs#2127schnie wants to merge 2 commits into
schnie wants to merge 2 commits into
Conversation
Pre-cleanup so the deadcode tool (added in the next commit) starts with a zero baseline. - `astro-client-core/client.test.go` and `astro-client-iam-core/client.test.go` were named `.test.go` instead of `_test.go`, so Go's test infrastructure silently never picked them up. Their `TestNewCoreClient` / `TestNewIamCoreClient` functions have been dead since they were introduced (PRs #873 and #1444). Renaming surfaces the tests; both pass. - `cmd/api/describe_test.go` had an unused `strPtr` helper. - `houston/suite_test.go` defined `SetupSuite` as a free function; testify's suite framework only invokes it via the `SetupAllSuite` interface, i.e. as a method on `*Suite`. Convert to a method so the test config actually initializes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a whole-program dead-function check using `golang.org/x/tools/cmd/deadcode` to catch exported orphan funcs that `golangci-lint`'s in-package `unused` analyzer cannot. This is the analogue of astro-desktop's setup. How it's wired: - `scripts/check-deadcode.sh` runs `deadcode -test` and fails on any finding within the cli's binary-style directories (`cmd/`, `airflow/`, `cloud/`, `software/`, `config/`, `settings/`, `houston/`, etc.). Library sub-modules (`pkg/airflowrt`, `pkg/proxy`, `pkg/astroauth`, `pkg/telemetry`, `astro-client-platform-core`) and the rest of `pkg/` are excluded because they are consumed by external Go modules (e.g. astro-desktop) — reachability from `cmd/astro/main` is not a correctness signal for them. - `prek.toml` gains a `deadcode` hook that pins `golang.org/x/tools/cmd/deadcode@v0.27.0` and runs the script. - `make lint` now runs `make lint-go` (golangci-lint) + `make lint-deadcode` (the new hook). CircleCI's `lint` job runs both as separate steps for clearer logs. - `CONTRIBUTING.md` documents the layers and scope. Baseline is zero — the previous commit cleaned up the four pre-existing dead test funcs the tool surfaced. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Coverage Report for CI Build 0Coverage increased (+0.1%) to 39.845%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
jlaneve
approved these changes
May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a whole-program dead-function check using
golang.org/x/tools/cmd/deadcodeso that exported orphan funcs are caught in CI, matching the pattern astro-desktop uses. Motivation: the recent #2126 incident showed that exported package-level identifiers can sit dead for years withoutgolangci-lint's in-packageunusedanalyzer noticing —airflow.Af2Gitignorewas effectively a no-op because nothing imported it.deadcodeis whole-program: it loads the cli starting fromcmd/astro/mainand reports any function that is unreachable. With-test, it also includes test executables, which avoids false positives on helpers that are only reached from tests.How it's wired
scripts/check-deadcode.sh— runsdeadcode -test ./...and fails on any finding inside the cli's binary-style directories. The wrapper exists becausedeadcodeitself exits 0 even when it finds dead code, so we need to gate on its output.prek.toml— a newdeadcodehook, in line with the existinggofumptandgolangci-linthooks. Pinsgolang.org/x/tools/cmd/deadcode@v0.27.0viaadditional_dependencies.Makefile—make lintnow runsmake lint-go(golangci-lint) followed bymake lint-deadcode. Each target wraps the corresponding prek hook so contributors can run them individually..circleci/config.yml— thelintjob now runs golangci-lint and deadcode as two separate steps for clearer CI logs.CONTRIBUTING.md— documents the layers and the scope decision.Scope decision
deadcodeenforcement is restricted to the cli's binary-style directories:cmd/,airflow/,cloud/,software/,config/,settings/,context/,houston/,internal/,version/,airflow_versions/,airflow-client/,astro-client-core/,astro-client-iam-core/,docker/.Excluded:
pkg/airflowrt,pkg/proxy,pkg/astroauth,pkg/telemetry,astro-client-platform-core— these are independently versioned and consumed by external Go modules (astro-desktop pulls all five), so reachability fromcmd/astro/mainis not a correctness signal.pkg/*subdirectories (pkg/ansi,pkg/fileutil,pkg/util, etc.) — although they live in the cli main module, they are import-style helpers that may have external Go consumers, and treating them as binary code would risk false-positive deletions of public-API surface.The exclusion list lives in
scripts/check-deadcode.shso it's easy to adjust.Baseline
The first commit fixes the four pre-existing dead test functions the tool surfaced — none of these were intentional, all were latent bugs:
astro-client-core/client.test.goandastro-client-iam-core/client.test.gowere named.test.goinstead of_test.go, so Go silently never picked upTestNewCoreClient/TestNewIamCoreClient. Renaming surfaces the tests; both pass.cmd/api/describe_test.gohad an unusedstrPtrhelper (deleted).houston/suite_test.godefinedSetupSuiteas a free function rather than a method on*Suite, so testify'sSetupAllSuiteinterface never invoked it. Converted to a method.After the cleanup, the deadcode baseline is zero — no allowlist needed.
Test plan
make lint-deadcodepasses locally on this branchmake lint-deadcodefails when a deliberately-unreachable function is added to a scoped directory (verified locally)go test ./astro-client-core/... ./astro-client-iam-core/... ./cmd/api/... ./houston/...passes after the test renames + suite fixmake lint-goandmake lint-deadcodeas separate steps and both pass🤖 Generated with Claude Code