You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* build: actually enable NuGet package validation
EnablePackageValidation and the CS1591 waiver were conditioned on
$(IsPackable) / $(PackageId) inside Directory.Build.props, which is
imported before project bodies set those properties — both conditions
always saw empty values, so package validation never ran for any project
and CS1591 was waived everywhere. The same evaluation-order rule was
already documented in Directory.Build.targets for PackageReadmeFile;
both conditions now live there. An unset IsPackable counts as packable
because NuGet's own IsPackable=true default is applied by the pack
targets, which import even later.
PackageValidationBaselineVersion stays in Directory.Build.props so the
bump-baseline workflow's sed keeps finding it.
Fallout from turning the gates on:
- CS1591 enforcement surfaced 16 undocumented public constants in
WopiTelemetry — documented.
- Baseline validation against 9.0.0 flagged the two intentional
AddActivities interface additions on WopiHost.Abstractions —
suppressed via the generated CompatibilitySuppressions.xml.
Verified with a release-style pack (dotnet pack -p:Version=9.99.0):
validation downloads the 9.0.0 baselines and passes for all nine
published packages.
https://claude.ai/code/session_019MeqK2SERqN3JAQKAKaRKR
* build: drop tombstone comments pointing from props to targets
The CS1591-waiver note and the EnablePackageValidation note in
Directory.Build.props described code that no longer lives there; the
conditions and their evaluation-order rationale are documented in
Directory.Build.targets where they actually run. The baseline-version
comment stays, since it documents the property directly below it.
* ci(bump-baseline): retire CompatibilitySuppressions.xml when the baseline advances
A suppression records an intentional break against the previous baseline.
Once bump-baseline moves the baseline to the just-released version those
breaks are part of the baseline and the suppressions match nothing, so the
auto-bump PR now git-rm's them in the same change. The glob matches at any
depth, so it works for a single shared file or per-project files.
* ci(api-compat): make the PR check suppression-aware and blocking
Feed each project's CompatibilitySuppressions.xml (the same default path
the SDK's pack-time validator reads at release) to the apicompat global
tool via --suppression-file, and fail the job on any break that isn't
suppressed. Acknowledged breaks are masked, so the report shows only what
the PR itself changes; a deliberate break is acknowledged by committing the
regenerated suppression file. The sticky comment now posts on always() so
the report is visible even when the check fails.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .github/workflows/bump-baseline.yml
+20Lines changed: 20 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -112,6 +112,24 @@ jobs:
112
112
113
113
sed -i "s|<PackageValidationBaselineVersion>[^<]*</PackageValidationBaselineVersion>|<PackageValidationBaselineVersion>${NEW}</PackageValidationBaselineVersion>|g" "$FILE"
114
114
115
+
- name: Retire suppressions absorbed into the new baseline
116
+
# A CompatibilitySuppressions.xml entry records an intentional API break against the
117
+
# *previous* baseline. Once the baseline advances to the just-released version those
118
+
# breaks are part of the baseline, so the suppressions match nothing and are dead
119
+
# weight. Drop them in the same bump PR so each release cycle starts clean and the
120
+
# files only ever carry breaks introduced *after* the last release. The glob matches
121
+
# at any depth, so it works whether suppressions live in one file or one per project.
echo "No CompatibilitySuppressions.xml files to retire."
128
+
else
129
+
printf 'Retiring: %s\n' "${files[@]}"
130
+
git rm --quiet "${files[@]}"
131
+
fi
132
+
115
133
- name: Open PR with the bump
116
134
# peter-evans/create-pull-request is intentionally idempotent: if Directory.Build.props
117
135
# has no diff (because CURRENT was already at NEW, or because the backward-bump guard
@@ -131,6 +149,8 @@ jobs:
131
149
${{ github.event_name == 'release' && format('Triggered by the [{0}]({1}) release.', github.event.release.tag_name, github.event.release.html_url) || 'Triggered manually via workflow_dispatch.' }}
132
150
133
151
Keeps the SDK's pack-time package validator comparing the current public surface against the version that's actually published to NuGet.org.
152
+
153
+
Any `CompatibilitySuppressions.xml` left over from the previous cycle is retired here too — those entries are now part of the baseline and would otherwise linger as dead weight.
Copy file name to clipboardExpand all lines: .github/workflows/pull_request.yml
+27-5Lines changed: 27 additions & 5 deletions
Original file line number
Diff line number
Diff line change
@@ -152,7 +152,11 @@ jobs:
152
152
echo "<!-- apicompat-report -->"
153
153
echo "## API Compatibility Report"
154
154
echo ""
155
-
echo "Compared this PR's packed assemblies against the latest stable release on [NuGet.org](https://www.nuget.org/packages?q=WopiHost) for each library. This check is **informational only** — intentional breaks at major version bumps are expected."
155
+
echo "Compared this PR's packed assemblies against the latest stable release on [NuGet.org](https://www.nuget.org/packages?q=WopiHost) for each library, honoring each project's \`CompatibilitySuppressions.xml\`. **This check fails on any public-API break not recorded as intentional** — already-suppressed breaks are masked, so what surfaces below is what *this PR* changes. If a break is deliberate, regenerate and commit the suppressions:"
# Run apicompat. Note: <package> is positional, --baseline-package is named, --run-api-compat is required.
191
203
# The tool installs as 'apicompat' (not 'dotnet apicompat') and exits 0 on both clean and break
192
204
# cases; detect findings via output text.
193
205
set +e
194
206
output="$(apicompat package "$new_nupkg" \
195
207
--baseline-package "$baseline_nupkg" \
196
208
--run-api-compat \
209
+
--permit-unnecessary-suppressions \
210
+
"${supp_args[@]}" \
197
211
--verbosity Normal 2>&1)"
198
212
set -e
199
213
200
214
if grep -Eq '^(CP|PKV)[0-9]+:' <<< "$output"; then
201
215
ANY_DIFFS=1
202
216
{
203
-
echo "### :warning: ${pkg} vs \`${baseline_version}\`"
204
-
echo "<details><summary>API differences found — click to expand</summary>"
217
+
echo "### :x: ${pkg} vs \`${baseline_version}\`"
218
+
echo "<details open><summary>Unsuppressed public-API break(s) — revert or suppress</summary>"
205
219
echo ""
206
220
echo '```'
207
221
echo "${output}"
@@ -222,15 +236,23 @@ jobs:
222
236
{
223
237
echo "---"
224
238
if [[ $ANY_DIFFS -eq 0 ]]; then
225
-
echo "_No API differences detected across any package._"
239
+
echo "_No unsuppressed public-API breaks across any package._"
226
240
else
227
-
echo "_Diagnostic IDs starting with \`CP\` are assembly-level diffs; \`PKV\` are package-shape diffs. See the [ApiCompat docs](https://learn.microsoft.com/dotnet/fundamentals/apicompat/diagnostic-ids) for details._"
241
+
echo "_If these breaks are intentional, run \`dotnet pack -c Release -p:ApiCompatGenerateSuppressionFile=true\` and commit the regenerated \`CompatibilitySuppressions.xml\`. \`CP\` IDs are assembly-level diffs; \`PKV\` are package-shape diffs ([docs](https://learn.microsoft.com/dotnet/fundamentals/apicompat/diagnostic-ids))._"
228
242
fi
229
243
} >> "$REPORT_FILE"
230
244
231
245
# Surface in the job log too.
232
246
cat "$REPORT_FILE"
247
+
248
+
# Fail the check on any unsuppressed break (the report is posted by the next step,
249
+
# which runs on always()). A deliberate break is acknowledged via its suppression file.
250
+
if [[ $ANY_DIFFS -ne 0 ]]; then
251
+
echo "::error::Unsuppressed public-API break(s) detected — see the API Compatibility Report comment."
0 commit comments