Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[duplicate-code] Duplicate `HasDuplicateModuleIdentity` logic between AzureDevOps and GitHub Actions reporters

Closed
#12,000 0 comments 1 reaction 2 assignees View on GitHub

Maintainers usually reply within 1 day

@Evangelink is already working on this.

Since Oct 18, 2026.

  • #12005 by @copilot-swe-agent — open

Assessment

This issue has not been assessed yet.

Description

type/automation type/tech-debt

Summary

The exact same module-identity-collision check is duplicated byte-for-byte between the Azure DevOps and GitHub Actions CI summary reporters, each operating on the already-shared CiRunSummaryModule type (src/Platform/SharedExtensionHelpers/CiRunSummaryModels.cs). The repo already has a precedent for extracting this kind of cross-reporter logic into src/Platform/SharedExtensionHelpers — see CiRunSummaryExitCode (added in #11970) which consolidated near-identical exit-code logic from GitHubActionsExitCode for reuse by the Azure DevOps reporter.

Duplication Details

Pattern: Identical HasDuplicateModuleIdentity private method
  • Severity: Medium
  • Occurrences: 2 (each called from 2–3 call sites within its own file, so the logic effectively has multiple internal users per project)
  • Locations:
    • src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsSummaryReporter.Markdown.cs (lines 547-551), called from lines 466 and 528
    • src/Platform/Microsoft.Testing.Extensions.GitHubActionsReport/GitHubActionsSummaryReporter.Markdown.Aggregate.cs (lines 197-201), called from line 122
  • Code Sample:
    private static bool HasDuplicateModuleIdentity(IReadOnlyList<CiRunSummaryModule> modules, CiRunSummaryModule module)
        => modules.Count(candidate =>
            string.Equals(candidate.AssemblyName, module.AssemblyName, StringComparison.Ordinal)
            && string.Equals(candidate.TargetFramework, module.TargetFramework, StringComparison.Ordinal)
            && string.Equals(candidate.Architecture, module.Architecture, StringComparison.OrdinalIgnoreCase)) > 1;
    
    Both copies are identical character-for-character (verified with diff).

Impact Analysis

  • Maintainability: Any future change to how module identity collisions are detected (e.g. adding a new discriminator field, changing comparison semantics) must be made in two places; it is easy to update one and forget the other, causing the two CI report flavors to silently disagree on when module attempt/session discriminators are shown.
  • Bug Risk: Because both copies currently operate on the shared CiRunSummaryModule type with no reporter-specific variation, there is no reason for behavior to diverge — any divergence introduced later would be an unintentional bug rather than a deliberate design choice.
  • Code Bloat: Small (5 lines each), but it sets a precedent of re-deriving shared CI-summary logic per reporter instead of consolidating it, which compounds as more reporters (e.g. future CI providers) are added.

Refactoring Recommendations

  1. Move HasDuplicateModuleIdentity into src/Platform/SharedExtensionHelpers
    • Add it as a new internal static method (e.g. a ModuleIdentity or CiRunSummaryModuleIdentity helper class, or append to the existing CiRunSummaryAggregation.cs since it already operates on CiRunSummaryModule/CiRunSummaryAggregate).
    • Mirror the pattern used for CiRunSummaryExitCode (added in #11970): a single implementation guarded by #pragma warning disable RS0051 since the helper compiles into multiple extension assemblies.
    • Update both AzureDevOpsSummaryReporter.Markdown.cs and GitHubActionsSummaryReporter.Markdown.Aggregate.cs to call the shared helper instead of their private copies.
    • Estimated effort: low (under an hour); purely mechanical extraction with no behavior change.
    • Benefits: single source of truth for module-identity-collision detection; consistent with the existing CiRunSummaryExitCode precedent; removes duplicate code that must otherwise be kept in sync manually.

Implementation Checklist

  • Review duplication findings
  • Extract HasDuplicateModuleIdentity into src/Platform/SharedExtensionHelpers
  • Update both reporters to call the shared helper
  • Remove the two private copies
  • Verify existing AzureDevOps and GitHub Actions summary reporter unit tests still pass unchanged (behavior-preserving refactor)

Analysis Metadata

  • Analyzed Files: Recent commits touching src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/ and src/Platform/Microsoft.Testing.Extensions.GitHubActionsReport/ (commits around 88788a9eb, 95c503f07, 73a403f7f, e51893b06)
  • Detection Method: Semantic code analysis + exact diff comparison
  • Commit: e51893b06f6a5c6faa3a702a8e9d78cd93c35ce9

🤖 Automated content by GitHub Copilot. Generated by the Duplicate Code Detector workflow. · copilot · auto · 123.1 AIC · ⌖ 6.64 AIC · ⊞ 13.9K · [◷]( · ◷)

Add this agentic workflow to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/duplicate-code-detector.md@main
  • expires on Oct 20, 2026, 4:31 AM UTC
Dominant language
C#
Stars
1.1k
Forks
312
Avg merge
8h 29m
Merged PRs (30d)
421

Getting set up

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.

More from microsoft/testfx

All issues in microsoft/testfx

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.