API Compat tool in ML.NET - #3623

Merged
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat
May 4, 2019
Merged

API Compat tool in ML.NET#3623
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat

Conversation

@artidoro

@artidoroartidoro commented Apr 30, 2019

Copy link
Copy Markdown
Contributor

Fixes#3602.

We need to ensure that future changes to ML.NET will not break the stable API released in 1.0.0.

This PR introduces the API Compat tool from dotnet/Arcade. The API Compat tool runs as part of the build process and compares the assemblies with those found in the stable nugets referenced in the Microsoft.ML.StableAPI project.

The tool is only run for the assemblies which will be part of the stable nugets. Here is a list of those assemblies and the relative nugets:

Stable NugetStable Assemblies
Microsoft.MLMicrosoft.ML.Core, Microsoft.ML.Data, Microsoft.ML.KMeansClustering, Microsoft.ML.PCA, Microsoft.ML.StandardTrainers, MIcrosoft.ML.Transforms, Microsoft.ML.Analyzer
Microsoft.ML.DataViewMicrosoft.ML.DataView
Microsoft.ML.CpuMathMicrosoft.ML.CpuMath
Microsoft.ML.FastTreeMicrosoft.ML.FastTree
Microsoft.ML.LightGbmMicrosoft.ML.LightGbm
Microsoft.ML.ImageAnalyticsMicrosoft.ML.ImageAnalytics
Microsoft.ML.MklComponentsMicrosoft.ML.Mkl.Components

Note: the tool does not run on Microsoft.ML.Analyzer as it does not have a public API, so no need to check backwards compatibility.

Still to do:

  • Fix possible bug in API Compat on handling of Attributes.
  • Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes. Not needed see comments below.
  • Update the version of the ML.NET nugets to 1.0.0 when available

@artidoroartidoro added the Build Build related issue label Apr 30, 2019
@artidoroartidoro self-assigned this Apr 30, 2019

@ericstjericstj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry if some of these were issues with my initial sample.

Comment threadDirectory.Build.props Outdated
Comment threadsrc/Directory.Build.targets Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated

</Target>

<!-- API Compat -->

@ericstjericstjApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider moving these to a seperate targets file if that is a convention you'd like to follow in this repo. #Pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we only have one for the src repo. But let me know if there is a better way.


In reply to: 279938766 [](ancestors = 279938766)

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview-27625-16"/>

@eerhardteerhardtApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nit) you can use the latest 1.0.0-preview build: 1.0.0-preview-27630-5. We just spun it and will have the official 1.0.0 up soon. #Resolved

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Will update to the new build and change to 1.0.0 as soon as it is available.


In reply to: 279941849 [](ancestors = 279941849)

@eerhardteerhardtMay 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's available on myget now. You should be able to use 1.0.0. #Resolved

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member
D:\a\1\s\packages\microsoft.dotnet.apicompat\1.0.0-beta.19225.5\build\Microsoft.DotNet.ApiCompat.targets(72,5): error : CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.ML.ExtensionBaseAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. [D:\a\1\s\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj]

This is happening because APICompat is not resolving the System.AttributeTargets enum from the contract. It's not resolving because you aren't providing the dependencies. Today these can be passed in via the $(ContractOutputPath) property but that isn't very sensible. I'll submit a change to APICompat to make that easier.
https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L46-L52 #Pending

@artidoro

Copy link
Copy Markdown
ContributorAuthor

That would be great! Thank you


In reply to: 488135991 [](ancestors = 488135991)

@artidoro

artidoro commented Apr 30, 2019

Copy link
Copy Markdown
ContributorAuthor

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version.

@ericstj is it possible to specify the path for the generated file?
Also, how would we specify known diffs going forward? I would like to write some documentation on how to do that. #Resolved

@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

by default the generated file gets written to the same directory as the project with the name, but you can customize it: https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L22-L23

how would we specify known diffs going forward?

You can use the same option I mentioned when building individual projects, you can also copy the errors and paste them into the baseline file. I want to stress that these aren't "known diffs" these are compatibility bugs that break your customers and you really shouldn't be baselining them or introducing the suppressions. #Resolved

@ericstjericstj mentioned this pull request May 1, 2019
4 tasks
@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

To provide paths to contract dependencies, add the following in your GetContract target:

 <_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_contractReferencePath DependencyPaths="@(_allReferenceDirectories)" />

Then in ResolveMatchingContract add the following after you get the ResolvedMatchingContract item:

<PropertyGroup>
<ContractOutputPath>%(ResolvedMatchingContract.DependencyPaths)</ContractOutputPath>
</PropertyGroup>

I'm putting a feature into the APICompat targets that will make the latter property unnecessary. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project will actually build a .dll when we build the .sln file. That seems unnecessary. Maybe we should override the Build target or maybe not name it .csproj and instead just .proj? It's mission in life isn't to build .cs files into a .dll, but instead pull down external packages and provide the GetContract target.

