Skip to content

[refactor] Consolidate 6 identical hasStringKey copies into a shared generic set helperΒ #40531

Description

@github-actions

πŸ”§ Semantic Function Clustering Analysis

Analysis of repository: github/gh-aw β€” non-test .go files under pkg/

Overview

A semantic clustering + duplicate sweep over 940 non-test Go files (4,405 top-level funcs, 1,233 methods) found the codebase already well-factored: nearly every same-name cross-package match is either an intentional delegating shim or a legitimate build-tag variant. One genuine duplicate stands out and is worth consolidating.

Metric Value
Non-test Go files analyzed 940
Largest packages workflow (408), cli (322), linters (81), parser (44)
Genuine cross-package duplicate found 1 (hasStringKey)
False positives correctly excluded shims + *_wasm.go build variants

Key finding: hasStringKey duplicated across 6 packages

The exact same 4-line helper is defined in 6 separate seenmapbool_helpers.go files (function bodies byte-identical; only the package line differs):

func hasStringKey(set map[string]struct{}, key string) bool {
	_, ok := set[key]
	return ok
}
Package File
constants pkg/constants/seenmapbool_helpers.go
linters/ssljson pkg/linters/ssljson/seenmapbool_helpers.go
agentdrain pkg/agentdrain/seenmapbool_helpers.go
workflow pkg/workflow/seenmapbool_helpers.go
parser pkg/parser/seenmapbool_helpers.go
cli pkg/cli/seenmapbool_helpers.go

Scale: 196 call sites across these packages (workflow ~90, cli ~50, parser ~12, plus constants/agentdrain/ssljson). The filename and the identical body indicate these were emitted by the map[string]bool β†’ map[string]struct{} migration codemod rather than hand-written.

Recommendation

Introduce a tiny dependency-free leaf util (matching the existing pkg/sliceutil / pkg/typeutil / pkg/stringutil convention) with a generic signature, then delete the 6 copies:

// pkg/setutil/setutil.go  (or add to pkg/typeutil)
package setutil

// Contains reports whether key is present in a set built as map[K]struct{}.
func Contains[K comparable](set map[K]struct{}, key K) bool {
	_, ok := set[key]
	return ok
}

Then replace hasStringKey(set, k) β†’ setutil.Contains(set, k) across the 196 sites (mechanical, e.g. gofmt -r or codemod). pkg/constants is low-level, but a brand-new leaf package with zero imports introduces no cycle. The generic form also covers any future non-string sets for free.

Also fix the source: update the codemod that emits seenmapbool_helpers.go so it references the shared helper instead of generating a per-package copy β€” otherwise the duplicates regrow on the next migration run.

Why the other same-name matches are not duplicates (verified)
  • SanitizeName / SanitizeOptions β€” pkg/workflow/strings.go is already a type-alias + delegating shim to pkg/stringutil (func SanitizeName(...) { return stringutil.SanitizeName(...) }). βœ… Already centralized.
  • LevenshteinDistance β€” pkg/parser/schema_suggestions.go is a one-line wrapper returning stringutil.LevenshteinDistance(a, b). βœ… Already centralized.
  • findGitRoot, RunGH, RunGHContext, RunGHCombined, getDefaultGHHost, IsWorkflowSpec/isWorkflowSpec β€” these pair foo.go with foo_wasm.go; the second copy is a build-tag-gated WASM stub, not a duplicate. βœ… Excluded.
  • extractToolsFromFrontmatter β€” exists in workflow (returns map[string]any) and parser (returns (string, error)): same name, genuinely different purpose/signature in different packages. Package namespacing, not duplication. βœ… Acceptable.
  • run (31Γ—), init (13Γ—) β€” standard Cobra command + package-init patterns. βœ… Idiomatic.

Next actions

  • Add pkg/setutil (or typeutil) with generic Contains[K comparable]
  • Replace 196 hasStringKey call sites; delete the 6 seenmapbool_helpers.go copies
  • Patch the migration codemod to emit a shared call instead of per-package copies
  • go build ./... && go test ./... to confirm no behavior change

Detection method: top-level func-name clustering across all non-test .go files + body-identity (md5) verification + manual confirmation of each candidate. Analysis date: 2026-06-21.

References: Β§27887885991

Generated by πŸ”§ Semantic Function Refactoring Β· 163.9 AIC Β· βŒ– 14.9 AIC Β· ⊞ 9.1K Β· β—·

  • expires on Jun 22, 2026, 4:10 PM UTC-08:00

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions