diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 4e770766..c47acfaa 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.202-focal +FROM mcr.microsoft.com/dotnet/sdk:6.0.100-focal # Installing mono makes `dotnet test` work without errors even for net472. # But installing it takes a long time, so it's excluded by default. diff --git a/.editorconfig b/.editorconfig index ffd1e2df..5d74b93e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,13 +20,14 @@ indent_style = space indent_size = 4 insert_final_newline = true trim_trailing_whitespace = true +charset = utf-8-bom # Xml project files -[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj,runsettings}] +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj,msbuildproj}] indent_size = 2 # Xml config files -[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct,runsettings}] indent_size = 2 # JSON files @@ -167,9 +168,6 @@ csharp_prefer_braces = true:silent # SA1130: Use lambda syntax dotnet_diagnostic.SA1130.severity = silent -# CA1508: Avoid dead conditional code -dotnet_diagnostic.CA1508.severity = warning - # IDE1006: Naming Styles - StyleCop handles these for us dotnet_diagnostic.IDE1006.severity = none diff --git a/.github/workflows/Linux.runsettings b/.github/workflows/Linux.runsettings index b444e819..db20611f 100644 --- a/.github/workflows/Linux.runsettings +++ b/.github/workflows/Linux.runsettings @@ -1 +1,12 @@ - + + + + + + + + + + + + diff --git a/.github/workflows/Windows.runsettings b/.github/workflows/Windows.runsettings index 7b2d40f1..580e242b 100644 --- a/.github/workflows/Windows.runsettings +++ b/.github/workflows/Windows.runsettings @@ -5,8 +5,6 @@ - - %GITHUB_WORKSPACE% diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b802a1d..704c1349 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v1.0.2 - name: Prepare Visual Studio - run: '&"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe" /RootSuffix Exp /ResetSettings General.vssettings /Command File.Exit' + run: '&"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.exe" /RootSuffix Exp /ResetSettings General.vssettings /Command File.Exit' - name: build run: msbuild /t:Build /p:Configuration=${{ env.BUILDCONFIGURATION }} /v:m /bl:"bin/build_logs/build.binlog" - name: pack @@ -67,9 +67,8 @@ jobs: - name: Upload variables uses: actions/upload-artifact@v1 with: - name: variables + name: variables-${{ runner.os }} path: obj/_artifacts/variables - if: runner.os == 'Windows' continue-on-error: true - name: Upload build_logs if: always() @@ -102,16 +101,15 @@ jobs: - name: Upload symbols uses: actions/upload-artifact@v1 with: - name: symbols + name: symbols-${{ runner.os }} path: obj/_artifacts/symbols - if: runner.os == 'Windows' continue-on-error: true - name: Upload deployables uses: actions/upload-artifact@v1 with: - name: deployables + name: deployables-${{ runner.os }} path: obj/_artifacts/deployables - if: always() && runner.os == 'Windows' + if: always() - name: Publish code coverage results to codecov.io run: bash <(curl -s https://codecov.io/bash) shell: bash diff --git a/.github/workflows/macOS.runsettings b/.github/workflows/macOS.runsettings index b444e819..db20611f 100644 --- a/.github/workflows/macOS.runsettings +++ b/.github/workflows/macOS.runsettings @@ -1 +1,12 @@ - + + + + + + + + + + + + diff --git a/.vscode/settings.json b/.vscode/settings.json index 00aaed88..3ae1371c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,8 @@ { - "files.trimTrailingWhitespace": true, - "files.insertFinalNewline": true, - "files.trimFinalNewlines": true, - "omnisharp.enableEditorConfigSupport": true, - "omnisharp.enableImportCompletion": true, - "omnisharp.enableRoslynAnalyzers": true + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "files.trimFinalNewlines": true, + "omnisharp.enableEditorConfigSupport": true, + "omnisharp.enableImportCompletion": true, + "omnisharp.enableRoslynAnalyzers": true } diff --git a/Directory.Build.props b/Directory.Build.props index 66c8761b..8e5b7212 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,12 +2,13 @@ Debug $(MSBuildThisFileDirectory) - $(RepoRootPath)obj\$(MSBuildProjectName)\ + $(RepoRootPath)obj\$([MSBuild]::MakeRelative($(RepoRootPath), $(MSBuildProjectDirectory)))\ $(RepoRootPath)bin\$(MSBuildProjectName)\ $(RepoRootPath)bin\Packages\$(Configuration)\NuGet\ 10.0 strict enable + disable latest true true @@ -30,16 +31,19 @@ - - + - + + + + + diff --git a/NuGet.config b/NuGet.config index ecf73faa..cf4f4a13 100644 --- a/NuGet.config +++ b/NuGet.config @@ -11,6 +11,10 @@ + + + + Microsoft;xunit;manuel.roemer;sharwell;jamesnk;aarnott;MarcoRossignoli;Thecentury diff --git a/azure-pipelines/Convert-PDB.ps1 b/azure-pipelines/Convert-PDB.ps1 index 7a20305d..2d394e72 100644 --- a/azure-pipelines/Convert-PDB.ps1 +++ b/azure-pipelines/Convert-PDB.ps1 @@ -18,13 +18,19 @@ [string]$OutputPath ) + if ($IsMacOS -or $IsLinux) { + Write-Error "This script only works on Windows" + return + } + $version = '1.1.0-beta2-21101-01' - $baseDir = "$PSScriptRoot\..\obj\tools" - $pdb2pdbpath = "$baseDir\Microsoft.DiaSymReader.Pdb2Pdb.$version\tools\Pdb2Pdb.exe" + $baseDir = "$PSScriptRoot/../obj/tools" + $pdb2pdbpath = "$baseDir/Microsoft.DiaSymReader.Pdb2Pdb.$version/tools/Pdb2Pdb.exe" if (-not (Test-Path $pdb2pdbpath)) { if (-not (Test-Path $baseDir)) { New-Item -Type Directory -Path $baseDir | Out-Null } $baseDir = (Resolve-Path $baseDir).Path # Normalize it - & (& $PSScriptRoot\Get-NuGetTool.ps1) install Microsoft.DiaSymReader.Pdb2Pdb -version $version -PackageSaveMode nuspec -OutputDirectory $baseDir -Source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json | Out-Null + Write-Verbose "& (& $PSScriptRoot/Get-NuGetTool.ps1) install Microsoft.DiaSymReader.Pdb2Pdb -version $version -PackageSaveMode nuspec -OutputDirectory $baseDir -Source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json | Out-Null" + & (& $PSScriptRoot/Get-NuGetTool.ps1) install Microsoft.DiaSymReader.Pdb2Pdb -version $version -PackageSaveMode nuspec -OutputDirectory $baseDir -Source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json | Out-Null } $args = $DllPath,'/out',$OutputPath,'/nowarn','0021' diff --git a/azure-pipelines/Darwin.runsettings b/azure-pipelines/Darwin.runsettings index b444e819..db20611f 100644 --- a/azure-pipelines/Darwin.runsettings +++ b/azure-pipelines/Darwin.runsettings @@ -1 +1,12 @@ - + + + + + + + + + + + + diff --git a/azure-pipelines/Get-SymbolFiles.ps1 b/azure-pipelines/Get-SymbolFiles.ps1 index bba177f1..8793e19c 100644 --- a/azure-pipelines/Get-SymbolFiles.ps1 +++ b/azure-pipelines/Get-SymbolFiles.ps1 @@ -5,19 +5,23 @@ The root path to recursively search for PDBs. .PARAMETER Tests A switch indicating to find test-related PDBs instead of product-only PDBs. +.PARAMETER ConvertToWindowsPDBs + A switch to convert and return paths to Windows PDBs instead of portable PDBs. + Ignored on non-Windows agents. #> [CmdletBinding()] param ( [parameter(Mandatory=$true)] [string]$Path, - [switch]$Tests + [switch]$Tests, + [switch]$ConvertToWindowsPDBs=$true ) $WindowsPdbSubDirName = "symstore" $ActivityName = "Collecting symbols from $Path" Write-Progress -Activity $ActivityName -CurrentOperation "Discovery PDB files" -$PDBs = Get-ChildItem -rec "$Path\*.pdb" |? { $_.FullName -notmatch "\W$WindowsPdbSubDirName\W" } +$PDBs = Get-ChildItem -rec "$Path/*.pdb" |? { $_.FullName -notmatch "\W$WindowsPdbSubDirName\W" } # Filter PDBs to product OR test related. $testregex = "unittest|tests" @@ -44,8 +48,8 @@ $PDBs |% { } } |% { # Collect the DLLs/EXEs as well. - $dllPath = "$($_.Directory)\$($_.BaseName).dll" - $exePath = "$($_.Directory)\$($_.BaseName).exe" + $dllPath = "$($_.Directory)/$($_.BaseName).dll" + $exePath = "$($_.Directory)/$($_.BaseName).exe" if (Test-Path $dllPath) { $BinaryImagePath = $dllPath } elseif (Test-Path $exePath) { @@ -54,14 +58,18 @@ $PDBs |% { Write-Output $BinaryImagePath - # Convert the PDB to legacy Windows PDBs - Write-Host "Converting PDB for $_" -ForegroundColor DarkGray - $WindowsPdbDir = "$($_.Directory.FullName)\$WindowsPdbSubDirName" - if (!(Test-Path $WindowsPdbDir)) { mkdir $WindowsPdbDir | Out-Null } - & "$PSScriptRoot\Convert-PDB.ps1" -DllPath $BinaryImagePath -PdbPath $_ -OutputPath "$WindowsPdbDir\$($_.BaseName).pdb" - if ($LASTEXITCODE -ne 0) { - Write-Warning "PDB conversion of `"$_`" failed." - } + if ($ConvertToWindowsPDBs -and -not ($IsMacOS -or $IsLinux)) { + # Convert the PDB to legacy Windows PDBs + Write-Host "Converting PDB for $_" -ForegroundColor DarkGray + $WindowsPdbDir = "$($_.Directory.FullName)\$WindowsPdbSubDirName" + if (!(Test-Path $WindowsPdbDir)) { mkdir $WindowsPdbDir | Out-Null } + & "$PSScriptRoot\Convert-PDB.ps1" -DllPath $BinaryImagePath -PdbPath $_ -OutputPath "$WindowsPdbDir\$($_.BaseName).pdb" + if ($LASTEXITCODE -ne 0) { + Write-Warning "PDB conversion of `"$_`" failed." + } - Write-Output "$WindowsPdbDir\$($_.BaseName).pdb" + Write-Output "$WindowsPdbDir\$($_.BaseName).pdb" + } else { + Write-Output $_.FullName + } } diff --git a/azure-pipelines/Linux.runsettings b/azure-pipelines/Linux.runsettings index b444e819..db20611f 100644 --- a/azure-pipelines/Linux.runsettings +++ b/azure-pipelines/Linux.runsettings @@ -1 +1,12 @@ - + + + + + + + + + + + + diff --git a/azure-pipelines/PoliCheckExclusions.xml b/azure-pipelines/PoliCheckExclusions.xml new file mode 100644 index 00000000..5ae16710 --- /dev/null +++ b/azure-pipelines/PoliCheckExclusions.xml @@ -0,0 +1,10 @@ + + + NODE_MODULES|.STORE + + + + + + + diff --git a/azure-pipelines/Windows_NT.runsettings b/azure-pipelines/Windows_NT.runsettings index ae7df64b..b2a73abb 100644 --- a/azure-pipelines/Windows_NT.runsettings +++ b/azure-pipelines/Windows_NT.runsettings @@ -5,8 +5,6 @@ - - %BUILD_ARTIFACTSTAGINGDIRECTORY% diff --git a/azure-pipelines/artifacts/_all.ps1 b/azure-pipelines/artifacts/_all.ps1 index efd6bdb3..db10c5ff 100644 --- a/azure-pipelines/artifacts/_all.ps1 +++ b/azure-pipelines/artifacts/_all.ps1 @@ -25,10 +25,9 @@ Function EnsureTrailingSlash($path) { Get-ChildItem "$PSScriptRoot\*.ps1" -Exclude "_*" -Recurse |% { $ArtifactName = $_.BaseName + $totalFileCount = 0 $fileGroups = & $_ - if (!$fileGroups -or $fileGroups.Count -eq 0) { - Write-Warning "No files found for the `"$ArtifactName`" artifact." - } else { + if ($fileGroups) { $fileGroups.GetEnumerator() | % { $BaseDirectory = New-Object Uri ((EnsureTrailingSlash $_.Key.ToString()), [UriKind]::Absolute) $_.Value | % { @@ -46,7 +45,12 @@ Get-ChildItem "$PSScriptRoot\*.ps1" -Exclude "_*" -Recurse |% { Add-Member -InputObject $artifact -MemberType NoteProperty -Name ContainerFolder -Value (Split-Path $RelativePath) Write-Output $artifact + $totalFileCount += 1 } } } + + if ($totalFileCount -eq 0) { + Write-Warning "No files found for the `"$ArtifactName`" artifact." + } } diff --git a/azure-pipelines/artifacts/coverageResults.ps1 b/azure-pipelines/artifacts/coverageResults.ps1 index addbf85c..8fdb3f72 100644 --- a/azure-pipelines/artifacts/coverageResults.ps1 +++ b/azure-pipelines/artifacts/coverageResults.ps1 @@ -3,7 +3,7 @@ $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") # Prepare code coverage reports for merging on another machine if ($env:SYSTEM_DEFAULTWORKINGDIRECTORY) { Write-Host "Substituting $env:SYSTEM_DEFAULTWORKINGDIRECTORY with `"{reporoot}`"" - $reports = Get-ChildItem "$RepoRoot/bin/coverage.*.cobertura.xml" -Recurse + $reports = Get-ChildItem "$RepoRoot/bin/coverage.*cobertura.xml" -Recurse $reports |% { $content = Get-Content -Path $_ |% { $_ -Replace [regex]::Escape($env:SYSTEM_DEFAULTWORKINGDIRECTORY), "{reporoot}" } Set-Content -Path $_ -Value $content -Encoding UTF8 @@ -16,7 +16,7 @@ if (!((Test-Path $RepoRoot\bin) -and (Test-Path $RepoRoot\obj))) { return } @{ $RepoRoot = ( - @(Get-ChildItem "$RepoRoot\bin\coverage.*.cobertura.xml" -Recurse) + + @(Get-ChildItem "$RepoRoot\bin\coverage.*cobertura.xml" -Recurse) + (Get-ChildItem "$RepoRoot\obj\*.cs" -Recurse) ); } diff --git a/azure-pipelines/artifacts/symbols.ps1 b/azure-pipelines/artifacts/symbols.ps1 index b3451ce1..8704571e 100644 --- a/azure-pipelines/artifacts/symbols.ps1 +++ b/azure-pipelines/artifacts/symbols.ps1 @@ -1,11 +1,5 @@ -# This doesn't work off Windows, nor do we need to convert symbols on multiple OS agents -if ($IsMacOS -or $IsLinux) { - return; -} - -$BinPath = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\bin") -if (!(Test-Path $BinPath)) { return } -$symbolfiles = & "$PSScriptRoot\..\Get-SymbolFiles.ps1" -Path $BinPath | Get-Unique +$BinPath = [System.IO.Path]::GetFullPath("$PSScriptRoot/../../bin") +$symbolfiles = & "$PSScriptRoot/../Get-SymbolFiles.ps1" -Path $BinPath | Get-Unique @{ "$BinPath" = $SymbolFiles; diff --git a/azure-pipelines/artifacts/testResults.ps1 b/azure-pipelines/artifacts/testResults.ps1 index c7184221..13e94b75 100644 --- a/azure-pipelines/artifacts/testResults.ps1 +++ b/azure-pipelines/artifacts/testResults.ps1 @@ -1,12 +1,18 @@ +$result = @{} + if ($env:AGENT_TEMPDIRECTORY) { # The DotNetCoreCLI uses an alternate location to publish these files $guidRegex = '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$' - @{ - $env:AGENT_TEMPDIRECTORY = (Get-ChildItem $env:AGENT_TEMPDIRECTORY -Directory |? { $_.Name -match $guidRegex } |% { Get-ChildItem "$($_.FullName)\testhost*.dmp","$($_.FullName)\devenv*.dmp","$($_.FullName)\Sequence_*.xml" -Recurse }); - } -} else { + $result[$env:AGENT_TEMPDIRECTORY] = (Get-ChildItem $env:AGENT_TEMPDIRECTORY -Directory |? { $_.Name -match $guidRegex } |% { Get-ChildItem "$($_.FullName)\dotnet*.dmp","$($_.FullName)\testhost*.dmp","$($_.FullName)\devenv*.dmp","$($_.FullName)\Sequence_*.xml" -Recurse }); +} +else { $testRoot = Resolve-Path "$PSScriptRoot\..\..\src\Microsoft.VisualStudio.Extensibility.Testing.Xunit.Legacy.IntegrationTests" - @{ - $testRoot = (Get-ChildItem "$testRoot\TestResults" -Recurse -Directory | Get-ChildItem -Recurse -File); - } + $result[$testRoot] = (Get-ChildItem "$testRoot\TestResults" -Recurse -Directory | Get-ChildItem -Recurse -File) +} + +$testlogsPath = "$env:BUILD_ARTIFACTSTAGINGDIRECTORY\test_logs" +if (Test-Path $testlogsPath) { + $result[$testlogsPath] = Get-ChildItem "$testlogsPath\*"; } + +$result diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml index ff3b1790..c713f4e5 100644 --- a/azure-pipelines/build.yml +++ b/azure-pipelines/build.yml @@ -1,9 +1,19 @@ parameters: - windowsPool: Hosted Windows 2019 with VS2019 +- name: windowsPool + type: object + default: + vmImage: windows-2022 +- name: EnableAPIScan + type: boolean + default: false jobs: - job: Windows pool: ${{ parameters.windowsPool }} + variables: + - ${{ if eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9') }}: + # https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/25351/APIScan-step-by-step-guide-to-setting-up-a-Pipeline + - group: VSCloudServices-APIScan steps: - checkout: self clean: true @@ -13,7 +23,7 @@ jobs: - template: install-dependencies.yml - - powershell: '& (./azure-pipelines/Get-nbgv.ps1) cloud' + - powershell: '& (./azure-pipelines/Get-nbgv.ps1) cloud -ca' displayName: Set build number - ${{ if eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9') }}: @@ -23,6 +33,8 @@ jobs: - ${{ if eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9') }}: - template: microbuild.after.yml + parameters: + EnableAPIScan: ${{ parameters.EnableAPIScan }} - job: WrapUp dependsOn: diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml index 4294bc5f..27702f98 100644 --- a/azure-pipelines/dotnet.yml +++ b/azure-pipelines/dotnet.yml @@ -22,7 +22,7 @@ steps: displayName: dotnet test -f net46 inputs: command: test - arguments: $(Build.Repository.LocalPath)/src/Microsoft.VisualStudio.Extensibility.Testing.Xunit.Legacy.IntegrationTests/Microsoft.VisualStudio.Extensibility.Testing.Xunit.Legacy.IntegrationTests.csproj --no-build -c $(BuildConfiguration) -f net46 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true --settings "$(Build.Repository.LocalPath)/azure-pipelines/$(Agent.OS).runsettings" /bl:"$(Build.ArtifactStagingDirectory)/build_logs/test_net46.binlog" + arguments: $(Build.Repository.LocalPath)/src/Microsoft.VisualStudio.Extensibility.Testing.Xunit.Legacy.IntegrationTests/Microsoft.VisualStudio.Extensibility.Testing.Xunit.Legacy.IntegrationTests.csproj --no-build -c $(BuildConfiguration) -f net46 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true --settings "$(Build.Repository.LocalPath)/azure-pipelines/$(Agent.OS).runsettings" /bl:"$(Build.ArtifactStagingDirectory)/build_logs/test_net46.binlog" --diag "$(Build.ArtifactStagingDirectory)/test_logs/net46.txt testRunTitle: net46-$(Agent.JobName) condition: eq(variables['SignTypeSelection'], '') @@ -30,7 +30,7 @@ steps: displayName: dotnet test -f net472 inputs: command: test - arguments: $(Build.Repository.LocalPath)/src/Microsoft.VisualStudio.Extensibility.Testing.Xunit.IntegrationTests/Microsoft.VisualStudio.Extensibility.Testing.Xunit.IntegrationTests.csproj --no-build -c $(BuildConfiguration) -f net472 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true --settings "$(Build.Repository.LocalPath)/azure-pipelines/$(Agent.OS).runsettings" /bl:"$(Build.ArtifactStagingDirectory)/build_logs/test_net472.binlog" + arguments: $(Build.Repository.LocalPath)/src/Microsoft.VisualStudio.Extensibility.Testing.Xunit.IntegrationTests/Microsoft.VisualStudio.Extensibility.Testing.Xunit.IntegrationTests.csproj --no-build -c $(BuildConfiguration) -f net472 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true --settings "$(Build.Repository.LocalPath)/azure-pipelines/$(Agent.OS).runsettings" /bl:"$(Build.ArtifactStagingDirectory)/build_logs/test_net472.binlog" --diag "$(Build.ArtifactStagingDirectory)/test_logs/net472.txt testRunTitle: net472-$(Agent.JobName) condition: eq(variables['SignTypeSelection'], '') diff --git a/azure-pipelines/expand-template.yml b/azure-pipelines/expand-template.yml deleted file mode 100644 index 9ee5a0a3..00000000 --- a/azure-pipelines/expand-template.yml +++ /dev/null @@ -1,27 +0,0 @@ -steps: -- script: | - dotnet build-server shutdown - git clean -fdx - displayName: Cleaning repo for template expansion -- powershell: | - git config user.name "test user" - git config user.email "andrewarnott@gmail.com" - ./Expand-Template.ps1 -LibraryName Calc -Author "Andrew Arnott" - displayName: Expanding template - failOnStderr: true -# TODO: Verify that all changes are staged to the git index - -- powershell: .\init.ps1 - displayName: Install prereqs and restore packages - -- task: VSBuild@1 - displayName: Build Visual Studio solution (expanded template) - inputs: - msbuildArgs: /t:build,pack /m - platform: Any CPU - configuration: $(BuildConfiguration) - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - -- script: dotnet build - displayName: dotnet build (expanded template) - condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) diff --git a/azure-pipelines/falsepositives.gdnsuppress b/azure-pipelines/falsepositives.gdnsuppress new file mode 100644 index 00000000..1248172b --- /dev/null +++ b/azure-pipelines/falsepositives.gdnsuppress @@ -0,0 +1,12 @@ +{ + "version": "latest", + "suppressionSets": { + "falsepositives": { + "name": "falsepositives", + "createdDate": "2021-12-03 00:23:08Z", + "lastUpdatedDate": "2021-12-03 00:23:08Z" + } + }, + "results": { + } +} diff --git a/azure-pipelines/microbuild.after.yml b/azure-pipelines/microbuild.after.yml index 8559b27a..6f107833 100644 --- a/azure-pipelines/microbuild.after.yml +++ b/azure-pipelines/microbuild.after.yml @@ -1,3 +1,7 @@ +parameters: +- name: EnableAPIScan + type: boolean + steps: - task: MicroBuildCodesignVerify@3 displayName: Verify Signed Files @@ -9,9 +13,6 @@ steps: condition: succeededOrFailed() displayName: MicroBuild Cleanup -- task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection - - task: Ref12Analyze@0 displayName: Ref12 (Codex) Analyze inputs: @@ -26,3 +27,5 @@ steps: continueOnError: true - template: secure-development-tools.yml + parameters: + EnableAPIScan: ${{ parameters.EnableAPIScan }} diff --git a/azure-pipelines/microbuild.before.yml b/azure-pipelines/microbuild.before.yml index 96cd3254..ab930694 100644 --- a/azure-pipelines/microbuild.before.yml +++ b/azure-pipelines/microbuild.before.yml @@ -1,4 +1,13 @@ steps: +- task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection + +- task: notice@0 + displayName: Generate NOTICE file + inputs: + outputfile: $(System.DefaultWorkingDirectory)/obj/NOTICE + outputformat: text + - task: MicroBuildSigningPlugin@3 inputs: signType: $(SignType) diff --git a/azure-pipelines/official.yml b/azure-pipelines/official.yml index 40008b53..1bdbfcd3 100644 --- a/azure-pipelines/official.yml +++ b/azure-pipelines/official.yml @@ -23,6 +23,10 @@ parameters: type: string default: Test values: [ 'Test', 'Real' ] +- name: EnableAPIScan + displayName: Run APIScan + type: boolean + default: true variables: NugetSecurityAnalysisWarningLevel: none # nuget.config requires signed packages by trusted owners @@ -44,14 +48,15 @@ stages: jobs: - template: build.yml parameters: - windowsPool: VSEngSS-MicroBuild2019-1ES + EnableAPIScan: ${{ parameters.EnableAPIScan }} + windowsPool: VSEngSS-MicroBuild2022-1ES - stage: symbol_archive displayName: Symbol archival condition: and(succeeded(), eq(dependencies.Build.outputs['Windows.SetPipelineVariables.SignType'], 'Real')) jobs: - job: archive - pool: VSEng-ReleasePool + pool: VSEng-ReleasePool-1ES steps: - download: current artifact: Variables-Windows diff --git a/azure-pipelines/publish-codecoverage.yml b/azure-pipelines/publish-codecoverage.yml index 8c70cbe8..dd2f30c6 100644 --- a/azure-pipelines/publish-codecoverage.yml +++ b/azure-pipelines/publish-codecoverage.yml @@ -6,10 +6,10 @@ steps: #- powershell: | # dotnet tool install --tool-path obj dotnet-reportgenerator-globaltool --version 4.8.5 --configfile azure-pipelines/justnugetorg.nuget.config # Copy-Item -Recurse $(Pipeline.Workspace)/coverageResults-Windows/obj/* $(System.DefaultWorkingDirectory)/obj -# Write-Host "Substituting {reporoot} with $(System.DefaultWorkingDirectory)" -# $reports = Get-ChildItem -Recurse "$(Pipeline.Workspace)/coverage.*.cobertura.xml" +# Write-Host 'Substituting {reporoot} with $(System.DefaultWorkingDirectory)' +# $reports = Get-ChildItem -Recurse '$(Pipeline.Workspace)/coverage.*cobertura.xml' # $reports |% { -# $content = Get-Content -Path $_ |% { $_.Replace("{reporoot}", "$(System.DefaultWorkingDirectory)") } +# $content = Get-Content -Path $_ |% { $_.Replace('{reporoot}', '$(System.DefaultWorkingDirectory)') } # Set-Content -Path $_ -Value $content -Encoding UTF8 # } # $Inputs = [string]::join(';', ($reports |% { Resolve-Path -relative $_ })) diff --git a/azure-pipelines/secure-development-tools.yml b/azure-pipelines/secure-development-tools.yml index 941d5b0c..99925c13 100644 --- a/azure-pipelines/secure-development-tools.yml +++ b/azure-pipelines/secure-development-tools.yml @@ -1,11 +1,74 @@ +parameters: +- name: EnableAPIScan + type: boolean + steps: - ### Check for checked in credentials. - task: CredScan@3 - displayName: 'Run CredScan' + displayName: Run CredScan - ### Run PoliCheck to check for disallowed terms. targetType: F indicates we're searching files and folders. -- task: PoliCheck@1 - displayName: 'Run PoliCheck' +- task: PoliCheck@2 + displayName: Run PoliCheck inputs: targetType: F + targetArgument: $(System.DefaultWorkingDirectory) + optionsUEPATH: $(System.DefaultWorkingDirectory)\azure-pipelines\PoliCheckExclusions.xml + +- task: BinSkim@3 + displayName: Run BinSkim + inputs: + InputType: Basic + Function: analyze + AnalyzeTarget: $(BinSkimTargets) + +- task: CopyFiles@2 + displayName: Collect APIScan inputs + inputs: + SourceFolder: $(Build.ArtifactStagingDirectory)/Symbols-$(Agent.JobName) + # Exclude any patterns from the Contents (e.g. `!**/git2*`) that we have symbols for but do not need to run APIScan on. + Contents: | + ** + TargetFolder: $(Build.ArtifactStagingDirectory)/APIScanInputs + condition: and(succeeded(), ${{ parameters.EnableAPIScan }}, ne(variables.ApiScanClientId, '')) + +- task: APIScan@2 + displayName: Run APIScan + inputs: + softwareFolder: $(Build.ArtifactStagingDirectory)/APIScanInputs + softwareName: $(SymbolsFeatureName) + softwareVersionNum: $(NBGV_MajorMinorVersion) + isLargeApp: false + toolVersion: Latest + condition: and(succeeded(), ${{ parameters.EnableAPIScan }}, ne(variables.ApiScanClientId, '')) + env: + AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanClientId);TenantId=$(ApiScanTenant);AppKey=$(ApiScanSecret) + +- task: SdtReport@2 + displayName: Create Security Analysis Report + inputs: + GdnExportAllTools: true + +- task: PublishSecurityAnalysisLogs@3 + displayName: Publish Code Analysis Logs + inputs: + ArtifactName: CodeAnalysisLogs + ArtifactType: Container + PublishProcessedResults: true + AllTools: true + ToolLogsNotFoundAction: Standard + +- task: PostAnalysis@2 + displayName: Break on compliance issues + inputs: + GdnBreakAllTools: true + GdnBreakGdnToolBinSkimSeverity: Warning + GdnBreakSuppressionFiles: $(System.DefaultWorkingDirectory)/azure-pipelines/falsepositives.gdnsuppress + GdnBreakSuppressionSets: falsepositives + GdnBreakOutputSuppressionFile: $(Build.ArtifactStagingDirectory)/guardian_failures_as_suppressions/ + GdnBreakOutputSuppressionSet: falsepositives + +# This is useful when false positives appear so we can copy some of the output into the suppressions file. +- publish: $(Build.ArtifactStagingDirectory)/guardian_failures_as_suppressions + artifact: guardian_failures_as_suppressions + displayName: Publish Guardian failures + condition: failed() diff --git a/azure-pipelines/variables/BinSkimTargets.ps1 b/azure-pipelines/variables/BinSkimTargets.ps1 new file mode 100644 index 00000000..5c0dd24e --- /dev/null +++ b/azure-pipelines/variables/BinSkimTargets.ps1 @@ -0,0 +1,4 @@ +$Path = "$PSScriptRoot\..\..\bin" +if (Test-Path $Path) { + [string]::join(';', (& "$PSScriptRoot\..\Get-SymbolFiles.ps1" -ConvertToWindowsPDBs:$false -Path $Path)) +} diff --git a/azure-pipelines/variables/TeamEmail.ps1 b/azure-pipelines/variables/TeamEmail.ps1 new file mode 100644 index 00000000..7cf66982 --- /dev/null +++ b/azure-pipelines/variables/TeamEmail.ps1 @@ -0,0 +1 @@ +'vsidemicrobuild@microsoft.com' diff --git a/azure-pipelines/vs-insertion.yml b/azure-pipelines/vs-insertion.yml index 90645cb2..6aef7889 100644 --- a/azure-pipelines/vs-insertion.yml +++ b/azure-pipelines/vs-insertion.yml @@ -17,7 +17,8 @@ stages: displayName: VS insertion jobs: - deployment: insertion - pool: VSEng-ReleasePool + pool: + vmImage: windows-latest environment: No-Approval strategy: runOnce: diff --git a/init.ps1 b/init.ps1 index fef2cb09..043d4551 100644 --- a/init.ps1 +++ b/init.ps1 @@ -42,10 +42,10 @@ .PARAMETER AccessToken An optional access token for authenticating to Azure Artifacts authenticated feeds. #> -[CmdletBinding(SupportsShouldProcess=$true)] +[CmdletBinding(SupportsShouldProcess = $true)] Param ( - [ValidateSet('repo','user','machine')] - [string]$InstallLocality='user', + [ValidateSet('repo', 'user', 'machine')] + [string]$InstallLocality = 'user', [Parameter()] [switch]$NoPrerequisites, [Parameter()] @@ -67,6 +67,7 @@ Param ( ) $EnvVars = @{} +$PrependPath = @() if (!$NoPrerequisites) { if (!$NoNuGetCredProvider) { @@ -86,8 +87,8 @@ if (!$NoPrerequisites) { } # Workaround nuget credential provider bug that causes very unreliable package restores on Azure Pipelines -$env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=20 -$env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 +$env:NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS = 20 +$env:NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS = 20 Push-Location $PSScriptRoot try { @@ -129,7 +130,7 @@ try { $EnvVars['LocLanguages'] = "JPN" } - & "$PSScriptRoot/tools/Set-EnvVars.ps1" -Variables $EnvVars | Out-Null + & "$PSScriptRoot/tools/Set-EnvVars.ps1" -Variables $EnvVars -PrependPath $PrependPath | Out-Null } catch { Write-Error $error[0] diff --git a/src/AssemblyInfo.cs b/src/AssemblyInfo.cs new file mode 100644 index 00000000..5ffb1c26 --- /dev/null +++ b/src/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for more information. + +using System.Runtime.InteropServices; + +[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)] diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index e7edee55..566ab4fc 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,3 +1,7 @@ + + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index ef88f73a..6ada957d 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -7,6 +7,6 @@ - + diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1 index 67c66c1e..3c82ee2b 100644 --- a/tools/Install-DotNetSdk.ps1 +++ b/tools/Install-DotNetSdk.ps1 @@ -29,8 +29,11 @@ $DotNetInstallScriptRoot = Resolve-Path $DotNetInstallScriptRoot # Look up actual required .NET Core SDK version from global.json $sdkVersion = & "$PSScriptRoot/../azure-pipelines/variables/DotNetSdkVersion.ps1" -$arch = 'x64' -if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { $arch = 'ARM64' } +$arch = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture +if (!$arch) { # Windows Powershell leaves this blank + $arch = 'x64' + if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { $arch = 'ARM64' } +} # Search for all .NET Core runtime versions referenced from MSBuild projects and arrange to install them. $runtimeVersions = @() @@ -47,7 +50,7 @@ Get-ChildItem "$PSScriptRoot\..\src\*.*proj","$PSScriptRoot\..\test\*.*proj","$P } } } - $targetFrameworks |? { $_ -match 'netcoreapp(\d+\.\d+)' } |% { + $targetFrameworks |? { $_ -match 'net(?:coreapp)?(\d+\.\d+)' } |% { $v = $Matches[1] $runtimeVersions += $v if ($v -ge '3.0' -and -not ($IsMacOS -or $IsLinux)) { @@ -154,10 +157,10 @@ if ($DotNetInstallDir) { } if ($IsMacOS -or $IsLinux) { - $DownloadUri = "https://raw.githubusercontent.com/dotnet/install-scripts/49d5da7f7d313aa65d24fe95cc29767faef553fd/src/dotnet-install.sh" + $DownloadUri = "https://raw.githubusercontent.com/dotnet/install-scripts/781752509a890ca7520f1182e8bae71f9a53d754/src/dotnet-install.sh" $DotNetInstallScriptPath = "$DotNetInstallScriptRoot/dotnet-install.sh" } else { - $DownloadUri = "https://raw.githubusercontent.com/dotnet/install-scripts/49d5da7f7d313aa65d24fe95cc29767faef553fd/src/dotnet-install.ps1" + $DownloadUri = "https://raw.githubusercontent.com/dotnet/install-scripts/781752509a890ca7520f1182e8bae71f9a53d754/src/dotnet-install.ps1" $DotNetInstallScriptPath = "$DotNetInstallScriptRoot/dotnet-install.ps1" } diff --git a/version.json b/version.json index f0da4f6a..39add986 100644 --- a/version.json +++ b/version.json @@ -4,5 +4,8 @@ "publicReleaseRefSpec": [ "^refs/heads/main$", "^refs/heads/v\\d+(?:\\.\\d+)?$" - ] + ], + "cloudBuild": { + "setVersionVariables": false + } }