Skip to content

Add CI enforcement to prevent removal of ApiCompatVersion from GA packages #57635

@m-redding

Description

@m-redding

Problem

There is no CI or build-time enforcement preventing a team from removing ApiCompatVersion from their .csproj file. If removed, API compatibility checking silently stops running — CI passes with zero errors, and the PR merges without any warning.

Current behavior

  • Update-PkgVersion.ps1 automatically adds ApiCompatVersion when a package transitions from GA to its next prerelease version (e.g., 1.0.01.1.0-beta.1)
  • The existing ValidateRunApiCompat target (line 16 of eng/Directory.Build.Common.targets) only checks that RunApiCompat isn't explicitly set to false
  • However, if ApiCompatVersion is removed entirely, the Microsoft.DotNet.ApiCompat NuGet package is never referenced, RunApiCompat is never set (it's empty, not false), and the validation check passes silently
  • The only current defense against removal is PR code review

Why this matters

A team could (intentionally or accidentally) delete ApiCompatVersion from their .csproj, and:

  1. CI passes ✅
  2. PR merges ✅
  3. Breaking API changes ship undetected ❌

Why pre-GA packages don't have ApiCompatVersion

Packages that have never shipped a GA release (e.g., still at 1.0.0-beta.3) don't have ApiCompatVersion because there's no prior GA version to compare against. The ApiCompatRequired property distinguishes "never been GA" (no property) from "was GA but someone removed ApiCompatVersion" (property is true but version is empty).

Related


The following is the AI proposed solutions, which I don't really like, so this is still a work in progress

AI proposed solutions

Add an ApiCompatRequired property that is automatically set by Update-PkgVersion.ps1 when it first adds ApiCompatVersion to a GA package:

  1. In Update-PkgVersion.ps1: When adding ApiCompatVersion, also add <ApiCompatRequired>true</ApiCompatRequired> to the .csproj
  2. In eng/Directory.Build.Common.targets: Add a new validation target:
    <Target Name="ValidateApiCompatVersionRequired" BeforeTargets="Build" 
            Condition="'$(ValidateRunApiCompat)' == 'true' and '$(ApiCompatRequired)' == 'true' and '$(ApiCompatVersion)' == '' and '$(IncludeBuildOutput)' != 'false'">
      <Error Text="Package $(PackageId) requires ApiCompatVersion to be set. Do not remove ApiCompatVersion from GA packages." />
    </Target>
  3. Backfill: Add <ApiCompatRequired>true</ApiCompatRequired> to all ~292 existing .csproj files that currently have ApiCompatVersion

Why not a list file?

A central list (e.g., eng/ApiCompatRequired.txt) was considered but rejected because it requires ongoing maintenance. The property-based approach is fully automatic — Update-PkgVersion.ps1 manages both properties, and no separate list needs to be kept in sync.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ClientThis issue is related to a non-management packageSDK Dev ExperienceIssues related to the development experience for Azure SDK libraries.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions