Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ApiCompat run to repo #17959

Closed
wants to merge 7 commits into from
Closed

Add ApiCompat run to repo #17959

wants to merge 7 commits into from

Conversation

wtgodbe
Copy link
Member

@wtgodbe wtgodbe commented Dec 19, 2019

Adds an APICompat run between our ref assemblies (Contract) and the corresponding implementation assemblies. CC @dougbu @JunTaoLuo @Pilchie

Part of #17957. We could also add a run in servicing branches that compares against the previous patch build, but that will be a little more custom (and would require us to restore all the packages we shipped in the last patch)

Currently I only have this running on windows

@wtgodbe
Copy link
Member Author

wtgodbe commented Dec 19, 2019

759d9ad adds the functionality, de05237 represents the set of errors logged. We can have the run either write to these baseline files, or fail when a new error appears that wasn't previously in the baseline files. There are a few real errors there we should look at and fix first (we probably don't need to care about CannotChangeAttribute)

CC @ericstj

CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.AspNetCore.Components.LayoutAttribute' changed from '[AttributeUsageAttribute(4, AllowMultiple=false, Inherited=true)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]' in the implementation.
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.AspNetCore.Components.ParameterAttribute' changed from '[AttributeUsageAttribute(128, AllowMultiple=false, Inherited=true)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Property, AllowMultiple=false, Inherited=true)]' in the implementation.
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.AspNetCore.Components.RouteAttribute' changed from '[AttributeUsageAttribute(4, AllowMultiple=true, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple=true, Inherited=false)]' in the implementation.
ParameterModifiersCannotChange : Custom modifiers on parameter 'renderBatch' on method 'Microsoft.AspNetCore.Components.RenderTree.Renderer.UpdateDisplayAsync(Microsoft.AspNetCore.Components.RenderTree.RenderBatch)' are 'System.Runtime.InteropServices.InAttribute' in the implementation but 'System.Runtime.InteropServices.InAttribute' in the contract.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a bug in the tool

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[In] is defined in a number of different assemblies. Perhaps something in how we build ref/ projects is very slightly different?

In any case, suggest a centralized exclusion for the [In] != [In] case.

@@ -0,0 +1,5 @@
Compat issues with assembly Microsoft.AspNetCore.Routing:
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.AspNetCore.Routing.HostAttribute' changed from '[AttributeUsageAttribute(68, AllowMultiple=false, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=false, Inherited=false)]' in the implementation.
MembersMustExist : Member 'Microsoft.AspNetCore.Routing.Matching.CandidateState.Values.set(Microsoft.AspNetCore.Routing.RouteValueDictionary)' does not exist in the implementation but it does exist in the contract.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should look into this one

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pilchie does this example refer to your question? The tool picked up a diff between the src file and the corresponding manual.cs file

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not conclusive, since it was public on at least one side. I'd want to see a case where it reports a mismatch in something that is internal on both sides.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's entirely possible we messed a few things up when creating and updating *.Manual.cs files e.g. did the all-important internal keyword get deleted accidentally? Suggest checking GenAPI output w/ --all because that tool uses the same base infrastructure as ApiCompat.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect we just messed up when updating Manual.cs files.

@@ -0,0 +1,4 @@
Compat issues with assembly Microsoft.AspNetCore.Server.Kestrel.Core:
ParameterModifiersCannotChange : Custom modifiers on parameter 'buffer' on method 'Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser<TRequestHandler>.Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpParser<TRequestHandler>.ParseRequestLine(TRequestHandler, System.Buffers.ReadOnlySequence<System.Byte>, System.SequencePosition, System.SequencePosition)' are 'System.Runtime.InteropServices.InAttribute' in the implementation but 'System.Runtime.InteropServices.InAttribute' in the contract.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look like bugs in the tool

