From ecdbec00aea85e13b1badc023de0c0143bf5a97b Mon Sep 17 00:00:00 2001 From: Turnerj Date: Fri, 13 Nov 2020 16:45:24 +1030 Subject: [PATCH 1/2] Add GitHub Actions CI support --- .appveyor.yml | 4 +- .github/release-drafter.yml | 33 + .github/workflows/build.yml | 114 ++++ .github/workflows/release-drafter.yml | 14 + CacheTower.sln | 1 + CodeCoverage.runsettings | 46 +- build.appveyor.ps1 | 2 +- build.ps1 | 36 +- build/dotnet-install.ps1 | 589 ------------------ .../CacheTower.Tests/CacheTower.Tests.csproj | 7 +- tests/CacheTower.Tests/TestBase.cs | 2 +- 11 files changed, 193 insertions(+), 655 deletions(-) create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release-drafter.yml delete mode 100644 build/dotnet-install.ps1 diff --git a/.appveyor.yml b/.appveyor.yml index db583278..b5d1bbeb 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -5,9 +5,7 @@ skip_branch_with_pr: true services: - mongodb install: - - choco install opencover.portable codecov - - choco install Memurai-Developer --version 2.0.0 - - ps: .\build\dotnet-install.ps1 -Version 3.0.100 + - choco install Memurai-Developer build_script: - ps: .\build.appveyor.ps1 diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 00000000..45a0235a --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,33 @@ +name-template: '$RESOLVED_VERSION' +tag-template: '$RESOLVED_VERSION' +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'bug' + - 'bugfix' + - title: '🧰 Maintenance' + label: + - 'dependencies' + - 'maintenance' +change-template: '- $TITLE by @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + patch: + labels: + - 'patch' + default: patch +template: | + ## Changes + $CHANGES + ## 👨🏼‍💻 Contributors + $CONTRIBUTORS \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..5c857801 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,114 @@ +name: Build + +on: + push: + branches: [ master ] + pull_request: + +env: + # Disable the .NET logo in the console output. + DOTNET_NOLOGO: true + # Disable the .NET first time experience to skip caching NuGet packages and speed up the build. + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + # Disable sending .NET CLI telemetry to Microsoft. + DOTNET_CLI_TELEMETRY_OPTOUT: true + + BUILD_ARTIFACT_PATH: ${{github.workspace}}/build-artifacts + +jobs: + + version: + name: Identify build version + runs-on: ubuntu-latest + outputs: + BuildVersion: ${{steps.configureBuildVersion.outputs.BUILD_VERSION}} + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Fetch all Git tags + run: git fetch --prune --unshallow --tags + - name: Configure build version + id: configureBuildVersion + run: | + $githubRunId = $env:GITHUB_RUN_ID; + $prNumber = $env:PR_NUMBER; + $gitSourceVersion = git describe --tags --abbrev=7 --always 2>$1; + $gitSourceVersionSplit = [regex]::split($gitSourceVersion, "-(?=\d+-\w+)"); + $version = $(if($gitSourceVersionSplit.length -eq 1){"0.0.0"}else{$gitSourceVersionSplit[0]}); + $commitsSinceTag = '0'; + $commitHash = $gitSourceVersionSplit[0]; + if ($gitSourceVersionSplit.length -eq 2) { + $gitMetadata = $gitSourceVersionSplit[1].split("-"); + $commitsSinceTag = $gitMetadata[0]; + $commitHash = $gitMetadata[1]; + } + $buildMetadata = "$($commitHash)-$($githubRunId)"; + $customSuffix = $(if($prNumber -ne ''){"-PR$($prNumber)"}elseif($commitsSinceTag -ne '0'){"-dev"}); + echo "::set-output name=BUILD_VERSION::$($version)$($customSuffix)+$($buildMetadata)"; + shell: pwsh + env: + PR_NUMBER: ${{github.event.number}} + - name: Print build version + run: echo ${{steps.configureBuildVersion.outputs.BUILD_VERSION}} + + + build: + name: Build ${{matrix.os}} + runs-on: ${{matrix.os}} + needs: version + env: + BUILD_VERSION: ${{needs.version.outputs.BuildVersion}} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - name: Configure Windows + if: matrix.os == 'windows-latest' + run: choco install Memurai-Developer + - name: Configure Ubuntu + if: matrix.os == 'ubuntu-latest' + run: sudo systemctl start mongod && sudo apt-get install redis-server + - name: Configure MacOS + if: matrix.os == 'macOS-latest' + run: brew services start mongodb-community && brew install redis && brew services start redis + + - name: Checkout + uses: actions/checkout@v2 + + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build -c Release --no-restore /p:Version=${{env.BUILD_VERSION}} + - name: Test with Coverage + run: dotnet test --logger trx --results-directory ${{env.BUILD_ARTIFACT_PATH}}/coverage --collect "XPlat Code Coverage" --settings CodeCoverage.runsettings + - name: Pack + run: dotnet pack -c Release --no-build /p:Version=${{env.BUILD_VERSION}} /p:PackageOutputPath=${{env.BUILD_ARTIFACT_PATH}} + - name: Publish artifacts + uses: actions/upload-artifact@v2 + with: + name: ${{matrix.os}} + path: ${{env.BUILD_ARTIFACT_PATH}} + + coverage: + name: Process code coverage + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Download coverage reports + uses: actions/download-artifact@v2 + - name: Install ReportGenerator tool + run: dotnet tool install -g dotnet-reportgenerator-globaltool + - name: Prepare coverage reports + run: reportgenerator -reports:*/coverage/*/coverage.cobertura.xml -targetdir:./ -reporttypes:Cobertura + - name: Upload coverage report + uses: codecov/codecov-action@v1.0.13 + with: + file: Cobertura.xml + fail_ci_if_error: false + - name: Save combined coverage report as artifact + uses: actions/upload-artifact@v2 + with: + name: coverage-report + path: Cobertura.xml \ No newline at end of file diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 00000000..0d72960a --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,14 @@ +name: Release Drafter + +on: + push: + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} \ No newline at end of file diff --git a/CacheTower.sln b/CacheTower.sln index 8c360ba5..a311f53b 100644 --- a/CacheTower.sln +++ b/CacheTower.sln @@ -23,6 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "global", "global", "{28E0B5 build.appveyor.ps1 = build.appveyor.ps1 build.ps1 = build.ps1 buildconfig.json = buildconfig.json + CodeCoverage.runsettings = CodeCoverage.runsettings License.txt = License.txt README.md = README.md EndProjectSection diff --git a/CodeCoverage.runsettings b/CodeCoverage.runsettings index 754249ec..209bebc6 100644 --- a/CodeCoverage.runsettings +++ b/CodeCoverage.runsettings @@ -1,31 +1,17 @@ - - - - - - - - - - - .*\.dll$ - - - CacheTower.Tests.dll - CacheTower.Benchmarks.dll - CacheTower.AlternativesBenchmark.dll - - - - - True - True - True - False - - - - - - + + + + + + + cobertura + [CacheTower.Tests]*,[CacheTower.Benchmarks]*,[CacheTower.AlternativesBenchmark]* + [CacheTower]*,[CacheTower.*]* + Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute + true + true + + + + \ No newline at end of file diff --git a/build.appveyor.ps1 b/build.appveyor.ps1 index 02c23616..a86ce584 100644 --- a/build.appveyor.ps1 +++ b/build.appveyor.ps1 @@ -29,7 +29,7 @@ if ($isTagBuild) { .\build.ps1 -CreatePackages $True -BuildVersion $buildVersion } else { - .\build.ps1 -CheckCoverage $True -BuildVersion $buildVersion + .\build.ps1 -BuildVersion $buildVersion } Exit $LastExitCode \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index ae156499..e992579c 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,7 +1,6 @@ [CmdletBinding(PositionalBinding=$false)] param( [bool] $RunTests = $true, - [bool] $CheckCoverage, [bool] $CreatePackages, [string] $BuildVersion ) @@ -22,12 +21,10 @@ if (-not $BuildVersion) { Write-Host "Run Parameters:" -ForegroundColor Cyan Write-Host " RunTests: $RunTests" -Write-Host " CheckCoverage: $CheckCoverage" Write-Host " CreatePackages: $CreatePackages" Write-Host " BuildVersion: $BuildVersion" Write-Host "Configuration:" -ForegroundColor Cyan Write-Host " TestProject: $($config.TestProject)" -Write-Host " TestCoverageFilter: $($config.TestCoverageFilter)" Write-Host "Environment:" -ForegroundColor Cyan Write-Host " .NET Version:" (dotnet --version) Write-Host " Artifact Path: $packageOutputFolder" @@ -41,34 +38,13 @@ if ($LastExitCode -ne 0) { Write-Host "Solution built!" -ForegroundColor "Green" if ($RunTests) { - if (-Not $CheckCoverage) { - Write-Host "Running tests without coverage..." -ForegroundColor "Magenta" - dotnet test $config.TestProject - if ($LastExitCode -ne 0) { - Write-Host "Tests failed, aborting build!" -Foreground "Red" - Exit 1 - } - Write-Host "Tests passed!" -ForegroundColor "Green" - } - else { - Write-Host "Running tests with coverage..." -ForegroundColor "Magenta" - OpenCover.Console.exe -register:user -target:"%LocalAppData%\Microsoft\dotnet\dotnet.exe" -targetargs:"test $($config.TestProject) /p:DebugType=Full" -filter:"$($config.TestCoverageFilter)" -output:"$packageOutputFolder\coverage.xml" -oldstyle - if ($LastExitCode -ne 0 -Or -Not $?) { - Write-Host "Failure performing tests with coverage, aborting!" -Foreground "Red" - Exit 1 - } - else { - Write-Host "Tests passed!" -ForegroundColor "Green" - Write-Host "Saving code coverage..." -ForegroundColor "Magenta" - codecov -f "$packageOutputFolder\coverage.xml" - if ($LastExitCode -ne 0 -Or -Not $?) { - Write-Host "Failure saving code coverage!" -Foreground "Red" - } - else { - Write-Host "Coverage saved!" -ForegroundColor "Green" - } - } + Write-Host "Running tests..." -ForegroundColor "Magenta" + dotnet test $config.TestProject + if ($LastExitCode -ne 0) { + Write-Host "Tests failed, aborting build!" -Foreground "Red" + Exit 1 } + Write-Host "Tests passed!" -ForegroundColor "Green" } if ($CreatePackages) { diff --git a/build/dotnet-install.ps1 b/build/dotnet-install.ps1 deleted file mode 100644 index 14ebe11a..00000000 --- a/build/dotnet-install.ps1 +++ /dev/null @@ -1,589 +0,0 @@ -# -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. -# - -<# -.SYNOPSIS - Installs dotnet cli -.DESCRIPTION - Installs dotnet cli. If dotnet installation already exists in the given directory - it will update it only if the requested version differs from the one already installed. -.PARAMETER Channel - Default: LTS - Download from the Channel specified. Possible values: - - Current - most current release - - LTS - most current supported release - - 2-part version in a format A.B - represents a specific release - examples: 2.0; 1.0 - - Branch name - examples: release/2.0.0; Master -.PARAMETER Version - Default: latest - Represents a build version on specific channel. Possible values: - - latest - most latest build on specific channel - - coherent - most latest coherent build on specific channel - coherent applies only to SDK downloads - - 3-part version in a format A.B.C - represents specific version of build - examples: 2.0.0-preview2-006120; 1.1.0 -.PARAMETER InstallDir - Default: %LocalAppData%\Microsoft\dotnet - Path to where to install dotnet. Note that binaries will be placed directly in a given directory. -.PARAMETER Architecture - Default: - this value represents currently running OS architecture - Architecture of dotnet binaries to be installed. - Possible values are: , x64 and x86 -.PARAMETER SharedRuntime - This parameter is obsolete and may be removed in a future version of this script. - The recommended alternative is '-Runtime dotnet'. - - Default: false - Installs just the shared runtime bits, not the entire SDK. - This is equivalent to specifying `-Runtime dotnet`. -.PARAMETER Runtime - Installs just a shared runtime, not the entire SDK. - Possible values: - - dotnet - the Microsoft.NETCore.App shared runtime - - aspnetcore - the Microsoft.AspNetCore.App shared runtime -.PARAMETER DryRun - If set it will not perform installation but instead display what command line to use to consistently install - currently requested version of dotnet cli. In example if you specify version 'latest' it will display a link - with specific version so that this command can be used deterministicly in a build script. - It also displays binaries location if you prefer to install or download it yourself. -.PARAMETER NoPath - By default this script will set environment variable PATH for the current process to the binaries folder inside installation folder. - If set it will display binaries location but not set any environment variable. -.PARAMETER Verbose - Displays diagnostics information. -.PARAMETER AzureFeed - Default: https://dotnetcli.azureedge.net/dotnet - This parameter typically is not changed by the user. - It allows changing the URL for the Azure feed used by this installer. -.PARAMETER UncachedFeed - This parameter typically is not changed by the user. - It allows changing the URL for the Uncached feed used by this installer. -.PARAMETER FeedCredential - Used as a query string to append to the Azure feed. - It allows changing the URL to use non-public blob storage accounts. -.PARAMETER ProxyAddress - If set, the installer will use the proxy when making web requests -.PARAMETER ProxyUseDefaultCredentials - Default: false - Use default credentials, when using proxy address. -.PARAMETER SkipNonVersionedFiles - Default: false - Skips installing non-versioned files if they already exist, such as dotnet.exe. -.PARAMETER NoCdn - Disable downloading from the Azure CDN, and use the uncached feed directly. -#> -[cmdletbinding()] -param( - [string]$Channel="LTS", - [string]$Version="Latest", - [string]$InstallDir="", - [string]$Architecture="", - [ValidateSet("dotnet", "aspnetcore", IgnoreCase = $false)] - [string]$Runtime, - [Obsolete("This parameter may be removed in a future version of this script. The recommended alternative is '-Runtime dotnet'.")] - [switch]$SharedRuntime, - [switch]$DryRun, - [switch]$NoPath, - [string]$AzureFeed="https://dotnetcli.azureedge.net/dotnet", - [string]$UncachedFeed="https://dotnetcli.blob.core.windows.net/dotnet", - [string]$FeedCredential, - [string]$ProxyAddress, - [switch]$ProxyUseDefaultCredentials, - [switch]$SkipNonVersionedFiles, - [switch]$NoCdn -) - -Set-StrictMode -Version Latest -$ErrorActionPreference="Stop" -$ProgressPreference="SilentlyContinue" - -if ($NoCdn) { - $AzureFeed = $UncachedFeed -} - -$BinFolderRelativePath="" - -if ($SharedRuntime -and (-not $Runtime)) { - $Runtime = "dotnet" -} - -# example path with regex: shared/1.0.0-beta-12345/somepath -$VersionRegEx="/\d+\.\d+[^/]+/" -$OverrideNonVersionedFiles = !$SkipNonVersionedFiles - -function Say($str) { - Write-Host "dotnet-install: $str" -} - -function Say-Verbose($str) { - Write-Verbose "dotnet-install: $str" -} - -function Say-Invocation($Invocation) { - $command = $Invocation.MyCommand; - $args = (($Invocation.BoundParameters.Keys | foreach { "-$_ `"$($Invocation.BoundParameters[$_])`"" }) -join " ") - Say-Verbose "$command $args" -} - -function Invoke-With-Retry([ScriptBlock]$ScriptBlock, [int]$MaxAttempts = 3, [int]$SecondsBetweenAttempts = 1) { - $Attempts = 0 - - while ($true) { - try { - return $ScriptBlock.Invoke() - } - catch { - $Attempts++ - if ($Attempts -lt $MaxAttempts) { - Start-Sleep $SecondsBetweenAttempts - } - else { - throw - } - } - } -} - -function Get-Machine-Architecture() { - Say-Invocation $MyInvocation - - # possible values: AMD64, IA64, x86 - return $ENV:PROCESSOR_ARCHITECTURE -} - -# TODO: Architecture and CLIArchitecture should be unified -function Get-CLIArchitecture-From-Architecture([string]$Architecture) { - Say-Invocation $MyInvocation - - switch ($Architecture.ToLower()) { - { $_ -eq "" } { return Get-CLIArchitecture-From-Architecture $(Get-Machine-Architecture) } - { ($_ -eq "amd64") -or ($_ -eq "x64") } { return "x64" } - { $_ -eq "x86" } { return "x86" } - default { throw "Architecture not supported. If you think this is a bug, please report it at https://github.com/dotnet/cli/issues" } - } -} - -function Get-Version-Info-From-Version-Text([string]$VersionText) { - Say-Invocation $MyInvocation - - $Data = @($VersionText.Split([char[]]@(), [StringSplitOptions]::RemoveEmptyEntries)); - - $VersionInfo = @{} - $VersionInfo.CommitHash = $Data[0].Trim() - $VersionInfo.Version = $Data[1].Trim() - return $VersionInfo -} - -function Load-Assembly([string] $Assembly) { - try { - Add-Type -Assembly $Assembly | Out-Null - } - catch { - # On Nano Server, Powershell Core Edition is used. Add-Type is unable to resolve base class assemblies because they are not GAC'd. - # Loading the base class assemblies is not unnecessary as the types will automatically get resolved. - } -} - -function GetHTTPResponse([Uri] $Uri) -{ - Invoke-With-Retry( - { - - $HttpClient = $null - - try { - # HttpClient is used vs Invoke-WebRequest in order to support Nano Server which doesn't support the Invoke-WebRequest cmdlet. - Load-Assembly -Assembly System.Net.Http - - if(-not $ProxyAddress) { - try { - # Despite no proxy being explicitly specified, we may still be behind a default proxy - $DefaultProxy = [System.Net.WebRequest]::DefaultWebProxy; - if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))) { - $ProxyAddress = $DefaultProxy.GetProxy($Uri).OriginalString - $ProxyUseDefaultCredentials = $true - } - } catch { - # Eat the exception and move forward as the above code is an attempt - # at resolving the DefaultProxy that may not have been a problem. - $ProxyAddress = $null - Say-Verbose("Exception ignored: $_.Exception.Message - moving forward...") - } - } - - if($ProxyAddress) { - $HttpClientHandler = New-Object System.Net.Http.HttpClientHandler - $HttpClientHandler.Proxy = New-Object System.Net.WebProxy -Property @{Address=$ProxyAddress;UseDefaultCredentials=$ProxyUseDefaultCredentials} - $HttpClient = New-Object System.Net.Http.HttpClient -ArgumentList $HttpClientHandler - } - else { - - $HttpClient = New-Object System.Net.Http.HttpClient - } - # Default timeout for HttpClient is 100s. For a 50 MB download this assumes 500 KB/s average, any less will time out - # 10 minutes allows it to work over much slower connections. - $HttpClient.Timeout = New-TimeSpan -Minutes 10 - $Response = $HttpClient.GetAsync("${Uri}${FeedCredential}").Result - if (($Response -eq $null) -or (-not ($Response.IsSuccessStatusCode))) { - # The feed credential is potentially sensitive info. Do not log FeedCredential to console output. - $ErrorMsg = "Failed to download $Uri." - if ($Response -ne $null) { - $ErrorMsg += " $Response" - } - - throw $ErrorMsg - } - - return $Response - } - finally { - if ($HttpClient -ne $null) { - $HttpClient.Dispose() - } - } - }) -} - - -function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Coherent) { - Say-Invocation $MyInvocation - - $VersionFileUrl = $null - if ($Runtime -eq "dotnet") { - $VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version" - } - elseif ($Runtime -eq "aspnetcore") { - $VersionFileUrl = "$UncachedFeed/aspnetcore/Runtime/$Channel/latest.version" - } - elseif (-not $Runtime) { - if ($Coherent) { - $VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.coherent.version" - } - else { - $VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.version" - } - } - else { - throw "Invalid value for `$Runtime" - } - - $Response = GetHTTPResponse -Uri $VersionFileUrl - $StringContent = $Response.Content.ReadAsStringAsync().Result - - switch ($Response.Content.Headers.ContentType) { - { ($_ -eq "application/octet-stream") } { $VersionText = $StringContent } - { ($_ -eq "text/plain") } { $VersionText = $StringContent } - { ($_ -eq "text/plain; charset=UTF-8") } { $VersionText = $StringContent } - default { throw "``$Response.Content.Headers.ContentType`` is an unknown .version file content type." } - } - - $VersionInfo = Get-Version-Info-From-Version-Text $VersionText - - return $VersionInfo -} - - -function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel, [string]$Version) { - Say-Invocation $MyInvocation - - switch ($Version.ToLower()) { - { $_ -eq "latest" } { - $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $False - return $LatestVersionInfo.Version - } - { $_ -eq "coherent" } { - $LatestVersionInfo = Get-Latest-Version-Info -AzureFeed $AzureFeed -Channel $Channel -Coherent $True - return $LatestVersionInfo.Version - } - default { return $Version } - } -} - -function Get-Download-Link([string]$AzureFeed, [string]$SpecificVersion, [string]$CLIArchitecture) { - Say-Invocation $MyInvocation - - if ($Runtime -eq "dotnet") { - $PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-runtime-$SpecificVersion-win-$CLIArchitecture.zip" - } - elseif ($Runtime -eq "aspnetcore") { - $PayloadURL = "$AzureFeed/aspnetcore/Runtime/$SpecificVersion/aspnetcore-runtime-$SpecificVersion-win-$CLIArchitecture.zip" - } - elseif (-not $Runtime) { - $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-sdk-$SpecificVersion-win-$CLIArchitecture.zip" - } - else { - throw "Invalid value for `$Runtime" - } - - Say-Verbose "Constructed primary payload URL: $PayloadURL" - - return $PayloadURL -} - -function Get-LegacyDownload-Link([string]$AzureFeed, [string]$SpecificVersion, [string]$CLIArchitecture) { - Say-Invocation $MyInvocation - - if (-not $Runtime) { - $PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip" - } - elseif ($Runtime -eq "dotnet") { - $PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-win-$CLIArchitecture.$SpecificVersion.zip" - } - else { - return $null - } - - Say-Verbose "Constructed legacy payload URL: $PayloadURL" - - return $PayloadURL -} - -function Get-User-Share-Path() { - Say-Invocation $MyInvocation - - $InstallRoot = $env:DOTNET_INSTALL_DIR - if (!$InstallRoot) { - $InstallRoot = "$env:LocalAppData\Microsoft\dotnet" - } - return $InstallRoot -} - -function Resolve-Installation-Path([string]$InstallDir) { - Say-Invocation $MyInvocation - - if ($InstallDir -eq "") { - return Get-User-Share-Path - } - return $InstallDir -} - -function Get-Version-Info-From-Version-File([string]$InstallRoot, [string]$RelativePathToVersionFile) { - Say-Invocation $MyInvocation - - $VersionFile = Join-Path -Path $InstallRoot -ChildPath $RelativePathToVersionFile - Say-Verbose "Local version file: $VersionFile" - - if (Test-Path $VersionFile) { - $VersionText = cat $VersionFile - Say-Verbose "Local version file text: $VersionText" - return Get-Version-Info-From-Version-Text $VersionText - } - - Say-Verbose "Local version file not found." - - return $null -} - -function Is-Dotnet-Package-Installed([string]$InstallRoot, [string]$RelativePathToPackage, [string]$SpecificVersion) { - Say-Invocation $MyInvocation - - $DotnetPackagePath = Join-Path -Path $InstallRoot -ChildPath $RelativePathToPackage | Join-Path -ChildPath $SpecificVersion - Say-Verbose "Is-Dotnet-Package-Installed: Path to a package: $DotnetPackagePath" - return Test-Path $DotnetPackagePath -PathType Container -} - -function Get-Absolute-Path([string]$RelativeOrAbsolutePath) { - # Too much spam - # Say-Invocation $MyInvocation - - return $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($RelativeOrAbsolutePath) -} - -function Get-Path-Prefix-With-Version($path) { - $match = [regex]::match($path, $VersionRegEx) - if ($match.Success) { - return $entry.FullName.Substring(0, $match.Index + $match.Length) - } - - return $null -} - -function Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package([System.IO.Compression.ZipArchive]$Zip, [string]$OutPath) { - Say-Invocation $MyInvocation - - $ret = @() - foreach ($entry in $Zip.Entries) { - $dir = Get-Path-Prefix-With-Version $entry.FullName - if ($dir -ne $null) { - $path = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $dir) - if (-Not (Test-Path $path -PathType Container)) { - $ret += $dir - } - } - } - - $ret = $ret | Sort-Object | Get-Unique - - $values = ($ret | foreach { "$_" }) -join ";" - Say-Verbose "Directories to unpack: $values" - - return $ret -} - -# Example zip content and extraction algorithm: -# Rule: files if extracted are always being extracted to the same relative path locally -# .\ -# a.exe # file does not exist locally, extract -# b.dll # file exists locally, override only if $OverrideFiles set -# aaa\ # same rules as for files -# ... -# abc\1.0.0\ # directory contains version and exists locally -# ... # do not extract content under versioned part -# abc\asd\ # same rules as for files -# ... -# def\ghi\1.0.1\ # directory contains version and does not exist locally -# ... # extract content -function Extract-Dotnet-Package([string]$ZipPath, [string]$OutPath) { - Say-Invocation $MyInvocation - - Load-Assembly -Assembly System.IO.Compression.FileSystem - Set-Variable -Name Zip - try { - $Zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath) - - $DirectoriesToUnpack = Get-List-Of-Directories-And-Versions-To-Unpack-From-Dotnet-Package -Zip $Zip -OutPath $OutPath - - foreach ($entry in $Zip.Entries) { - $PathWithVersion = Get-Path-Prefix-With-Version $entry.FullName - if (($PathWithVersion -eq $null) -Or ($DirectoriesToUnpack -contains $PathWithVersion)) { - $DestinationPath = Get-Absolute-Path $(Join-Path -Path $OutPath -ChildPath $entry.FullName) - $DestinationDir = Split-Path -Parent $DestinationPath - $OverrideFiles=$OverrideNonVersionedFiles -Or (-Not (Test-Path $DestinationPath)) - if ((-Not $DestinationPath.EndsWith("\")) -And $OverrideFiles) { - New-Item -ItemType Directory -Force -Path $DestinationDir | Out-Null - [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $DestinationPath, $OverrideNonVersionedFiles) - } - } - } - } - finally { - if ($Zip -ne $null) { - $Zip.Dispose() - } - } -} - -function DownloadFile([Uri]$Uri, [string]$OutPath) { - if ($Uri -notlike "http*") { - Say-Verbose "Copying file from $Uri to $OutPath" - Copy-Item $Uri.AbsolutePath $OutPath - return - } - - $Stream = $null - - try { - $Response = GetHTTPResponse -Uri $Uri - $Stream = $Response.Content.ReadAsStreamAsync().Result - $File = [System.IO.File]::Create($OutPath) - $Stream.CopyTo($File) - $File.Close() - } - finally { - if ($Stream -ne $null) { - $Stream.Dispose() - } - } -} - -function Prepend-Sdk-InstallRoot-To-Path([string]$InstallRoot, [string]$BinFolderRelativePath) { - $BinPath = Get-Absolute-Path $(Join-Path -Path $InstallRoot -ChildPath $BinFolderRelativePath) - if (-Not $NoPath) { - Say "Adding to current process PATH: `"$BinPath`". Note: This change will not be visible if PowerShell was run as a child process." - $env:path = "$BinPath;" + $env:path - } - else { - Say "Binaries of dotnet can be found in $BinPath" - } -} - -$CLIArchitecture = Get-CLIArchitecture-From-Architecture $Architecture -$SpecificVersion = Get-Specific-Version-From-Version -AzureFeed $AzureFeed -Channel $Channel -Version $Version -$DownloadLink = Get-Download-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture -$LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVersion $SpecificVersion -CLIArchitecture $CLIArchitecture - -if ($DryRun) { - Say "Payload URLs:" - Say "Primary - $DownloadLink" - if ($LegacyDownloadLink) { - Say "Legacy - $LegacyDownloadLink" - } - Say "Repeatable invocation: .\$($MyInvocation.Line)" - exit 0 -} - -$InstallRoot = Resolve-Installation-Path $InstallDir -Say-Verbose "InstallRoot: $InstallRoot" - -if ($Runtime -eq "dotnet") { - $assetName = ".NET Core Runtime" - $dotnetPackageRelativePath = "shared\Microsoft.NETCore.App" -} -elseif ($Runtime -eq "aspnetcore") { - $assetName = "ASP.NET Core Runtime" - $dotnetPackageRelativePath = "shared\Microsoft.AspNetCore.App" -} -elseif (-not $Runtime) { - $assetName = ".NET Core SDK" - $dotnetPackageRelativePath = "sdk" -} -else { - throw "Invalid value for `$Runtime" -} - -# Check if the SDK version is already installed. -$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion -if ($isAssetInstalled) { - Say "$assetName version $SpecificVersion is already installed." - Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath - exit 0 -} - -New-Item -ItemType Directory -Force -Path $InstallRoot | Out-Null - -$installDrive = $((Get-Item $InstallRoot).PSDrive.Name); -$free = Get-CimInstance -Class win32_logicaldisk | where Deviceid -eq "${installDrive}:" -if ($free.Freespace / 1MB -le 100 ) { - Say "There is not enough disk space on drive ${installDrive}:" - exit 0 -} - -$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) -Say-Verbose "Zip path: $ZipPath" -Say "Downloading link: $DownloadLink" -try { - DownloadFile -Uri $DownloadLink -OutPath $ZipPath -} -catch { - Say "Cannot download: $DownloadLink" - if ($LegacyDownloadLink) { - $DownloadLink = $LegacyDownloadLink - $ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) - Say-Verbose "Legacy zip path: $ZipPath" - Say "Downloading legacy link: $DownloadLink" - DownloadFile -Uri $DownloadLink -OutPath $ZipPath - } - else { - throw "Could not download $assetName version $SpecificVersion" - } -} - -Say "Extracting zip from $DownloadLink" -Extract-Dotnet-Package -ZipPath $ZipPath -OutPath $InstallRoot - -# Check if the SDK version is now installed; if not, fail the installation. -$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion -if (!$isAssetInstalled) { - throw "$assetName version $SpecificVersion failed to install with an unknown error." -} - -Remove-Item $ZipPath - -Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath - -Say "Installation finished" -exit 0 diff --git a/tests/CacheTower.Tests/CacheTower.Tests.csproj b/tests/CacheTower.Tests/CacheTower.Tests.csproj index 8988ef3b..29c2ed89 100644 --- a/tests/CacheTower.Tests/CacheTower.Tests.csproj +++ b/tests/CacheTower.Tests/CacheTower.Tests.csproj @@ -1,7 +1,7 @@  - net461;netcoreapp2.1;netcoreapp3.0 + net461;netcoreapp2.1;netcoreapp3.1 false @@ -10,6 +10,11 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/tests/CacheTower.Tests/TestBase.cs b/tests/CacheTower.Tests/TestBase.cs index fbdfec6c..c7150bc0 100644 --- a/tests/CacheTower.Tests/TestBase.cs +++ b/tests/CacheTower.Tests/TestBase.cs @@ -15,7 +15,7 @@ protected static Task DisposeOf(IDisposable disposable) } -#if NETCOREAPP3_0 +#if NETCOREAPP3_1 protected static async Task DisposeOf(IAsyncDisposable disposable) { await disposable.DisposeAsync(); From 023bc3964e9a531819faf337797c4f648330d004 Mon Sep 17 00:00:00 2001 From: Turnerj Date: Fri, 13 Nov 2020 17:21:00 +1030 Subject: [PATCH 2/2] Enhanced detail for dependency issue debugging --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5c857801..7223114d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@v2 - name: Install dependencies - run: dotnet restore + run: dotnet --version && dotnet nuget list source && dotnet restore --verbosity normal - name: Build run: dotnet build -c Release --no-restore /p:Version=${{env.BUILD_VERSION}} - name: Test with Coverage