From 96ecd814a78f589cccd654414be4f687e1326bb2 Mon Sep 17 00:00:00 2001 From: DotNet-Bot Date: Tue, 27 Jan 2026 01:17:50 +0000 Subject: [PATCH 01/18] Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260126.10 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.24-servicing.26070.10 -> To Version 8.0.24-servicing.26076.10 Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 From Version 8.0.24 -> To Version 8.0.24 --- NuGet.config | 4 ++-- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/NuGet.config b/NuGet.config index 9dd9747dcb0..117ea75571a 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a4c219563bc..3b4a1af85f1 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,9 +29,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime dcf4a22cf8671c1abe880ebec4cfd906c99588bf - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - b3b35ce80e9eb94f72c4aa36a171a5e1cde72ace + 6c702d318982ec11fd712c5ab1126070407f8609 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime @@ -47,16 +47,16 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - b3b35ce80e9eb94f72c4aa36a171a5e1cde72ace + 6c702d318982ec11fd712c5ab1126070407f8609 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - b3b35ce80e9eb94f72c4aa36a171a5e1cde72ace + 6c702d318982ec11fd712c5ab1126070407f8609 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - b3b35ce80e9eb94f72c4aa36a171a5e1cde72ace + 6c702d318982ec11fd712c5ab1126070407f8609 diff --git a/eng/Versions.props b/eng/Versions.props index fdc8b8502d0..8de6487b85e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -24,13 +24,13 @@ 8.0.1 8.0.1 8.0.2 - 8.0.24-servicing.26070.10 + 8.0.24-servicing.26076.10 8.0.1 8.0.6 8.0.2 8.0.24 8.0.24 - 8.0.24-servicing.26070.10 + 8.0.24-servicing.26076.10 8.0.0-beta.25611.2 From 693c77afd2b96eecff3dccd41a22e6519204cad0 Mon Sep 17 00:00:00 2001 From: DotNet-Bot Date: Thu, 5 Feb 2026 21:38:49 +0000 Subject: [PATCH 02/18] Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260205.6 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.24-servicing.26070.10 -> To Version 8.0.25-servicing.26105.6 Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 From Version 8.0.24 -> To Version 8.0.25 --- NuGet.config | 4 ++-- eng/Version.Details.xml | 16 ++++++++-------- eng/Versions.props | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/NuGet.config b/NuGet.config index 117ea75571a..90e436cb345 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 3b4a1af85f1..47cc2a07fd2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,9 +29,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime dcf4a22cf8671c1abe880ebec4cfd906c99588bf - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 6c702d318982ec11fd712c5ab1126070407f8609 + df16015b1a435d46f6ad77ee6da30834f5dd29f8 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime @@ -45,18 +45,18 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime ef853a71052646a42abf17e888ec6d9a69614ad9 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 6c702d318982ec11fd712c5ab1126070407f8609 + df16015b1a435d46f6ad77ee6da30834f5dd29f8 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 6c702d318982ec11fd712c5ab1126070407f8609 + df16015b1a435d46f6ad77ee6da30834f5dd29f8 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 6c702d318982ec11fd712c5ab1126070407f8609 + df16015b1a435d46f6ad77ee6da30834f5dd29f8 diff --git a/eng/Versions.props b/eng/Versions.props index 8de6487b85e..b74236e10da 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -24,13 +24,13 @@ 8.0.1 8.0.1 8.0.2 - 8.0.24-servicing.26076.10 + 8.0.25-servicing.26105.6 8.0.1 8.0.6 8.0.2 - 8.0.24 - 8.0.24 - 8.0.24-servicing.26076.10 + 8.0.25 + 8.0.25 + 8.0.25-servicing.26105.6 8.0.0-beta.25611.2 From d13bef65ef27a646b4593beecceff24b70539ce0 Mon Sep 17 00:00:00 2001 From: DotNet-Bot Date: Fri, 6 Feb 2026 02:01:19 +0000 Subject: [PATCH 03/18] Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260205.10 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.25-servicing.26105.6 -> To Version 8.0.25-servicing.26105.10 Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 From Version 8.0.25 -> To Version 8.0.25 --- NuGet.config | 4 ++-- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/NuGet.config b/NuGet.config index 90e436cb345..87eb8e7a55a 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 47cc2a07fd2..ec401ccb815 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,9 +29,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime dcf4a22cf8671c1abe880ebec4cfd906c99588bf - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - df16015b1a435d46f6ad77ee6da30834f5dd29f8 + 5fc1194e87d3524b586f3e313e93a10391d0cc97 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime @@ -47,16 +47,16 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - df16015b1a435d46f6ad77ee6da30834f5dd29f8 + 5fc1194e87d3524b586f3e313e93a10391d0cc97 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - df16015b1a435d46f6ad77ee6da30834f5dd29f8 + 5fc1194e87d3524b586f3e313e93a10391d0cc97 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - df16015b1a435d46f6ad77ee6da30834f5dd29f8 + 5fc1194e87d3524b586f3e313e93a10391d0cc97 diff --git a/eng/Versions.props b/eng/Versions.props index fc0e464fd69..06f209afe04 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -24,13 +24,13 @@ 8.0.1 8.0.1 8.0.2 - 8.0.25-servicing.26105.6 + 8.0.25-servicing.26105.10 8.0.1 8.0.6 8.0.2 8.0.25 8.0.25 - 8.0.25-servicing.26105.6 + 8.0.25-servicing.26105.10 8.0.0-beta.25611.2 From 26eda04d6596a67a7b2291b2adfe9fcaa84a9a2a Mon Sep 17 00:00:00 2001 From: ProductConstructionServiceProd Date: Wed, 11 Feb 2026 05:46:40 +0000 Subject: [PATCH 04/18] Merged PR 57701: [internal/release/8.0] Update dependencies from dnceng/internal/dotnet-runtime This pull request updates the following dependencies [marker]: <> (Begin:922981e1-18b6-46aa-2468-08dbd53ba9ce) ## From https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - **Subscription**: [922981e1-18b6-46aa-2468-08dbd53ba9ce](https://maestro.dot.net/subscriptions?search=922981e1-18b6-46aa-2468-08dbd53ba9ce) - **Build**: [20260209.11](https://dev.azure.com/dnceng/internal/_build/results?buildId=2899229) ([301001](https://maestro.dot.net/channel/3880/azdo:dnceng:internal:dotnet-runtime/build/301001)) - **Date Produced**: February 9, 2026 8:00:37 PM UTC - **Commit**: [651453b8e3f93d8fb35dd1be1a726158366249fc](https://dev.azure.com/dnceng/internal/_git/dotnet-runtime?_a=history&version=GC651453b8e3f93d8fb35dd1be1a726158366249fc) - **Branch**: [refs/heads/internal/release/8.0](https://dev.azure.com/dnceng/internal/_git/dotnet-runtime?version=GBrefs/heads/internal/release/8.0) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [8.0.25-servicing.26105.10 to 8.0.25-servicing.26109.11][1] - Microsoft.Extensions.HostFactoryResolver.Sources - Microsoft.NETCore.BrowserDebugHost.Transport - From [8.0.25 to 8.0.25][1] - Microsoft.NETCore.App.Ref - Microsoft.NETCore.App.Runtime.win-x64 [1]: https://dev.azure.com/dnceng/internal/_git/dotnet-runtime/branches?baseVersion=GC5fc1194e87d3524b586f3e313e93a10391d0cc97&targetVersion=GC651453b8e3f93d8fb35dd1be1a726158366249fc&_a=files [DependencyUpdate]: <> (End) [marker]: <> (End:922981e1-18b6-46aa-2468-08dbd53ba9ce) --- NuGet.config | 4 ++-- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/NuGet.config b/NuGet.config index 87eb8e7a55a..2632778f394 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ec401ccb815..831ebfb41f3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,9 +29,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime dcf4a22cf8671c1abe880ebec4cfd906c99588bf - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 5fc1194e87d3524b586f3e313e93a10391d0cc97 + 651453b8e3f93d8fb35dd1be1a726158366249fc https://dev.azure.com/dnceng/internal/_git/dotnet-runtime @@ -47,16 +47,16 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 5fc1194e87d3524b586f3e313e93a10391d0cc97 + 651453b8e3f93d8fb35dd1be1a726158366249fc https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 5fc1194e87d3524b586f3e313e93a10391d0cc97 + 651453b8e3f93d8fb35dd1be1a726158366249fc - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 5fc1194e87d3524b586f3e313e93a10391d0cc97 + 651453b8e3f93d8fb35dd1be1a726158366249fc diff --git a/eng/Versions.props b/eng/Versions.props index 06f209afe04..b091ce95128 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -24,13 +24,13 @@ 8.0.1 8.0.1 8.0.2 - 8.0.25-servicing.26105.10 + 8.0.25-servicing.26109.11 8.0.1 8.0.6 8.0.2 8.0.25 8.0.25 - 8.0.25-servicing.26105.10 + 8.0.25-servicing.26109.11 8.0.0-beta.25611.2 From fb9efa304e0e4e63339ab45c2b033a3c14932579 Mon Sep 17 00:00:00 2001 From: DotNet-Bot Date: Thu, 12 Feb 2026 14:24:55 +0000 Subject: [PATCH 05/18] Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260212.3 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.25-servicing.26109.11 -> To Version 8.0.25-servicing.26112.3 Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 From Version 8.0.25 -> To Version 8.0.25 --- NuGet.config | 4 ++-- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/NuGet.config b/NuGet.config index 2632778f394..135bb26cb45 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + @@ -19,7 +19,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 831ebfb41f3..016c0a5f552 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -29,9 +29,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime dcf4a22cf8671c1abe880ebec4cfd906c99588bf - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 651453b8e3f93d8fb35dd1be1a726158366249fc + b753199016332cbf257e70c417aa5d1d02202dc7 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime @@ -47,16 +47,16 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 651453b8e3f93d8fb35dd1be1a726158366249fc + b753199016332cbf257e70c417aa5d1d02202dc7 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 651453b8e3f93d8fb35dd1be1a726158366249fc + b753199016332cbf257e70c417aa5d1d02202dc7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 651453b8e3f93d8fb35dd1be1a726158366249fc + b753199016332cbf257e70c417aa5d1d02202dc7 diff --git a/eng/Versions.props b/eng/Versions.props index b091ce95128..4d804f65efc 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -24,13 +24,13 @@ 8.0.1 8.0.1 8.0.2 - 8.0.25-servicing.26109.11 + 8.0.25-servicing.26112.3 8.0.1 8.0.6 8.0.2 8.0.25 8.0.25 - 8.0.25-servicing.26109.11 + 8.0.25-servicing.26112.3 8.0.0-beta.25611.2 From 6e2ae933301138809da626a7861af025ab9489ee Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Thu, 26 Mar 2026 18:58:07 -0700 Subject: [PATCH 06/18] Remove darc-int-dotnet-runtime package source --- NuGet.config | 2 -- 1 file changed, 2 deletions(-) diff --git a/NuGet.config b/NuGet.config index f5c4733af2f..d1a8a417e43 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,6 @@ - @@ -21,7 +20,6 @@ - From 1a7876ae5f3a8a7cf073214862813f3ff662c5a5 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:06:15 +0000 Subject: [PATCH 07/18] [release/10.0] Source code updates from dotnet/dotnet (#38026) [release/10.0] Source code updates from dotnet/dotnet --- NuGet.config | 2 +- eng/Version.Details.props | 10 ++-- eng/Version.Details.xml | 48 +++++++++---------- eng/common/core-templates/job/onelocbuild.yml | 4 +- .../job/publish-build-assets.yml | 4 +- .../core-templates/post-build/post-build.yml | 16 +++---- .../variables/pool-providers.yml | 2 +- .../templates/variables/pool-providers.yml | 2 +- global.json | 4 +- 9 files changed, 46 insertions(+), 46 deletions(-) diff --git a/NuGet.config b/NuGet.config index 4a757d1ad04..14a08b08f87 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 70fac2cdd7d..87f55622995 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,9 +6,9 @@ This file should be imported by eng/Versions.props - 10.0.0-beta.26176.117 - 10.0.0-beta.26176.117 - 10.0.0-beta.26176.117 + 10.0.0-beta.26201.102 + 10.0.0-beta.26201.102 + 10.0.0-beta.26201.102 10.0.6 10.0.6 10.0.6 @@ -16,10 +16,10 @@ This file should be imported by eng/Versions.props 10.0.6 10.0.6 10.0.6 - 10.0.6-servicing.26176.117 + 10.0.6-servicing.26201.102 10.0.6 10.0.6 - 10.0.6-servicing.26176.117 + 10.0.6-servicing.26201.102 10.0.6 10.0.6 10.0.6 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2531628161b..c46cb650982 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,80 +1,80 @@ - + https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa - + https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa - + https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa - + https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa - + https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa - + https://github.com/dotnet/dotnet - 8dc731afc09c5dca3dc7cee575f3bf0c61c2d919 + dfa4d1ceb91729e3e28f23c83e7d153a74510aaa diff --git a/eng/common/core-templates/job/onelocbuild.yml b/eng/common/core-templates/job/onelocbuild.yml index c5788829a87..eefed3b667a 100644 --- a/eng/common/core-templates/job/onelocbuild.yml +++ b/eng/common/core-templates/job/onelocbuild.yml @@ -52,13 +52,13 @@ jobs: # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: name: AzurePipelines-EO - image: 1ESPT-Windows2022 + image: 1ESPT-Windows2025 demands: Cmd os: windows # If it's not devdiv, it's dnceng ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 + image: windows.vs2026.amd64 os: windows steps: diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml index b955fac6e13..9afcb8ae159 100644 --- a/eng/common/core-templates/job/publish-build-assets.yml +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -74,13 +74,13 @@ jobs: # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: name: AzurePipelines-EO - image: 1ESPT-Windows2022 + image: 1ESPT-Windows2025 demands: Cmd os: windows # If it's not devdiv, it's dnceng ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: name: NetCore1ESPool-Publishing-Internal - image: windows.vs2022.amd64 + image: windows.vs2026.amd64 os: windows steps: - ${{ if eq(parameters.is1ESPipeline, '') }}: diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml index b942a79ef02..2df4acb7685 100644 --- a/eng/common/core-templates/post-build/post-build.yml +++ b/eng/common/core-templates/post-build/post-build.yml @@ -120,7 +120,7 @@ stages: # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: name: AzurePipelines-EO - image: 1ESPT-Windows2022 + image: 1ESPT-Windows2025 demands: Cmd os: windows # If it's not devdiv, it's dnceng @@ -164,14 +164,14 @@ stages: # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: name: AzurePipelines-EO - image: 1ESPT-Windows2022 + image: 1ESPT-Windows2025 demands: Cmd os: windows # If it's not devdiv, it's dnceng ${{ else }}: ${{ if eq(parameters.is1ESPipeline, true) }}: name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 + image: windows.vs2026.amd64 os: windows ${{ else }}: name: $(DncEngInternalBuildPool) @@ -225,14 +225,14 @@ stages: # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: name: AzurePipelines-EO - image: 1ESPT-Windows2022 + image: 1ESPT-Windows2025 demands: Cmd os: windows # If it's not devdiv, it's dnceng ${{ else }}: ${{ if eq(parameters.is1ESPipeline, true) }}: name: $(DncEngInternalBuildPool) - image: 1es-windows-2022 + image: windows.vs2026.amd64 os: windows ${{ else }}: name: $(DncEngInternalBuildPool) @@ -286,18 +286,18 @@ stages: # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: name: AzurePipelines-EO - image: 1ESPT-Windows2022 + image: 1ESPT-Windows2025 demands: Cmd os: windows # If it's not devdiv, it's dnceng ${{ else }}: ${{ if eq(parameters.is1ESPipeline, true) }}: name: NetCore1ESPool-Publishing-Internal - image: windows.vs2022.amd64 + image: windows.vs2026.amd64 os: windows ${{ else }}: name: NetCore1ESPool-Publishing-Internal - demands: ImageOverride -equals windows.vs2022.amd64 + demands: ImageOverride -equals windows.vs2026.amd64 steps: - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml parameters: diff --git a/eng/common/templates-official/variables/pool-providers.yml b/eng/common/templates-official/variables/pool-providers.yml index 1f308b24efc..2cc3ae305d5 100644 --- a/eng/common/templates-official/variables/pool-providers.yml +++ b/eng/common/templates-official/variables/pool-providers.yml @@ -23,7 +23,7 @@ # # pool: # name: $(DncEngInternalBuildPool) -# image: 1es-windows-2022 +# image: windows.vs2026.amd64 variables: # Coalesce the target and source branches so we know when a PR targets a release branch diff --git a/eng/common/templates/variables/pool-providers.yml b/eng/common/templates/variables/pool-providers.yml index 18693ea120d..587770f0add 100644 --- a/eng/common/templates/variables/pool-providers.yml +++ b/eng/common/templates/variables/pool-providers.yml @@ -23,7 +23,7 @@ # # pool: # name: $(DncEngInternalBuildPool) -# demands: ImageOverride -equals windows.vs2022.amd64 +# demands: ImageOverride -equals windows.vs2026.amd64 variables: - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - template: /eng/common/templates-official/variables/pool-providers.yml diff --git a/global.json b/global.json index fb86d4ee51f..b195495dbf7 100644 --- a/global.json +++ b/global.json @@ -18,7 +18,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26176.117", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26176.117" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26201.102", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26201.102" } } From 5e2677f120d7b8b1502257000157938c656d5600 Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Tue, 7 Apr 2026 19:04:56 -0700 Subject: [PATCH 08/18] [release/9.0] Update branding to 9.0.16 (#38063) --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 4b4561295ce..6ba2b65949d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,6 +1,6 @@ - 9.0.15 + 9.0.16 servicing From 576af874329ed1e21433b5e47e77dd9691aea7af Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 03:02:08 +0000 Subject: [PATCH 09/18] Update dependencies from https://github.com/dotnet/arcade build 20260401.6 (#38053) [release/9.0] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 2 +- global.json | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 404589533db..573b42f26bb 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -67,17 +67,17 @@ - + https://github.com/dotnet/arcade - 91828e6fea5ea06bea2d06532af9b974a8742ef4 + e1240639569fad610705b52713d6d6b19f8fe433 - + https://github.com/dotnet/arcade - 91828e6fea5ea06bea2d06532af9b974a8742ef4 + e1240639569fad610705b52713d6d6b19f8fe433 - + https://github.com/dotnet/arcade - 91828e6fea5ea06bea2d06532af9b974a8742ef4 + e1240639569fad610705b52713d6d6b19f8fe433 diff --git a/eng/Versions.props b/eng/Versions.props index 6ba2b65949d..5a0478c6a98 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -34,7 +34,7 @@ 9.0.14 - 9.0.0-beta.26168.2 + 9.0.0-beta.26201.6 17.8.43 diff --git a/global.json b/global.json index 84c678ff9ed..5b3bcffb8b4 100644 --- a/global.json +++ b/global.json @@ -13,7 +13,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26168.2", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26168.2" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.26201.6", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.26201.6" } } From 3c2677e1d1206698b54f706fab02b6182f31ecda Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 03:24:48 +0000 Subject: [PATCH 10/18] Update dependencies from build 309217 (#38046) [release/10.0] Source code updates from dotnet/dotnet --- NuGet.config | 2 +- eng/Version.Details.props | 10 ++++---- eng/Version.Details.xml | 48 +++++++++++++++++++-------------------- global.json | 4 ++-- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/NuGet.config b/NuGet.config index 14a08b08f87..fb6ced9117b 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 87f55622995..7b15f2563f7 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,9 +6,9 @@ This file should be imported by eng/Versions.props - 10.0.0-beta.26201.102 - 10.0.0-beta.26201.102 - 10.0.0-beta.26201.102 + 10.0.0-beta.26203.109 + 10.0.0-beta.26203.109 + 10.0.0-beta.26203.109 10.0.6 10.0.6 10.0.6 @@ -16,10 +16,10 @@ This file should be imported by eng/Versions.props 10.0.6 10.0.6 10.0.6 - 10.0.6-servicing.26201.102 + 10.0.6-servicing.26203.109 10.0.6 10.0.6 - 10.0.6-servicing.26201.102 + 10.0.6-servicing.26203.109 10.0.6 10.0.6 10.0.6 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c46cb650982..78ec0e47f68 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,80 +1,80 @@ - + https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a - + https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a - + https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a - + https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a - + https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a - + https://github.com/dotnet/dotnet - dfa4d1ceb91729e3e28f23c83e7d153a74510aaa + 6165bd7ac3499cb712ca489f2ce44bb665174a1a diff --git a/global.json b/global.json index b195495dbf7..d764fd5da7e 100644 --- a/global.json +++ b/global.json @@ -18,7 +18,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26201.102", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26201.102" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26203.109", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26203.109" } } From 137123b4aafc607845ec138f417c43480dae0e4e Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 05:49:18 +0000 Subject: [PATCH 11/18] [release/10.0] Source code updates from dotnet/dotnet (#38073) [release/10.0] Source code updates from dotnet/dotnet --- NuGet.config | 2 +- eng/Version.Details.props | 36 +++++++++---------- eng/Version.Details.xml | 74 +++++++++++++++++++-------------------- eng/Versions.props | 2 +- global.json | 4 +-- 5 files changed, 59 insertions(+), 59 deletions(-) diff --git a/NuGet.config b/NuGet.config index fb6ced9117b..3d23648e12e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + diff --git a/eng/Version.Details.props b/eng/Version.Details.props index 7b15f2563f7..e903460789b 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,24 +6,24 @@ This file should be imported by eng/Versions.props - 10.0.0-beta.26203.109 - 10.0.0-beta.26203.109 - 10.0.0-beta.26203.109 - 10.0.6 - 10.0.6 - 10.0.6 - 10.0.6 - 10.0.6 - 10.0.6 - 10.0.6 - 10.0.6-servicing.26203.109 - 10.0.6 - 10.0.6 - 10.0.6-servicing.26203.109 - 10.0.6 - 10.0.6 - 10.0.6 - 10.0.6 + 10.0.0-beta.26209.115 + 10.0.0-beta.26209.115 + 10.0.0-beta.26209.115 + 10.0.7 + 10.0.7 + 10.0.7 + 10.0.7 + 10.0.7 + 10.0.7 + 10.0.7 + 10.0.7-servicing.26209.115 + 10.0.7 + 10.0.7 + 10.0.7-servicing.26209.115 + 10.0.7 + 10.0.7 + 10.0.7 + 10.0.7 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 78ec0e47f68..aad560232b0 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,80 +1,80 @@ - + - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 - + https://github.com/dotnet/dotnet - 6165bd7ac3499cb712ca489f2ce44bb665174a1a + 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 diff --git a/eng/Versions.props b/eng/Versions.props index d040107ab1b..8dba19ed039 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,7 +1,7 @@ - 10.0.6 + 10.0.7 servicing False diff --git a/global.json b/global.json index d764fd5da7e..6b18b79005c 100644 --- a/global.json +++ b/global.json @@ -18,7 +18,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26203.109", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26203.109" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26209.115", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26209.115" } } From 4c78aa79820592d3682f641b875f1a4bfd92c079 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Fri, 10 Apr 2026 00:37:20 -0700 Subject: [PATCH 12/18] Fix permissions for the API workflow (#38072) --- .github/workflows/api-review-baselines.yml | 95 ++++++++++++---------- .gitignore | 3 + 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/.github/workflows/api-review-baselines.yml b/.github/workflows/api-review-baselines.yml index 76551cc729a..469d15be308 100644 --- a/.github/workflows/api-review-baselines.yml +++ b/.github/workflows/api-review-baselines.yml @@ -1,8 +1,8 @@ -# This workflow labels merged PRs that modify `*.baseline.json` files with `api-review`, -# computes ApiChief deltas between the original and merged baseline files, and posts the -# results back to the pull request as a review comment. +# This workflow labels PRs that modify `*.baseline.json` files with `api-review`, +# computes ApiChief deltas between the base and selected PR baseline files, and posts the +# results back to the pull request as a comment. -name: Comment API baseline deltas on merged PRs +name: Comment API baseline deltas on PRs on: pull_request_target: @@ -10,15 +10,21 @@ on: branches: - main - release/** + workflow_dispatch: + inputs: + pr-number: + description: Pull request number to process + required: true + type: number permissions: contents: read issues: write - pull-requests: read + pull-requests: write jobs: api-review: - if: github.event.pull_request.merged == true + if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - name: Detect changed baseline files and add label @@ -28,7 +34,20 @@ jobs: script: | const owner = context.repo.owner; const repo = context.repo.repo; - const prNumber = context.payload.pull_request.number; + const prNumber = context.eventName === 'workflow_dispatch' + ? Number(core.getInput('pr-number')) + : context.payload.pull_request.number; + + if (!Number.isInteger(prNumber) || prNumber <= 0) { + core.setFailed(`Invalid PR number: ${prNumber}`); + return; + } + + const { data: pullRequest } = await github.rest.pulls.get({ + owner, + repo, + pull_number: prNumber + }); const files = await github.paginate(github.rest.pulls.listFiles, { owner, @@ -45,11 +64,18 @@ jobs: previous_filename: file.previous_filename ?? null })); + core.setOutput('pr_number', String(prNumber)); + core.setOutput('base_sha', pullRequest.base.sha); + core.setOutput('target_sha', pullRequest.merge_commit_sha ?? pullRequest.head.sha); core.setOutput('has_baselines', String(baselineFiles.length > 0)); core.setOutput('files_json', JSON.stringify(baselineFiles)); + if (!pullRequest.merged) { + console.log(`PR #${prNumber} is not merged; using head SHA ${pullRequest.head.sha}.`); + } + if (baselineFiles.length === 0) { - console.log('No changed baseline files detected on this merged PR.'); + console.log(`No changed baseline files detected on PR #${prNumber}.`); return; } @@ -60,13 +86,13 @@ jobs: labels: ['api-review'] }); - console.log(`Detected ${baselineFiles.length} changed baseline file(s).`); + console.log(`Detected ${baselineFiles.length} changed baseline file(s) on PR #${prNumber}.`); - - name: Check out merged commit + - name: Check out selected commit if: steps.detect.outputs.has_baselines == 'true' uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.merge_commit_sha }} + ref: ${{ steps.detect.outputs.target_sha }} fetch-depth: 1 - name: Restore repo-local .NET SDK @@ -82,8 +108,8 @@ jobs: FILES_JSON: ${{ steps.detect.outputs.files_json }} OWNER: ${{ github.repository_owner }} REPO: ${{ github.event.repository.name }} - BASE_SHA: ${{ github.event.pull_request.base.sha }} - MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha }} + BASE_SHA: ${{ steps.detect.outputs.base_sha }} + TARGET_SHA: ${{ steps.detect.outputs.target_sha }} run: | set -euo pipefail @@ -110,7 +136,7 @@ jobs: owner = os.environ['OWNER'] repo = os.environ['REPO'] base_sha = os.environ['BASE_SHA'] - merge_sha = os.environ['MERGE_SHA'] + target_sha = os.environ['TARGET_SHA'] dotnet = os.environ['DOTNET'] apichief = os.environ['APICHIEF_PATH'] workdir = pathlib.Path(os.environ['WORKDIR']) @@ -144,7 +170,7 @@ jobs: delta_path = workdir / f'{index}.delta.json' old_exists = download_file(base_sha, filename, old_path) - new_exists = download_file(merge_sha, filename, new_path) + new_exists = download_file(target_sha, filename, new_path) if old_exists and new_exists: result = subprocess.run( @@ -166,18 +192,17 @@ jobs: f"### `{filename}`\n\n" f"
\nShow delta\n\n```json\n{delta_text}\n```\n
") elif new_exists: - sections.append(f"### `{filename}`\n\nThis baseline file was **added** in the merged PR.") + sections.append(f"### `{filename}`\n\nThis baseline file was **added** in the selected PR.") elif old_exists: - sections.append(f"### `{filename}`\n\nThis baseline file was **removed** in the merged PR.") + sections.append(f"### `{filename}`\n\nThis baseline file was **removed** in the selected PR.") if not sections: sections.append('No API deltas were produced for the modified baseline files.') body = ( - '\n' '## API review baseline changes\n\n' - 'This merged PR modified one or more `*.baseline.json` files. ' - 'The deltas below were generated by `ApiChief` between the pre-merge and merged versions.\n\n' + 'This PR modified one or more `*.baseline.json` files. ' + 'The deltas below were generated by `ApiChief` between the base and selected PR versions.\n\n' + '\n\n'.join(sections) ) @@ -188,43 +213,25 @@ jobs: output.write(f'comment_path={comment_path}\n') PY - - name: Upsert PR comment with delta + - name: Create PR comment with delta if: steps.detect.outputs.has_baselines == 'true' uses: actions/github-script@v8 env: COMMENT_PATH: ${{ steps.delta.outputs.comment_path }} + PR_NUMBER: ${{ steps.detect.outputs.pr_number }} with: script: | const fs = require('fs'); const owner = context.repo.owner; const repo = context.repo.repo; - const issue_number = context.payload.pull_request.number; - const marker = ''; + const issue_number = Number(process.env.PR_NUMBER); const body = fs.readFileSync(process.env.COMMENT_PATH, 'utf8'); - const comments = await github.paginate(github.rest.issues.listComments, { + await github.rest.issues.createComment({ owner, repo, issue_number, - per_page: 100 + body }); - const existing = comments.find(comment => comment.body?.includes(marker)); - - if (existing) { - await github.rest.issues.updateComment({ - owner, - repo, - comment_id: existing.id, - body - }); - console.log(`Updated existing API review comment (${existing.id}).`); - } else { - await github.rest.issues.createComment({ - owner, - repo, - issue_number, - body - }); - console.log('Created new API review comment.'); - } + console.log(`Created new API review comment for PR #${issue_number}.`); diff --git a/.gitignore b/.gitignore index 55ebf0a8e2d..c64dc0e4c07 100644 --- a/.gitignore +++ b/.gitignore @@ -218,6 +218,9 @@ _pkginfo.txt # but keep track of directories ending in .cache !*.[Cc]ache/ +# VS Code cache files +*.lscache + # Others ClientBin/ ~$* From c5255f37c917f9c66d2d305164f722a86c29e636 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:19:10 +0000 Subject: [PATCH 13/18] Update dependencies from build 309867 (#38078) [release/10.0] Source code updates from dotnet/dotnet --- NuGet.config | 2 +- eng/Version.Details.props | 10 +- eng/Version.Details.xml | 48 ++++---- eng/common/core-templates/job/job.yml | 5 +- .../job/publish-build-assets.yml | 14 ++- eng/common/core-templates/jobs/jobs.yml | 5 + .../core-templates/post-build/post-build.yml | 105 ++++++++++++------ .../post-build/setup-maestro-vars.yml | 5 +- .../steps/component-governance.yml | 16 --- .../core-templates/steps/generate-sbom.yml | 60 ++-------- .../core-templates/steps/publish-logs.yml | 9 +- .../core-templates/steps/source-build.yml | 2 +- eng/common/generate-sbom-prep.ps1 | 29 ----- eng/common/generate-sbom-prep.sh | 39 ------- eng/common/template-guidance.md | 2 - eng/common/templates-official/job/job.yml | 64 ++++++----- .../steps/component-governance.yml | 7 -- .../steps/publish-pipeline-artifacts.yml | 4 +- eng/common/templates/job/job.yml | 57 +++++----- .../templates/steps/component-governance.yml | 7 -- global.json | 4 +- 21 files changed, 204 insertions(+), 290 deletions(-) delete mode 100644 eng/common/core-templates/steps/component-governance.yml delete mode 100644 eng/common/generate-sbom-prep.ps1 delete mode 100755 eng/common/generate-sbom-prep.sh delete mode 100644 eng/common/templates-official/steps/component-governance.yml delete mode 100644 eng/common/templates/steps/component-governance.yml diff --git a/NuGet.config b/NuGet.config index 3d23648e12e..fcc1723d8a9 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + diff --git a/eng/Version.Details.props b/eng/Version.Details.props index e903460789b..01740e38fc8 100644 --- a/eng/Version.Details.props +++ b/eng/Version.Details.props @@ -6,9 +6,9 @@ This file should be imported by eng/Versions.props - 10.0.0-beta.26209.115 - 10.0.0-beta.26209.115 - 10.0.0-beta.26209.115 + 10.0.0-beta.26210.105 + 10.0.0-beta.26210.105 + 10.0.0-beta.26210.105 10.0.7 10.0.7 10.0.7 @@ -16,10 +16,10 @@ This file should be imported by eng/Versions.props 10.0.7 10.0.7 10.0.7 - 10.0.7-servicing.26209.115 + 10.0.7-servicing.26210.105 10.0.7 10.0.7 - 10.0.7-servicing.26209.115 + 10.0.7-servicing.26210.105 10.0.7 10.0.7 10.0.7 diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index aad560232b0..af0e6a92b33 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,80 +1,80 @@ - + https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 - + https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 - + https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 - + https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 - + https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 - + https://github.com/dotnet/dotnet - 8639c3b28a6eac36e38a59c9cae67aa52b1b06a8 + d14d02dd9f70268be43db2ae722433f7d4461fb8 diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml index 5ce51840619..eaed6d87e65 100644 --- a/eng/common/core-templates/job/job.yml +++ b/eng/common/core-templates/job/job.yml @@ -24,12 +24,12 @@ parameters: enablePublishBuildArtifacts: false enablePublishBuildAssets: false enablePublishTestResults: false + enablePublishing: false enableBuildRetry: false mergeTestResults: false testRunTitle: '' testResultsFormat: '' name: '' - componentGovernanceSteps: [] preSteps: [] artifactPublishSteps: [] runAsPublic: false @@ -146,9 +146,6 @@ jobs: - ${{ each step in parameters.steps }}: - ${{ step }} - - ${{ each step in parameters.componentGovernanceSteps }}: - - ${{ step }} - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - template: /eng/common/core-templates/steps/cleanup-microbuild.yml parameters: diff --git a/eng/common/core-templates/job/publish-build-assets.yml b/eng/common/core-templates/job/publish-build-assets.yml index 9afcb8ae159..06f2eed0323 100644 --- a/eng/common/core-templates/job/publish-build-assets.yml +++ b/eng/common/core-templates/job/publish-build-assets.yml @@ -172,17 +172,18 @@ jobs: targetPath: '$(Build.ArtifactStagingDirectory)/MergedManifest.xml' artifactName: AssetManifests displayName: 'Publish Merged Manifest' - retryCountOnTaskFailure: 10 # for any logs being locked - sbomEnabled: false # we don't need SBOM for logs + retryCountOnTaskFailure: 10 # for any files being locked + isProduction: false # just metadata for publishing - - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} args: displayName: Publish ReleaseConfigs Artifact - pathToPublish: '$(Build.StagingDirectory)/ReleaseConfigs' - publishLocation: Container + targetPath: '$(Build.StagingDirectory)/ReleaseConfigs' artifactName: ReleaseConfigs + retryCountOnTaskFailure: 10 # for any files being locked + isProduction: false # just metadata for publishing - ${{ if or(eq(parameters.publishAssetsImmediately, 'true'), eq(parameters.isAssetlessBuild, 'true')) }}: - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml @@ -218,4 +219,5 @@ jobs: - template: /eng/common/core-templates/steps/publish-logs.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} - JobLabel: 'Publish_Artifacts_Logs' + StageLabel: 'BuildAssetRegistry' + JobLabel: 'Publish_Artifacts_Logs' diff --git a/eng/common/core-templates/jobs/jobs.yml b/eng/common/core-templates/jobs/jobs.yml index 01ada747665..cc8cce45278 100644 --- a/eng/common/core-templates/jobs/jobs.yml +++ b/eng/common/core-templates/jobs/jobs.yml @@ -43,6 +43,10 @@ parameters: artifacts: {} is1ESPipeline: '' + + # Publishing version w/default. + publishingVersion: 3 + repositoryAlias: self officialBuildId: '' @@ -102,6 +106,7 @@ jobs: parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} continueOnError: ${{ parameters.continueOnError }} + publishingVersion: ${{ parameters.publishingVersion }} dependsOn: - ${{ if ne(parameters.publishBuildAssetsDependsOn, '') }}: - ${{ each job in parameters.publishBuildAssetsDependsOn }}: diff --git a/eng/common/core-templates/post-build/post-build.yml b/eng/common/core-templates/post-build/post-build.yml index 2df4acb7685..905a6315e2d 100644 --- a/eng/common/core-templates/post-build/post-build.yml +++ b/eng/common/core-templates/post-build/post-build.yml @@ -9,6 +9,7 @@ parameters: default: 3 values: - 3 + - 4 - name: BARBuildId displayName: BAR Build Id @@ -140,16 +141,30 @@ stages: PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} is1ESPipeline: ${{ parameters.is1ESPipeline }} - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true + - ${{ if ne(parameters.publishingInfraVersion, 4) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + - ${{ if eq(parameters.publishingInfraVersion, 4) }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Pipeline Artifacts (V4) + inputs: + itemPattern: '*/packages/**/*.nupkg' + targetPath: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + - task: CopyFiles@2 + displayName: Flatten packages to PackageArtifacts + inputs: + SourceFolder: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + Contents: '**/*.nupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)/PackageArtifacts' + flattenFolders: true - task: PowerShell@2 displayName: Validate @@ -183,16 +198,30 @@ stages: PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} is1ESPipeline: ${{ parameters.is1ESPipeline }} - - task: DownloadBuildArtifacts@0 - displayName: Download Package Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: PackageArtifacts - checkDownloadedFiles: true + - ${{ if ne(parameters.publishingInfraVersion, 4) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: PackageArtifacts + checkDownloadedFiles: true + - ${{ if eq(parameters.publishingInfraVersion, 4) }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Pipeline Artifacts (V4) + inputs: + itemPattern: '*/packages/**/*.nupkg' + targetPath: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + - task: CopyFiles@2 + displayName: Flatten packages to PackageArtifacts + inputs: + SourceFolder: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + Contents: '**/*.nupkg' + TargetFolder: '$(Build.ArtifactStagingDirectory)/PackageArtifacts' + flattenFolders: true # This is necessary whenever we want to publish/restore to an AzDO private feed # Since sdk-task.ps1 tries to restore packages we need to do this authentication here @@ -244,16 +273,30 @@ stages: PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} is1ESPipeline: ${{ parameters.is1ESPipeline }} - - task: DownloadBuildArtifacts@0 - displayName: Download Blob Artifacts - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - artifactName: BlobArtifacts - checkDownloadedFiles: true + - ${{ if ne(parameters.publishingInfraVersion, 4) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: specific + buildVersionToDownload: specific + project: $(AzDOProjectName) + pipeline: $(AzDOPipelineId) + buildId: $(AzDOBuildId) + artifactName: BlobArtifacts + checkDownloadedFiles: true + - ${{ if eq(parameters.publishingInfraVersion, 4) }}: + - task: DownloadPipelineArtifact@2 + displayName: Download Pipeline Artifacts (V4) + inputs: + itemPattern: '*/assets/**' + targetPath: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + - task: CopyFiles@2 + displayName: Flatten assets to BlobArtifacts + inputs: + SourceFolder: '$(Build.ArtifactStagingDirectory)/PipelineArtifactsDownload' + Contents: '**/*' + TargetFolder: '$(Build.ArtifactStagingDirectory)/BlobArtifacts' + flattenFolders: true - task: PowerShell@2 displayName: Validate @@ -328,7 +371,7 @@ stages: scriptPath: $(System.DefaultWorkingDirectory)/eng/common/post-build/publish-using-darc.ps1 arguments: > -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} + -PublishingInfraVersion 3 -AzdoToken '$(System.AccessToken)' -WaitPublishingFinish true -RequireDefaultChannels ${{ parameters.requireDefaultChannels }} diff --git a/eng/common/core-templates/post-build/setup-maestro-vars.yml b/eng/common/core-templates/post-build/setup-maestro-vars.yml index a7abd58c4bb..6dfa99ec5e3 100644 --- a/eng/common/core-templates/post-build/setup-maestro-vars.yml +++ b/eng/common/core-templates/post-build/setup-maestro-vars.yml @@ -8,12 +8,11 @@ steps: - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 + - task: DownloadPipelineArtifact@2 displayName: Download Release Configs inputs: - buildType: current artifactName: ReleaseConfigs - checkDownloadedFiles: true + targetPath: '$(Build.StagingDirectory)/ReleaseConfigs' - task: AzureCLI@2 name: setReleaseVars diff --git a/eng/common/core-templates/steps/component-governance.yml b/eng/common/core-templates/steps/component-governance.yml deleted file mode 100644 index cf0649aa956..00000000000 --- a/eng/common/core-templates/steps/component-governance.yml +++ /dev/null @@ -1,16 +0,0 @@ -parameters: - disableComponentGovernance: false - componentGovernanceIgnoreDirectories: '' - is1ESPipeline: false - displayName: 'Component Detection' - -steps: -- ${{ if eq(parameters.disableComponentGovernance, 'true') }}: - - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" - displayName: Set skipComponentGovernanceDetection variable -- ${{ if ne(parameters.disableComponentGovernance, 'true') }}: - - task: ComponentGovernanceComponentDetection@0 - continueOnError: true - displayName: ${{ parameters.displayName }} - inputs: - ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} diff --git a/eng/common/core-templates/steps/generate-sbom.yml b/eng/common/core-templates/steps/generate-sbom.yml index c05f6502797..aad0a8aeda3 100644 --- a/eng/common/core-templates/steps/generate-sbom.yml +++ b/eng/common/core-templates/steps/generate-sbom.yml @@ -1,54 +1,14 @@ -# BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. -# PackageName - The name of the package this SBOM represents. -# PackageVersion - The version of the package this SBOM represents. -# ManifestDirPath - The path of the directory where the generated manifest files will be placed -# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. - parameters: - PackageVersion: 10.0.0 - BuildDropPath: '$(System.DefaultWorkingDirectory)/artifacts' - PackageName: '.NET' - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - IgnoreDirectories: '' - sbomContinueOnError: true - is1ESPipeline: false - # disable publishArtifacts if some other step is publishing the artifacts (like job.yml). - publishArtifacts: true + PackageVersion: unused + BuildDropPath: unused + PackageName: unused + ManifestDirPath: unused + IgnoreDirectories: unused + sbomContinueOnError: unused + is1ESPipeline: unused + publishArtifacts: unused steps: -- task: PowerShell@2 - displayName: Prep for SBOM generation in (Non-linux) - condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) - inputs: - filePath: ./eng/common/generate-sbom-prep.ps1 - arguments: ${{parameters.manifestDirPath}} - -# Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 - script: | - chmod +x ./eng/common/generate-sbom-prep.sh - ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} - displayName: Prep for SBOM generation in (Linux) - condition: eq(variables['Agent.Os'], 'Linux') - continueOnError: ${{ parameters.sbomContinueOnError }} - -- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'Generate SBOM manifest' - continueOnError: ${{ parameters.sbomContinueOnError }} - inputs: - PackageName: ${{ parameters.packageName }} - BuildDropPath: ${{ parameters.buildDropPath }} - PackageVersion: ${{ parameters.packageVersion }} - ManifestDirPath: ${{ parameters.manifestDirPath }}/$(ARTIFACT_NAME) - ${{ if ne(parameters.IgnoreDirectories, '') }}: - AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' - -- ${{ if eq(parameters.publishArtifacts, 'true')}}: - - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml - parameters: - is1ESPipeline: ${{ parameters.is1ESPipeline }} - args: - displayName: Publish SBOM manifest - continueOnError: ${{parameters.sbomContinueOnError}} - targetPath: '${{ parameters.manifestDirPath }}' - artifactName: $(ARTIFACT_NAME) - + echo "##vso[task.logissue type=warning]Including generate-sbom.yml is deprecated, SBOM generation is handled 1ES PT now. Remove this include." + displayName: Issue generate-sbom.yml deprecation warning diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml index a9ea99ba6aa..4eed0312b80 100644 --- a/eng/common/core-templates/steps/publish-logs.yml +++ b/eng/common/core-templates/steps/publish-logs.yml @@ -50,13 +50,14 @@ steps: TargetFolder: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' condition: always() -- template: /eng/common/core-templates/steps/publish-build-artifacts.yml +- template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml parameters: is1ESPipeline: ${{ parameters.is1ESPipeline }} args: displayName: Publish Logs - pathToPublish: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' - publishLocation: Container - artifactName: PostBuildLogs + targetPath: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' + artifactName: PostBuildLogs_${{ parameters.StageLabel }}_${{ parameters.JobLabel }}_Attempt$(System.JobAttempt) continueOnError: true condition: always() + retryCountOnTaskFailure: 10 # for any files being locked + isProduction: false # logs are non-production artifacts diff --git a/eng/common/core-templates/steps/source-build.yml b/eng/common/core-templates/steps/source-build.yml index b9c86c18ae4..09ae5cd73ae 100644 --- a/eng/common/core-templates/steps/source-build.yml +++ b/eng/common/core-templates/steps/source-build.yml @@ -62,4 +62,4 @@ steps: artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) continueOnError: true condition: succeededOrFailed() - sbomEnabled: false # we don't need SBOM for logs + isProduction: false # logs are non-production artifacts diff --git a/eng/common/generate-sbom-prep.ps1 b/eng/common/generate-sbom-prep.ps1 deleted file mode 100644 index a0c7d792a76..00000000000 --- a/eng/common/generate-sbom-prep.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -Param( - [Parameter(Mandatory=$true)][string] $ManifestDirPath # Manifest directory where sbom will be placed -) - -. $PSScriptRoot\pipeline-logging-functions.ps1 - -# Normally - we'd listen to the manifest path given, but 1ES templates will overwrite if this level gets uploaded directly -# with their own overwriting ours. So we create it as a sub directory of the requested manifest path. -$ArtifactName = "${env:SYSTEM_STAGENAME}_${env:AGENT_JOBNAME}_SBOM" -$SafeArtifactName = $ArtifactName -replace '["/:<>\\|?@*"() ]', '_' -$SbomGenerationDir = Join-Path $ManifestDirPath $SafeArtifactName - -Write-Host "Artifact name before : $ArtifactName" -Write-Host "Artifact name after : $SafeArtifactName" - -Write-Host "Creating dir $ManifestDirPath" - -# create directory for sbom manifest to be placed -if (!(Test-Path -path $SbomGenerationDir)) -{ - New-Item -ItemType Directory -path $SbomGenerationDir - Write-Host "Successfully created directory $SbomGenerationDir" -} -else{ - Write-PipelineTelemetryError -category 'Build' "Unable to create sbom folder." -} - -Write-Host "Updating artifact name" -Write-Host "##vso[task.setvariable variable=ARTIFACT_NAME]$SafeArtifactName" diff --git a/eng/common/generate-sbom-prep.sh b/eng/common/generate-sbom-prep.sh deleted file mode 100755 index b8ecca72bbf..00000000000 --- a/eng/common/generate-sbom-prep.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -source="${BASH_SOURCE[0]}" - -# resolve $SOURCE until the file is no longer a symlink -while [[ -h $source ]]; do - scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" - source="$(readlink "$source")" - - # if $source was a relative symlink, we need to resolve it relative to the path where the - # symlink file was located - [[ $source != /* ]] && source="$scriptroot/$source" -done -scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" -. $scriptroot/pipeline-logging-functions.sh - - -# replace all special characters with _, some builds use special characters like : in Agent.Jobname, that is not a permissible name while uploading artifacts. -artifact_name=$SYSTEM_STAGENAME"_"$AGENT_JOBNAME"_SBOM" -safe_artifact_name="${artifact_name//["/:<>\\|?@*$" ]/_}" -manifest_dir=$1 - -# Normally - we'd listen to the manifest path given, but 1ES templates will overwrite if this level gets uploaded directly -# with their own overwriting ours. So we create it as a sub directory of the requested manifest path. -sbom_generation_dir="$manifest_dir/$safe_artifact_name" - -if [ ! -d "$sbom_generation_dir" ] ; then - mkdir -p "$sbom_generation_dir" - echo "Sbom directory created." $sbom_generation_dir -else - Write-PipelineTelemetryError -category 'Build' "Unable to create sbom folder." -fi - -echo "Artifact name before : "$artifact_name -echo "Artifact name after : "$safe_artifact_name -export ARTIFACT_NAME=$safe_artifact_name -echo "##vso[task.setvariable variable=ARTIFACT_NAME]$safe_artifact_name" - -exit 0 diff --git a/eng/common/template-guidance.md b/eng/common/template-guidance.md index 4bf4cf41bd7..e2b07a865f1 100644 --- a/eng/common/template-guidance.md +++ b/eng/common/template-guidance.md @@ -82,7 +82,6 @@ eng\common\ publish-build-artifacts.yml (logic) publish-pipeline-artifacts.yml (logic) component-governance.yml (shim) - generate-sbom.yml (shim) publish-logs.yml (shim) retain-build.yml (shim) send-to-helix.yml (shim) @@ -107,7 +106,6 @@ eng\common\ setup-maestro-vars.yml (logic) steps\ component-governance.yml (logic) - generate-sbom.yml (logic) publish-build-artifacts.yml (redirect) publish-logs.yml (logic) publish-pipeline-artifacts.yml (redirect) diff --git a/eng/common/templates-official/job/job.yml b/eng/common/templates-official/job/job.yml index 92a0664f564..d68e9fbc265 100644 --- a/eng/common/templates-official/job/job.yml +++ b/eng/common/templates-official/job/job.yml @@ -1,24 +1,15 @@ parameters: -# Sbom related params - enableSbom: true runAsPublic: false - PackageVersion: 9.0.0 - BuildDropPath: '$(System.DefaultWorkingDirectory)/artifacts' +# Sbom related params, unused now and can eventually be removed + enableSbom: unused + PackageVersion: unused + BuildDropPath: unused jobs: - template: /eng/common/core-templates/job/job.yml parameters: is1ESPipeline: true - componentGovernanceSteps: - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - - template: /eng/common/templates/steps/generate-sbom.yml - parameters: - PackageVersion: ${{ parameters.packageVersion }} - BuildDropPath: ${{ parameters.buildDropPath }} - ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom - publishArtifacts: false - # publish artifacts # for 1ES managed templates, use the templateContext.output to handle multiple outputs. templateContext: @@ -26,12 +17,19 @@ jobs: outputs: - ${{ if ne(parameters.artifacts.publish, '') }}: - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - output: buildArtifacts + - output: pipelineArtifact displayName: Publish pipeline artifacts - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - ArtifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} - condition: always() - retryCountOnTaskFailure: 10 # for any logs being locked + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts' + artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} + condition: succeeded() + retryCountOnTaskFailure: 10 # for any files being locked + continueOnError: true + - output: pipelineArtifact + displayName: Publish pipeline artifacts + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts' + artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }}_Attempt$(System.JobAttempt) + condition: not(succeeded()) + retryCountOnTaskFailure: 10 # for any files being locked continueOnError: true - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - output: pipelineArtifact @@ -40,18 +38,18 @@ jobs: displayName: 'Publish logs' continueOnError: true condition: always() - retryCountOnTaskFailure: 10 # for any logs being locked - sbomEnabled: false # we don't need SBOM for logs + retryCountOnTaskFailure: 10 # for any files being locked + isProduction: false # logs are non-production artifacts - ${{ if eq(parameters.enablePublishBuildArtifacts, true) }}: - - output: buildArtifacts + - output: pipelineArtifact displayName: Publish Logs - PathtoPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' - publishLocation: Container - ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)_Attempt$(System.JobAttempt)' ) }} + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + artifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)_Attempt$(System.JobAttempt)' ) }} continueOnError: true condition: always() - sbomEnabled: false # we don't need SBOM for logs + retryCountOnTaskFailure: 10 # for any files being locked + isProduction: false # logs are non-production artifacts - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - output: pipelineArtifact @@ -59,14 +57,20 @@ jobs: artifactName: 'BuildConfiguration' displayName: 'Publish build retry configuration' continueOnError: true - sbomEnabled: false # we don't need SBOM for BuildConfiguration + retryCountOnTaskFailure: 10 # for any files being locked + isProduction: false # BuildConfiguration is a non-production artifact - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: + # V4 publishing: automatically publish staged artifacts as a pipeline artifact. + # The artifact name matches the SDK's FutureArtifactName ($(System.PhaseName)_Artifacts), + # which is encoded in the asset manifest for downstream publishing to discover. + # Jobs can opt in by setting enablePublishing: true. + - ${{ if and(eq(parameters.publishingVersion, 4), eq(parameters.enablePublishing, 'true')) }}: - output: pipelineArtifact - displayName: Publish SBOM manifest + displayName: 'Publish V4 pipeline artifacts' + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts' + artifactName: '$(System.PhaseName)_Artifacts' continueOnError: true - targetPath: $(Build.ArtifactStagingDirectory)/sbom - artifactName: $(ARTIFACT_NAME) + retryCountOnTaskFailure: 10 # for any files being locked # add any outputs provided via root yaml - ${{ if ne(parameters.templateContext.outputs, '') }}: diff --git a/eng/common/templates-official/steps/component-governance.yml b/eng/common/templates-official/steps/component-governance.yml deleted file mode 100644 index 30bb3985ca2..00000000000 --- a/eng/common/templates-official/steps/component-governance.yml +++ /dev/null @@ -1,7 +0,0 @@ -steps: -- template: /eng/common/core-templates/steps/component-governance.yml - parameters: - is1ESPipeline: true - - ${{ each parameter in parameters }}: - ${{ parameter.key }}: ${{ parameter.value }} diff --git a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml index 172f9f0fdc9..9e5981365e5 100644 --- a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml +++ b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml @@ -24,5 +24,7 @@ steps: artifactName: ${{ parameters.args.artifactName }} ${{ if parameters.args.properties }}: properties: ${{ parameters.args.properties }} - ${{ if parameters.args.sbomEnabled }}: + ${{ if ne(parameters.args.sbomEnabled, '') }}: sbomEnabled: ${{ parameters.args.sbomEnabled }} + ${{ if ne(parameters.args.isProduction, '') }}: + isProduction: ${{ parameters.args.isProduction }} diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 238fa0818f7..5e261f34db4 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -1,12 +1,12 @@ parameters: enablePublishBuildArtifacts: false - disableComponentGovernance: '' - componentGovernanceIgnoreDirectories: '' -# Sbom related params - enableSbom: true runAsPublic: false - PackageVersion: 9.0.0 - BuildDropPath: '$(System.DefaultWorkingDirectory)/artifacts' +# CG related params, unused now and can eventually be removed + disableComponentGovernance: unused +# Sbom related params, unused now and can eventually be removed + enableSbom: unused + PackageVersion: unused + BuildDropPath: unused jobs: - template: /eng/common/core-templates/job/job.yml @@ -21,32 +21,34 @@ jobs: - ${{ each step in parameters.steps }}: - ${{ step }} - componentGovernanceSteps: - - template: /eng/common/templates/steps/component-governance.yml - parameters: - ${{ if eq(parameters.disableComponentGovernance, '') }}: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.runAsPublic, 'false'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/dotnet/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/microsoft/'), eq(variables['Build.SourceBranch'], 'refs/heads/main'))) }}: - disableComponentGovernance: false - ${{ else }}: - disableComponentGovernance: true - ${{ else }}: - disableComponentGovernance: ${{ parameters.disableComponentGovernance }} - componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} + # we don't run CG in public + - ${{ if eq(variables['System.TeamProject'], 'public') }}: + - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" + displayName: Set skipComponentGovernanceDetection variable artifactPublishSteps: - ${{ if ne(parameters.artifacts.publish, '') }}: - ${{ if and(ne(parameters.artifacts.publish.artifacts, 'false'), ne(parameters.artifacts.publish.artifacts, '')) }}: - - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml parameters: is1ESPipeline: false args: displayName: Publish pipeline artifacts - pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts' - publishLocation: Container + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts' artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }} continueOnError: true - condition: always() - retryCountOnTaskFailure: 10 # for any logs being locked + condition: succeeded() + retryCountOnTaskFailure: 10 # for any files being locked + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml + parameters: + is1ESPipeline: false + args: + displayName: Publish pipeline artifacts + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts' + artifactName: ${{ coalesce(parameters.artifacts.publish.artifacts.name , 'Artifacts_$(Agent.Os)_$(_BuildConfig)') }}_Attempt$(System.JobAttempt) + continueOnError: true + condition: not(succeeded()) + retryCountOnTaskFailure: 10 # for any files being locked - ${{ if and(ne(parameters.artifacts.publish.logs, 'false'), ne(parameters.artifacts.publish.logs, '')) }}: - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml parameters: @@ -57,20 +59,19 @@ jobs: displayName: 'Publish logs' continueOnError: true condition: always() - retryCountOnTaskFailure: 10 # for any logs being locked - sbomEnabled: false # we don't need SBOM for logs + retryCountOnTaskFailure: 10 # for any files being locked - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - - template: /eng/common/core-templates/steps/publish-build-artifacts.yml + - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml parameters: is1ESPipeline: false args: displayName: Publish Logs - pathToPublish: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' - publishLocation: Container + targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' artifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)_Attempt$(System.JobAttempt)' ) }} continueOnError: true condition: always() + retryCountOnTaskFailure: 10 # for any files being locked - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml @@ -81,4 +82,4 @@ jobs: artifactName: 'BuildConfiguration' displayName: 'Publish build retry configuration' continueOnError: true - sbomEnabled: false # we don't need SBOM for BuildConfiguration + retryCountOnTaskFailure: 10 # for any files being locked diff --git a/eng/common/templates/steps/component-governance.yml b/eng/common/templates/steps/component-governance.yml deleted file mode 100644 index c12a5f8d21d..00000000000 --- a/eng/common/templates/steps/component-governance.yml +++ /dev/null @@ -1,7 +0,0 @@ -steps: -- template: /eng/common/core-templates/steps/component-governance.yml - parameters: - is1ESPipeline: false - - ${{ each parameter in parameters }}: - ${{ parameter.key }}: ${{ parameter.value }} diff --git a/global.json b/global.json index 6b18b79005c..9a50634c305 100644 --- a/global.json +++ b/global.json @@ -18,7 +18,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26209.115", - "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26209.115" + "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26210.105", + "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.26210.105" } } From c6beae7408542e2a5a6ff4de00f8178cad7d4f42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 11:38:03 -0700 Subject: [PATCH 14/18] Bump actions/github-script from 8 to 9 (#38080) Bumps [actions/github-script](https://github.com/actions/github-script) from 8 to 9. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v8...v9) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: '9' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/api-review-baselines.yml | 4 ++-- .github/workflows/issues-closed.yml | 2 +- .github/workflows/label-and-milestone-issues.yml | 2 +- .github/workflows/validate-pr-target-branch.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/api-review-baselines.yml b/.github/workflows/api-review-baselines.yml index 469d15be308..798f0f6134c 100644 --- a/.github/workflows/api-review-baselines.yml +++ b/.github/workflows/api-review-baselines.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Detect changed baseline files and add label id: detect - uses: actions/github-script@v8 + uses: actions/github-script@v9 with: script: | const owner = context.repo.owner; @@ -215,7 +215,7 @@ jobs: - name: Create PR comment with delta if: steps.detect.outputs.has_baselines == 'true' - uses: actions/github-script@v8 + uses: actions/github-script@v9 env: COMMENT_PATH: ${{ steps.delta.outputs.comment_path }} PR_NUMBER: ${{ steps.detect.outputs.pr_number }} diff --git a/.github/workflows/issues-closed.yml b/.github/workflows/issues-closed.yml index 2d8d81e3e78..de01fd7c0f3 100644 --- a/.github/workflows/issues-closed.yml +++ b/.github/workflows/issues-closed.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-slim steps: - name: Reclose as not planned if external user - uses: actions/github-script@v8 + uses: actions/github-script@v9 with: script: | const issue = context.payload.issue; diff --git a/.github/workflows/label-and-milestone-issues.yml b/.github/workflows/label-and-milestone-issues.yml index 7a5f30005ff..f1c98b36754 100644 --- a/.github/workflows/label-and-milestone-issues.yml +++ b/.github/workflows/label-and-milestone-issues.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-slim steps: - name: Label issues and update milestones - uses: actions/github-script@v8 + uses: actions/github-script@v9 with: script: | const owner = context.repo.owner; diff --git a/.github/workflows/validate-pr-target-branch.yml b/.github/workflows/validate-pr-target-branch.yml index 5cc4b2b4bbb..c8380e1381c 100644 --- a/.github/workflows/validate-pr-target-branch.yml +++ b/.github/workflows/validate-pr-target-branch.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-slim steps: - name: Check PR target branch and author permissions - uses: actions/github-script@v8 + uses: actions/github-script@v9 with: script: | const pr = context.payload.pull_request; From 74e800c10f8fbdfee63f0377a928c1d197769c7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 18:56:15 +0000 Subject: [PATCH 15/18] Bump actions/checkout from 4 to 6 (#38081) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/api-review-baselines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/api-review-baselines.yml b/.github/workflows/api-review-baselines.yml index 798f0f6134c..b9d0930dab0 100644 --- a/.github/workflows/api-review-baselines.yml +++ b/.github/workflows/api-review-baselines.yml @@ -90,7 +90,7 @@ jobs: - name: Check out selected commit if: steps.detect.outputs.has_baselines == 'true' - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ steps.detect.outputs.target_sha }} fetch-depth: 1 From f7d73016c3cfdcebfee57c1fbb6dadb0ed143219 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Fri, 10 Apr 2026 12:24:50 -0700 Subject: [PATCH 16/18] Fix API diff workflow manual trigger input (#38082) --- .github/workflows/api-review-baselines.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/api-review-baselines.yml b/.github/workflows/api-review-baselines.yml index b9d0930dab0..059a7400cb1 100644 --- a/.github/workflows/api-review-baselines.yml +++ b/.github/workflows/api-review-baselines.yml @@ -34,9 +34,10 @@ jobs: script: | const owner = context.repo.owner; const repo = context.repo.repo; - const prNumber = context.eventName === 'workflow_dispatch' - ? Number(core.getInput('pr-number')) + const prNumberInput = context.eventName === 'workflow_dispatch' + ? context.payload.inputs?.['pr-number'] : context.payload.pull_request.number; + const prNumber = Number(prNumberInput); if (!Number.isInteger(prNumber) || prNumber <= 0) { core.setFailed(`Invalid PR number: ${prNumber}`); From 0de56fb201f812d4cbdb96708d07d3fb7b32b209 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Sat, 11 Apr 2026 01:00:39 +0300 Subject: [PATCH 17/18] Filter out full-text catalog operations from history table creation (#38050) This is a workaround for #34991. Part of #11488 --- .../Migrations/HistoryRepository.cs | 9 ++- .../Internal/SqlServerHistoryRepository.cs | 31 +++++++++ .../SqlServerHistoryRepositoryTest.cs | 67 +++++++++++++++++-- 3 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/EFCore.Relational/Migrations/HistoryRepository.cs b/src/EFCore.Relational/Migrations/HistoryRepository.cs index 48934123be0..714797d9fea 100644 --- a/src/EFCore.Relational/Migrations/HistoryRepository.cs +++ b/src/EFCore.Relational/Migrations/HistoryRepository.cs @@ -85,7 +85,14 @@ protected virtual string MigrationIdColumnName .FindProperty(nameof(HistoryRow.MigrationId))! .GetColumnName(); - private IModel EnsureModel() + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + protected virtual IModel EnsureModel() { if (_model == null) { diff --git a/src/EFCore.SqlServer/Migrations/Internal/SqlServerHistoryRepository.cs b/src/EFCore.SqlServer/Migrations/Internal/SqlServerHistoryRepository.cs index e8128cd0ef5..6189774c621 100644 --- a/src/EFCore.SqlServer/Migrations/Internal/SqlServerHistoryRepository.cs +++ b/src/EFCore.SqlServer/Migrations/Internal/SqlServerHistoryRepository.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; +using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.SqlServer.Migrations.Internal; @@ -24,6 +25,36 @@ public SqlServerHistoryRepository(HistoryRepositoryDependencies dependencies) { } + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + protected override IReadOnlyList GetCreateCommands() + { + // TODO: This is a hack around https://github.com/dotnet/efcore/issues/34991: provider-specific conventions may add + // database-level annotations (e.g. full-text catalogs) to the model, and the default EF logic causes them to be created + // at this point, when the history table is being created. This is too early, and causes the later actual migration to fail. + // So we filter out full-text catalog annotations from AlterDatabaseOperation. + // This follows the same approach as the Npgsql provider (npgsql/efcore.pg#3713). +#pragma warning disable EF1001 // Internal EF Core API usage. + var model = EnsureModel(); +#pragma warning restore EF1001 // Internal EF Core API usage. + + var operations = Dependencies.ModelDiffer.GetDifferences(null, model.GetRelationalModel()); + + foreach (var operation in operations) + { + if (operation is AlterDatabaseOperation alterDatabaseOperation) + { + alterDatabaseOperation.RemoveAnnotation(SqlServerAnnotationNames.FullTextCatalogs); + } + } + + return Dependencies.MigrationsSqlGenerator.Generate(operations, model); + } + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/test/EFCore.SqlServer.Tests/Migrations/SqlServerHistoryRepositoryTest.cs b/test/EFCore.SqlServer.Tests/Migrations/SqlServerHistoryRepositoryTest.cs index a19a9c536f1..273953819b5 100644 --- a/test/EFCore.SqlServer.Tests/Migrations/SqlServerHistoryRepositoryTest.cs +++ b/test/EFCore.SqlServer.Tests/Migrations/SqlServerHistoryRepositoryTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal; // ReSharper disable InconsistentNaming namespace Microsoft.EntityFrameworkCore.Migrations; @@ -21,6 +22,25 @@ [ProductVersion] nvarchar(32) NOT NULL, CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) ); +""", sql, ignoreLineEndingDifferences: true); + } + + [ConditionalFact] + public void GetCreateScript_works_with_full_text_catalog() + { + // Inject a model finalizing convention that adds a full-text catalog to the model, simulating a scenario where + // provider conventions add database-level annotations. Without filtering, the history table creation script would + // include CREATE FULLTEXT CATALOG. + var sql = CreateHistoryRepository(addFullTextCatalogConvention: true).GetCreateScript(); + + Assert.Equal( + """ +CREATE TABLE [__EFMigrationsHistory] ( + [MigrationId] nvarchar(150) NOT NULL, + [ProductVersion] nvarchar(32) NOT NULL, + CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) +); + """, sql, ignoreLineEndingDifferences: true); } @@ -149,17 +169,28 @@ public void GetEndIfScript_works() """, sql, ignoreLineEndingDifferences: true); } - private static IHistoryRepository CreateHistoryRepository(string schema = null) - => new TestDbContext( + private static IHistoryRepository CreateHistoryRepository( + string schema = null, + Action configureModel = null, + bool addFullTextCatalogConvention = false) + { + var serviceProvider = addFullTextCatalogConvention + ? SqlServerTestHelpers.Instance.CreateServiceProvider( + new ServiceCollection().AddSingleton()) + : SqlServerTestHelpers.Instance.CreateServiceProvider(); + + return new TestDbContext( new DbContextOptionsBuilder() - .UseInternalServiceProvider(SqlServerTestHelpers.Instance.CreateServiceProvider()) + .UseInternalServiceProvider(serviceProvider) .UseSqlServer( new SqlConnection("Database=DummyDatabase"), b => b.MigrationsHistoryTable(HistoryRepository.DefaultTableName, schema)) - .Options) + .Options, + configureModel) .GetService(); + } - private class TestDbContext(DbContextOptions options) : DbContext(options) + private class TestDbContext(DbContextOptions options, Action configureModel = null) : DbContext(options) { public DbSet Blogs { get; set; } @@ -169,9 +200,35 @@ public IQueryable TableFunction() protected override void OnModelCreating(ModelBuilder modelBuilder) { + configureModel?.Invoke(modelBuilder); + } + } + + /// + /// A convention plugin that adds a full-text catalog annotation to the model, simulating what a provider convention + /// might do. This allows testing that properly filters + /// out the full-text catalog from the history table creation script. + /// + private class FullTextCatalogConventionPlugin : IConventionSetPlugin + { + public ConventionSet ModifyConventions(ConventionSet conventionSet) + { + conventionSet.ModelFinalizingConventions.Add(new FullTextCatalogAddingConvention()); + return conventionSet; } } + private class FullTextCatalogAddingConvention : IModelFinalizingConvention + { +#pragma warning disable EF1001 // Internal EF Core API usage. + public void ProcessModelFinalizing( + IConventionModelBuilder modelBuilder, + IConventionContext context) + => SqlServerFullTextCatalog.AddFullTextCatalog( + (IMutableModel)modelBuilder.Metadata, "TestCatalog", ConfigurationSource.Convention); +#pragma warning restore EF1001 // Internal EF Core API usage. + } + private class Blog { public int Id { get; set; } From 3e204deb7341df29c4e991b971d1776f8f5427f9 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Fri, 10 Apr 2026 15:02:30 -0700 Subject: [PATCH 18/18] Format the API change comment as a C# diff for readability (#38084) --- .agents/skills/run-apichief/SKILL.md | 8 +- .github/workflows/api-review-baselines.yml | 108 ++++--- eng/Tools/ApiChief/Commands/EmitDelta.cs | 345 +++++++++++++++++++-- eng/Tools/ApiChief/Model/ApiModel.cs | 8 +- eng/Tools/ApiChief/Program.cs | 2 +- 5 files changed, 406 insertions(+), 65 deletions(-) diff --git a/.agents/skills/run-apichief/SKILL.md b/.agents/skills/run-apichief/SKILL.md index e3cc6769ef7..d78eef1d2e6 100644 --- a/.agents/skills/run-apichief/SKILL.md +++ b/.agents/skills/run-apichief/SKILL.md @@ -17,7 +17,7 @@ ApiChief can run against either a compiled assembly or a previously emitted base | `emit baseline` | Emit a JSON API baseline | `-o ` | | `emit summary` | Emit a human-readable API summary | `-o `, `-x` | | `emit review` | Emit API review files | `-o `, `-n` | -| `emit delta` | Emit a delta against an existing baseline | ``, `-o ` | +| `emit delta` | Emit a delta against an existing baseline, or markdown diff review files | ``, `-o `, `--diff` | | `check breaking` | Fail if breaking changes exist vs. a baseline | `` | Default to `emit baseline` if the user only asks to "run ApiChief". @@ -105,6 +105,9 @@ Before running, report the selected TFM if it matters for the task. # Emit API review artifacts & $dotnet $apiChief $assemblyPath emit review -o ".\\artifacts\\tmp\\API.$name" + +# Emit GitHub-friendly markdown diff files against a baseline +& $dotnet $apiChief $assemblyPath emit delta ".\\src\\$name\\$name.baseline.json" --diff -o ".\\artifacts\\tmp\\API.$name.Diff" ``` `emit delta` also supports passing a `.json` file as the current input instead of a DLL. @@ -124,4 +127,5 @@ After `emit baseline`: - show the chosen TFM(s) - report the output path(s) - for `check breaking`, state pass/fail -- for `emit delta`, mention that exit code `0` means changes, `2` means no changes, and `-1` means an error +- for `emit delta` and `emit delta --diff`, mention that exit code `0` means changes, `2` means no changes, and `-1` means an error +- prefer `emit delta --diff` output because it generates ready-to-post ```diff fenced markdown split across per-type `.md` files diff --git a/.github/workflows/api-review-baselines.yml b/.github/workflows/api-review-baselines.yml index 059a7400cb1..5d407919e6d 100644 --- a/.github/workflows/api-review-baselines.yml +++ b/.github/workflows/api-review-baselines.yml @@ -101,7 +101,7 @@ jobs: shell: bash run: ./restore.sh - - name: Build ApiChief and compute baseline deltas + - name: Build ApiChief and compute review diffs if: steps.detect.outputs.has_baselines == 'true' id: delta shell: bash @@ -157,25 +157,36 @@ jobs: return False raise - def truncate(text: str, limit: int = 20000) -> str: - if len(text) <= limit: - return text - return text[:limit] + '\n... (truncated)\n' + max_comment_length = 60000 + comment_bodies: list[str] = [] + current_body = '' - sections: list[str] = [] + def append_section(section: str) -> None: + nonlocal current_body + + if not current_body: + current_body = section + return + + candidate = current_body + '\n\n' + section + if len(candidate) > max_comment_length: + comment_bodies.append(current_body) + current_body = section + else: + current_body = candidate for index, file in enumerate(files): filename = file['filename'] old_path = workdir / f'{index}.old.baseline.json' new_path = workdir / f'{index}.new.baseline.json' - delta_path = workdir / f'{index}.delta.json' + review_dir = workdir / f'{index}.review' old_exists = download_file(base_sha, filename, old_path) new_exists = download_file(target_sha, filename, new_path) if old_exists and new_exists: result = subprocess.run( - [dotnet, apichief, str(new_path), 'emit', 'delta', str(old_path), '-o', str(delta_path)], + [dotnet, apichief, str(new_path), 'emit', 'delta', str(old_path), '--diff', '-o', str(review_dir)], capture_output=True, text=True, check=False) @@ -185,54 +196,77 @@ jobs: if result.returncode != 0: raise RuntimeError( - f'ApiChief delta failed for {filename} with exit code {result.returncode}:\n' + f'ApiChief delta diff failed for {filename} with exit code {result.returncode}:\n' f'{result.stdout}\n{result.stderr}') - delta_text = truncate(delta_path.read_text(encoding='utf-8')) - sections.append( - f"### `{filename}`\n\n" - f"
\nShow delta\n\n```json\n{delta_text}\n```\n
") + review_files = sorted(review_dir.rglob('*.md')) + if not review_files: + continue + + section = ( + f"## API review baseline changes for `{filename}`\n\n" + 'The diff below was generated by `ApiChief` between the base and selected PR versions.\n\n') + + for review_file in review_files: + section += ( + f"{review_file.read_text(encoding='utf-8').rstrip()}\n\n") + + append_section(section.rstrip()) elif new_exists: - sections.append(f"### `{filename}`\n\nThis baseline file was **added** in the selected PR.") + append_section( + f"## API review baseline changes for `{filename}`\n\n" + 'This baseline file was **added** in the selected PR.') elif old_exists: - sections.append(f"### `{filename}`\n\nThis baseline file was **removed** in the selected PR.") + append_section( + f"## API review baseline changes for `{filename}`\n\n" + 'This baseline file was **removed** in the selected PR.') - if not sections: - sections.append('No API deltas were produced for the modified baseline files.') + if not current_body: + append_section( + '## API review baseline changes\n\n' + 'No API deltas were produced for the modified baseline files.') - body = ( - '## API review baseline changes\n\n' - 'This PR modified one or more `*.baseline.json` files. ' - 'The deltas below were generated by `ApiChief` between the base and selected PR versions.\n\n' - + '\n\n'.join(sections) - ) + if current_body: + comment_bodies.append(current_body) - comment_path = workdir / 'comment.md' - comment_path.write_text(body[:65000], encoding='utf-8') + comments_dir = workdir / 'comments' + comments_dir.mkdir(parents=True, exist_ok=True) + + for index, body in enumerate(comment_bodies, start=1): + comment_path = comments_dir / f'{index:03}.md' + comment_path.write_text(body.rstrip() + '\n', encoding='utf-8') with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as output: - output.write(f'comment_path={comment_path}\n') + output.write(f'comments_dir={comments_dir}\n') PY - - name: Create PR comment with delta + - name: Create PR comment with diffs if: steps.detect.outputs.has_baselines == 'true' uses: actions/github-script@v9 env: - COMMENT_PATH: ${{ steps.delta.outputs.comment_path }} + COMMENTS_DIR: ${{ steps.delta.outputs.comments_dir }} PR_NUMBER: ${{ steps.detect.outputs.pr_number }} with: script: | const fs = require('fs'); + const path = require('path'); const owner = context.repo.owner; const repo = context.repo.repo; const issue_number = Number(process.env.PR_NUMBER); - const body = fs.readFileSync(process.env.COMMENT_PATH, 'utf8'); - - await github.rest.issues.createComment({ - owner, - repo, - issue_number, - body - }); + const commentsDir = process.env.COMMENTS_DIR; + + const commentFiles = fs.readdirSync(commentsDir) + .filter(file => file.endsWith('.md')) + .sort((a, b) => a.localeCompare(b)); + + for (const file of commentFiles) { + const body = fs.readFileSync(path.join(commentsDir, file), 'utf8'); + await github.rest.issues.createComment({ + owner, + repo, + issue_number, + body + }); + } - console.log(`Created new API review comment for PR #${issue_number}.`); + console.log(`Created ${commentFiles.length} API review comment(s) for PR #${issue_number}.`); diff --git a/eng/Tools/ApiChief/Commands/EmitDelta.cs b/eng/Tools/ApiChief/Commands/EmitDelta.cs index f2354555598..eb4a031bc82 100644 --- a/eng/Tools/ApiChief/Commands/EmitDelta.cs +++ b/eng/Tools/ApiChief/Commands/EmitDelta.cs @@ -2,8 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.CommandLine; using System.IO; +using System.Linq; using System.Threading.Tasks; using ApiChief.Model; @@ -11,6 +13,8 @@ namespace ApiChief.Commands; internal static class EmitDelta { + private static readonly HashSet InvalidFileNameChars = [..Path.GetInvalidFileNameChars(), ',']; + public const int NoChangesExitCode = 2; private sealed class EmitDeltaArgs @@ -20,6 +24,8 @@ private sealed class EmitDeltaArgs public string BaselinePath { get; set; } = string.Empty; public string? Output { get; set; } + + public bool Diff { get; set; } } public static Command Create(Argument assemblyPathArgument) @@ -31,13 +37,19 @@ public static Command Create(Argument assemblyPathArgument) var outputOption = new Option("--output", ["-o"]) { - Description = "Path of the delta file to produce" + Description = "Path of the delta file or diff directory to produce" + }; + + var diffOption = new Option("--diff") + { + Description = "Emit GitHub-friendly markdown diff files instead of JSON delta output" }; var command = new Command("delta", "Creates an API delta") { baselinePathArgument, outputOption, + diffOption, }; command.SetAction(parseResult => ExecuteAsync(new EmitDeltaArgs @@ -45,6 +57,7 @@ public static Command Create(Argument assemblyPathArgument) AssemblyPath = parseResult.GetValue(assemblyPathArgument), BaselinePath = parseResult.GetValue(baselinePathArgument) ?? string.Empty, Output = parseResult.GetValue(outputOption), + Diff = parseResult.GetValue(diffOption), })); return command; @@ -53,32 +66,18 @@ public static Command Create(Argument assemblyPathArgument) private static async Task ExecuteAsync(EmitDeltaArgs args) { - ApiModel current; - ApiModel baseline; - - try - { - current = LoadCurrentModel(args.AssemblyPath!.FullName); - } - catch (Exception ex) + if (args.Diff) { - Console.Error.WriteLine($"Unable to load current API model from '{args.AssemblyPath!.FullName}': {ex.Message}"); - return -1; + return await ExecuteDiffAsync(args).ConfigureAwait(false); } - try - { - baseline = ApiModel.LoadFromFile(args.BaselinePath); - } - catch (Exception ex) + var exitCode = TryCreateDeltaModel(args.AssemblyPath!.FullName, args.BaselinePath, out var current); + if (exitCode != 0 && exitCode != NoChangesExitCode) { - Console.Error.WriteLine($"Unable to load baseline report '{args.BaselinePath}': {ex.Message}"); - return -1; + return exitCode; } - baseline.EvaluateDelta(current); - - var result = current.ToString(); + var result = current!.ToString(); var hasChanges = current.Types.Count > 0; if (args.Output == null) @@ -101,6 +100,310 @@ private static async Task ExecuteAsync(EmitDeltaArgs args) return hasChanges ? 0 : NoChangesExitCode; } + private static async Task ExecuteDiffAsync(EmitDeltaArgs args) + { + var exitCode = TryCreateDeltaModel(args.AssemblyPath!.FullName, args.BaselinePath, out var deltaModel); + if (exitCode != 0) + { + return exitCode; + } + + var output = args.Output; + if (string.IsNullOrWhiteSpace(output)) + { + var name = Path.GetFileNameWithoutExtension(args.AssemblyPath!.Name); + output = $"API.{name}.Diff"; + } + + var names = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var type in deltaModel!.Types.OrderBy(t => t.Type, StringComparer.Ordinal)) + { + var file = GetOutputFileStem(type.Type); + + var tmp = file; + if (names.Contains(tmp)) + { + var count = 2; + while (names.Contains(tmp)) + { + tmp = file + "_" + count++; + } + } + + names.Add(tmp); + var fullFile = Path.Combine(output, tmp + ".md"); + + try + { + Directory.CreateDirectory(output); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unable to create output directory '{output}': {ex.Message}"); + return -1; + } + + try + { + await File.WriteAllTextAsync(fullFile, FormatDiffMarkdown(type)).ConfigureAwait(false); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unable to write output delta diff file '{fullFile}': {ex.Message}"); + return -1; + } + } + + return 0; + } + + private static string FormatDiffMarkdown(ApiType type) + { + List lines = []; + + var typeAdded = type.Additions != null && type.Removals == null; + var typeRemoved = type.Removals != null && type.Additions == null; + + if (typeRemoved) + { + lines.Add($"- {type.Type}"); + } + else if (typeAdded) + { + lines.Add($"+ {type.Type}"); + } + + AppendStageDiffLine(lines, type.Removals, '-'); + AppendStageDiffLine(lines, type.Additions, '+'); + AppendGroupedDiffMembers(lines, type.Removals, type.Additions); + + return $"### `{type.Type}`{Environment.NewLine}{Environment.NewLine}```diff{Environment.NewLine}{string.Join(Environment.NewLine, lines)}{Environment.NewLine}```{Environment.NewLine}"; + } + + private static void AppendStageDiffLine(List lines, ApiType? changeSet, char prefix) + { + if (changeSet?.Stage != null && changeSet.Stage != ApiStage.Stable) + { + lines.Add($"{prefix} [Stage] {changeSet.Stage}"); + } + } + + private static void AppendGroupedDiffMembers(List lines, ApiType? removals, ApiType? additions) + { + var removedEntries = GetDiffEntries(removals, '-'); + var addedEntries = GetDiffEntries(additions, '+'); + + var sharedNames = removedEntries + .Select(static entry => entry.Name) + .Intersect(addedEntries.Select(static entry => entry.Name), StringComparer.Ordinal) + .ToHashSet(StringComparer.Ordinal); + + foreach (var name in sharedNames.OrderBy(static name => name, StringComparer.Ordinal)) + { + foreach (var entry in removedEntries.Where(entry => entry.Name == name)) + { + lines.Add(entry.Line); + } + + foreach (var entry in addedEntries.Where(entry => entry.Name == name)) + { + lines.Add(entry.Line); + } + } + + foreach (var entry in removedEntries.Where(entry => !sharedNames.Contains(entry.Name))) + { + lines.Add(entry.Line); + } + + foreach (var entry in addedEntries.Where(entry => !sharedNames.Contains(entry.Name))) + { + lines.Add(entry.Line); + } + } + + private static List<(string Name, string Line)> GetDiffEntries(ApiType? changeSet, char prefix) + { + List<(string Name, string Line)> entries = []; + + if (changeSet == null) + { + return entries; + } + + AddDiffMembers(entries, changeSet.Fields, prefix); + AddDiffMembers(entries, changeSet.Properties, prefix); + AddDiffMembers(entries, changeSet.Methods, prefix); + + return entries; + } + + private static void AddDiffMembers(List<(string Name, string Line)> entries, ISet? members, char prefix) + { + if (members == null) + { + return; + } + + foreach (var member in members.OrderBy(m => GetMemberName(m.Member), StringComparer.Ordinal).ThenBy(m => m.Member, StringComparer.Ordinal)) + { + entries.Add((GetMemberName(member.Member), $"{prefix} {member.Member}")); + } + } + + private static string GetMemberName(string declaration) + { + var headerEnd = declaration.IndexOf(" {", StringComparison.Ordinal); + var parameterListStart = declaration.IndexOf('('); + + if (headerEnd < 0 || (parameterListStart >= 0 && parameterListStart < headerEnd)) + { + headerEnd = parameterListStart; + } + + if (headerEnd < 0) + { + headerEnd = declaration.Length; + } + + var header = declaration[..headerEnd].Trim(); + var lastDot = header.LastIndexOf('.'); + if (lastDot >= 0) + { + return header[(lastDot + 1)..]; + } + + var lastSpace = header.LastIndexOf(' '); + return lastSpace >= 0 ? header[(lastSpace + 1)..] : header; + } + + private static string GetOutputFileStem(string typeDeclaration) + => SanitizeFileName(StripTypeNameDecorations(typeDeclaration)); + + private static string StripTypeNameDecorations(string typeDeclaration) + { + var typeName = RemoveBracketedSections(typeDeclaration).Trim(); + + var removedPrefix = true; + while (removedPrefix) + { + removedPrefix = false; + + foreach (var prefix in new[] + { + "abstract ", "sealed ", "static ", "readonly ", "ref ", "partial ", + "record ", "class ", "struct ", "interface ", "enum ", "delegate " + }) + { + if (!typeName.StartsWith(prefix, StringComparison.Ordinal)) + { + continue; + } + + typeName = typeName[prefix.Length..].TrimStart(); + removedPrefix = true; + break; + } + } + + var whereIndex = typeName.IndexOf(" where ", StringComparison.Ordinal); + if (whereIndex >= 0) + { + typeName = typeName[..whereIndex]; + } + + var terminator = typeName.IndexOfAny([':', '(']); + if (terminator >= 0) + { + typeName = typeName[..terminator]; + } + + return typeName.Trim(); + } + + private static string RemoveBracketedSections(string value) + { + var buffer = new char[value.Length]; + var index = 0; + var depth = 0; + + foreach (var c in value) + { + switch (c) + { + case '[': + depth++; + continue; + case ']' when depth > 0: + depth--; + continue; + default: + if (depth == 0) + { + buffer[index++] = c; + } + + break; + } + } + + return new string(buffer, 0, index); + } + + private static string SanitizeFileName(string value) + { + var trimmed = value.Trim(); + if (trimmed.Length == 0) + { + return "_"; + } + + var buffer = new char[trimmed.Length]; + var current = 0; + foreach (var c in trimmed) + { + if (c == ' ') + { + continue; + } + + buffer[current++] = InvalidFileNameChars.Contains(c) ? '_' : c; + } + + return new string(buffer, 0, current); + } + + private static int TryCreateDeltaModel(string currentPath, string baselinePath, out ApiModel? current) + { + ApiModel baseline; + + try + { + current = LoadCurrentModel(currentPath); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unable to load current API model from '{currentPath}': {ex.Message}"); + current = null; + return -1; + } + + try + { + baseline = ApiModel.LoadFromFile(baselinePath); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unable to load baseline report '{baselinePath}': {ex.Message}"); + current = null; + return -1; + } + + baseline.EvaluateDelta(current); + + return current.Types.Count > 0 ? 0 : NoChangesExitCode; + } + private static ApiModel LoadCurrentModel(string path) => Path.GetExtension(path).Equals(".json", StringComparison.OrdinalIgnoreCase) ? ApiModel.LoadFromFile(path) diff --git a/eng/Tools/ApiChief/Model/ApiModel.cs b/eng/Tools/ApiChief/Model/ApiModel.cs index 060a2644338..15b67a3d6bb 100644 --- a/eng/Tools/ApiChief/Model/ApiModel.cs +++ b/eng/Tools/ApiChief/Model/ApiModel.cs @@ -44,8 +44,8 @@ public static ApiModel LoadFromAssembly(string path) public static ApiModel LoadFromFile(string path) => JsonSerializer.Deserialize(File.ReadAllText(path), _serializerOptions)!; - public void EvaluateDelta(ApiModel current) - => current.Types = FindChanges(this, current); + public void EvaluateDelta(ApiModel current, bool includeSharedMembers = false) + => current.Types = FindChanges(this, current, includeSharedMembers); public bool HasRemovals() => Types.Any(static type => type.Removals != null); @@ -53,7 +53,7 @@ public bool HasRemovals() public override string ToString() => JsonSerializer.Serialize(this, _serializerOptions).ReplaceLineEndings(Environment.NewLine); - private static ISet FindChanges(ApiModel baseline, ApiModel current) + private static ISet FindChanges(ApiModel baseline, ApiModel current, bool includeSharedMembers) { ISet result = new HashSet(); @@ -66,7 +66,7 @@ private static ISet FindChanges(ApiModel baseline, ApiModel current) continue; } - var typeDelta = CreateTypeDelta(currentType, currentType, baselineType, includeSharedMembers: true); + var typeDelta = CreateTypeDelta(currentType, currentType, baselineType, includeSharedMembers); if (typeDelta != null) { result.Add(typeDelta); diff --git a/eng/Tools/ApiChief/Program.cs b/eng/Tools/ApiChief/Program.cs index 24e36985eb2..1baa6e4eab1 100644 --- a/eng/Tools/ApiChief/Program.cs +++ b/eng/Tools/ApiChief/Program.cs @@ -14,7 +14,7 @@ public static Task Main(string[] args) { var assemblyPathArgument = new Argument("assembly-path") { - Description = "Path to the assembly to work with." + Description = "Path to the assembly or baseline file to work with." }; var rootCommand = new RootCommand("Helps with .NET API management activities")