From 557edde1c48ae3cab2d3560755e17f72c9b1f967 Mon Sep 17 00:00:00 2001 From: Tim Mulholland Date: Mon, 8 Jun 2026 13:11:00 -0700 Subject: [PATCH 1/2] Publish symbols from CI builds to internal symbol server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add MicroBuildArchiveSymbols@6 to both build pipelines so PDBs for the shipping assemblies are archived to the internal symbol server. SubmitToInternet is false, so symbols never reach the public MSDL. - New publish-symbols-stage.yml + publish-symbols-upload.yml templates so the same staging/upload pair can be reused by both pipelines. They're split because the staging step must run before the test step (the test step's DebugType, if it differed from the build step's, would invalidate MSBuild's up-to-date check and rebuild Core with a new MVID; combined with GeneratePackageOnBuild=true, that would also overwrite the produced nupkg with a DLL whose MVID no longer matched the PDB we uploaded). - Align the test step's DebugType with the build step's DebugType in both pipelines, so the test step doesn't trigger that rebuild. - build-core-lib (per-commit preview builds): gate the upload to main, dev, dev-v5, and archives/* — the branches in the pipeline's trigger that produce shipping nupkgs. - build-all-lib (v* tag-triggered release builds, all 6 packages): gate the upload to refs/tags/v*. - Stage glob covers src/**/bin/Release/**/Microsoft.FluentUI.*.{dll,pdb} with src/Templates/** excluded (Templates.csproj has IncludeBuildOutput=false; its placeholder DLL doesn't ship). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eng/pipelines/build-all-lib.yml | 12 ++++++++++ eng/pipelines/build-core-lib.yml | 10 ++++++++ eng/pipelines/publish-symbols-stage.yml | 30 ++++++++++++++++++++++++ eng/pipelines/publish-symbols-upload.yml | 27 +++++++++++++++++++++ 4 files changed, 79 insertions(+) create mode 100644 eng/pipelines/publish-symbols-stage.yml create mode 100644 eng/pipelines/publish-symbols-upload.yml diff --git a/eng/pipelines/build-all-lib.yml b/eng/pipelines/build-all-lib.yml index 7405ab6df3..d170d8c917 100644 --- a/eng/pipelines/build-all-lib.yml +++ b/eng/pipelines/build-all-lib.yml @@ -180,6 +180,14 @@ extends: projects: ${{ parameters.Projects }} arguments: '--configuration Release /p:ContinuousIntegrationBuild=true /p:DebugType=portable /p:DebugSymbols=true' + # Stage shipping binaries for symbol upload BEFORE the test step; + # see publish-symbols-stage.yml for why this must run pre-test. + # Pipeline only triggers on v* tags, but condition is explicit so + # a manual queue against a branch does not unintentionally upload. + - template: /eng/pipelines/publish-symbols-stage.yml@self + parameters: + condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + # Test and generate Code Coverage - task: DotNetCoreCLI@2 condition: eq(variables['ShouldTest'], 'true') @@ -215,6 +223,10 @@ extends: SearchPattern: '**/bin/**/*.pdb' # string. Required. Search pattern. Default: **/bin/**/*.pdb. SymbolServerType: 'TeamServices' + - template: /eng/pipelines/publish-symbols-upload.yml@self + parameters: + condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + # Since NuGet packages are generated during the build, we need to copy them to the artifacts folder. - task: CopyFiles@2 displayName: 'Pack $(Build.BuildNumber)' diff --git a/eng/pipelines/build-core-lib.yml b/eng/pipelines/build-core-lib.yml index d443896bc1..f56a7fe6b3 100644 --- a/eng/pipelines/build-core-lib.yml +++ b/eng/pipelines/build-core-lib.yml @@ -211,6 +211,12 @@ extends: #arguments: '--configuration Release /p:ContinuousIntegrationBuild=true -warnaserror' temp remove warnaserror arguments: '--configuration Release /p:ContinuousIntegrationBuild=true' + # Stage shipping binaries for symbol upload BEFORE the test step; + # see publish-symbols-stage.yml for why this must run pre-test. + - template: /eng/pipelines/publish-symbols-stage.yml@self + parameters: + condition: and(succeeded(), or(in(variables['Build.SourceBranch'], 'refs/heads/main', 'refs/heads/dev', 'refs/heads/dev-v5'), startsWith(variables['Build.SourceBranch'], 'refs/heads/archives/'))) + # Test and generate Code Coverage - task: DotNetCoreCLI@2 condition: eq(variables['ShouldTest'], 'true') @@ -239,6 +245,10 @@ extends: summaryFileLocation: '**/*.cobertura.xml' reportDirectory: CoverageFolder + - template: /eng/pipelines/publish-symbols-upload.yml@self + parameters: + condition: and(succeeded(), or(in(variables['Build.SourceBranch'], 'refs/heads/main', 'refs/heads/dev', 'refs/heads/dev-v5'), startsWith(variables['Build.SourceBranch'], 'refs/heads/archives/'))) + # Index sources and publish symbols - task: PublishSymbols@2 displayName: 'Publish Symbols to Artifact Services' diff --git a/eng/pipelines/publish-symbols-stage.yml b/eng/pipelines/publish-symbols-stage.yml new file mode 100644 index 0000000000..16400d2c86 --- /dev/null +++ b/eng/pipelines/publish-symbols-stage.yml @@ -0,0 +1,30 @@ +# Stage shipping binaries for symbol upload. Place this immediately after +# the Build step, BEFORE any task that runs `dotnet test` with a different +# /p:DebugType. The test step passes /p:DebugType=Full as a global MSBuild +# property, which propagates through P2P refs and rebuilds Core with a +# different MVID; if we staged after the test step, the binaries we upload +# would not match the binaries inside the shipping nupkg. +# +# The .pdb pattern is included for pipelines that build with +# /p:DebugType=portable (standalone PDBs). For pipelines using the csproj +# default of embedded, the PDB rides inside the DLL +# and the .pdb pattern matches nothing — harmless. We deliberately stay on +# SymWeb only (see publish-symbols-upload.yml's SubmitToInternet:false), +# so embedded-in-DLL is fine here. +parameters: +- name: condition + type: string + +steps: +- task: CopyFiles@2 + displayName: 'Collect shipping binaries for symbol upload' + condition: ${{ parameters.condition }} + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + src/**/bin/Release/**/Microsoft.FluentUI.*.dll + src/**/bin/Release/**/Microsoft.FluentUI.*.pdb + !src/Templates/** + TargetFolder: '$(Build.ArtifactStagingDirectory)/Symbols' + CleanTargetFolder: true + flattenFolders: false diff --git a/eng/pipelines/publish-symbols-upload.yml b/eng/pipelines/publish-symbols-upload.yml new file mode 100644 index 0000000000..7cba95abc9 --- /dev/null +++ b/eng/pipelines/publish-symbols-upload.yml @@ -0,0 +1,27 @@ +# Upload the staged DLL (+ PDB, if standalone) pairs to the internal +# symbol server. SubmitToInternet:false keeps these out of the public +# symbol server (MSDL); the task will print a warning about that override +# which is intentional and safe to ignore. The pair to this template is +# publish-symbols-stage.yml, which must run earlier in the same job. +parameters: +- name: condition + type: string + +steps: +- task: MicroBuildArchiveSymbols@6 + displayName: 'Archive symbols to internal symbol server' + condition: ${{ parameters.condition }} + inputs: + azureSubscription: 'VSEng-SymbolsUpload' + SymbolsFeatureName: 'FluentUIBlazor' + SymbolsProject: 'DDE' + SymbolsAgentPath: '$(Build.ArtifactStagingDirectory)/Symbols' + # FluentUI is a public Blazor library; we publish to SymWeb for + # internal debugging but intentionally skip MSDL because we do not + # currently publish symbols there for our packages. The task warns + # when SubmitToInternet is overridden — SuppressSymwebOnlyWarning + # acknowledges the override is deliberate. + SubmitToInternet: false + SuppressSymwebOnlyWarning: true + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) From 234eb5ab7b944780deef28a1b52c90fb295f51cd Mon Sep 17 00:00:00 2001 From: Tim Mulholland Date: Wed, 10 Jun 2026 15:22:17 -0700 Subject: [PATCH 2/2] Clarify wording in template comment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eng/pipelines/publish-symbols-upload.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/publish-symbols-upload.yml b/eng/pipelines/publish-symbols-upload.yml index 7cba95abc9..b14f293e6e 100644 --- a/eng/pipelines/publish-symbols-upload.yml +++ b/eng/pipelines/publish-symbols-upload.yml @@ -1,8 +1,8 @@ # Upload the staged DLL (+ PDB, if standalone) pairs to the internal # symbol server. SubmitToInternet:false keeps these out of the public # symbol server (MSDL); the task will print a warning about that override -# which is intentional and safe to ignore. The pair to this template is -# publish-symbols-stage.yml, which must run earlier in the same job. +# which is intentional and safe to ignore. The counterpart to this template +# is publish-symbols-stage.yml, which must run earlier in the same job. parameters: - name: condition type: string