@artidoroartidoroMay 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I tried renaming, but that did not work (it gave an error saying that project.assets.json was not generated.
I have also tried to overwrite the Build target, but I must have made some mistake since I still found the generated .dll.

What I did was adding:

 <Target Name="Build">
<!-- This will override the default Build target. -->
</Target>

to the .csproj file.

What is the correct way to overwrite it?


In reply to: 280105436 [](ancestors = 280105436)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I think that is fine.

Comment threadDirectory.Build.props Outdated
@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you that seems to make it work!


In reply to: 488287870 [](ancestors = 488287870)

@artidoroartidoro changed the title WIP: API Compat tool in ML.NETAPI Compat tool in ML.NETMay 3, 2019
@codecov

codecovBot commented May 3, 2019

Copy link
Copy Markdown

Codecov Report

Merging #3623 into master will increase coverage by <.01%.
The diff coverage is n/a.

@@ Coverage Diff @@## master #3623 +/- ##
==========================================
+ Coverage 72.78% 72.78% +<.01% 
==========================================
Files 808 808 Lines 145588 145588 Branches 16250 16250 ==========================================
+ Hits 105960 105968 +8 + Misses 35205 35198 -7 + Partials 4423 4422 -1
FlagCoverage Δ
#Debug72.78% <ø> (ø)⬆️
#production68.28% <ø> (ø)⬆️
#test89.04% <ø> (ø)⬆️
Impacted FilesCoverage Δ
...StandardTrainers/Standard/LinearModelParameters.cs60.05% <0%> (-0.27%)⬇️
...icrosoft.ML.TensorFlow/TensorFlow/TensorGeneric.cs44.21% <0%> (ø)⬆️
...c/Microsoft.ML.FastTree/Utils/BufferPoolManager.cs0% <0%> (ø)⬆️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.26% <0%> (+0.15%)⬆️
...soft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs84.9% <0%> (+0.2%)⬆️
...soft.ML.TestFramework/DataPipe/TestDataPipeBase.cs73.93% <0%> (+0.32%)⬆️
src/Microsoft.ML.Transforms/Text/LdaTransform.cs89.89% <0%> (+0.62%)⬆️

@ericstj

Copy link
Copy Markdown
Member

failing on linux because dotnet is not on the path and the $(ToolHostCmd) is not set to point to it.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you @ericstj and @eerhardt for looking at the PR, I have addressed your comments.
Let me know if there are other things I should look into!

@ericstj

Copy link
Copy Markdown
Member

Cool, this is looking pretty good. You may want to wait for my changes dotnet/arcade#2672 which help simplify some of this.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

I would prefer checking in this change as soon as possible and updating it with the new buyer as soon as it is available.

Since we have released yesterday, it would be great to have the API Compat tool in the repo.

Comment threadMicrosoft.ML.sln Outdated
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2026
# Visual Studio Version 16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You may want to revert these two lines. I don't know what happens if someone tries opening the solution with VS 2017 (which is version 15) and this .sln says it is for VS 2019.

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks good. But I'd wait for @ericstj to give the thumbs up as he's the expert here.

<PropertyGroup>
<!-- needs to contain all frameworks which src projects wish to restore -->
<TargetFramework Condition="'$(UseIntrinsics)' != 'true'">netstandard2.0</TargetFramework>
<TargetFrameworks Condition="'$(UseIntrinsics)' == 'true'">netstandard2.0;netcoreapp3.0</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why should we have the condition here? Is there any harm in always resolving for both TFMs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usually netcoreapp3.0 causes problems when you are building in VS 2017 where the SDK throws an error saying I don't support netcoreapp3.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

<Error Condition="'@(_contractReferencePath)' == ''" Text="Could not locate $(ContractName)" />
</Target>

<Target Name="Build">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be improved by changing the project extension and defining a couple targets. We do that elsewhere:
dotnet/project-system#4647

IOW: call this a .proj, or a .restoreproj or something. SLN entry looks the same (you have to do it manually in text editor, IDE won't let you). Add the workaround I linked, define stub targets for anything that fails, and it should avoid
the confusion around a CSProj that doesn't build anything.
You don't need to do that now, but I think it would make this more sensible.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I have tried to add the lines found in the issue to the new .restoreproj file but that did not work.
I will keep it as is for now then.

@ericstj

Copy link
Copy Markdown
Member

Have you made sure you see a failure when making a breaking API change?

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Yes I have done a few tests where I rename methods and such and the build was failing.

<ItemGroup>
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lines 24 and 26 are identical... 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@RussKie - can you log an issue (or even submit a PR for the fix)?

@ghostghost locked as resolved and limited conversation to collaborators Mar 22, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

BuildBuild related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add API breaking change definition and enforce it

4 participants

@artidoro@ericstj@RussKie@eerhardt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

API Compat tool in ML.NET - #3623

Merged
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat
May 4, 2019
Merged

API Compat tool in ML.NET#3623
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat

Conversation

@artidoro

@artidoroartidoro commented Apr 30, 2019

Copy link
Copy Markdown
Contributor

Fixes#3602.

We need to ensure that future changes to ML.NET will not break the stable API released in 1.0.0.

This PR introduces the API Compat tool from dotnet/Arcade. The API Compat tool runs as part of the build process and compares the assemblies with those found in the stable nugets referenced in the Microsoft.ML.StableAPI project.

The tool is only run for the assemblies which will be part of the stable nugets. Here is a list of those assemblies and the relative nugets:

Stable NugetStable Assemblies
Microsoft.MLMicrosoft.ML.Core, Microsoft.ML.Data, Microsoft.ML.KMeansClustering, Microsoft.ML.PCA, Microsoft.ML.StandardTrainers, MIcrosoft.ML.Transforms, Microsoft.ML.Analyzer
Microsoft.ML.DataViewMicrosoft.ML.DataView
Microsoft.ML.CpuMathMicrosoft.ML.CpuMath
Microsoft.ML.FastTreeMicrosoft.ML.FastTree
Microsoft.ML.LightGbmMicrosoft.ML.LightGbm
Microsoft.ML.ImageAnalyticsMicrosoft.ML.ImageAnalytics
Microsoft.ML.MklComponentsMicrosoft.ML.Mkl.Components

Note: the tool does not run on Microsoft.ML.Analyzer as it does not have a public API, so no need to check backwards compatibility.

Still to do:

  • Fix possible bug in API Compat on handling of Attributes.
  • Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes. Not needed see comments below.
  • Update the version of the ML.NET nugets to 1.0.0 when available

@artidoroartidoro added the Build Build related issue label Apr 30, 2019
@artidoroartidoro self-assigned this Apr 30, 2019

@ericstjericstj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry if some of these were issues with my initial sample.

Comment threadDirectory.Build.props Outdated
Comment threadsrc/Directory.Build.targets Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated

</Target>

<!-- API Compat -->

@ericstjericstjApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider moving these to a seperate targets file if that is a convention you'd like to follow in this repo. #Pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we only have one for the src repo. But let me know if there is a better way.


In reply to: 279938766 [](ancestors = 279938766)

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview-27625-16"/>

@eerhardteerhardtApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nit) you can use the latest 1.0.0-preview build: 1.0.0-preview-27630-5. We just spun it and will have the official 1.0.0 up soon. #Resolved

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Will update to the new build and change to 1.0.0 as soon as it is available.


In reply to: 279941849 [](ancestors = 279941849)

@eerhardteerhardtMay 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's available on myget now. You should be able to use 1.0.0. #Resolved

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member
D:\a\1\s\packages\microsoft.dotnet.apicompat\1.0.0-beta.19225.5\build\Microsoft.DotNet.ApiCompat.targets(72,5): error : CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.ML.ExtensionBaseAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. [D:\a\1\s\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj]

This is happening because APICompat is not resolving the System.AttributeTargets enum from the contract. It's not resolving because you aren't providing the dependencies. Today these can be passed in via the $(ContractOutputPath) property but that isn't very sensible. I'll submit a change to APICompat to make that easier.
https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L46-L52 #Pending

@artidoro

Copy link
Copy Markdown
ContributorAuthor

That would be great! Thank you


In reply to: 488135991 [](ancestors = 488135991)

@artidoro

artidoro commented Apr 30, 2019

Copy link
Copy Markdown
ContributorAuthor

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version.

@ericstj is it possible to specify the path for the generated file?
Also, how would we specify known diffs going forward? I would like to write some documentation on how to do that. #Resolved

@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

by default the generated file gets written to the same directory as the project with the name, but you can customize it: https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L22-L23

how would we specify known diffs going forward?

You can use the same option I mentioned when building individual projects, you can also copy the errors and paste them into the baseline file. I want to stress that these aren't "known diffs" these are compatibility bugs that break your customers and you really shouldn't be baselining them or introducing the suppressions. #Resolved

@ericstjericstj mentioned this pull request May 1, 2019
4 tasks
@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

To provide paths to contract dependencies, add the following in your GetContract target:

 <_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_contractReferencePath DependencyPaths="@(_allReferenceDirectories)" />

Then in ResolveMatchingContract add the following after you get the ResolvedMatchingContract item:

<PropertyGroup>
<ContractOutputPath>%(ResolvedMatchingContract.DependencyPaths)</ContractOutputPath>
</PropertyGroup>

I'm putting a feature into the APICompat targets that will make the latter property unnecessary. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project will actually build a .dll when we build the .sln file. That seems unnecessary. Maybe we should override the Build target or maybe not name it .csproj and instead just .proj? It's mission in life isn't to build .cs files into a .dll, but instead pull down external packages and provide the GetContract target.

@artidoroartidoroMay 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I tried renaming, but that did not work (it gave an error saying that project.assets.json was not generated.
I have also tried to overwrite the Build target, but I must have made some mistake since I still found the generated .dll.

What I did was adding:

 <Target Name="Build">
<!-- This will override the default Build target. -->
</Target>

to the .csproj file.

What is the correct way to overwrite it?


In reply to: 280105436 [](ancestors = 280105436)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I think that is fine.

Comment threadDirectory.Build.props Outdated
@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you that seems to make it work!


In reply to: 488287870 [](ancestors = 488287870)

@artidoroartidoro changed the title WIP: API Compat tool in ML.NETAPI Compat tool in ML.NETMay 3, 2019
@codecov

codecovBot commented May 3, 2019

Copy link
Copy Markdown

Codecov Report

Merging #3623 into master will increase coverage by <.01%.
The diff coverage is n/a.

@@ Coverage Diff @@## master #3623 +/- ##
==========================================
+ Coverage 72.78% 72.78% +<.01% 
==========================================
Files 808 808 Lines 145588 145588 Branches 16250 16250 ==========================================
+ Hits 105960 105968 +8 + Misses 35205 35198 -7 + Partials 4423 4422 -1
FlagCoverage Δ
#Debug72.78% <ø> (ø)⬆️
#production68.28% <ø> (ø)⬆️
#test89.04% <ø> (ø)⬆️
Impacted FilesCoverage Δ
...StandardTrainers/Standard/LinearModelParameters.cs60.05% <0%> (-0.27%)⬇️
...icrosoft.ML.TensorFlow/TensorFlow/TensorGeneric.cs44.21% <0%> (ø)⬆️
...c/Microsoft.ML.FastTree/Utils/BufferPoolManager.cs0% <0%> (ø)⬆️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.26% <0%> (+0.15%)⬆️
...soft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs84.9% <0%> (+0.2%)⬆️
...soft.ML.TestFramework/DataPipe/TestDataPipeBase.cs73.93% <0%> (+0.32%)⬆️
src/Microsoft.ML.Transforms/Text/LdaTransform.cs89.89% <0%> (+0.62%)⬆️

@ericstj

Copy link
Copy Markdown
Member

failing on linux because dotnet is not on the path and the $(ToolHostCmd) is not set to point to it.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you @ericstj and @eerhardt for looking at the PR, I have addressed your comments.
Let me know if there are other things I should look into!

@ericstj

Copy link
Copy Markdown
Member

Cool, this is looking pretty good. You may want to wait for my changes dotnet/arcade#2672 which help simplify some of this.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

I would prefer checking in this change as soon as possible and updating it with the new buyer as soon as it is available.

Since we have released yesterday, it would be great to have the API Compat tool in the repo.

Comment threadMicrosoft.ML.sln Outdated
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2026
# Visual Studio Version 16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You may want to revert these two lines. I don't know what happens if someone tries opening the solution with VS 2017 (which is version 15) and this .sln says it is for VS 2019.

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks good. But I'd wait for @ericstj to give the thumbs up as he's the expert here.

<PropertyGroup>
<!-- needs to contain all frameworks which src projects wish to restore -->
<TargetFramework Condition="'$(UseIntrinsics)' != 'true'">netstandard2.0</TargetFramework>
<TargetFrameworks Condition="'$(UseIntrinsics)' == 'true'">netstandard2.0;netcoreapp3.0</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why should we have the condition here? Is there any harm in always resolving for both TFMs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usually netcoreapp3.0 causes problems when you are building in VS 2017 where the SDK throws an error saying I don't support netcoreapp3.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

<Error Condition="'@(_contractReferencePath)' == ''" Text="Could not locate $(ContractName)" />
</Target>

<Target Name="Build">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be improved by changing the project extension and defining a couple targets. We do that elsewhere:
dotnet/project-system#4647

IOW: call this a .proj, or a .restoreproj or something. SLN entry looks the same (you have to do it manually in text editor, IDE won't let you). Add the workaround I linked, define stub targets for anything that fails, and it should avoid
the confusion around a CSProj that doesn't build anything.
You don't need to do that now, but I think it would make this more sensible.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I have tried to add the lines found in the issue to the new .restoreproj file but that did not work.
I will keep it as is for now then.

@ericstj

Copy link
Copy Markdown
Member

Have you made sure you see a failure when making a breaking API change?

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Yes I have done a few tests where I rename methods and such and the build was failing.

<ItemGroup>
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lines 24 and 26 are identical... 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@RussKie - can you log an issue (or even submit a PR for the fix)?

@ghostghost locked as resolved and limited conversation to collaborators Mar 22, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

BuildBuild related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add API breaking change definition and enforce it

4 participants

@artidoro@ericstj@RussKie@eerhardt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

API Compat tool in ML.NET - #3623

Merged
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat
May 4, 2019
Merged

API Compat tool in ML.NET#3623
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat

Conversation

@artidoro

@artidoroartidoro commented Apr 30, 2019

Copy link
Copy Markdown
Contributor

Fixes#3602.

We need to ensure that future changes to ML.NET will not break the stable API released in 1.0.0.

This PR introduces the API Compat tool from dotnet/Arcade. The API Compat tool runs as part of the build process and compares the assemblies with those found in the stable nugets referenced in the Microsoft.ML.StableAPI project.

The tool is only run for the assemblies which will be part of the stable nugets. Here is a list of those assemblies and the relative nugets:

Stable NugetStable Assemblies
Microsoft.MLMicrosoft.ML.Core, Microsoft.ML.Data, Microsoft.ML.KMeansClustering, Microsoft.ML.PCA, Microsoft.ML.StandardTrainers, MIcrosoft.ML.Transforms, Microsoft.ML.Analyzer
Microsoft.ML.DataViewMicrosoft.ML.DataView
Microsoft.ML.CpuMathMicrosoft.ML.CpuMath
Microsoft.ML.FastTreeMicrosoft.ML.FastTree
Microsoft.ML.LightGbmMicrosoft.ML.LightGbm
Microsoft.ML.ImageAnalyticsMicrosoft.ML.ImageAnalytics
Microsoft.ML.MklComponentsMicrosoft.ML.Mkl.Components

Note: the tool does not run on Microsoft.ML.Analyzer as it does not have a public API, so no need to check backwards compatibility.

Still to do:

  • Fix possible bug in API Compat on handling of Attributes.
  • Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes. Not needed see comments below.
  • Update the version of the ML.NET nugets to 1.0.0 when available

@artidoroartidoro added the Build Build related issue label Apr 30, 2019
@artidoroartidoro self-assigned this Apr 30, 2019

@ericstjericstj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry if some of these were issues with my initial sample.

Comment threadDirectory.Build.props Outdated
Comment threadsrc/Directory.Build.targets Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated

</Target>

<!-- API Compat -->

@ericstjericstjApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider moving these to a seperate targets file if that is a convention you'd like to follow in this repo. #Pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we only have one for the src repo. But let me know if there is a better way.


In reply to: 279938766 [](ancestors = 279938766)

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview-27625-16"/>

@eerhardteerhardtApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nit) you can use the latest 1.0.0-preview build: 1.0.0-preview-27630-5. We just spun it and will have the official 1.0.0 up soon. #Resolved

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Will update to the new build and change to 1.0.0 as soon as it is available.


In reply to: 279941849 [](ancestors = 279941849)

@eerhardteerhardtMay 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's available on myget now. You should be able to use 1.0.0. #Resolved

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member
D:\a\1\s\packages\microsoft.dotnet.apicompat\1.0.0-beta.19225.5\build\Microsoft.DotNet.ApiCompat.targets(72,5): error : CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.ML.ExtensionBaseAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. [D:\a\1\s\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj]

This is happening because APICompat is not resolving the System.AttributeTargets enum from the contract. It's not resolving because you aren't providing the dependencies. Today these can be passed in via the $(ContractOutputPath) property but that isn't very sensible. I'll submit a change to APICompat to make that easier.
https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L46-L52 #Pending

@artidoro

Copy link
Copy Markdown
ContributorAuthor

That would be great! Thank you


In reply to: 488135991 [](ancestors = 488135991)

@artidoro

artidoro commented Apr 30, 2019

Copy link
Copy Markdown
ContributorAuthor

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version.

@ericstj is it possible to specify the path for the generated file?
Also, how would we specify known diffs going forward? I would like to write some documentation on how to do that. #Resolved

@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

by default the generated file gets written to the same directory as the project with the name, but you can customize it: https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L22-L23

how would we specify known diffs going forward?

You can use the same option I mentioned when building individual projects, you can also copy the errors and paste them into the baseline file. I want to stress that these aren't "known diffs" these are compatibility bugs that break your customers and you really shouldn't be baselining them or introducing the suppressions. #Resolved

@ericstjericstj mentioned this pull request May 1, 2019
4 tasks
@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

To provide paths to contract dependencies, add the following in your GetContract target:

 <_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_contractReferencePath DependencyPaths="@(_allReferenceDirectories)" />

Then in ResolveMatchingContract add the following after you get the ResolvedMatchingContract item:

<PropertyGroup>
<ContractOutputPath>%(ResolvedMatchingContract.DependencyPaths)</ContractOutputPath>
</PropertyGroup>

I'm putting a feature into the APICompat targets that will make the latter property unnecessary. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project will actually build a .dll when we build the .sln file. That seems unnecessary. Maybe we should override the Build target or maybe not name it .csproj and instead just .proj? It's mission in life isn't to build .cs files into a .dll, but instead pull down external packages and provide the GetContract target.

@artidoroartidoroMay 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I tried renaming, but that did not work (it gave an error saying that project.assets.json was not generated.
I have also tried to overwrite the Build target, but I must have made some mistake since I still found the generated .dll.

What I did was adding:

 <Target Name="Build">
<!-- This will override the default Build target. -->
</Target>

to the .csproj file.

What is the correct way to overwrite it?


In reply to: 280105436 [](ancestors = 280105436)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I think that is fine.

Comment threadDirectory.Build.props Outdated
@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you that seems to make it work!


In reply to: 488287870 [](ancestors = 488287870)

@artidoroartidoro changed the title WIP: API Compat tool in ML.NETAPI Compat tool in ML.NETMay 3, 2019
@codecov

codecovBot commented May 3, 2019

Copy link
Copy Markdown

Codecov Report

Merging #3623 into master will increase coverage by <.01%.
The diff coverage is n/a.

@@ Coverage Diff @@## master #3623 +/- ##
==========================================
+ Coverage 72.78% 72.78% +<.01% 
==========================================
Files 808 808 Lines 145588 145588 Branches 16250 16250 ==========================================
+ Hits 105960 105968 +8 + Misses 35205 35198 -7 + Partials 4423 4422 -1
FlagCoverage Δ
#Debug72.78% <ø> (ø)⬆️
#production68.28% <ø> (ø)⬆️
#test89.04% <ø> (ø)⬆️
Impacted FilesCoverage Δ
...StandardTrainers/Standard/LinearModelParameters.cs60.05% <0%> (-0.27%)⬇️
...icrosoft.ML.TensorFlow/TensorFlow/TensorGeneric.cs44.21% <0%> (ø)⬆️
...c/Microsoft.ML.FastTree/Utils/BufferPoolManager.cs0% <0%> (ø)⬆️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.26% <0%> (+0.15%)⬆️
...soft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs84.9% <0%> (+0.2%)⬆️
...soft.ML.TestFramework/DataPipe/TestDataPipeBase.cs73.93% <0%> (+0.32%)⬆️
src/Microsoft.ML.Transforms/Text/LdaTransform.cs89.89% <0%> (+0.62%)⬆️

@ericstj

Copy link
Copy Markdown
Member

failing on linux because dotnet is not on the path and the $(ToolHostCmd) is not set to point to it.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you @ericstj and @eerhardt for looking at the PR, I have addressed your comments.
Let me know if there are other things I should look into!

@ericstj

Copy link
Copy Markdown
Member

Cool, this is looking pretty good. You may want to wait for my changes dotnet/arcade#2672 which help simplify some of this.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

I would prefer checking in this change as soon as possible and updating it with the new buyer as soon as it is available.

Since we have released yesterday, it would be great to have the API Compat tool in the repo.

Comment threadMicrosoft.ML.sln Outdated
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2026
# Visual Studio Version 16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You may want to revert these two lines. I don't know what happens if someone tries opening the solution with VS 2017 (which is version 15) and this .sln says it is for VS 2019.

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks good. But I'd wait for @ericstj to give the thumbs up as he's the expert here.

<PropertyGroup>
<!-- needs to contain all frameworks which src projects wish to restore -->
<TargetFramework Condition="'$(UseIntrinsics)' != 'true'">netstandard2.0</TargetFramework>
<TargetFrameworks Condition="'$(UseIntrinsics)' == 'true'">netstandard2.0;netcoreapp3.0</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why should we have the condition here? Is there any harm in always resolving for both TFMs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usually netcoreapp3.0 causes problems when you are building in VS 2017 where the SDK throws an error saying I don't support netcoreapp3.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

<Error Condition="'@(_contractReferencePath)' == ''" Text="Could not locate $(ContractName)" />
</Target>

<Target Name="Build">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be improved by changing the project extension and defining a couple targets. We do that elsewhere:
dotnet/project-system#4647

IOW: call this a .proj, or a .restoreproj or something. SLN entry looks the same (you have to do it manually in text editor, IDE won't let you). Add the workaround I linked, define stub targets for anything that fails, and it should avoid
the confusion around a CSProj that doesn't build anything.
You don't need to do that now, but I think it would make this more sensible.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I have tried to add the lines found in the issue to the new .restoreproj file but that did not work.
I will keep it as is for now then.

@ericstj

Copy link
Copy Markdown
Member

Have you made sure you see a failure when making a breaking API change?

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Yes I have done a few tests where I rename methods and such and the build was failing.

<ItemGroup>
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lines 24 and 26 are identical... 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@RussKie - can you log an issue (or even submit a PR for the fix)?

@ghostghost locked as resolved and limited conversation to collaborators Mar 22, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

BuildBuild related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add API breaking change definition and enforce it

4 participants

@artidoro@ericstj@RussKie@eerhardt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

API Compat tool in ML.NET - #3623

Merged
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat
May 4, 2019
Merged

API Compat tool in ML.NET#3623
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat

Conversation

@artidoro

@artidoroartidoro commented Apr 30, 2019

Copy link
Copy Markdown
Contributor

Fixes#3602.

We need to ensure that future changes to ML.NET will not break the stable API released in 1.0.0.

This PR introduces the API Compat tool from dotnet/Arcade. The API Compat tool runs as part of the build process and compares the assemblies with those found in the stable nugets referenced in the Microsoft.ML.StableAPI project.

The tool is only run for the assemblies which will be part of the stable nugets. Here is a list of those assemblies and the relative nugets:

Stable NugetStable Assemblies
Microsoft.MLMicrosoft.ML.Core, Microsoft.ML.Data, Microsoft.ML.KMeansClustering, Microsoft.ML.PCA, Microsoft.ML.StandardTrainers, MIcrosoft.ML.Transforms, Microsoft.ML.Analyzer
Microsoft.ML.DataViewMicrosoft.ML.DataView
Microsoft.ML.CpuMathMicrosoft.ML.CpuMath
Microsoft.ML.FastTreeMicrosoft.ML.FastTree
Microsoft.ML.LightGbmMicrosoft.ML.LightGbm
Microsoft.ML.ImageAnalyticsMicrosoft.ML.ImageAnalytics
Microsoft.ML.MklComponentsMicrosoft.ML.Mkl.Components

Note: the tool does not run on Microsoft.ML.Analyzer as it does not have a public API, so no need to check backwards compatibility.

Still to do:

  • Fix possible bug in API Compat on handling of Attributes.
  • Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes. Not needed see comments below.
  • Update the version of the ML.NET nugets to 1.0.0 when available

@artidoroartidoro added the Build Build related issue label Apr 30, 2019
@artidoroartidoro self-assigned this Apr 30, 2019

@ericstjericstj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry if some of these were issues with my initial sample.

Comment threadDirectory.Build.props Outdated
Comment threadsrc/Directory.Build.targets Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated

</Target>

<!-- API Compat -->

@ericstjericstjApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider moving these to a seperate targets file if that is a convention you'd like to follow in this repo. #Pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we only have one for the src repo. But let me know if there is a better way.


In reply to: 279938766 [](ancestors = 279938766)

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview-27625-16"/>

@eerhardteerhardtApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nit) you can use the latest 1.0.0-preview build: 1.0.0-preview-27630-5. We just spun it and will have the official 1.0.0 up soon. #Resolved

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Will update to the new build and change to 1.0.0 as soon as it is available.


In reply to: 279941849 [](ancestors = 279941849)

@eerhardteerhardtMay 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's available on myget now. You should be able to use 1.0.0. #Resolved

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member
D:\a\1\s\packages\microsoft.dotnet.apicompat\1.0.0-beta.19225.5\build\Microsoft.DotNet.ApiCompat.targets(72,5): error : CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.ML.ExtensionBaseAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. [D:\a\1\s\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj]

This is happening because APICompat is not resolving the System.AttributeTargets enum from the contract. It's not resolving because you aren't providing the dependencies. Today these can be passed in via the $(ContractOutputPath) property but that isn't very sensible. I'll submit a change to APICompat to make that easier.
https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L46-L52 #Pending

@artidoro

Copy link
Copy Markdown
ContributorAuthor

That would be great! Thank you


In reply to: 488135991 [](ancestors = 488135991)

@artidoro

artidoro commented Apr 30, 2019

Copy link
Copy Markdown
ContributorAuthor

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version.

@ericstj is it possible to specify the path for the generated file?
Also, how would we specify known diffs going forward? I would like to write some documentation on how to do that. #Resolved

@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

by default the generated file gets written to the same directory as the project with the name, but you can customize it: https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L22-L23

how would we specify known diffs going forward?

You can use the same option I mentioned when building individual projects, you can also copy the errors and paste them into the baseline file. I want to stress that these aren't "known diffs" these are compatibility bugs that break your customers and you really shouldn't be baselining them or introducing the suppressions. #Resolved

@ericstjericstj mentioned this pull request May 1, 2019
4 tasks
@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

To provide paths to contract dependencies, add the following in your GetContract target:

 <_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_contractReferencePath DependencyPaths="@(_allReferenceDirectories)" />

Then in ResolveMatchingContract add the following after you get the ResolvedMatchingContract item:

<PropertyGroup>
<ContractOutputPath>%(ResolvedMatchingContract.DependencyPaths)</ContractOutputPath>
</PropertyGroup>

I'm putting a feature into the APICompat targets that will make the latter property unnecessary. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project will actually build a .dll when we build the .sln file. That seems unnecessary. Maybe we should override the Build target or maybe not name it .csproj and instead just .proj? It's mission in life isn't to build .cs files into a .dll, but instead pull down external packages and provide the GetContract target.

@artidoroartidoroMay 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I tried renaming, but that did not work (it gave an error saying that project.assets.json was not generated.
I have also tried to overwrite the Build target, but I must have made some mistake since I still found the generated .dll.

What I did was adding:

 <Target Name="Build">
<!-- This will override the default Build target. -->
</Target>

to the .csproj file.

What is the correct way to overwrite it?


In reply to: 280105436 [](ancestors = 280105436)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I think that is fine.

Comment threadDirectory.Build.props Outdated
@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you that seems to make it work!


In reply to: 488287870 [](ancestors = 488287870)

@artidoroartidoro changed the title WIP: API Compat tool in ML.NETAPI Compat tool in ML.NETMay 3, 2019
@codecov

codecovBot commented May 3, 2019

Copy link
Copy Markdown

Codecov Report

Merging #3623 into master will increase coverage by <.01%.
The diff coverage is n/a.

@@ Coverage Diff @@## master #3623 +/- ##
==========================================
+ Coverage 72.78% 72.78% +<.01% 
==========================================
Files 808 808 Lines 145588 145588 Branches 16250 16250 ==========================================
+ Hits 105960 105968 +8 + Misses 35205 35198 -7 + Partials 4423 4422 -1
FlagCoverage Δ
#Debug72.78% <ø> (ø)⬆️
#production68.28% <ø> (ø)⬆️
#test89.04% <ø> (ø)⬆️
Impacted FilesCoverage Δ
...StandardTrainers/Standard/LinearModelParameters.cs60.05% <0%> (-0.27%)⬇️
...icrosoft.ML.TensorFlow/TensorFlow/TensorGeneric.cs44.21% <0%> (ø)⬆️
...c/Microsoft.ML.FastTree/Utils/BufferPoolManager.cs0% <0%> (ø)⬆️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.26% <0%> (+0.15%)⬆️
...soft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs84.9% <0%> (+0.2%)⬆️
...soft.ML.TestFramework/DataPipe/TestDataPipeBase.cs73.93% <0%> (+0.32%)⬆️
src/Microsoft.ML.Transforms/Text/LdaTransform.cs89.89% <0%> (+0.62%)⬆️

@ericstj

Copy link
Copy Markdown
Member

failing on linux because dotnet is not on the path and the $(ToolHostCmd) is not set to point to it.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you @ericstj and @eerhardt for looking at the PR, I have addressed your comments.
Let me know if there are other things I should look into!

@ericstj

Copy link
Copy Markdown
Member

Cool, this is looking pretty good. You may want to wait for my changes dotnet/arcade#2672 which help simplify some of this.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

I would prefer checking in this change as soon as possible and updating it with the new buyer as soon as it is available.

Since we have released yesterday, it would be great to have the API Compat tool in the repo.

Comment threadMicrosoft.ML.sln Outdated
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2026
# Visual Studio Version 16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You may want to revert these two lines. I don't know what happens if someone tries opening the solution with VS 2017 (which is version 15) and this .sln says it is for VS 2019.

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks good. But I'd wait for @ericstj to give the thumbs up as he's the expert here.

<PropertyGroup>
<!-- needs to contain all frameworks which src projects wish to restore -->
<TargetFramework Condition="'$(UseIntrinsics)' != 'true'">netstandard2.0</TargetFramework>
<TargetFrameworks Condition="'$(UseIntrinsics)' == 'true'">netstandard2.0;netcoreapp3.0</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why should we have the condition here? Is there any harm in always resolving for both TFMs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usually netcoreapp3.0 causes problems when you are building in VS 2017 where the SDK throws an error saying I don't support netcoreapp3.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

<Error Condition="'@(_contractReferencePath)' == ''" Text="Could not locate $(ContractName)" />
</Target>

<Target Name="Build">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be improved by changing the project extension and defining a couple targets. We do that elsewhere:
dotnet/project-system#4647

IOW: call this a .proj, or a .restoreproj or something. SLN entry looks the same (you have to do it manually in text editor, IDE won't let you). Add the workaround I linked, define stub targets for anything that fails, and it should avoid
the confusion around a CSProj that doesn't build anything.
You don't need to do that now, but I think it would make this more sensible.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I have tried to add the lines found in the issue to the new .restoreproj file but that did not work.
I will keep it as is for now then.

@ericstj

Copy link
Copy Markdown
Member

Have you made sure you see a failure when making a breaking API change?

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Yes I have done a few tests where I rename methods and such and the build was failing.

<ItemGroup>
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lines 24 and 26 are identical... 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@RussKie - can you log an issue (or even submit a PR for the fix)?

@ghostghost locked as resolved and limited conversation to collaborators Mar 22, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

BuildBuild related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add API breaking change definition and enforce it

4 participants

@artidoro@ericstj@RussKie@eerhardt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

API Compat tool in ML.NET - #3623

Merged
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat
May 4, 2019
Merged

API Compat tool in ML.NET#3623
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat

Conversation

@artidoro

@artidoroartidoro commented Apr 30, 2019

Copy link
Copy Markdown
Contributor

Fixes#3602.

We need to ensure that future changes to ML.NET will not break the stable API released in 1.0.0.

This PR introduces the API Compat tool from dotnet/Arcade. The API Compat tool runs as part of the build process and compares the assemblies with those found in the stable nugets referenced in the Microsoft.ML.StableAPI project.

The tool is only run for the assemblies which will be part of the stable nugets. Here is a list of those assemblies and the relative nugets:

Stable NugetStable Assemblies
Microsoft.MLMicrosoft.ML.Core, Microsoft.ML.Data, Microsoft.ML.KMeansClustering, Microsoft.ML.PCA, Microsoft.ML.StandardTrainers, MIcrosoft.ML.Transforms, Microsoft.ML.Analyzer
Microsoft.ML.DataViewMicrosoft.ML.DataView
Microsoft.ML.CpuMathMicrosoft.ML.CpuMath
Microsoft.ML.FastTreeMicrosoft.ML.FastTree
Microsoft.ML.LightGbmMicrosoft.ML.LightGbm
Microsoft.ML.ImageAnalyticsMicrosoft.ML.ImageAnalytics
Microsoft.ML.MklComponentsMicrosoft.ML.Mkl.Components

Note: the tool does not run on Microsoft.ML.Analyzer as it does not have a public API, so no need to check backwards compatibility.

Still to do:

  • Fix possible bug in API Compat on handling of Attributes.
  • Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes. Not needed see comments below.
  • Update the version of the ML.NET nugets to 1.0.0 when available

@artidoroartidoro added the Build Build related issue label Apr 30, 2019
@artidoroartidoro self-assigned this Apr 30, 2019

@ericstjericstj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry if some of these were issues with my initial sample.

Comment threadDirectory.Build.props Outdated
Comment threadsrc/Directory.Build.targets Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated

</Target>

<!-- API Compat -->

@ericstjericstjApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider moving these to a seperate targets file if that is a convention you'd like to follow in this repo. #Pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we only have one for the src repo. But let me know if there is a better way.


In reply to: 279938766 [](ancestors = 279938766)

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview-27625-16"/>

@eerhardteerhardtApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nit) you can use the latest 1.0.0-preview build: 1.0.0-preview-27630-5. We just spun it and will have the official 1.0.0 up soon. #Resolved

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Will update to the new build and change to 1.0.0 as soon as it is available.


In reply to: 279941849 [](ancestors = 279941849)

@eerhardteerhardtMay 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's available on myget now. You should be able to use 1.0.0. #Resolved

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member
D:\a\1\s\packages\microsoft.dotnet.apicompat\1.0.0-beta.19225.5\build\Microsoft.DotNet.ApiCompat.targets(72,5): error : CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.ML.ExtensionBaseAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. [D:\a\1\s\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj]

This is happening because APICompat is not resolving the System.AttributeTargets enum from the contract. It's not resolving because you aren't providing the dependencies. Today these can be passed in via the $(ContractOutputPath) property but that isn't very sensible. I'll submit a change to APICompat to make that easier.
https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L46-L52 #Pending

@artidoro

Copy link
Copy Markdown
ContributorAuthor

That would be great! Thank you


In reply to: 488135991 [](ancestors = 488135991)

@artidoro

artidoro commented Apr 30, 2019

Copy link
Copy Markdown
ContributorAuthor

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version.

@ericstj is it possible to specify the path for the generated file?
Also, how would we specify known diffs going forward? I would like to write some documentation on how to do that. #Resolved

@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

by default the generated file gets written to the same directory as the project with the name, but you can customize it: https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L22-L23

how would we specify known diffs going forward?

You can use the same option I mentioned when building individual projects, you can also copy the errors and paste them into the baseline file. I want to stress that these aren't "known diffs" these are compatibility bugs that break your customers and you really shouldn't be baselining them or introducing the suppressions. #Resolved

@ericstjericstj mentioned this pull request May 1, 2019
4 tasks
@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

To provide paths to contract dependencies, add the following in your GetContract target:

 <_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_contractReferencePath DependencyPaths="@(_allReferenceDirectories)" />

Then in ResolveMatchingContract add the following after you get the ResolvedMatchingContract item:

<PropertyGroup>
<ContractOutputPath>%(ResolvedMatchingContract.DependencyPaths)</ContractOutputPath>
</PropertyGroup>

I'm putting a feature into the APICompat targets that will make the latter property unnecessary. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project will actually build a .dll when we build the .sln file. That seems unnecessary. Maybe we should override the Build target or maybe not name it .csproj and instead just .proj? It's mission in life isn't to build .cs files into a .dll, but instead pull down external packages and provide the GetContract target.

@artidoroartidoroMay 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I tried renaming, but that did not work (it gave an error saying that project.assets.json was not generated.
I have also tried to overwrite the Build target, but I must have made some mistake since I still found the generated .dll.

What I did was adding:

 <Target Name="Build">
<!-- This will override the default Build target. -->
</Target>

to the .csproj file.

What is the correct way to overwrite it?


In reply to: 280105436 [](ancestors = 280105436)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I think that is fine.

Comment threadDirectory.Build.props Outdated
@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you that seems to make it work!


In reply to: 488287870 [](ancestors = 488287870)

@artidoroartidoro changed the title WIP: API Compat tool in ML.NETAPI Compat tool in ML.NETMay 3, 2019
@codecov

codecovBot commented May 3, 2019

Copy link
Copy Markdown

Codecov Report

Merging #3623 into master will increase coverage by <.01%.
The diff coverage is n/a.

@@ Coverage Diff @@## master #3623 +/- ##
==========================================
+ Coverage 72.78% 72.78% +<.01% 
==========================================
Files 808 808 Lines 145588 145588 Branches 16250 16250 ==========================================
+ Hits 105960 105968 +8 + Misses 35205 35198 -7 + Partials 4423 4422 -1
FlagCoverage Δ
#Debug72.78% <ø> (ø)⬆️
#production68.28% <ø> (ø)⬆️
#test89.04% <ø> (ø)⬆️
Impacted FilesCoverage Δ
...StandardTrainers/Standard/LinearModelParameters.cs60.05% <0%> (-0.27%)⬇️
...icrosoft.ML.TensorFlow/TensorFlow/TensorGeneric.cs44.21% <0%> (ø)⬆️
...c/Microsoft.ML.FastTree/Utils/BufferPoolManager.cs0% <0%> (ø)⬆️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.26% <0%> (+0.15%)⬆️
...soft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs84.9% <0%> (+0.2%)⬆️
...soft.ML.TestFramework/DataPipe/TestDataPipeBase.cs73.93% <0%> (+0.32%)⬆️
src/Microsoft.ML.Transforms/Text/LdaTransform.cs89.89% <0%> (+0.62%)⬆️

@ericstj

Copy link
Copy Markdown
Member

failing on linux because dotnet is not on the path and the $(ToolHostCmd) is not set to point to it.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you @ericstj and @eerhardt for looking at the PR, I have addressed your comments.
Let me know if there are other things I should look into!

@ericstj

Copy link
Copy Markdown
Member

Cool, this is looking pretty good. You may want to wait for my changes dotnet/arcade#2672 which help simplify some of this.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

I would prefer checking in this change as soon as possible and updating it with the new buyer as soon as it is available.

Since we have released yesterday, it would be great to have the API Compat tool in the repo.

Comment threadMicrosoft.ML.sln Outdated
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2026
# Visual Studio Version 16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You may want to revert these two lines. I don't know what happens if someone tries opening the solution with VS 2017 (which is version 15) and this .sln says it is for VS 2019.

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks good. But I'd wait for @ericstj to give the thumbs up as he's the expert here.

<PropertyGroup>
<!-- needs to contain all frameworks which src projects wish to restore -->
<TargetFramework Condition="'$(UseIntrinsics)' != 'true'">netstandard2.0</TargetFramework>
<TargetFrameworks Condition="'$(UseIntrinsics)' == 'true'">netstandard2.0;netcoreapp3.0</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why should we have the condition here? Is there any harm in always resolving for both TFMs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usually netcoreapp3.0 causes problems when you are building in VS 2017 where the SDK throws an error saying I don't support netcoreapp3.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

<Error Condition="'@(_contractReferencePath)' == ''" Text="Could not locate $(ContractName)" />
</Target>

<Target Name="Build">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be improved by changing the project extension and defining a couple targets. We do that elsewhere:
dotnet/project-system#4647

IOW: call this a .proj, or a .restoreproj or something. SLN entry looks the same (you have to do it manually in text editor, IDE won't let you). Add the workaround I linked, define stub targets for anything that fails, and it should avoid
the confusion around a CSProj that doesn't build anything.
You don't need to do that now, but I think it would make this more sensible.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I have tried to add the lines found in the issue to the new .restoreproj file but that did not work.
I will keep it as is for now then.

@ericstj

Copy link
Copy Markdown
Member

Have you made sure you see a failure when making a breaking API change?

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Yes I have done a few tests where I rename methods and such and the build was failing.

<ItemGroup>
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lines 24 and 26 are identical... 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@RussKie - can you log an issue (or even submit a PR for the fix)?

@ghostghost locked as resolved and limited conversation to collaborators Mar 22, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

BuildBuild related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add API breaking change definition and enforce it

4 participants

@artidoro@ericstj@RussKie@eerhardt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

API Compat tool in ML.NET - #3623

Merged
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat
May 4, 2019
Merged

API Compat tool in ML.NET#3623
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat

Conversation

@artidoro

@artidoroartidoro commented Apr 30, 2019

Copy link
Copy Markdown
Contributor

Fixes#3602.

We need to ensure that future changes to ML.NET will not break the stable API released in 1.0.0.

This PR introduces the API Compat tool from dotnet/Arcade. The API Compat tool runs as part of the build process and compares the assemblies with those found in the stable nugets referenced in the Microsoft.ML.StableAPI project.

The tool is only run for the assemblies which will be part of the stable nugets. Here is a list of those assemblies and the relative nugets:

Stable NugetStable Assemblies
Microsoft.MLMicrosoft.ML.Core, Microsoft.ML.Data, Microsoft.ML.KMeansClustering, Microsoft.ML.PCA, Microsoft.ML.StandardTrainers, MIcrosoft.ML.Transforms, Microsoft.ML.Analyzer
Microsoft.ML.DataViewMicrosoft.ML.DataView
Microsoft.ML.CpuMathMicrosoft.ML.CpuMath
Microsoft.ML.FastTreeMicrosoft.ML.FastTree
Microsoft.ML.LightGbmMicrosoft.ML.LightGbm
Microsoft.ML.ImageAnalyticsMicrosoft.ML.ImageAnalytics
Microsoft.ML.MklComponentsMicrosoft.ML.Mkl.Components

Note: the tool does not run on Microsoft.ML.Analyzer as it does not have a public API, so no need to check backwards compatibility.

Still to do:

  • Fix possible bug in API Compat on handling of Attributes.
  • Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes. Not needed see comments below.
  • Update the version of the ML.NET nugets to 1.0.0 when available

@artidoroartidoro added the Build Build related issue label Apr 30, 2019
@artidoroartidoro self-assigned this Apr 30, 2019

@ericstjericstj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry if some of these were issues with my initial sample.

Comment threadDirectory.Build.props Outdated
Comment threadsrc/Directory.Build.targets Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated

</Target>

<!-- API Compat -->

@ericstjericstjApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider moving these to a seperate targets file if that is a convention you'd like to follow in this repo. #Pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we only have one for the src repo. But let me know if there is a better way.


In reply to: 279938766 [](ancestors = 279938766)

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview-27625-16"/>

@eerhardteerhardtApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nit) you can use the latest 1.0.0-preview build: 1.0.0-preview-27630-5. We just spun it and will have the official 1.0.0 up soon. #Resolved

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Will update to the new build and change to 1.0.0 as soon as it is available.


In reply to: 279941849 [](ancestors = 279941849)

@eerhardteerhardtMay 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's available on myget now. You should be able to use 1.0.0. #Resolved

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member
D:\a\1\s\packages\microsoft.dotnet.apicompat\1.0.0-beta.19225.5\build\Microsoft.DotNet.ApiCompat.targets(72,5): error : CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.ML.ExtensionBaseAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. [D:\a\1\s\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj]

This is happening because APICompat is not resolving the System.AttributeTargets enum from the contract. It's not resolving because you aren't providing the dependencies. Today these can be passed in via the $(ContractOutputPath) property but that isn't very sensible. I'll submit a change to APICompat to make that easier.
https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L46-L52 #Pending

@artidoro

Copy link
Copy Markdown
ContributorAuthor

That would be great! Thank you


In reply to: 488135991 [](ancestors = 488135991)

@artidoro

artidoro commented Apr 30, 2019

Copy link
Copy Markdown
ContributorAuthor

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version.

@ericstj is it possible to specify the path for the generated file?
Also, how would we specify known diffs going forward? I would like to write some documentation on how to do that. #Resolved

@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

by default the generated file gets written to the same directory as the project with the name, but you can customize it: https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L22-L23

how would we specify known diffs going forward?

You can use the same option I mentioned when building individual projects, you can also copy the errors and paste them into the baseline file. I want to stress that these aren't "known diffs" these are compatibility bugs that break your customers and you really shouldn't be baselining them or introducing the suppressions. #Resolved

@ericstjericstj mentioned this pull request May 1, 2019
4 tasks
@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

To provide paths to contract dependencies, add the following in your GetContract target:

 <_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_contractReferencePath DependencyPaths="@(_allReferenceDirectories)" />

Then in ResolveMatchingContract add the following after you get the ResolvedMatchingContract item:

<PropertyGroup>
<ContractOutputPath>%(ResolvedMatchingContract.DependencyPaths)</ContractOutputPath>
</PropertyGroup>

I'm putting a feature into the APICompat targets that will make the latter property unnecessary. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project will actually build a .dll when we build the .sln file. That seems unnecessary. Maybe we should override the Build target or maybe not name it .csproj and instead just .proj? It's mission in life isn't to build .cs files into a .dll, but instead pull down external packages and provide the GetContract target.

@artidoroartidoroMay 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I tried renaming, but that did not work (it gave an error saying that project.assets.json was not generated.
I have also tried to overwrite the Build target, but I must have made some mistake since I still found the generated .dll.

What I did was adding:

 <Target Name="Build">
<!-- This will override the default Build target. -->
</Target>

to the .csproj file.

What is the correct way to overwrite it?


In reply to: 280105436 [](ancestors = 280105436)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I think that is fine.

Comment threadDirectory.Build.props Outdated
@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you that seems to make it work!


In reply to: 488287870 [](ancestors = 488287870)

@artidoroartidoro changed the title WIP: API Compat tool in ML.NETAPI Compat tool in ML.NETMay 3, 2019
@codecov

codecovBot commented May 3, 2019

Copy link
Copy Markdown

Codecov Report

Merging #3623 into master will increase coverage by <.01%.
The diff coverage is n/a.

@@ Coverage Diff @@## master #3623 +/- ##
==========================================
+ Coverage 72.78% 72.78% +<.01% 
==========================================
Files 808 808 Lines 145588 145588 Branches 16250 16250 ==========================================
+ Hits 105960 105968 +8 + Misses 35205 35198 -7 + Partials 4423 4422 -1
FlagCoverage Δ
#Debug72.78% <ø> (ø)⬆️
#production68.28% <ø> (ø)⬆️
#test89.04% <ø> (ø)⬆️
Impacted FilesCoverage Δ
...StandardTrainers/Standard/LinearModelParameters.cs60.05% <0%> (-0.27%)⬇️
...icrosoft.ML.TensorFlow/TensorFlow/TensorGeneric.cs44.21% <0%> (ø)⬆️
...c/Microsoft.ML.FastTree/Utils/BufferPoolManager.cs0% <0%> (ø)⬆️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.26% <0%> (+0.15%)⬆️
...soft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs84.9% <0%> (+0.2%)⬆️
...soft.ML.TestFramework/DataPipe/TestDataPipeBase.cs73.93% <0%> (+0.32%)⬆️
src/Microsoft.ML.Transforms/Text/LdaTransform.cs89.89% <0%> (+0.62%)⬆️

@ericstj

Copy link
Copy Markdown
Member

failing on linux because dotnet is not on the path and the $(ToolHostCmd) is not set to point to it.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you @ericstj and @eerhardt for looking at the PR, I have addressed your comments.
Let me know if there are other things I should look into!

@ericstj

Copy link
Copy Markdown
Member

Cool, this is looking pretty good. You may want to wait for my changes dotnet/arcade#2672 which help simplify some of this.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

I would prefer checking in this change as soon as possible and updating it with the new buyer as soon as it is available.

Since we have released yesterday, it would be great to have the API Compat tool in the repo.

Comment threadMicrosoft.ML.sln Outdated
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2026
# Visual Studio Version 16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You may want to revert these two lines. I don't know what happens if someone tries opening the solution with VS 2017 (which is version 15) and this .sln says it is for VS 2019.

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks good. But I'd wait for @ericstj to give the thumbs up as he's the expert here.

<PropertyGroup>
<!-- needs to contain all frameworks which src projects wish to restore -->
<TargetFramework Condition="'$(UseIntrinsics)' != 'true'">netstandard2.0</TargetFramework>
<TargetFrameworks Condition="'$(UseIntrinsics)' == 'true'">netstandard2.0;netcoreapp3.0</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why should we have the condition here? Is there any harm in always resolving for both TFMs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usually netcoreapp3.0 causes problems when you are building in VS 2017 where the SDK throws an error saying I don't support netcoreapp3.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

<Error Condition="'@(_contractReferencePath)' == ''" Text="Could not locate $(ContractName)" />
</Target>

<Target Name="Build">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be improved by changing the project extension and defining a couple targets. We do that elsewhere:
dotnet/project-system#4647

IOW: call this a .proj, or a .restoreproj or something. SLN entry looks the same (you have to do it manually in text editor, IDE won't let you). Add the workaround I linked, define stub targets for anything that fails, and it should avoid
the confusion around a CSProj that doesn't build anything.
You don't need to do that now, but I think it would make this more sensible.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I have tried to add the lines found in the issue to the new .restoreproj file but that did not work.
I will keep it as is for now then.

@ericstj

Copy link
Copy Markdown
Member

Have you made sure you see a failure when making a breaking API change?

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Yes I have done a few tests where I rename methods and such and the build was failing.

<ItemGroup>
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lines 24 and 26 are identical... 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@RussKie - can you log an issue (or even submit a PR for the fix)?

@ghostghost locked as resolved and limited conversation to collaborators Mar 22, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

BuildBuild related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add API breaking change definition and enforce it

4 participants

@artidoro@ericstj@RussKie@eerhardt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

API Compat tool in ML.NET - #3623

Merged
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat
May 4, 2019
Merged

API Compat tool in ML.NET#3623
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat

Conversation

@artidoro

@artidoroartidoro commented Apr 30, 2019

Copy link
Copy Markdown
Contributor

Fixes#3602.

We need to ensure that future changes to ML.NET will not break the stable API released in 1.0.0.

This PR introduces the API Compat tool from dotnet/Arcade. The API Compat tool runs as part of the build process and compares the assemblies with those found in the stable nugets referenced in the Microsoft.ML.StableAPI project.

The tool is only run for the assemblies which will be part of the stable nugets. Here is a list of those assemblies and the relative nugets:

Stable NugetStable Assemblies
Microsoft.MLMicrosoft.ML.Core, Microsoft.ML.Data, Microsoft.ML.KMeansClustering, Microsoft.ML.PCA, Microsoft.ML.StandardTrainers, MIcrosoft.ML.Transforms, Microsoft.ML.Analyzer
Microsoft.ML.DataViewMicrosoft.ML.DataView
Microsoft.ML.CpuMathMicrosoft.ML.CpuMath
Microsoft.ML.FastTreeMicrosoft.ML.FastTree
Microsoft.ML.LightGbmMicrosoft.ML.LightGbm
Microsoft.ML.ImageAnalyticsMicrosoft.ML.ImageAnalytics
Microsoft.ML.MklComponentsMicrosoft.ML.Mkl.Components

Note: the tool does not run on Microsoft.ML.Analyzer as it does not have a public API, so no need to check backwards compatibility.

Still to do:

  • Fix possible bug in API Compat on handling of Attributes.
  • Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes. Not needed see comments below.
  • Update the version of the ML.NET nugets to 1.0.0 when available

@artidoroartidoro added the Build Build related issue label Apr 30, 2019
@artidoroartidoro self-assigned this Apr 30, 2019

@ericstjericstj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry if some of these were issues with my initial sample.

Comment threadDirectory.Build.props Outdated
Comment threadsrc/Directory.Build.targets Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated

</Target>

<!-- API Compat -->

@ericstjericstjApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider moving these to a seperate targets file if that is a convention you'd like to follow in this repo. #Pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we only have one for the src repo. But let me know if there is a better way.


In reply to: 279938766 [](ancestors = 279938766)

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview-27625-16"/>

@eerhardteerhardtApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nit) you can use the latest 1.0.0-preview build: 1.0.0-preview-27630-5. We just spun it and will have the official 1.0.0 up soon. #Resolved

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Will update to the new build and change to 1.0.0 as soon as it is available.


In reply to: 279941849 [](ancestors = 279941849)

@eerhardteerhardtMay 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's available on myget now. You should be able to use 1.0.0. #Resolved

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member
D:\a\1\s\packages\microsoft.dotnet.apicompat\1.0.0-beta.19225.5\build\Microsoft.DotNet.ApiCompat.targets(72,5): error : CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.ML.ExtensionBaseAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. [D:\a\1\s\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj]

This is happening because APICompat is not resolving the System.AttributeTargets enum from the contract. It's not resolving because you aren't providing the dependencies. Today these can be passed in via the $(ContractOutputPath) property but that isn't very sensible. I'll submit a change to APICompat to make that easier.
https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L46-L52 #Pending

@artidoro

Copy link
Copy Markdown
ContributorAuthor

That would be great! Thank you


In reply to: 488135991 [](ancestors = 488135991)

@artidoro

artidoro commented Apr 30, 2019

Copy link
Copy Markdown
ContributorAuthor

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version.

@ericstj is it possible to specify the path for the generated file?
Also, how would we specify known diffs going forward? I would like to write some documentation on how to do that. #Resolved

@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

by default the generated file gets written to the same directory as the project with the name, but you can customize it: https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L22-L23

how would we specify known diffs going forward?

You can use the same option I mentioned when building individual projects, you can also copy the errors and paste them into the baseline file. I want to stress that these aren't "known diffs" these are compatibility bugs that break your customers and you really shouldn't be baselining them or introducing the suppressions. #Resolved

@ericstjericstj mentioned this pull request May 1, 2019
4 tasks
@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

To provide paths to contract dependencies, add the following in your GetContract target:

 <_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_contractReferencePath DependencyPaths="@(_allReferenceDirectories)" />

Then in ResolveMatchingContract add the following after you get the ResolvedMatchingContract item:

<PropertyGroup>
<ContractOutputPath>%(ResolvedMatchingContract.DependencyPaths)</ContractOutputPath>
</PropertyGroup>

I'm putting a feature into the APICompat targets that will make the latter property unnecessary. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project will actually build a .dll when we build the .sln file. That seems unnecessary. Maybe we should override the Build target or maybe not name it .csproj and instead just .proj? It's mission in life isn't to build .cs files into a .dll, but instead pull down external packages and provide the GetContract target.

@artidoroartidoroMay 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I tried renaming, but that did not work (it gave an error saying that project.assets.json was not generated.
I have also tried to overwrite the Build target, but I must have made some mistake since I still found the generated .dll.

What I did was adding:

 <Target Name="Build">
<!-- This will override the default Build target. -->
</Target>

to the .csproj file.

What is the correct way to overwrite it?


In reply to: 280105436 [](ancestors = 280105436)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I think that is fine.

Comment threadDirectory.Build.props Outdated
@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you that seems to make it work!


In reply to: 488287870 [](ancestors = 488287870)

@artidoroartidoro changed the title WIP: API Compat tool in ML.NETAPI Compat tool in ML.NETMay 3, 2019
@codecov

codecovBot commented May 3, 2019

Copy link
Copy Markdown

Codecov Report

Merging #3623 into master will increase coverage by <.01%.
The diff coverage is n/a.

@@ Coverage Diff @@## master #3623 +/- ##
==========================================
+ Coverage 72.78% 72.78% +<.01% 
==========================================
Files 808 808 Lines 145588 145588 Branches 16250 16250 ==========================================
+ Hits 105960 105968 +8 + Misses 35205 35198 -7 + Partials 4423 4422 -1
FlagCoverage Δ
#Debug72.78% <ø> (ø)⬆️
#production68.28% <ø> (ø)⬆️
#test89.04% <ø> (ø)⬆️
Impacted FilesCoverage Δ
...StandardTrainers/Standard/LinearModelParameters.cs60.05% <0%> (-0.27%)⬇️
...icrosoft.ML.TensorFlow/TensorFlow/TensorGeneric.cs44.21% <0%> (ø)⬆️
...c/Microsoft.ML.FastTree/Utils/BufferPoolManager.cs0% <0%> (ø)⬆️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.26% <0%> (+0.15%)⬆️
...soft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs84.9% <0%> (+0.2%)⬆️
...soft.ML.TestFramework/DataPipe/TestDataPipeBase.cs73.93% <0%> (+0.32%)⬆️
src/Microsoft.ML.Transforms/Text/LdaTransform.cs89.89% <0%> (+0.62%)⬆️

@ericstj

Copy link
Copy Markdown
Member

failing on linux because dotnet is not on the path and the $(ToolHostCmd) is not set to point to it.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you @ericstj and @eerhardt for looking at the PR, I have addressed your comments.
Let me know if there are other things I should look into!

@ericstj

Copy link
Copy Markdown
Member

Cool, this is looking pretty good. You may want to wait for my changes dotnet/arcade#2672 which help simplify some of this.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

I would prefer checking in this change as soon as possible and updating it with the new buyer as soon as it is available.

Since we have released yesterday, it would be great to have the API Compat tool in the repo.

Comment threadMicrosoft.ML.sln Outdated
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2026
# Visual Studio Version 16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You may want to revert these two lines. I don't know what happens if someone tries opening the solution with VS 2017 (which is version 15) and this .sln says it is for VS 2019.

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks good. But I'd wait for @ericstj to give the thumbs up as he's the expert here.

<PropertyGroup>
<!-- needs to contain all frameworks which src projects wish to restore -->
<TargetFramework Condition="'$(UseIntrinsics)' != 'true'">netstandard2.0</TargetFramework>
<TargetFrameworks Condition="'$(UseIntrinsics)' == 'true'">netstandard2.0;netcoreapp3.0</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why should we have the condition here? Is there any harm in always resolving for both TFMs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usually netcoreapp3.0 causes problems when you are building in VS 2017 where the SDK throws an error saying I don't support netcoreapp3.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

<Error Condition="'@(_contractReferencePath)' == ''" Text="Could not locate $(ContractName)" />
</Target>

<Target Name="Build">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be improved by changing the project extension and defining a couple targets. We do that elsewhere:
dotnet/project-system#4647

IOW: call this a .proj, or a .restoreproj or something. SLN entry looks the same (you have to do it manually in text editor, IDE won't let you). Add the workaround I linked, define stub targets for anything that fails, and it should avoid
the confusion around a CSProj that doesn't build anything.
You don't need to do that now, but I think it would make this more sensible.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I have tried to add the lines found in the issue to the new .restoreproj file but that did not work.
I will keep it as is for now then.

@ericstj

Copy link
Copy Markdown
Member

Have you made sure you see a failure when making a breaking API change?

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Yes I have done a few tests where I rename methods and such and the build was failing.

<ItemGroup>
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lines 24 and 26 are identical... 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@RussKie - can you log an issue (or even submit a PR for the fix)?

@ghostghost locked as resolved and limited conversation to collaborators Mar 22, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

BuildBuild related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add API breaking change definition and enforce it

4 participants

@artidoro@ericstj@RussKie@eerhardt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

API Compat tool in ML.NET - #3623

Merged
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat
May 4, 2019
Merged

API Compat tool in ML.NET#3623
artidoro merged 7 commits into
dotnet:masterfrom
artidoro:apicompat

Conversation

@artidoro

@artidoroartidoro commented Apr 30, 2019

Copy link
Copy Markdown
Contributor

Fixes#3602.

We need to ensure that future changes to ML.NET will not break the stable API released in 1.0.0.

This PR introduces the API Compat tool from dotnet/Arcade. The API Compat tool runs as part of the build process and compares the assemblies with those found in the stable nugets referenced in the Microsoft.ML.StableAPI project.

The tool is only run for the assemblies which will be part of the stable nugets. Here is a list of those assemblies and the relative nugets:

Stable NugetStable Assemblies
Microsoft.MLMicrosoft.ML.Core, Microsoft.ML.Data, Microsoft.ML.KMeansClustering, Microsoft.ML.PCA, Microsoft.ML.StandardTrainers, MIcrosoft.ML.Transforms, Microsoft.ML.Analyzer
Microsoft.ML.DataViewMicrosoft.ML.DataView
Microsoft.ML.CpuMathMicrosoft.ML.CpuMath
Microsoft.ML.FastTreeMicrosoft.ML.FastTree
Microsoft.ML.LightGbmMicrosoft.ML.LightGbm
Microsoft.ML.ImageAnalyticsMicrosoft.ML.ImageAnalytics
Microsoft.ML.MklComponentsMicrosoft.ML.Mkl.Components

Note: the tool does not run on Microsoft.ML.Analyzer as it does not have a public API, so no need to check backwards compatibility.

Still to do:

  • Fix possible bug in API Compat on handling of Attributes.
  • Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes. Not needed see comments below.
  • Update the version of the ML.NET nugets to 1.0.0 when available

@artidoroartidoro added the Build Build related issue label Apr 30, 2019
@artidoroartidoro self-assigned this Apr 30, 2019

@ericstjericstj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry if some of these were issues with my initial sample.

Comment threadDirectory.Build.props Outdated
Comment threadsrc/Directory.Build.targets Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated

</Target>

<!-- API Compat -->

@ericstjericstjApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider moving these to a seperate targets file if that is a convention you'd like to follow in this repo. #Pending

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I think we only have one for the src repo. But let me know if there is a better way.


In reply to: 279938766 [](ancestors = 279938766)

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.ML" Version="1.0.0-preview-27625-16"/>

@eerhardteerhardtApr 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nit) you can use the latest 1.0.0-preview build: 1.0.0-preview-27630-5. We just spun it and will have the official 1.0.0 up soon. #Resolved

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Will update to the new build and change to 1.0.0 as soon as it is available.


In reply to: 279941849 [](ancestors = 279941849)

@eerhardteerhardtMay 1, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's available on myget now. You should be able to use 1.0.0. #Resolved

@ericstj

ericstj commented Apr 30, 2019

Copy link
Copy Markdown
Member
D:\a\1\s\packages\microsoft.dotnet.apicompat\1.0.0-beta.19225.5\build\Microsoft.DotNet.ApiCompat.targets(72,5): error : CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'Microsoft.ML.ExtensionBaseAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. [D:\a\1\s\src\Microsoft.ML.Core\Microsoft.ML.Core.csproj]

This is happening because APICompat is not resolving the System.AttributeTargets enum from the contract. It's not resolving because you aren't providing the dependencies. Today these can be passed in via the $(ContractOutputPath) property but that isn't very sensible. I'll submit a change to APICompat to make that easier.
https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L46-L52 #Pending

@artidoro

Copy link
Copy Markdown
ContributorAuthor

That would be great! Thank you


In reply to: 488135991 [](ancestors = 488135991)

@artidoro

artidoro commented Apr 30, 2019

Copy link
Copy Markdown
ContributorAuthor

Add a build setting to disable the API Compat tool from command line. This will allow people to work on breaking changes.

The right way to do this is to build once specifying /p:BaselineAllAPICompatError=true. This will generate text files in the repo that list all the errors and let the build succeed despite the compatibility issues. Typically you then file issues to address all the baselines by the time you ship the next version.

@ericstj is it possible to specify the path for the generated file?
Also, how would we specify known diffs going forward? I would like to write some documentation on how to do that. #Resolved

@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

by default the generated file gets written to the same directory as the project with the name, but you can customize it: https://github.com/dotnet/arcade/blob/ac8d88df02d246d3147338fcfb03b1b93dc84b53/src/Microsoft.DotNet.ApiCompat/build/Microsoft.DotNet.ApiCompat.targets#L22-L23

how would we specify known diffs going forward?

You can use the same option I mentioned when building individual projects, you can also copy the errors and paste them into the baseline file. I want to stress that these aren't "known diffs" these are compatibility bugs that break your customers and you really shouldn't be baselining them or introducing the suppressions. #Resolved

@ericstjericstj mentioned this pull request May 1, 2019
4 tasks
@ericstj

ericstj commented May 1, 2019

Copy link
Copy Markdown
Member

To provide paths to contract dependencies, add the following in your GetContract target:

 <_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_contractReferencePath DependencyPaths="@(_allReferenceDirectories)" />

Then in ResolveMatchingContract add the following after you get the ResolvedMatchingContract item:

<PropertyGroup>
<ContractOutputPath>%(ResolvedMatchingContract.DependencyPaths)</ContractOutputPath>
</PropertyGroup>

I'm putting a feature into the APICompat targets that will make the latter property unnecessary. #Resolved

Comment threadsrc/Microsoft.ML.Core/Microsoft.ML.Core.csproj Outdated
Comment threadsrc/Microsoft.ML.Analyzer/Microsoft.ML.Analyzer.csproj Outdated
Comment threadtools-local/Microsoft.ML.StableApi/Microsoft.ML.StableApi.csproj Outdated
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project will actually build a .dll when we build the .sln file. That seems unnecessary. Maybe we should override the Build target or maybe not name it .csproj and instead just .proj? It's mission in life isn't to build .cs files into a .dll, but instead pull down external packages and provide the GetContract target.

@artidoroartidoroMay 3, 2019

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I tried renaming, but that did not work (it gave an error saying that project.assets.json was not generated.
I have also tried to overwrite the Build target, but I must have made some mistake since I still found the generated .dll.

What I did was adding:

 <Target Name="Build">
<!-- This will override the default Build target. -->
</Target>

to the .csproj file.

What is the correct way to overwrite it?


In reply to: 280105436 [](ancestors = 280105436)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, I think that is fine.

Comment threadDirectory.Build.props Outdated
@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you that seems to make it work!


In reply to: 488287870 [](ancestors = 488287870)

@artidoroartidoro changed the title WIP: API Compat tool in ML.NETAPI Compat tool in ML.NETMay 3, 2019
@codecov

codecovBot commented May 3, 2019

Copy link
Copy Markdown

Codecov Report

Merging #3623 into master will increase coverage by <.01%.
The diff coverage is n/a.

@@ Coverage Diff @@## master #3623 +/- ##
==========================================
+ Coverage 72.78% 72.78% +<.01% 
==========================================
Files 808 808 Lines 145588 145588 Branches 16250 16250 ==========================================
+ Hits 105960 105968 +8 + Misses 35205 35198 -7 + Partials 4423 4422 -1
FlagCoverage Δ
#Debug72.78% <ø> (ø)⬆️
#production68.28% <ø> (ø)⬆️
#test89.04% <ø> (ø)⬆️
Impacted FilesCoverage Δ
...StandardTrainers/Standard/LinearModelParameters.cs60.05% <0%> (-0.27%)⬇️
...icrosoft.ML.TensorFlow/TensorFlow/TensorGeneric.cs44.21% <0%> (ø)⬆️
...c/Microsoft.ML.FastTree/Utils/BufferPoolManager.cs0% <0%> (ø)⬆️
...ML.Transforms/Text/StopWordsRemovingTransformer.cs86.26% <0%> (+0.15%)⬆️
...soft.ML.Data/DataLoadSave/Text/TextLoaderCursor.cs84.9% <0%> (+0.2%)⬆️
...soft.ML.TestFramework/DataPipe/TestDataPipeBase.cs73.93% <0%> (+0.32%)⬆️
src/Microsoft.ML.Transforms/Text/LdaTransform.cs89.89% <0%> (+0.62%)⬆️

@ericstj

Copy link
Copy Markdown
Member

failing on linux because dotnet is not on the path and the $(ToolHostCmd) is not set to point to it.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Thank you @ericstj and @eerhardt for looking at the PR, I have addressed your comments.
Let me know if there are other things I should look into!

@ericstj

Copy link
Copy Markdown
Member

Cool, this is looking pretty good. You may want to wait for my changes dotnet/arcade#2672 which help simplify some of this.

@artidoro

Copy link
Copy Markdown
ContributorAuthor

I would prefer checking in this change as soon as possible and updating it with the new buyer as soon as it is available.

Since we have released yesterday, it would be great to have the API Compat tool in the repo.

Comment threadMicrosoft.ML.sln Outdated
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2026
# Visual Studio Version 16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You may want to revert these two lines. I don't know what happens if someone tries opening the solution with VS 2017 (which is version 15) and this .sln says it is for VS 2019.

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks good. But I'd wait for @ericstj to give the thumbs up as he's the expert here.

<PropertyGroup>
<!-- needs to contain all frameworks which src projects wish to restore -->
<TargetFramework Condition="'$(UseIntrinsics)' != 'true'">netstandard2.0</TargetFramework>
<TargetFrameworks Condition="'$(UseIntrinsics)' == 'true'">netstandard2.0;netcoreapp3.0</TargetFrameworks>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why should we have the condition here? Is there any harm in always resolving for both TFMs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Usually netcoreapp3.0 causes problems when you are building in VS 2017 where the SDK throws an error saying I don't support netcoreapp3.0.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, makes sense.

<Error Condition="'@(_contractReferencePath)' == ''" Text="Could not locate $(ContractName)" />
</Target>

<Target Name="Build">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be improved by changing the project extension and defining a couple targets. We do that elsewhere:
dotnet/project-system#4647

IOW: call this a .proj, or a .restoreproj or something. SLN entry looks the same (you have to do it manually in text editor, IDE won't let you). Add the workaround I linked, define stub targets for anything that fails, and it should avoid
the confusion around a CSProj that doesn't build anything.
You don't need to do that now, but I think it would make this more sensible.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I have tried to add the lines found in the issue to the new .restoreproj file but that did not work.
I will keep it as is for now then.

@ericstj

Copy link
Copy Markdown
Member

Have you made sure you see a failure when making a breaking API change?

@artidoro

Copy link
Copy Markdown
ContributorAuthor

Yes I have done a few tests where I rename methods and such and the build was failing.

<ItemGroup>
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />
<_allReferenceDirectories Include="%(ReferencePath.RootDir)%(ReferencePath.Directory)" />
<_contractReferencePath Include="@(ReferencePath)" Condition="'%(FileName)' == '$(ContractName)'" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lines 24 and 26 are identical... 😕

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@RussKie - can you log an issue (or even submit a PR for the fix)?

@ghostghost locked as resolved and limited conversation to collaborators Mar 22, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

BuildBuild related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to add API breaking change definition and enforce it

4 participants

@artidoro@ericstj@RussKie@eerhardt