diff --git a/.travis.yml b/.travis.yml index a6993951b..18e8b5c24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,46 +1,7 @@ -# Travis-CI Build for libgit2sharp -# see travis-ci.org for details - language: csharp mono: none -matrix: - include: - - os: linux - dist: xenial - before_install: - - | - wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb - sudo dpkg -i packages-microsoft-prod.deb - sudo apt-get update - sudo apt-get install -y powershell - - os: osx - osx_image: xcode8.3 - before_install: - - brew update # This is necessary to get pwsh 6.2 instead of some 6.0-preview that isn't named `pwsh` - - brew cask install powershell - fast_finish: true - -before_install: - - date -u - - uname -a - - env | sort - -install: - - git fetch --unshallow - - pwsh ./tools/Install-DotNetSdk.ps1 ; export PATH=~/.dotnet:$PATH - -# Build libgit2, LibGit2Sharp and run the tests -script: - - ./buildandtest.sh 'LEAKS_IDENTIFYING' - -# Only watch the development branch +# Disable Travis-CI branches: only: - - master - - /^maint.*/ - -# Notify of build changes -notifications: - email: - - emeric.fermas@gmail.com + - NOTTHISONE diff --git a/Directory.Build.props b/Directory.Build.props index fb2ca9ca9..d98520a64 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,11 @@ true $(MSBuildThisFileDirectory)bin\$(MSBuildProjectName)\$(Configuration)\ $(MSBuildThisFileDirectory)obj\$(MSBuildProjectName)\ + $(MSBuildThisFileDirectory)bin\Packages\$(Configuration)\ $(DefineConstants);$(ExtraDefine) + + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 000000000..1ddcba6f4 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,8 @@ + + + cobertura + [xunit.*]* + + $(OutputPath)/ + + diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 3503801c9..4a73bd401 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -11,7 +11,8 @@ - + + diff --git a/LibGit2Sharp.Tests/StatusFixture.cs b/LibGit2Sharp.Tests/StatusFixture.cs index 7ba561def..698639aa4 100644 --- a/LibGit2Sharp.Tests/StatusFixture.cs +++ b/LibGit2Sharp.Tests/StatusFixture.cs @@ -640,7 +640,7 @@ public void CanIncludeStatusOfUnalteredFiles() RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = true }); Assert.Equal(unalteredPaths.Length, status.Unaltered.Count()); - Assert.Equal(unalteredPaths, status.Unaltered.OrderBy(s => s.FilePath).Select(s => s.FilePath).ToArray()); + Assert.Equal(unalteredPaths, status.Unaltered.OrderBy(s => s.FilePath, StringComparer.OrdinalIgnoreCase).Select(s => s.FilePath).ToArray()); } } diff --git a/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs b/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs index 34719635e..d9618c06c 100644 --- a/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs +++ b/LibGit2Sharp.Tests/desktop/ShadowCopyFixture.cs @@ -11,6 +11,7 @@ namespace LibGit2Sharp.Tests public class ShadowCopyFixture : BaseFixture { [Fact] + [Trait("TestCategory", "FailsWhileInstrumented")] public void CanProbeForNativeBinariesFromAShadowCopiedAssembly() { Type type = typeof(Wrapper); diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index bb64842f3..ede588064 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -14,13 +14,16 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb true ..\libgit2sharp.snk + square-logo.png + App_Readme/LICENSE.md - - - + + + + @@ -28,8 +31,8 @@ - - + + @@ -37,9 +40,7 @@ - https://github.com/libgit2/libgit2sharp/raw/$(GitCommitIdShort)/square-logo.png https://github.com/libgit2/libgit2sharp/blob/$(GitCommitIdShort)/CHANGES.md#libgit2sharp-changes - https://github.com/libgit2/libgit2sharp/raw/$(GitCommitIdShort)/LICENSE.md diff --git a/appveyor.yml b/appveyor.yml index 3b46955f4..6eeeedba4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,158 +1,4 @@ -version: '{build}' - -os: Visual Studio 2019 - +# Disable AppVeyor branches: - only: - - master - - /^maint.*/ - -configuration: release - -skip_tags: true - -nuget: - disable_publish_on_pr: true - -environment: - coveralls_token: - secure: ixIsBslo9NheDb5lJknF58EYdgvZ0r3/L0ecRiXjfXmjHBLvoSU6/ZRwaMM+BAlG - coverity_token: - secure: nuzUT+HecXGIi3KaPd/1hgFEZJan/j6+oNbPV75JKjk= - coverity_email: - secure: eGVilNg1Yuq+Xj+SW8r3WCtjnzhoDV0sNJkma4NRq7A= - matrix: - - publish_on_success: False - ExtraDefine: LEAKS_IDENTIFYING - - publish_on_success: True - -matrix: - fast_finish: true - -install: -- ps: | - Write-Host "Commit being built = " -NoNewLine - Write-Host $Env:APPVEYOR_REPO_COMMIT -ForegroundColor "Green" - Write-Host "Target branch = " -NoNewLine - Write-Host $Env:APPVEYOR_REPO_BRANCH -ForegroundColor "Green" - Write-Host "Is a Pull Request = " -NoNewLine - Write-Host $($Env:APPVEYOR_PULL_REQUEST_NUMBER -ne $null) -ForegroundColor "Green" - - $CommitDate = [DateTime]::Parse($Env:APPVEYOR_REPO_COMMIT_TIMESTAMP) - $BuildDate = $CommitDate.ToUniversalTime().ToString("yyyyMMddHHmmss") - Write-Host "Merge commit UTC timestamp = " -NoNewLine - Write-Host $BuildDate -ForegroundColor "Green" - - $Env:SHOULD_RUN_COVERITY_ANALYSIS = $($Env:APPVEYOR_SCHEDULED_BUILD -eq $True) - Write-Host "Should run Coverity analysis = " -NoNewLine - Write-Host $Env:SHOULD_RUN_COVERITY_ANALYSIS -ForegroundColor "Green" - - $Env:SHOULD_RUN_COVERALLS = $($Env:APPVEYOR_SCHEDULED_BUILD -eq $True) - Write-Host "Should run Coveralls = " -NoNewLine - Write-Host $Env:SHOULD_RUN_COVERALLS -ForegroundColor "Green" - - Write-Host "Identifying leaks = " -NoNewLine - Write-Host ($Env:ExtraDefine -eq "LEAKS_IDENTIFYING") -ForegroundColor "Green" - - Write-Host "Should publish on success = " -NoNewLine - Write-Host $Env:publish_on_success -ForegroundColor "Green" - - If ($Env:SHOULD_RUN_COVERALLS -eq $True) - { - nuget install OpenCover -Version 4.6.166 -ExcludeVersion -OutputDirectory .\packages - nuget install coveralls.net -Version 0.6.0 -ExcludeVersion -OutputDirectory .\packages - } - - If ($Env:SHOULD_RUN_COVERITY_ANALYSIS -eq $True) - { - cinst curl -y - } - - ./tools/Install-DotNetSdk.ps1 - -before_build: -- ps: | - msbuild "$Env:APPVEYOR_BUILD_FOLDER\LibGit2Sharp.sln" ` - /nologo /verbosity:quiet ` - /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" ` - /t:restore - -build_script: -- ps: | - & cov-build.exe --dir cov-int msbuild "$Env:APPVEYOR_BUILD_FOLDER\LibGit2Sharp.sln" ` - /nologo /verbosity:minimal /fl /flp:verbosity=normal ` - /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" ` - /t:build,pack - -test_script: -- ps: | - Foreach ($runner in 'xunit.console.exe','xunit.console.x86.exe') - { - If ($Env:SHOULD_RUN_COVERALLS -eq $True -and $Env:publish_on_success -eq $True) - { - .\packages\OpenCover\tools\OpenCover.Console.exe ` - -register:user ` - "-target:""$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\$runner""" ` - "-targetargs:""$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net46\LibGit2Sharp.Tests.dll"" -noshadow" ` - "-filter:+[LibGit2Sharp]* -[LibGit2Sharp.Tests]*" ` - -hideskipped:All ` - -output:opencoverCoverage.xml - } - ElseIf ($Env:SHOULD_RUN_COVERITY_ANALYSIS -eq $False) - { - & "$Env:userprofile\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\$runner" ` - "$Env:APPVEYOR_BUILD_FOLDER\bin\LibGit2Sharp.Tests\Release\net46\LibGit2Sharp.Tests.dll" -noshadow - } - } - -- dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.1 --no-restore --no-build - -after_test: -- ps: | - If ($Env:SHOULD_RUN_COVERALLS -eq $True -and $Env:publish_on_success -eq $True) - { - Write-Host "Uploading code coverage result..." -ForegroundColor "Green" - - .\packages\coveralls.net\tools\csmacnz.Coveralls.exe ` - --opencover -i opencoverCoverage.xml ` - --repoToken $Env:coveralls_token ` - --useRelativePaths ` - --basePath "$Env:APPVEYOR_BUILD_FOLDER\"` - } - - If ($Env:SHOULD_RUN_COVERITY_ANALYSIS -eq $True -and $Env:publish_on_success -eq $True) - { - 7z a "$Env:APPVEYOR_BUILD_FOLDER\$Env:APPVEYOR_PROJECT_NAME.zip" "$Env:APPVEYOR_BUILD_FOLDER\cov-int\" - - # cf. http://stackoverflow.com/a/25045154/335418 - Remove-item alias:curl - - Write-Host "Uploading Coverity analysis result..." -ForegroundColor "Green" - - curl --silent --show-error ` - --output curl-out.txt ` - --form token="$Env:coverity_token" ` - --form email="$Env:coverity_email" ` - --form "file=@$Env:APPVEYOR_BUILD_FOLDER\$Env:APPVEYOR_PROJECT_NAME.zip" ` - --form version="$Env:APPVEYOR_REPO_COMMIT" ` - --form description="CI server scheduled build." ` - https://scan.coverity.com/builds?project=libgit2%2Flibgit2sharp - - cat .\curl-out.txt - } - -on_finish: -- ps: Push-AppveyorArtifact "msbuild.log" - -on_success: -- ps: | - if ($Env:publish_on_success -eq $True) - { - Get-ChildItem "bin\LibGit2Sharp\$env:configuration\*.nupkg" |% { Push-AppveyorArtifact $_.FullName -FileName $_.Name } - } - -notifications: -- provider: Email - to: - - emeric.fermas@gmail.com - on_build_status_changed: true + only: + - NOTTHISONE diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d34e9af7c..c25545a56 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -3,32 +3,10 @@ trigger: - maint/* variables: - solution: '**/*.sln' - buildPlatform: 'Any CPU' - buildConfiguration: 'Release' + TreatWarningsAsErrors: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + BuildConfiguration: Release + NUGET_PACKAGES: $(Agent.TempDirectory)/.nuget/packages jobs: -- job: Windows - pool: - vmImage: 'windows-2019' - steps: - - pwsh: ./tools/Install-DotNetSdk.ps1 - displayName: Installing .NET Core SDK and runtimes - - script: buildandtest.cmd - displayName: Build and test -- job: Linux - pool: - vmImage: 'Ubuntu 16.04' - steps: - - pwsh: ./tools/Install-DotNetSdk.ps1 - displayName: Installing .NET Core SDK and runtimes - - script: ./buildandtest.sh - displayName: Build and test -- job: macOS - pool: - vmImage: 'macOS 10.13' - steps: - - pwsh: ./tools/Install-DotNetSdk.ps1 - displayName: Installing .NET Core SDK and runtimes - - script: ./buildandtest.sh - displayName: Build and test +- template: azure-pipelines/build.yml diff --git a/tools/Set-EnvVars.ps1 b/azure-pipelines/Set-EnvVars.ps1 similarity index 100% rename from tools/Set-EnvVars.ps1 rename to azure-pipelines/Set-EnvVars.ps1 diff --git a/azure-pipelines/artifacts/_all.ps1 b/azure-pipelines/artifacts/_all.ps1 new file mode 100644 index 000000000..6f62be5c3 --- /dev/null +++ b/azure-pipelines/artifacts/_all.ps1 @@ -0,0 +1,50 @@ +# This script returns all the artifacts that should be collected after a build. +# +# Each powershell artifact is expressed as an object with these properties: +# Source - the full path to the source file +# ArtifactName - the name of the artifact to upload to +# ContainerFolder - the relative path within the artifact in which the file should appear +# +# Each artifact aggregating .ps1 script should return a hashtable: +# Key = path to the directory from which relative paths within the artifact should be calculated +# Value = an array of paths (absolute or relative to the BaseDirectory) to files to include in the artifact. +# FileInfo objects are also allowed. + +$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") + +Function EnsureTrailingSlash($path) { + if ($path.length -gt 0 -and !$path.EndsWith('\') -and !$path.EndsWith('/')) { + $path = $path + [IO.Path]::DirectorySeparatorChar + } + + $path.Replace('\', [IO.Path]::DirectorySeparatorChar) +} + +Get-ChildItem "$PSScriptRoot\*.ps1" -Exclude "_*" -Recurse |% { + $ArtifactName = $_.BaseName + + $fileGroups = & $_ + if (!$fileGroups -or $fileGroups.Count -eq 0) { + Write-Warning "No files found for the `"$ArtifactName`" artifact." + } else { + $fileGroups.GetEnumerator() | % { + $BaseDirectory = New-Object Uri ((EnsureTrailingSlash $_.Key), [UriKind]::Absolute) + $_.Value | % { + if ($_.GetType() -eq [IO.FileInfo] -or $_.GetType() -eq [IO.DirectoryInfo]) { + $_ = $_.FullName + } + + $artifact = New-Object -TypeName PSObject + Add-Member -InputObject $artifact -MemberType NoteProperty -Name ArtifactName -Value $ArtifactName + + $SourceFullPath = New-Object Uri ($BaseDirectory, $_) + Add-Member -InputObject $artifact -MemberType NoteProperty -Name Source -Value $SourceFullPath.LocalPath + + $RelativePath = [Uri]::UnescapeDataString($BaseDirectory.MakeRelative($SourceFullPath)) + Add-Member -InputObject $artifact -MemberType NoteProperty -Name ContainerFolder -Value (Split-Path $RelativePath) + + Write-Output $artifact + } + } + } +} diff --git a/azure-pipelines/artifacts/_pipelines.ps1 b/azure-pipelines/artifacts/_pipelines.ps1 new file mode 100644 index 000000000..5bca7c6c1 --- /dev/null +++ b/azure-pipelines/artifacts/_pipelines.ps1 @@ -0,0 +1,10 @@ +# This script translates all the artifacts described by _all.ps1 +# into commands that instruct Azure Pipelines to actually collect those artifacts. + +param ( + [string]$ArtifactNameSuffix +) + +& "$PSScriptRoot/_stage_all.ps1" -ArtifactNameSuffix $ArtifactNameSuffix |% { + Write-Host "##vso[artifact.upload containerfolder=$($_.Name);artifactname=$($_.Name);]$($_.Path)" +} diff --git a/azure-pipelines/artifacts/_stage_all.ps1 b/azure-pipelines/artifacts/_stage_all.ps1 new file mode 100644 index 000000000..a05db5292 --- /dev/null +++ b/azure-pipelines/artifacts/_stage_all.ps1 @@ -0,0 +1,59 @@ +# This script links all the artifacts described by _all.ps1 +# into a staging directory, reading for uploading to a cloud build artifact store. +# It returns a sequence of objects with Name and Path properties. + +param ( + [string]$ArtifactNameSuffix +) + +$RepoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot (Join-Path .. ..))) +if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) { + $ArtifactStagingFolder = $env:BUILD_ARTIFACTSTAGINGDIRECTORY +} else { + $ArtifactStagingFolder = Join-Path $RepoRoot (Join-Path obj _artifacts) + if (Test-Path $ArtifactStagingFolder) { + Remove-Item $ArtifactStagingFolder -Recurse -Force + } +} + +function Create-SymbolicLink { + param ( + $Link, + $Target + ) + + if ($Link -eq $Target) { + return + } + + if (Test-Path $Link) { Remove-Item $Link } + $LinkContainer = Split-Path $Link -Parent + if (!(Test-Path $LinkContainer)) { mkdir $LinkContainer } + Write-Verbose "Linking $Link to $Target" + if ($IsMacOS -or $IsLinux) { + ln $Target $Link | Out-Null + } else { + cmd /c mklink $Link $Target | Out-Null + } +} + +# Stage all artifacts +$Artifacts = & "$PSScriptRoot\_all.ps1" +$Artifacts |% { + $DestinationFolder = (Join-Path (Join-Path $ArtifactStagingFolder "$($_.ArtifactName)$ArtifactNameSuffix") $_.ContainerFolder).TrimEnd('\') + $Name = "$(Split-Path $_.Source -Leaf)" + + #Write-Host "$($_.Source) -> $($_.ArtifactName)\$($_.ContainerFolder)" -ForegroundColor Yellow + + if (-not (Test-Path $DestinationFolder)) { New-Item -ItemType Directory -Path $DestinationFolder | Out-Null } + if (Test-Path -PathType Leaf $_.Source) { # skip folders + Create-SymbolicLink -Link (Join-Path $DestinationFolder $Name) -Target $_.Source + } +} + +$Artifacts |% { "$($_.ArtifactName)$ArtifactNameSuffix" } | Get-Unique |% { + $artifact = New-Object -TypeName PSObject + Add-Member -InputObject $artifact -MemberType NoteProperty -Name Name -Value $_ + Add-Member -InputObject $artifact -MemberType NoteProperty -Name Path -Value (Join-Path $ArtifactStagingFolder $_) + Write-Output $artifact +} diff --git a/azure-pipelines/artifacts/build_logs.ps1 b/azure-pipelines/artifacts/build_logs.ps1 new file mode 100644 index 000000000..b55ba48f3 --- /dev/null +++ b/azure-pipelines/artifacts/build_logs.ps1 @@ -0,0 +1,12 @@ +if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) { + $artifactsRoot = $env:BUILD_ARTIFACTSTAGINGDIRECTORY +} else { + $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") + $artifactsRoot = "$RepoRoot\bin" +} + +if (!(Test-Path $artifactsRoot/build_logs)) { return } + +@{ + "$artifactsRoot/build_logs" = (Get-ChildItem -Recurse "$artifactsRoot/build_logs") +} diff --git a/azure-pipelines/artifacts/coverageResults.ps1 b/azure-pipelines/artifacts/coverageResults.ps1 new file mode 100644 index 000000000..7d1e9a35f --- /dev/null +++ b/azure-pipelines/artifacts/coverageResults.ps1 @@ -0,0 +1,22 @@ +$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 |% { + $content = Get-Content -Path $_ |% { $_ -Replace [regex]::Escape($env:SYSTEM_DEFAULTWORKINGDIRECTORY), "{reporoot}" } + Set-Content -Path $_ -Value $content -Encoding UTF8 + } +} else { + Write-Warning "coverageResults: Azure Pipelines not detected. Machine-neutral token replacement skipped." +} + +if (!((Test-Path $RepoRoot\bin) -and (Test-Path $RepoRoot\obj))) { return } + +@{ + $RepoRoot = ( + @(Get-ChildItem "$RepoRoot\bin\coverage.cobertura.xml" -Recurse) + + (Get-ChildItem "$RepoRoot\obj\*.cs" -Recurse) + ); +} diff --git a/azure-pipelines/artifacts/deployables.ps1 b/azure-pipelines/artifacts/deployables.ps1 new file mode 100644 index 000000000..94c48cdd9 --- /dev/null +++ b/azure-pipelines/artifacts/deployables.ps1 @@ -0,0 +1,13 @@ +$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..") +$BuildConfiguration = $env:BUILDCONFIGURATION +if (!$BuildConfiguration) { + $BuildConfiguration = 'Debug' +} + +$PackagesRoot = "$RepoRoot/bin/Packages/$BuildConfiguration" + +if (!(Test-Path $PackagesRoot)) { return } + +@{ + "$PackagesRoot" = (Get-ChildItem $PackagesRoot -Recurse) +} diff --git a/azure-pipelines/artifacts/projectAssetsJson.ps1 b/azure-pipelines/artifacts/projectAssetsJson.ps1 new file mode 100644 index 000000000..d2e85ffbe --- /dev/null +++ b/azure-pipelines/artifacts/projectAssetsJson.ps1 @@ -0,0 +1,9 @@ +$ObjRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\obj") + +if (!(Test-Path $ObjRoot)) { return } + +@{ + "$ObjRoot" = ( + (Get-ChildItem "$ObjRoot\project.assets.json" -Recurse) + ); +} diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml new file mode 100644 index 000000000..1462628c8 --- /dev/null +++ b/azure-pipelines/build.yml @@ -0,0 +1,50 @@ +parameters: + windowsPool: Hosted Windows 2019 with VS2019 + +jobs: +- job: Windows + pool: ${{ parameters.windowsPool }} + steps: + - template: install-dependencies.yml + - template: dotnet.yml + +- job: Linux + pool: + vmImage: Ubuntu 18.04 + steps: + - template: install-dependencies.yml + - template: dotnet.yml + +- job: macOS + pool: + vmImage: macOS 10.13 + steps: + - template: install-dependencies.yml + - template: dotnet.yml + +- job: WrapUp + dependsOn: + - Windows + - Linux + - macOS + pool: + vmImage: Ubuntu 18.04 + condition: succeededOrFailed() + steps: + - template: install-dependencies.yml + parameters: + initArgs: -NoRestore + - template: publish-codecoverage.yml + - template: publish-deployables.yml + +- job: leak_check + pool: + vmImage: Ubuntu 18.04 + steps: + - template: install-dependencies.yml + - task: DotNetCoreCLI@2 + displayName: dotnet test -f netcoreapp2.1 + inputs: + command: test + arguments: --no-restore -c $(BuildConfiguration) -f netcoreapp2.1 --filter "TestCategory!=FailsInCloudTest" -v m /p:ExtraDefine=LEAKS_IDENTIFYING + testRunTitle: netcoreapp2.1-$(Agent.JobName) diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml new file mode 100644 index 000000000..8c9f5f909 --- /dev/null +++ b/azure-pipelines/dotnet.yml @@ -0,0 +1,42 @@ +steps: + +- script: dotnet build --no-restore -c $(BuildConfiguration) /v:m /bl:"$(Build.ArtifactStagingDirectory)/build_logs/build.binlog" + displayName: dotnet build + +- script: dotnet pack --no-build -c $(BuildConfiguration) /v:m /bl:"$(Build.ArtifactStagingDirectory)/build_logs/pack.binlog" + displayName: dotnet pack + +- task: DotNetCoreCLI@2 + displayName: dotnet test -f net46 (w/ coverage) + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f net46 --filter "TestCategory!=FailsInCloudTest & TestCategory!=FailsWhileInstrumented" -v n /p:CollectCoverage=true + testRunTitle: net46-$(Agent.JobName) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +- task: DotNetCoreCLI@2 + displayName: dotnet test -f net46 (w/o coverage) + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f net46 --filter "TestCategory!=FailsInCloudTest & TestCategory=FailsWhileInstrumented" -v n + testRunTitle: net46-$(Agent.JobName)-nocoverage + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + +- task: DotNetCoreCLI@2 + displayName: dotnet test -f netcoreapp2.1 + inputs: + command: test + arguments: --no-build -c $(BuildConfiguration) -f netcoreapp2.1 --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true + testRunTitle: netcoreapp2.1-$(Agent.JobName) + +- task: PowerShell@2 + inputs: + filePath: azure-pipelines/artifacts/_pipelines.ps1 + arguments: -ArtifactNameSuffix "-$(Agent.JobName)" + displayName: Publish artifacts + condition: succeededOrFailed() + +- bash: bash <(curl -s https://codecov.io/bash) + displayName: Publish code coverage results to codecov.io + timeoutInMinutes: 3 + continueOnError: true diff --git a/azure-pipelines/install-dependencies.yml b/azure-pipelines/install-dependencies.yml new file mode 100644 index 000000000..5b008c6e8 --- /dev/null +++ b/azure-pipelines/install-dependencies.yml @@ -0,0 +1,9 @@ +parameters: + initArgs: + +steps: + +- powershell: | + .\init.ps1 -AccessToken '$(System.AccessToken)' ${{ parameters['initArgs'] }} -UpgradePrerequisites + dotnet --info + displayName: Install prerequisites diff --git a/azure-pipelines/publish-codecoverage.yml b/azure-pipelines/publish-codecoverage.yml new file mode 100644 index 000000000..59dba9d40 --- /dev/null +++ b/azure-pipelines/publish-codecoverage.yml @@ -0,0 +1,31 @@ +steps: +- download: current + artifact: coverageResults-Windows + displayName: Download Windows code coverage results + continueOnError: true +- download: current + artifact: coverageResults-Linux + displayName: Download Linux code coverage results + continueOnError: true +- download: current + artifact: coverageResults-macOS + displayName: Download macOS code coverage results + continueOnError: true +- powershell: | + dotnet tool install --tool-path obj dotnet-reportgenerator-globaltool --version 4.2.2 + 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" + $reports |% { + $content = Get-Content -Path $_ |% { $_.Replace("{reporoot}", "$(System.DefaultWorkingDirectory)") } + Set-Content -Path $_ -Value $content -Encoding UTF8 + } + $Inputs = [string]::join(';', ($reports |% { Resolve-Path -relative $_ })) + obj/reportgenerator -reports:"$Inputs" -targetdir:coveragereport -reporttypes:Cobertura + displayName: Merge coverage +- task: PublishCodeCoverageResults@1 + displayName: Publish code coverage results to Azure DevOps + inputs: + codeCoverageTool: cobertura + summaryFileLocation: 'coveragereport/Cobertura.xml' + failIfCoverageEmpty: true diff --git a/azure-pipelines/publish-deployables.yml b/azure-pipelines/publish-deployables.yml new file mode 100644 index 000000000..a89f389fd --- /dev/null +++ b/azure-pipelines/publish-deployables.yml @@ -0,0 +1,14 @@ +steps: +- download: current + displayName: Download deployables + artifact: deployables-Windows + +- task: NuGetCommand@2 + displayName: Push packages to CI feed + inputs: + command: push + packagesToPush: $(Pipeline.Workspace)/deployables-Windows/*.nupkg + nuGetFeedType: internal + publishVstsFeed: $(ci_feed) + allowPackageConflicts: true + condition: and(succeeded(), ne(variables['ci_feed'], ''), ne(variables['Build.Reason'], 'PullRequest')) diff --git a/azure-pipelines/variables/DotNetSdkVersion.ps1 b/azure-pipelines/variables/DotNetSdkVersion.ps1 new file mode 100644 index 000000000..b213fbc27 --- /dev/null +++ b/azure-pipelines/variables/DotNetSdkVersion.ps1 @@ -0,0 +1,2 @@ +$globalJson = Get-Content -Path "$PSScriptRoot\..\..\global.json" | ConvertFrom-Json +$globalJson.sdk.version diff --git a/buildandtest.cmd b/buildandtest.cmd deleted file mode 100644 index 612161b87..000000000 --- a/buildandtest.cmd +++ /dev/null @@ -1,39 +0,0 @@ -@ECHO OFF - -REM Sample usages: -REM -REM Building and running tests -REM - buildandtest.cmd -REM -REM Building and identifying potential leaks while running tests -REM - buildandtest.cmd "LEAKS_IDENTIFYING" - -SETLOCAL - -SET EXTRADEFINE=%~1 - -where dotnet 1>nul 2>nul -IF ERRORLEVEL 1 ( - ECHO Cannot find dotnet.exe. Run from a VS2017 Developer Prompt. - EXIT /B 1 -) - -ECHO ON - -SET Configuration=Release - -:: Restore packages -dotnet restore "%~dp0\" -@IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% - -:: Build -dotnet build "%~dp0\" /v:minimal /nologo /property:ExtraDefine="%EXTRADEFINE%" -@IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% - -:: Run tests on Desktop and CoreCLR -"%userprofile%\.nuget\packages\xunit.runner.console\2.4.1\tools\net46\xunit.console.exe" "%~dp0bin\LibGit2Sharp.Tests\%Configuration%\net46\LibGit2Sharp.Tests.dll" -noshadow -@IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% -dotnet test "%~dp0LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj" -f netcoreapp2.1 --no-restore --no-build -@IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% - -EXIT /B %ERRORLEVEL% diff --git a/buildandtest.sh b/buildandtest.sh deleted file mode 100755 index 24994cdae..000000000 --- a/buildandtest.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -set -e - -EXTRADEFINE="$1" - -# Setting LD_LIBRARY_PATH to the current working directory is needed to run -# the tests successfully in linux. Without this, mono can't find libgit when -# the libgit2sharp assembly has been shadow copied. OS X includes the current -# working directory in its library search path, so it works without this value. -export LD_LIBRARY_PATH=. - -# Build release for the code generator and the product itself. -export Configuration=release - -# On linux we don't pack because we can't build for net40. -# We just build for CoreCLR and run tests for it. -dotnet restore -dotnet build LibGit2Sharp.Tests -f netcoreapp2.1 -property:ExtraDefine="$EXTRADEFINE" -fl -flp:verbosity=detailed -dotnet test LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj -f netcoreapp2.1 --no-restore --no-build - -exit $? diff --git a/global.json b/global.json index b354da963..e9aac8c22 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "2.1.802" + "version": "3.1.100" } } diff --git a/init.cmd b/init.cmd new file mode 100644 index 000000000..970285c2f --- /dev/null +++ b/init.cmd @@ -0,0 +1,4 @@ +@echo off +SETLOCAL +set PS1UnderCmd=1 +powershell.exe -NoProfile -NoLogo -ExecutionPolicy bypass -Command "try { & '%~dpn0.ps1' %*; exit $LASTEXITCODE } catch { write-host $_; exit 1 }" diff --git a/init.ps1 b/init.ps1 new file mode 100644 index 000000000..907d85a5c --- /dev/null +++ b/init.ps1 @@ -0,0 +1,66 @@ +<# +.SYNOPSIS +Installs dependencies required to build and test the projects in this repository. +.DESCRIPTION +This MAY not require elevation, as the SDK and runtimes are installed to a per-user location, +unless the `-InstallLocality` switch is specified directing to a per-repo or per-machine location. +See detailed help on that switch for more information. +.PARAMETER InstallLocality +A value indicating whether dependencies should be installed locally to the repo or at a per-user location. +Per-user allows sharing the installed dependencies across repositories and allows use of a shared expanded package cache. +Visual Studio will only notice and use these SDKs/runtimes if VS is launched from the environment that runs this script. +Per-repo allows for high isolation, allowing for a more precise recreation of the environment within an Azure Pipelines build. +When using 'repo', environment variables are set to cause the locally installed dotnet SDK to be used. +Per-repo can lead to file locking issues when dotnet.exe is left running as a build server and can be mitigated by running `dotnet build-server shutdown`. +Per-machine requires elevation and will download and install all SDKs and runtimes to machine-wide locations so all applications can find it. +.PARAMETER NoPrerequisites +Skips the installation of prerequisite software (e.g. SDKs, tools). +.PARAMETER UpgradePrerequisites +Takes time to install prerequisites even if they are already present in case they need to be upgraded. +No effect if -NoPrerequisites is specified. +.PARAMETER NoRestore +Skips the package restore step. +.PARAMETER AccessToken +An optional access token for authenticating to Azure Artifacts authenticated feeds. +#> +[CmdletBinding(SupportsShouldProcess=$true)] +Param ( + [ValidateSet('repo','user','machine')] + [string]$InstallLocality='user', + [Parameter()] + [switch]$NoPrerequisites, + [Parameter()] + [switch]$UpgradePrerequisites, + [Parameter()] + [switch]$NoRestore, + [Parameter()] + [string]$AccessToken +) + +if (!$NoPrerequisites) { + & "$PSScriptRoot\tools\Install-DotNetSdk.ps1" -InstallLocality $InstallLocality +} + +# 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 + +Push-Location $PSScriptRoot +try { + $HeaderColor = 'Green' + + if (!$NoRestore -and $PSCmdlet.ShouldProcess("NuGet packages", "Restore")) { + Write-Host "Restoring NuGet packages" -ForegroundColor $HeaderColor + dotnet restore + if ($lastexitcode -ne 0) { + throw "Failure while restoring packages." + } + } +} +catch { + Write-Error $error[0] + exit $lastexitcode +} +finally { + Pop-Location +} diff --git a/tools/DotNetSdkVersion.ps1 b/tools/DotNetSdkVersion.ps1 deleted file mode 100644 index 41b89d7fd..000000000 --- a/tools/DotNetSdkVersion.ps1 +++ /dev/null @@ -1,2 +0,0 @@ -$globalJson = Get-Content -Path "$PSScriptRoot\..\global.json" | ConvertFrom-Json -$globalJson.sdk.version diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1 index e769aa2ed..10ed02b8b 100644 --- a/tools/Install-DotNetSdk.ps1 +++ b/tools/Install-DotNetSdk.ps1 @@ -25,7 +25,7 @@ if (!(Test-Path $DotNetInstallScriptRoot)) { New-Item -ItemType Directory -Path $DotNetInstallScriptRoot = Resolve-Path $DotNetInstallScriptRoot # Look up actual required .NET Core SDK version from global.json -$sdkVersion = & "$PSScriptRoot/DotNetSdkVersion.ps1" +$sdkVersion = & "$PSScriptRoot/../azure-pipelines/variables/DotNetSdkVersion.ps1" # Search for all .NET Core runtime versions referenced from MSBuild projects and arrange to install them. $runtimeVersions = @() @@ -156,5 +156,5 @@ $runtimeVersions | Get-Unique |% { } if ($PSCmdlet.ShouldProcess("Set DOTNET environment variables to discover these installed runtimes?")) { - & "$PSScriptRoot/Set-EnvVars.ps1" -Variables $envVars -PrependPath $DotNetInstallDir | Out-Null + & "$PSScriptRoot/../azure-pipelines/Set-EnvVars.ps1" -Variables $envVars -PrependPath $DotNetInstallDir | Out-Null }