@wtgodbe wtgodbe added this to the 3.1.2 milestone Dec 19, 2019
@wtgodbe wtgodbe changed the title Api compat Add ApiCompat run to repo Dec 19, 2019
@Pilchie Pilchie added the area-infrastructure Includes: MSBuild projects/targets, build scripts, CI, Installers and shared framework label Dec 19, 2019
Copy link
Member

@Pilchie Pilchie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, it's great to have this (apart from those bugs in the tool of course). However, I'm not confident that it actually protects us all the problems we might face. Specifically, if the internal surface area that is duplicated into our Manual.cs files changes, will we get an error so that we know to update the Manual.cs as well as the original file, or does the tool only look at public surface area?

@wtgodbe
Copy link
Member Author

wtgodbe commented Dec 19, 2019

The tool just compares the two assemblies - I believe it looks at internal surface area as well as public, and would therefore tell us if we added something to a src file without updating the manual.cs files, but I'm not 100% sure - @ericstj can you confirm?

@wtgodbe
Copy link
Member Author

wtgodbe commented Dec 20, 2019

Hmm, this approach won't work. APICompat depends on the ref assembly being built before the implementation assembly, which isn't always the case for us. Will try adding another pass thru all the projects post-build.

Directory.Build.targets Outdated Show resolved Hide resolved
Directory.Build.targets Outdated Show resolved Hide resolved
@@ -0,0 +1 @@
Total Issues: 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid checking in all of these tiny files? E.g. include one Total Issues: 0 default file plus those containing issues we actually want to ignore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just exclude these files if there are no issues
https://github.com/dotnet/arcade/blob/767154ac5bb8715ab1357c63f346244de6d4aa6b/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L56
It seems like if a baseline does not exist, it will simply not be passed to apicompat.

Note that there's no corresponding option to output a file only when there are errors since when the option is set, the baseline file is always written: https://github.com/dotnet/arcade/blob/767154ac5bb8715ab1357c63f346244de6d4aa6b/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L108

@@ -0,0 +1,5 @@
Compat issues with assembly Microsoft.AspNetCore.Routing:
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.AspNetCore.Routing.HostAttribute' changed from '[AttributeUsageAttribute(68, AllowMultiple=false, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=false, Inherited=false)]' in the implementation.
MembersMustExist : Member 'Microsoft.AspNetCore.Routing.Matching.CandidateState.Values.set(Microsoft.AspNetCore.Routing.RouteValueDictionary)' does not exist in the implementation but it does exist in the contract.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's entirely possible we messed a few things up when creating and updating *.Manual.cs files e.g. did the all-important internal keyword get deleted accidentally? Suggest checking GenAPI output w/ --all because that tool uses the same base infrastructure as ApiCompat.

CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.AspNetCore.Components.LayoutAttribute' changed from '[AttributeUsageAttribute(4, AllowMultiple=false, Inherited=true)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]' in the implementation.
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.AspNetCore.Components.ParameterAttribute' changed from '[AttributeUsageAttribute(128, AllowMultiple=false, Inherited=true)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Property, AllowMultiple=false, Inherited=true)]' in the implementation.
CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.AspNetCore.Components.RouteAttribute' changed from '[AttributeUsageAttribute(4, AllowMultiple=true, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple=true, Inherited=false)]' in the implementation.
ParameterModifiersCannotChange : Custom modifiers on parameter 'renderBatch' on method 'Microsoft.AspNetCore.Components.RenderTree.Renderer.UpdateDisplayAsync(Microsoft.AspNetCore.Components.RenderTree.RenderBatch)' are 'System.Runtime.InteropServices.InAttribute' in the implementation but 'System.Runtime.InteropServices.InAttribute' in the contract.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[In] is defined in a number of different assemblies. Perhaps something in how we build ref/ projects is very slightly different?

In any case, suggest a centralized exclusion for the [In] != [In] case.

@wtgodbe
Copy link
Member Author

wtgodbe commented Dec 26, 2019

Maybe I can make it work during the normal pass, these are the projects complaining about the ref assembly not being available when building the impl:

