microsoft / microsoft/FluidFramework

Duplicate Code: filterPackages duplicated in build-cli and build-infrastructure

Open
#26,747 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
4.9k
Forks
586
Avg merge
1d 15h
Merged PRs (30d)
146

Description

🔍 Duplicate Code Detected: filterPackages package-filter logic duplicated

Analysis of commit c9659f0d8c6b7a7314eff8e5f0ad29f4c30e2aab

Assignee: @copilot

Summary

The filterPackages implementation (including its scopesToPrefix helper) is effectively identical in both @fluid-tools/build-cli and @fluid-tools/build-infrastructure. This is a >10-line duplication that increases the risk of divergence if filtering semantics need to change (e.g., scope handling, private filtering).

Duplication Details

Pattern: identical filterPackages + scopesToPrefix
  • Severity: Medium

  • Occurrences: 2

  • Locations:

    • build-tools/packages/build-cli/src/filter.ts (lines 290–339; filterPackages at 298–335, helper at 337–339)
    • build-tools/packages/build-infrastructure/src/filter.ts (lines 241–290; filterPackages at 249–286, helper at 288–290)
  • Code Sample (from build-tools/packages/build-cli/src/filter.ts):

    export async function filterPackages(T extends FilterablePackage)(
    	packages: T[],
    	filters: PackageFilterOptions,
    ): Promise(T[]) {
    	const filtered = packages.filter((pkg) => {
    		if (filters === undefined) {
    			return true;
    		}
    
    		const isPrivate: boolean = pkg.private ?? false;
    		if (filters.private !== undefined && filters.private !== isPrivate) {
    			return false;
    		}
    
    		const scopeIn = scopesToPrefix(filters?.scope);
    		const scopeOut = scopesToPrefix(filters?.skipScope);
    
    		if (scopeIn !== undefined) {
    			let found = false;
    			for (const scope of scopeIn) {
    				found ||= pkg.name.startsWith(scope);
    			}
    			if (!found) {
    				return false;
    			}
    		}
    		if (scopeOut !== undefined) {
    			for (const scope of scopeOut) {
    				if (pkg.name.startsWith(scope) === true) {
    					return false;
    				}
    			}
    		}
    		return true;
    	});
    
    	return filtered;
    }
    
    function scopesToPrefix(scopes: string[] | undefined): string[] | undefined {
    	return scopes === undefined ? undefined : scopes.map((s) => `\$\{s}/`);
    }
    

Impact Analysis

  • Maintainability: Changes to package filtering semantics must be made in two places.
  • Bug Risk: High chance of inconsistency if one copy is updated without the other.
  • Code Bloat: Small but avoidable; the larger cost is duplicated ownership and review surface.

Refactoring Recommendations

  1. Make build-cli reuse build-infrastructure’s implementation

    • @fluid-tools/build-cli already depends on @fluid-tools/build-infrastructure.
    • Replace the local filterPackages/scopesToPrefix in build-cli/src/filter.ts with imports from @fluid-tools/build-infrastructure (likely from its filter.ts module, or a new exported helper if needed).
    • Estimated effort: Low (≤1 hour) + test validation.
  2. (Optional) Extract to a small shared helper module

    • If filter.ts exports are not intended for consumption, move filterPackages + helper into a dedicated shared module under build-infrastructure (or another shared build-tools package) and re-export from both.

Implementation Checklist

  • Confirm desired ownership for package-filtering semantics (build-infrastructure vs build-cli)
  • Refactor build-cli to import shared implementation
  • Remove duplicate implementation from build-cli
  • Update any affected types (ensure FilterablePackage remains compatible)
  • Run build-cli/build-infrastructure unit tests (or relevant build validation)

Analysis Metadata

  • Analyzed Files: 135 (scoped to build-cli, build-infrastructure, and azure-service-utils TypeScript sources; excluding tests)
  • Detection Method: Serena symbol overview + semantic/structural duplicate-block scan
  • Commit: c9659f0d8c6b7a7314eff8e5f0ad29f4c30e2aab
  • Analysis Date: 2026-03-16T21:51:01.514Z

Generated by Duplicate Code Detector ·

To install this agentic workflow, run

gh aw add github/gh-aw/.github/workflows/duplicate-code-detector.md@94662b1dee8ce96c876ba9f33b3ab8be32de82a4

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read build-tools/packages/build-cli/src/filter.ts and build-tools/packages/build-infrastructure/src/filter.ts, comparing the duplicated filterPackages and scopesToPrefix implementations and their exports and types. Confirm the shared ownership choice, then remove the duplicate and run the relevant build-cli and build-infrastructure unit tests or build validation; done means both packages use one compatible implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
build-system, tooling
Issue type
Refactor
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.