Microsoft.AspNetCore.Cryptography.Internal.csproj
Microsoft.AspNetCore.Metadata.csproj
Microsoft.AspNetCore.Http.Features.csproj
Microsoft.AspNetCore.DataProtection.Abstractions.csproj
Microsoft.AspNetCore.Components.csproj

Looking for what these have in common. They all have netstandard2.0 configurations & IsAspNetCoreApp=true, but so does https://github.com/aspnet/AspNetCore/blob/release/3.1/src/Components/Web/src/Microsoft.AspNetCore.Components.Web.csproj, which doesn't hit this problem.

@wtgodbe
Copy link
Member Author

wtgodbe commented Dec 26, 2019

Oh, some of this might be because projects in the Components dir output their artifacts directly into the source tree...

  Microsoft.AspNetCore.Components -> F:\workspace\_work\1\s\src\Components\Components\ref\bin\Release\netcoreapp3.1\Microsoft.AspNetCore.Components.dll

But others like Http.Features don't do that, and still get the same issue. Very confusing. Still looking around.

@dougbu
Copy link
Member

dougbu commented Dec 27, 2019

@wtgodbe the ref/ projects are currently built before the corresponding src/ projects only when targeting netcoreapp3.0. To relax this and ensure consistent ref/ before src/ builds, remove the second part of the condition at https://github.com/aspnet/AspNetCore/blob/release/3.1/eng/targets/ResolveReferences.targets#L258. This will add the @(ProjectReference) more often.

Note: Do not change how $(_CompileTfmUsingReferenceAssemblies) is set. Other uses of that property avoid a number of build problems -- as discussed offline.

dougbu added 3 commits January 5, 2020 21:54
- !important! only run ApiCompat in inner builds
- get ref/ assembly path from the relevant project
  - not all projects write into artifacts/...
- make incompatibilities errors (unless overridden)

nits:
- use `$(HasReferenceAssembly)` short form
@dougbu
Copy link
Member

dougbu commented Jan 8, 2020

@wtgodbe the broken *.Manual.cs file is still broken and I haven't addressed all comments above.

@wtgodbe
Copy link
Member Author

wtgodbe commented Jan 8, 2020

The same set of projects is still broken, but now with:

F:\workspace_work\1\s.packages\microsoft.dotnet.apicompat\1.0.0-beta.19607.3\build\Microsoft.DotNet.ApiCompat.targets(49,5): error : ResolvedMatchingContract item must be specified to run API compat. [F:\workspace_work\1\s\src\Components\Components\src\Microsoft.AspNetCore.Components.csproj]

Will look in a bit

- ensure `ResolveCustomReferences` target runs consistently
  - `ResolveAssemblyReferences` didn't actually drive execution and it runs too late anyhow
- remove redundant `$(_GenAPICmd)` setting
@dougbu
Copy link
Member

dougbu commented Jan 10, 2020

🆙📅 to include two more fixes, one a nit the other important

@analogrelay
Copy link
Contributor

analogrelay commented Feb 13, 2020

I'm trying to clear up the state of outstanding servicing PRs. Whats the situation with this? Just holding waiting to fix it it up and merge? Is this infrastructure-only (sounds like it)? If so, we can slap the tell-mode label on it.

@dougbu dougbu modified the milestones: 3.1.3, 3.1.x Feb 13, 2020
@dougbu
Copy link
Member

dougbu commented Feb 13, 2020

@anurse to do this right requires Arcade changes from dotnet/arcade#4585 and I haven't quite got that working yet (thought it's close). Moved the PR to 3.1.x because it's not going to be ready for 3.1.3.

@wtgodbe wtgodbe closed this Feb 14, 2020
@wtgodbe wtgodbe deleted the ApiCompat branch February 14, 2020 18:19
@dougbu dougbu removed this from the 3.1.x milestone Dec 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-infrastructure Includes: MSBuild projects/targets, build scripts, CI, Installers and shared framework
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants