diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000000..31e896e989 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "cake.tool": { + "version": "2.0.0", + "commands": [ + "dotnet-cake" + ] + } + } +} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index a1e1e97ac2..4cfbb10890 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,7 @@ # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto +*.sh text eol=lf ############################################################################### # Set default behavior for command prompt diff. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index a0c8ae48d7..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,67 +0,0 @@ - - -### What You Are Seeing? - -### What is Expected? - -### What version of Cake are you using? - -### Are you running on a 32 or 64 bit system? - -### What environment are you running on? Windows? Linux? Mac? - -### Are you running on a CI Server? If so, which one? - - - -### How Did You Get This To Happen? (Steps to Reproduce) - - - -### Output Log - - -GIST LINK - Please create a gist and link to that gist here - -OR - -~~~sh -PLACE LOG CONTENT HERE -~~~ - - diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000000..befab0db1f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,77 @@ +name: Bug report +description: Create a report to help us improve +body: +- type: checkboxes + attributes: + label: Prerequisites + options: + - label: I have written a descriptive issue title + required: true + - label: I have searched [issues](https://github.com/cake-build/cake/issues) to ensure it has not already been reported + required: true +- type: dropdown + attributes: + label: Cake runner + options: + - Cake .NET Tool + - Cake Frosting + - Cake runner for .NET Framework + - Cake runner for .NET Core + multiple: true + validations: + required: true +- type: input + attributes: + label: Cake version + validations: + required: true +- type: dropdown + attributes: + label: Operating system + options: + - Linux + - Windows + - macOS + - N/A + multiple: true + validations: + required: true +- type: dropdown + attributes: + label: Operating system architecture + options: + - 32-Bit + - 64-Bit + - N/A + validations: + required: true +- type: input + attributes: + label: CI Server + description: If you're running on a build server (GitHub Actions, Azure DevOps, etc) + validations: + required: false +- type: textarea + attributes: + label: What are you seeing? + description: Describe the issue you are seeing + validations: + required: true +- type: textarea + attributes: + label: What is expected? + description: Describe what you would expect + validations: + required: true +- type: textarea + attributes: + label: Steps to Reproduce + description: List of steps or sample project to reproduce the issue + validations: + required: true +- type: textarea + attributes: + label: Output log + description: Log messages you receive when running with --verbosity=diagnostic. Make sure there is no sensitive data shared and that you place a stack trace inside a code (```) block to avoid formatting issues. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..e3826d7bd4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Ask for help or share ideas + url: https://github.com/cake-build/cake/discussions/category_choices + about: Ask the community for help or share ideas for new features. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77302fee1f..84aa424a94 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,13 +5,15 @@ on: branches: - main - develop + - hotfix/* jobs: build: name: Build runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [windows-latest, ubuntu-latest, macos-latest] + os: [windows-latest, ubuntu-18.04, macos-latest] steps: - name: Get the sources uses: actions/checkout@v2 @@ -19,15 +21,30 @@ jobs: - name: Fetch all history for all tags and branches run: git fetch --prune --unshallow - - name: Install .NET Core SDK 3.1.301 + - name: Install .NET Core SDK 3.1.x uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.301' + dotnet-version: '3.1.x' + + - name: Install .NET Core SDK 5.0.x + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '5.0.x' + + - name: Install .NET Core SDK (global.json) + uses: actions/setup-dotnet@v1 + with: + include-prerelease: 'true' - name: Run Cake script - uses: ecampidoglio/cake-action@v1.1.1 - env: - DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 + uses: cake-build/cake-action@v1 with: target: Run-Integration-Tests - cake-bootstrap: true + cake-version: tool-manifest + + - name: Validate Integration Tests + uses: cake-build/cake-action@master + with: + script-path: tests/integration/Cake.Common/Build/GitHubActions/ValidateGitHubActionsProvider.cake + cake-version: tool-manifest + diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000000..adf93dbf3b --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,36 @@ +name: "CodeQL" + +on: + push: + branches: [ develop, main] + pull_request: + branches: [ develop ] + schedule: + - cron: '41 21 * * 2' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-18.04 + + strategy: + fail-fast: false + matrix: + language: [ 'csharp' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 780678a6d9..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,32 +0,0 @@ -language: csharp -os: - - osx - - linux - -# Ubuntu 16.04 -sudo: required -dist: bionic - -# OS X 10.12 -osx_image: xcode11.2 - -mono: - - 5.12.0 - - 5.20.1 - -dotnet: 3.1.301 - -before_install: - - git fetch --unshallow # Travis always does a shallow clone, but GitVersion needs the full history including branches and tags - - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" - - git fetch origin - -script: - - ./build.sh --target="Travis" - -cache: - directories: - - .packages - - tools/Addins - - tools/gitreleasemanager - - tools/GitVersion.CommandLine \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 16cd746464..3f48e8560c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,9 +64,9 @@ Any new code should also have reasonable unit test coverage. ## Contributing process ### Get buyoff or find open community issues or features - * Through GitHub, or through the [Gitter chat](https://gitter.im/cake-build/cake) (preferred), + * Through GitHub, or through the [GitHub discussions](https://github.com/cake-build/cake/discussions) (preferred), you talk about a feature you would like to see (or a bug), and why it should be in Cake. - * If approved through the Gitter chat, ensure an accompanying GitHub issue is created with + * If approved through the GitHub discussions, ensure an accompanying GitHub issue is created with information and a link back to the discussion. * Once you get a nod from one of the [Cake Team](https://github.com/cake-build?tab=members), you can start on the feature. * Alternatively, if a feature is on the issues list with the diff --git a/GitReleaseManager.yaml b/GitReleaseManager.yaml index cd526e78ae..6b71b019b1 100644 --- a/GitReleaseManager.yaml +++ b/GitReleaseManager.yaml @@ -1,8 +1,8 @@ issue-labels-include: - Breaking change - Feature -- Bug - Improvement +- Bug - Documentation issue-labels-exclude: - Build diff --git a/GitVersion.yml b/GitVersion.yml index 8ff7a54f98..1461a0e91d 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,4 +1,4 @@ -next-version: 1.0.0 +next-version: 2.0.0 branches: master: regex: main diff --git a/README.md b/README.md index 487b2ab758..e1665e5485 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Cake -[![NuGet](https://img.shields.io/nuget/v/Cake.svg)](https://www.nuget.org/packages/Cake) [![Azure Artifacts](https://azpkgsshield.azurevoodoo.net/cake-build/Cake/cake/cake)](https://dev.azure.com/cake-build/Cake/_packaging?_a=package&feed=cake&package=Cake&protocolType=NuGet) [![Chocolatey](https://img.shields.io/chocolatey/v/Cake.portable.svg)](https://chocolatey.org/packages/cake.portable) -[![homebrew](https://img.shields.io/homebrew/v/cake.svg)](http://braumeister.org/formula/cake) -[![Help Contribute to Open Source](https://www.codetriage.com/cake-build/cake/badges/users.svg)](https://www.codetriage.com/cake-build/cake) +Cake (C# Make) is a build automation system with a C# DSL to do things like compiling code, copy files/folders, running unit tests, compress files and build NuGet packages. -[![Source Browser](https://img.shields.io/badge/Browse-Source-green.svg)](http://sourcebrowser.io/Browse/cake-build/cake) +| Runner | Latest Released | Latest Develop | +|----------------|-----------------|----------------| +| Cake .NET Tool | [![NuGet](https://img.shields.io/nuget/v/Cake.Tool.svg)](https://www.nuget.org/packages/Cake.Tool) | [![Azure Artifacts](https://azpkgsshield.azurevoodoo.net/cake-build/Cake/cake/cake.tool)](https://dev.azure.com/cake-build/Cake/_packaging?_a=package&feed=cake&package=Cake.Tool&protocolType=NuGet) | +| Cake Frosting | [![NuGet](https://img.shields.io/nuget/v/Cake.Frosting.svg)](https://www.nuget.org/packages/Cake.Frosting) | [![Azure Artifacts](https://azpkgsshield.azurevoodoo.net/cake-build/Cake/cake/Cake.Frosting)](https://dev.azure.com/cake-build/Cake/_packaging?_a=package&feed=cake&package=Cake.Frosting&protocolType=NuGet) | -Cake (C# Make) is a build automation system with a C# DSL to do things like compiling code, copy files/folders, running unit tests, compress files and build NuGet packages. ## Continuous integration @@ -19,7 +19,6 @@ Cake (C# Make) is a build automation system with a C# DSL to do things like comp | Azure Pipelines | Centos | [![Azure Pipelines Cake Centos status](https://dev.azure.com/cake-build/Cake/_apis/build/status/Azure%20Pipelines%20-%20Build%20Cake%20Centos%207?&branchName=develop)](https://dev.azure.com/cake-build/Cake/_build/latest?definitionId=5) | | | Azure Pipelines | Ubuntu | [![Azure Pipelines Ubuntu Build status](https://dev.azure.com/cake-build/Cake/_apis/build/status/Azure%20Pipelines%20-%20Build%20Cake%20Ubuntu?&branchName=develop)](https://dev.azure.com/cake-build/Cake/_build/latest?definitionId=3) | | | AppVeyor | Windows | [![AppVeyor branch](https://img.shields.io/appveyor/ci/cakebuild/cake/develop.svg)](https://ci.appveyor.com/project/cakebuild/cake/branch/develop) | [![AppVeyor branch](https://img.shields.io/appveyor/ci/cakebuild/cake-eijwj/develop.svg)](https://ci.appveyor.com/project/cakebuild/cake-eijwj) | -| Travis | Ubuntu / MacOS | [![Travis build status](https://travis-ci.org/cake-build/cake.svg?branch=develop)](https://travis-ci.org/cake-build/cake) | | | TeamCity | Windows | [![TeamCity Build Status](http://img.shields.io/teamcity/codebetter/Cake_CakeMaster.svg)](http://teamcity.codebetter.com/viewType.html?buildTypeId=Cake_CakeMaster) | | | Bitrise | MacOS | [![Build Status](https://app.bitrise.io/app/42eaef77e8db4a5c/status.svg?token=EDjHGK5njNJ-MrhSbvKM1w&branch=develop)](https://app.bitrise.io/app/42eaef77e8db4a5c) | ![Build Status](https://app.bitrise.io/app/804b431c1f27e0a0/status.svg?token=qKosHEaJAJEqzZcq4s5WRg&branch=develop) | | Bitrise | Debian | [![Build Status](https://app.bitrise.io/app/ea0c6b3c61eb1e79/status.svg?token=KJqOWXllYXz3WYqcB861Uw&branch=develop)](https://app.bitrise.io/app/ea0c6b3c61eb1e79) | ![Build Status](https://app.bitrise.io/app/5a406f34f22113c6/status.svg?token=TQPbsmA9yP-iJOhzunIP4w&branch=develop) | @@ -34,86 +33,15 @@ Cake (C# Make) is a build automation system with a C# DSL to do things like comp ## Table of Contents 1. [Documentation](https://github.com/cake-build/cake#documentation) -2. [Example](https://github.com/cake-build/cake#example) - - [Install the Cake bootstrapper](https://github.com/cake-build/cake#1-install-the-cake-bootstrapper) - - [Create a Cake script](https://github.com/cake-build/cake#2-create-a-cake-script) - - [Run it!](https://github.com/cake-build/cake#3-run-it) -3. [Contributing](https://github.com/cake-build/cake#contributing) -4. [Get in touch](https://github.com/cake-build/cake#get-in-touch) -5. [License](https://github.com/cake-build/cake#license) +2. [Contributing](https://github.com/cake-build/cake#contributing) +3. [Get in touch](https://github.com/cake-build/cake#get-in-touch) +4. [License](https://github.com/cake-build/cake#license) ## Documentation You can read the latest documentation at [https://cakebuild.net/](https://cakebuild.net/). -## Example - -This example downloads the Cake bootstrapper and executes a simple build script. -The bootstrapper is used to bootstrap Cake in a simple way and is not in -required in any way to execute build scripts. If you prefer to invoke the Cake -executable yourself, [take a look at the command line usage](https://cakebuild.net/docs/cli/usage). - -This example is also available on our homepage: -[https://cakebuild.net/docs/tutorials/setting-up-a-new-project](https://cakebuild.net/docs/tutorials/setting-up-a-new-project) - -### 1. Install the Cake bootstrapper - -The bootstrapper is used to download Cake and the tools required by the -build script. - -##### Windows - -```powershell -Invoke-WebRequest https://cakebuild.net/download/bootstrapper/windows -OutFile build.ps1 -``` - -##### Linux - -```console -curl -Lsfo build.sh https://cakebuild.net/download/bootstrapper/linux -``` - -##### OS X - -```console -curl -Lsfo build.sh https://cakebuild.net/download/bootstrapper/osx -``` - -### 2. Create a Cake script - -Add a cake script called `build.cake` to the same location as the -bootstrapper script that you downloaded. - -```cake -var target = Argument("target", "Default"); - -Task("Default") - .Does(() => -{ - Information("Hello World!"); -}); - -RunTarget(target); -``` - -### 3. Run it! - -##### Windows - -```powershell -# Execute the bootstrapper script. -./build.ps1 -``` - -##### Linux / OS X - -```console -# Adjust the permissions for the bootstrapper script. -chmod +x build.sh - -# Execute the bootstrapper script. -./build.sh -``` +For a simple example to get started see [Setting up a new project](https://cakebuild.net/docs/getting-started/setting-up-a-new-project). ## Contributing @@ -131,11 +59,11 @@ Make sure you've read the [contribution guidelines](https://cakebuild.net/docs/c [![Follow @cakebuildnet](https://img.shields.io/badge/Twitter-Follow%20%40cakebuildnet-blue.svg)](https://twitter.com/intent/follow?screen_name=cakebuildnet) -[![Join the chat at https://gitter.im/cake-build/cake](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cake-build/cake?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Join the chat at https://github.com/cake-build/cake/discussions](https://img.shields.io/badge/discussions-join%20chat-brightgreen)](https://github.com/cake-build/cake/discussions?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ## License -Copyright © .NET Foundation, Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio and contributors. +Copyright © .NET Foundation, Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio, C. Augusto Proiete, Nils Andresen, and contributors. Cake is provided as-is under the MIT license. For more information see [LICENSE](https://github.com/cake-build/cake/blob/develop/LICENSE). @@ -145,7 +73,19 @@ Cake is provided as-is under the MIT license. For more information see [LICENSE] ## Thanks -A big thank you has to go to [JetBrains](https://www.jetbrains.com) who provide each of the Cake Developers with an [Open Source License](https://www.jetbrains.com/support/community/#section=open-source) for [ReSharper](https://www.jetbrains.com/resharper/) that helps with the development of Cake. +A big thank you has to go to [JetBrains](https://www.jetbrains.com) who provide each of the Cake Developers with an [Open Source License](https://www.jetbrains.com/community/opensource/#support) for [ReSharper](https://www.jetbrains.com/resharper/) that helps with the development of Cake. + +### Sponsors + +Our wonderful sponsors: + +[![Sponsors](https://opencollective.com/cake/sponsors.svg)](https://opencollective.com/cake) + +### Backers + +Our wonderful backers: + +[![Backers](https://opencollective.com/cake/backers.svg)](https://opencollective.com/cake) ## Code of Conduct diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 14857f3d3b..e894398bcf 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,464 @@ +### New in 2.0.0 (Released 2021/11/30) + +* 3714 Use Basic.Reference.Assemblies.* to ensure all standard reference assemblies are available for Roslyn. +* 3654 IsRunningOnAzurePipelines should ignore agent type. +* 3631 Refactor GitHub Actions Paths. +* 3610 Remove TFBuildProvider. +* 3590 Directories in AzurePipelinesBuildInfo are FilePaths - FilePath.GetDirectory then inconsistent. +* 3581 Stop shipping Cake.Portable Chocolatey package and Cake Homebrew formulae. +* 3579 Stop shipping Cake runner for .NET Framework and Cake runner for .NET Core. +* 3577 Remove ReverseDependencyAttribute. +* 3572 Only build for TargetFrameworks netcoreapp3.1, net5.0 and net6.0. +* 3282 GitVersion Tool: Rename verbosity values to match GitVersion values. +* 3222 Add Xamarin.iOS platform targets to MSBuildSettings PlatformTarget enumeration. +* 3151 Add support for Engine event hooks after execution as well as before. +* 3003 Remove DependencyAttribute. +* 2872 Bump eol target frameworks. +* 2788 Tool:OpenCover - the register-setting should be an option, rather than a string. +* 1111 DotNetCoreRestore: dotnet restore no longer supports globbing. +* 3630 Add GitHub Actions Environment properties. +* 3629 Add GitHub Actions UploadArtifact Command. +* 3628 Add GitHub Actions SetEnvironmentVariable Command. +* 3627 Add GitHub Actions AddPath Command. +* 3341 Epic: Introduce DotNet aliases (synonyms to DotNetCore aliases). +* 3709 Arguments alias should support ICollection as default value. +* 3691 Update Microsoft.NETCore.Platforms to 6.0.0. +* 3690 Update Microsoft.Extensions.DependencyInjection to 6.0.0. +* 3689 Update System.Reflection.Metadata to 6.0.0. +* 3688 Update System.Collections.Immutable to 6.0.0. +* 3681 ScriptAssemblyResolver logging should be at debug/diagnostic level. +* 3662 Update Microsoft.CodeAnalysis.CSharp.Scripting to 4.0.0-6.final. +* 3647 Display message of criteria when task fails to run due to criteria not being met. +* 3644 Add DotNetNuGetUpdateSource aliases (synonym to DotNetCoreNuGetUpdateSource). +* 3643 Add DotNetNuGetRemoveSource aliases (synonym to DotNetCoreNuGetRemoveSource). +* 3642 Add DotNetNuGetListSourceSettings (derived from to DotNetNuGetSource). +* 3641 Add DotNetNuGetHasSource aliases (synonym to DotNetCoreNuGetHasSource). +* 3640 Add DotNetNuGetEnableSource aliases (synonym to DotNetCoreNuGetEnableSource). +* 3639 Add DotNetNuGetDisableSource aliases (synonym to DotNetCoreNuGetDisableSource). +* 3607 Add EnableCompressionInSingleFile to DotNetCorePublishSettings. +* 3599 Add VS2022 to default MSBuild Resolver. +* 3598 Remove Preview from VS2022 MSBuild Resolver. +* 3595 Update Autofac to 6.3.0. +* 3593 Update Microsoft.CodeAnalysis.CSharp.Scripting to 4.0.0-5.final. +* 3591 Update Microsoft.NETCore.Platforms to 6.0.0-rc.2.21480.5. +* 3555 Add DotNetNuGetAddSource aliases (synonym to DotNetCoreNuGetAddSource). +* 3554 Add DotNetNuGetDelete aliases (synonym to DotNetCoreNuGetDelete). +* 3553 Add DotNetNuGetPush aliases (synonym to DotNetCoreNuGetPush). +* 3552 Add DotNetPack alias (synonym to DotNetCorePack). +* 3551 Add DotNetPublish alias (synonym to DotNetCorePublish). +* 3550 Add DotNetVSTest alias (synonym to DotNetCoreVSTest). +* 3549 Add DotNetTest alias (synonym to DotNetCoreTest). +* 3548 Add DotNetBuildServer alias (synonym to DotNetCoreBuildServer). +* 3547 Add DotNetBuild alias (synonym to DotNetCoreBuild). +* 3546 Add DotNetRestore alias (synonym to DotNetCoreRestore). +* 3545 Add DotNetClean alias (synonym to DotNetCoreClean). +* 3544 Add DotNetExecute alias (synonym to DotNetCoreExecute). +* 3543 Add DotNetRun alias (synonym to DotNetCoreRun). +* 3542 Add DotNetTool alias (synonym to DotNetCoreTool). +* 3523 Add DotNetMSBuild alias (synonym to DotNetCoreMSBuild). +* 3215 Add RunCommand with postAction parameter to DotNetCoreTool. +* 3075 Make FilePath and DirectoryPath comparable by value. +* 2571 OctopusDeploy DeployTo property to take collection of string to specify multiple environments. +* 2075 Add overloads for DotNetCore*() methods taking FilePath instead of string. +* 1794 Private is missing from ProjectReference. +* 1616 Error message on circular references leads to poor developer experience. +* 3701 Add cake-module tag to Cake.DotNetTool.Module NuGet package. +* 3602 Switch to Cake.Tool as primary package in REAME.md. +* 3711 SemanticVersion missing equals/not equals operator, prerelease sorted wrong. +* 3697 Error: The requested service 'Cake.Commands.DefaultCommandSettings' has not been registered. +* 3693 Core suffix is still used in some settings classes. +* 3683 Use DotNetMSBuildSettings instead of DotNetCoreMSBuildSettings on new dotnet aliases settings. +* 3671 VS2022: msbuild can not be located, only Build Tools are installed. +* 2665 C* 8 Using Statement produces compile error. +* 2443 Erroneous "Target path must be an absolute path" when preserveFolderStructure is used with CopyFiles. +* 1669 Release notes does not tolerate prerelease versions. + +### New in 2.0.0-rc0002 (Released 2021/11/26) + +* 3714 Use Basic.Reference.Assemblies.* to ensure all standard reference assemblies are available for Roslyn +* 3654 IsRunningOnAzurePipelines should ignore agent type +* 3631 Refactor GitHub Actions Paths +* 3610 Remove TFBuildProvider +* 3590 Directories in AzurePipelinesBuildInfo are FilePaths - FilePath.GetDirectory then inconsistent +* 3581 Stop shipping Cake.Portable Chocolatey package and Cake Homebrew formulae +* 3579 Stop shipping Cake runner for .NET Framework and Cake runner for .NET Core +* 3577 Remove ReverseDependencyAttribute +* 3572 Only build for TargetFrameworks netcoreapp3.1, net5.0 and net6.0 +* 3282 GitVersion Tool: Rename verbosity values to match GitVersion values +* 3222 Add Xamarin.iOS platform targets to MSBuildSettings PlatformTarget enumeration +* 3151 Add support for Engine event hooks after execution as well as before +* 3003 Remove DependencyAttribute +* 2872 Bump eol target frameworks +* 2788 Tool:OpenCover - the register-setting should be an option, rather than a string +* 1111 DotNetCoreRestore: dotnet restore no longer supports globbing +* 3630 Add GitHub Actions Environment properties +* 3629 Add GitHub Actions UploadArtifact Command +* 3628 Add GitHub Actions SetEnvironmentVariable Command +* 3627 Add GitHub Actions AddPath Command +* 3341 Epic: Introduce DotNet aliases (synonyms to DotNetCore aliases) +* 3711 SemanticVersion missing equals/not equals operator, prerelease sorted wrong +* 3697 Error: The requested service 'Cake.Commands.DefaultCommandSettings' has not been registered +* 3693 `Core` suffix is still used in some settings classes +* 3683 Use DotNetMSBuildSettings instead of DotNetCoreMSBuildSettings on new dotnet aliases settings +* 3671 VS2022: msbuild can not be located, only Build Tools are installed +* 2443 Erroneous "Target path must be an absolute path" when preserveFolderStructure is used with CopyFiles +* 1669 Release notes does not tolerate prerelease versions +* 3709 Arguments alias should support ICollection as default value +* 3691 Update Microsoft.NETCore.Platforms to 6.0.0 +* 3690 Update Microsoft.Extensions.DependencyInjection to 6.0.0 +* 3689 Update System.Reflection.Metadata to 6.0.0 +* 3688 Update System.Collections.Immutable to 6.0.0 +* 3681 `ScriptAssemblyResolver` logging should be at debug/diagnostic level +* 3662 Update Microsoft.CodeAnalysis.CSharp.Scripting to 4.0.0-6.final +* 3647 Display message of criteria when task fails to run due to criteria not being met +* 3644 Add DotNetNuGetUpdateSource aliases (synonym to DotNetCoreNuGetUpdateSource) +* 3643 Add DotNetNuGetRemoveSource aliases (synonym to DotNetCoreNuGetRemoveSource) +* 3642 Add DotNetNuGetListSourceSettings (derived from to DotNetNuGetSource) +* 3641 Add DotNetNuGetHasSource aliases (synonym to DotNetCoreNuGetHasSource) +* 3640 Add DotNetNuGetEnableSource aliases (synonym to DotNetCoreNuGetEnableSource) +* 3639 Add DotNetNuGetDisableSource aliases (synonym to DotNetCoreNuGetDisableSource) +* 3607 Add `EnableCompressionInSingleFile` to `DotNetCorePublishSettings` +* 3599 Add VS2022 to default MSBuild Resolver +* 3598 Remove Preview from VS2022 MSBuild Resolver +* 3595 Update Autofac to 6.3.0 +* 3593 Update Microsoft.CodeAnalysis.CSharp.Scripting to 4.0.0-5.final +* 3591 Update Microsoft.NETCore.Platforms to 6.0.0-rc.2.21480.5 +* 3555 Add DotNetNuGetAddSource aliases (synonym to DotNetCoreNuGetAddSource) +* 3554 Add DotNetNuGetDelete aliases (synonym to DotNetCoreNuGetDelete) +* 3553 Add DotNetNuGetPush aliases (synonym to DotNetCoreNuGetPush) +* 3552 Add DotNetPack alias (synonym to DotNetCorePack) +* 3551 Add DotNetPublish alias (synonym to DotNetCorePublish) +* 3550 Add DotNetVSTest alias (synonym to DotNetCoreVSTest) +* 3549 Add DotNetTest alias (synonym to DotNetCoreTest) +* 3548 Add DotNetBuildServer alias (synonym to DotNetCoreBuildServer) +* 3547 Add DotNetBuild alias (synonym to DotNetCoreBuild) +* 3546 Add DotNetRestore alias (synonym to DotNetCoreRestore) +* 3545 Add DotNetClean alias (synonym to DotNetCoreClean) +* 3544 Add DotNetExecute alias (synonym to DotNetCoreExecute) +* 3543 Add DotNetRun alias (synonym to DotNetCoreRun) +* 3542 Add DotNetTool alias (synonym to DotNetCoreTool) +* 3523 Add DotNetMSBuild alias (synonym to DotNetCoreMSBuild) +* 3215 Add RunCommand with postAction parameter to DotNetCoreTool +* 3075 Make FilePath and DirectoryPath comparable by value +* 2571 OctopusDeploy DeployTo property to take collection of string to specify multiple environments +* 2075 Add overloads for DotNetCore*() methods taking FilePath instead of string +* 1794 Private is missing from ProjectReference +* 1616 Error message on circular references leads to poor developer experience +* 3701 Add cake-module tag to Cake.DotNetTool.Module NuGet package +* 3602 Switch to Cake.Tool as primary package in REAME.md + +### New in 2.0.0-rc0001 (Released 2021/11/07) + +* 3654 IsRunningOnAzurePipelines should ignore agent type +* 3631 Refactor GitHub Actions Paths +* 3610 Remove TFBuildProvider +* 3590 Directories in AzurePipelinesBuildInfo are FilePaths - FilePath.GetDirectory then inconsistent +* 3581 Stop shipping Cake.Portable Chocolatey package and Cake Homebrew formulae +* 3579 Stop shipping Cake runner for .NET Framework and Cake runner for .NET Core +* 3577 Remove ReverseDependencyAttribute +* 3572 Only build for TargetFrameworks netcoreapp3.1, net5.0 and net6.0 +* 3282 GitVersion Tool: Rename verbosity values to match GitVersion values +* 3222 Add Xamarin.iOS platform targets to MSBuildSettings PlatformTarget enumeration +* 3151 Add support for Engine event hooks after execution as well as before +* 3003 Remove DependencyAttribute +* 2872 Bump eol target frameworks +* 2788 Tool:OpenCover - the register-setting should be an option, rather than a string +* 1111 DotNetCoreRestore: dotnet restore no longer supports globbing +* 3341 Introduce DotNet aliases (synonyms to DotNetCore aliases +* 3627 Add GitHub Actions AddPath Command +* 3628 Add GitHub Actions SetEnvironmentVariable Command +* 3629 Add GitHub Actions UploadArtifact Command +* 3630 Add GitHub Actions Environment properties +* 3662 Update Microsoft.CodeAnalysis.CSharp.Scripting to 4.0.0-6.final +* 3647 Display message of criteria when task fails to run due to criteria not being met +* 3644 Add DotNetNuGetUpdateSource aliases (synonym to DotNetCoreNuGetUpdateSource) +* 3643 Add DotNetNuGetRemoveSource aliases (synonym to DotNetCoreNuGetRemoveSource) +* 3642 Add DotNetNuGetListSourceSettings (derived from to DotNetNuGetSource) +* 3641 Add DotNetNuGetHasSource aliases (synonym to DotNetCoreNuGetHasSource) +* 3640 Add DotNetNuGetEnableSource aliases (synonym to DotNetCoreNuGetEnableSource) +* 3639 Add DotNetNuGetDisableSource aliases (synonym to DotNetCoreNuGetDisableSource) +* 3607 Add EnableCompressionInSingleFile to DotNetCorePublishSettings +* 3599 Add VS2022 to default MSBuild Resolver +* 3598 Remove Preview from VS2022 MSBuild Resolver +* 3595 Update Autofac to 6.3.0 +* 3593 Update Microsoft.CodeAnalysis.CSharp.Scripting to 4.0.0-5.final +* 3591 Update Microsoft.NETCore.Platforms to 6.0.0-rc.2.21480.5 +* 3555 Add DotNetNuGetAddSource aliases (synonym to DotNetCoreNuGetAddSource) +* 3554 Add DotNetNuGetDelete aliases (synonym to DotNetCoreNuGetDelete) +* 3553 Add DotNetNuGetPush aliases (synonym to DotNetCoreNuGetPush) +* 3552 Add DotNetPack alias (synonym to DotNetCorePack) +* 3551 Add DotNetPublish alias (synonym to DotNetCorePublish) +* 3550 Add DotNetVSTest alias (synonym to DotNetCoreVSTest) +* 3549 Add DotNetTest alias (synonym to DotNetCoreTest) +* 3548 Add DotNetBuildServer alias (synonym to DotNetCoreBuildServer) +* 3547 Add DotNetBuild alias (synonym to DotNetCoreBuild) +* 3546 Add DotNetRestore alias (synonym to DotNetCoreRestore) +* 3545 Add DotNetClean alias (synonym to DotNetCoreClean) +* 3544 Add DotNetExecute alias (synonym to DotNetCoreExecute) +* 3543 Add DotNetRun alias (synonym to DotNetCoreRun) +* 3542 Add DotNetTool alias (synonym to DotNetCoreTool) +* 3523 Add DotNetMSBuild alias (synonym to DotNetCoreMSBuild) +* 3215 Add RunCommand with postAction parameter to DotNetCoreTool +* 3075 Make FilePath and DirectoryPath comparable by value +* 2571 OctopusDeploy DeployTo property to take collection of string to specify multiple environments +* 2075 Add overloads for DotNetCore*() methods taking FilePath instead of string +* 1794 Private is missing from ProjectReference +* 1616 Error message on circular references leads to poor developer experience +* 1669 Release notes does not tolerate prerelease versions +* 2443 Erroneous "Target path must be an absolute path" when preserveFolderStructure is used with CopyFiles +* 3602 Switch to Cake.Tool as primary package in REAME.md + +### New in 1.3.0 (Released 2021/10/07) + +* 3469 Add support for .NET 6 +* 3493 .NET CLI Build Binary log filenames aren't quoted correctly +* 3477 parsing of solution files with absolute paths to projects throws exception +* 3455 NuGet Resolver native dependencies fails on latest macOS +* 3352 Cake Frosting Parent DirectoryPath Fails To Combine with Slash +* 3291 Unable to retrieve target argument with Frosting +* 2048 DotNetCoreToolSettings.WorkingDirectory is not respected when running DotNetCoreTool +* 3521 Update Microsoft.NETCore.Platforms to 6.0.0-rc.1.21451.13 +* 3519 Update Spectre.Console to 0.42.0 +* 3503 Add NuGet Sources argument to DotNetCoreTestSettings +* 3502 Add NuGet Sources argument to DotNetCoreRunSettings +* 3501 Add NuGet Sources argument to DotNetCorePackSettings +* 3464 Support MSBuild version 17 +* 3452 Missing option in InspectCodeSettings: `--build` and `--no-build` flags +* 3449 Add Version, AssemblyVersion, FileVersion, and AssemblyInformationalVersion properties to DotNetCoreMSBuildSettings +* 3447 Add ContinuousIntegrationBuild to DotNetCoreMSBuildSettings +* 3445 Highlight failed tasks on summary when Error handler is defined +* 3237 Allow setting MSBuildToolVersion using custom string - Part 1 +* 3065 Add DOTNET_ROLL_FORWARD setting to DotNetCoreSettings +* 2165 DotNetCore Build misses Sources settings +* 2104 Make possibility to set Process Exit Code +* 1882 DeleteDirectory throws exception if directory doesn't exist +* 3515 Add a simple README to the packages to be shown on NuGet.org +* 3466 Fix two typos in GitReleaseManagerAliases documentation + +### New in 1.2.0 (Released 2021/08/29) + +* 2690 Consider adding some kind of "GetArguments()" alias, similar to the EnvironmentVariables() one. +* 2578 Feature request: nuget version ranges support. +* 2362 Add Support for New snupkg Symbol Packages. +* 3429 Microsoft.Extensions.DependencyInjection to 5.0.2. +* 3427 Update Microsoft.CodeAnalysis.CSharp.Scripting to 3.11.0. +* 3425 Update NuGet Client libraries to 5.11.0. +* 3423 Update Spectre.Console to 0.41.0. +* 3337 Suppress compilation warnings CS1701, CS1702, and CS1705. +* 3316 Bump NuGet client libraries to 5.9.1. +* 3314 Bump .NET SDK to 5.0.202. +* 3294 Clean up task builder extensions. +* 3281 GitVersion Tool: Remap existing verbosity values to valid GitVersion values. +* 3255 Update NuGet client libraries to 5.9.0. +* 3253 Update Microsoft.CodeAnalysis.CSharp.Scripting to 3.9.0 stable. +* 3246 Update Spectre.Console to 0.38.0. +* 3223 Feature request: Environment variable substitution in cake.config. +* 2654 NUnit3Settings should support TestParam. +* 2168 TypeConverter to enable Argument(...). +* 2030 NuGetHasSource is case sensitive. +* 3365 Typo in documentation of NuGetAdd alias. +* 3355 VSTest alias documentation contains holdover from (context => new AssemblyInfoSettings { Description = parameters.Version.SemVersion }); } - if(!parameters.IsRunningOnWindows) - { - var frameworkPathOverride = context.Environment.Runtime.IsCoreClr - ? new []{ - new DirectoryPath("/Library/Frameworks/Mono.framework/Versions/Current/lib/mono"), - new DirectoryPath("/usr/lib/mono"), - new DirectoryPath("/usr/local/lib/mono") - } - .Select(directory =>directory.Combine("4.5")) - .FirstOrDefault(directory => context.DirectoryExists(directory)) - ?.FullPath + "/" - : new FilePath(typeof(object).Assembly.Location).GetDirectory().FullPath + "/"; - - // Use FrameworkPathOverride when not running on Windows. - Information("Build will use FrameworkPathOverride={0} since not building on Windows.", frameworkPathOverride); - parameters.MSBuildSettings.WithProperty("FrameworkPathOverride", frameworkPathOverride); - } - return parameters; }); @@ -76,25 +48,25 @@ Teardown((context, parameters) => { if(parameters.ShouldPublish) { + var message = $"Version {parameters.Version.SemVersion} of Cake has just been released, https://www.nuget.org/packages/Cake.Tool/{parameters.Version.SemVersion} 🎉"; + if(parameters.CanPostToTwitter) { - var message = "Version " + parameters.Version.SemVersion + " of Cake has just been released, https://www.nuget.org/packages/Cake."; - TwitterSendTweet(parameters.Twitter.ConsumerKey, parameters.Twitter.ConsumerSecret, parameters.Twitter.AccessToken, parameters.Twitter.AccessTokenSecret, message); } if(parameters.CanPostToGitter) { - var message = "@/all Version " + parameters.Version.SemVersion + " of the Cake has just been released, https://www.nuget.org/packages/Cake."; + var gitterMessage = $"@/all {message}"; var postMessageResult = Gitter.Chat.PostMessage( - message: message, + message: gitterMessage, messageSettings: new GitterChatMessageSettings { Token = parameters.Gitter.Token, RoomId = parameters.Gitter.RoomId} ); if (postMessageResult.Ok) { - Information("Message {0} succcessfully sent", postMessageResult.TimeStamp); + Information("Message {0} successfully sent", postMessageResult.TimeStamp); } else { @@ -123,9 +95,9 @@ Task("Restore-NuGet-Packages") .IsDependentOn("Clean") .Does((context, parameters) => { - DotNetCoreRestore("./src/Cake.sln", new DotNetCoreRestoreSettings + DotNetRestore("./src/Cake.sln", new DotNetRestoreSettings { - Verbosity = DotNetCoreVerbosity.Minimal, + Verbosity = DotNetVerbosity.Minimal, Sources = new [] { "https://api.nuget.org/v3/index.json" }, MSBuildSettings = parameters.MSBuildSettings }); @@ -137,7 +109,7 @@ Task("Build") { // Build the solution. var path = MakeAbsolute(new DirectoryPath("./src/Cake.sln")); - DotNetCoreBuild(path.FullPath, new DotNetCoreBuildSettings() + DotNetBuild(path.FullPath, new DotNetBuildSettings { Configuration = parameters.Configuration, NoRestore = true, @@ -151,12 +123,12 @@ Task("Run-Unit-Tests") () => GetFiles("./src/**/*.Tests.csproj"), (parameters, project, context) => { - foreach(var framework in new[] { "netcoreapp2.0", "netcoreapp3.0", "net461" }) + foreach(var framework in new[] { "netcoreapp3.1", "net5.0", "net6.0" }) { FilePath testResultsPath = MakeAbsolute(parameters.Paths.Directories.TestResults .CombineWithFilePath($"{project.GetFilenameWithoutExtension()}_{framework}_TestResults.xml")); - DotNetCoreTest(project.FullPath, new DotNetCoreTestSettings + DotNetTest(project.FullPath, new DotNetTestSettings { Framework = framework, NoBuild = true, @@ -167,146 +139,21 @@ Task("Run-Unit-Tests") } }); -Task("Copy-Files") - .IsDependentOn("Run-Unit-Tests") - .Does((context, parameters) => -{ - // .NET 4.6 - DotNetCorePublish("./src/Cake/Cake.csproj", new DotNetCorePublishSettings - { - Framework = "net461", - NoRestore = true, - VersionSuffix = parameters.Version.DotNetAsterix, - Configuration = parameters.Configuration, - OutputDirectory = parameters.Paths.Directories.ArtifactsBinFullFx, - MSBuildSettings = parameters.MSBuildSettings - }); - - // .NET Core - DotNetCorePublish("./src/Cake/Cake.csproj", new DotNetCorePublishSettings - { - Framework = "netcoreapp2.0", - NoRestore = true, - Configuration = parameters.Configuration, - OutputDirectory = parameters.Paths.Directories.ArtifactsBinNetCore, - MSBuildSettings = parameters.MSBuildSettings - }); - - // Copy license - CopyFileToDirectory("./LICENSE", parameters.Paths.Directories.ArtifactsBinFullFx); - CopyFileToDirectory("./LICENSE", parameters.Paths.Directories.ArtifactsBinNetCore); - - // Copy icon - CopyFileToDirectory("./nuspec/cake-medium.png", parameters.Paths.Directories.ArtifactsBinFullFx); - CopyFileToDirectory("./nuspec/cake-medium.png", parameters.Paths.Directories.ArtifactsBinNetCore); - - // Copy Cake.XML (since publish does not do this anymore) - CopyFileToDirectory("./src/Cake/bin/" + parameters.Configuration + "/net461/Cake.xml", parameters.Paths.Directories.ArtifactsBinFullFx); - CopyFileToDirectory("./src/Cake/bin/" + parameters.Configuration + "/netcoreapp2.0/Cake.xml", parameters.Paths.Directories.ArtifactsBinNetCore); -}); - -Task("Validate-Version") - .IsDependentOn("Copy-Files") - .Does((context, parameters) => -{ - var fullFxExe = MakeAbsolute(parameters.Paths.Directories.ArtifactsBinFullFx.CombineWithFilePath("Cake.exe")); - var coreFxExe = MakeAbsolute(parameters.Paths.Directories.ArtifactsBinNetCore.CombineWithFilePath("Cake.dll")); - - IEnumerable fullFxOutput; - var fullFxResult = StartProcess( - fullFxExe, - new ProcessSettings { - Arguments = "--version", - RedirectStandardOutput = true, - WorkingDirectory = parameters.Paths.Directories.ArtifactsBinFullFx - }, - out fullFxOutput - ); - var fullFxVersion = string.Concat(fullFxOutput); - - IEnumerable coreFxOutput; - var coreFxResult = StartProcess( - "dotnet", - new ProcessSettings { - Arguments = $"\"{coreFxExe}\" --version", - RedirectStandardOutput = true, - WorkingDirectory = parameters.Paths.Directories.ArtifactsBinNetCore - }, - out coreFxOutput - ); - var coreFxVersion = string.Concat(coreFxOutput); - - Information("{0}, ExitCode: {1}, Version: {2}", - fullFxExe, - fullFxResult, - string.Concat(fullFxVersion) - ); - - Information("{0}, ExitCode: {1}, Version: {2}", - coreFxExe, - coreFxResult, - string.Concat(coreFxVersion) - ); - - if (parameters.Version.SemVersion != fullFxVersion || parameters.Version.SemVersion != coreFxVersion) - { - throw new Exception( - $"Invalid version, expected \"{parameters.Version.SemVersion}\", got .NET \"{fullFxVersion}\" and .NET Core \"{coreFxVersion}\""); - } -}); - -Task("Zip-Files") - .IsDependentOn("Validate-Version") - .Does((context, parameters) => -{ - // .NET 4.6 - var homebrewFiles = GetFiles( parameters.Paths.Directories.ArtifactsBinFullFx.FullPath + "/**/*"); - Zip(parameters.Paths.Directories.ArtifactsBinFullFx, parameters.Paths.Files.ZipArtifactPathDesktop, homebrewFiles); - - // .NET Core - var coreclrFiles = GetFiles( parameters.Paths.Directories.ArtifactsBinNetCore.FullPath + "/**/*"); - Zip(parameters.Paths.Directories.ArtifactsBinNetCore, parameters.Paths.Files.ZipArtifactPathCoreClr, coreclrFiles); -}); - -Task("Create-Chocolatey-Packages") - .IsDependentOn("Validate-Version") - .IsDependentOn("Package") - .WithCriteria((context, parameters) => parameters.IsRunningOnWindows) - .Does((context, parameters) => -{ - foreach(var package in parameters.Packages.Chocolatey) - { - var netFxFullArtifactPath = MakeAbsolute(parameters.Paths.Directories.ArtifactsBinFullFx).FullPath; - var curDirLength = MakeAbsolute(Directory("./")).FullPath.Length + 1; - - // Create package. - ChocolateyPack(package.NuspecPath, new ChocolateyPackSettings { - Version = parameters.Version.SemVersion, - ReleaseNotes = parameters.ReleaseNotes.Notes.ToArray(), - OutputDirectory = parameters.Paths.Directories.NuGetRoot, - Files = (GetFiles(netFxFullArtifactPath + "/*.*") + GetFiles("./nuspec/*.txt") + GetFiles("./LICENSE")) - .Select(file=>"../" + file.FullPath.Substring(curDirLength)) - .Select(file=> new ChocolateyNuSpecContent { Source = file }) - .ToArray() - }); - } -}); - Task("Create-NuGet-Packages") - .IsDependentOn("Validate-Version") + .IsDependentOn("Run-Unit-Tests") .Does((context, parameters) => { // Build libraries - var projects = GetFiles("./src/**/*.csproj"); + var projects = GetFiles("./src/*/*.csproj"); foreach(var project in projects) { var name = project.GetDirectory().FullPath; - if(name.EndsWith("Cake") || name.EndsWith("Tests")) + if(name.EndsWith("Tests") || name.EndsWith("Example")) { continue; } - DotNetCorePack(project.FullPath, new DotNetCorePackSettings { + DotNetPack(project.FullPath, new DotNetPackSettings { Configuration = parameters.Configuration, OutputDirectory = parameters.Paths.Directories.NuGetRoot, NoBuild = true, @@ -314,50 +161,9 @@ Task("Create-NuGet-Packages") MSBuildSettings = parameters.MSBuildSettings }); } - - var netFxFullArtifactPath = MakeAbsolute(parameters.Paths.Directories.ArtifactsBinFullFx).FullPath; - var netFxFullArtifactPathLength = netFxFullArtifactPath.Length+1; - - // Cake - .NET 4.6.1 - NuGetPack("./nuspec/Cake.nuspec", new NuGetPackSettings { - Version = parameters.Version.SemVersion, - ReleaseNotes = parameters.ReleaseNotes.Notes.ToArray(), - BasePath = netFxFullArtifactPath, - OutputDirectory = parameters.Paths.Directories.NuGetRoot, - NoPackageAnalysis = true, - Files = GetFiles(netFxFullArtifactPath + "/*") - .Select(file=>file.FullPath.Substring(netFxFullArtifactPathLength)) - .Select(file=> new NuSpecContent { Source = file, Target = file }) - .ToArray() - }); - - var netCoreFullArtifactPath = MakeAbsolute(parameters.Paths.Directories.ArtifactsBinNetCore).FullPath; - var netCoreFullArtifactPathLength = netCoreFullArtifactPath.Length+1; - - // Cake - .NET Core - NuGetPack("./nuspec/Cake.CoreCLR.nuspec", new NuGetPackSettings { - Version = parameters.Version.SemVersion, - ReleaseNotes = parameters.ReleaseNotes.Notes.ToArray(), - BasePath = netCoreFullArtifactPath, - OutputDirectory = parameters.Paths.Directories.NuGetRoot, - NoPackageAnalysis = true, - Files = GetFiles(netCoreFullArtifactPath + "/**/*") - .Select(file=>file.FullPath.Substring(netCoreFullArtifactPathLength)) - .Select(file=> new NuSpecContent { Source = file, Target = file }) - .ToArray() - }); - - DotNetCorePack("./src/Cake/Cake.csproj", new DotNetCorePackSettings { - Configuration = parameters.Configuration, - OutputDirectory = parameters.Paths.Directories.NuGetRoot, - MSBuildSettings = parameters.MSBuildSettings, - ArgumentCustomization = arg => arg.Append("/p:PackAsTool=true") - }); }); Task("Sign-Binaries") - .IsDependentOn("Zip-Files") - .IsDependentOn("Create-Chocolatey-Packages") .IsDependentOn("Create-NuGet-Packages") .WithCriteria((context, parameters) => (parameters.ShouldPublish && !parameters.SkipSigning) || @@ -379,9 +185,7 @@ Task("Sign-Binaries") var filter = File("./signclient.filter"); // Get the files to sign. - var files = GetFiles(string.Concat(parameters.Paths.Directories.NuGetRoot, "/", "*.nupkg")) - + parameters.Paths.Files.ZipArtifactPathDesktop - + parameters.Paths.Files.ZipArtifactPathCoreClr; + var files = GetFiles(string.Concat(parameters.Paths.Directories.NuGetRoot, "/", "*.nupkg")); foreach(var file in files) { @@ -411,32 +215,15 @@ Task("Sign-Binaries") Task("Upload-AppVeyor-Artifacts") .IsDependentOn("Sign-Binaries") - .IsDependentOn("Create-Chocolatey-Packages") .WithCriteria((context, parameters) => parameters.IsRunningOnAppVeyor) .Does((context, parameters) => { - AppVeyor.UploadArtifact(parameters.Paths.Files.ZipArtifactPathDesktop); - AppVeyor.UploadArtifact(parameters.Paths.Files.ZipArtifactPathCoreClr); foreach(var package in GetFiles(parameters.Paths.Directories.NuGetRoot + "/*")) { AppVeyor.UploadArtifact(package); } }); -Task("Upload-Coverage-Report") - .WithCriteria((context, parameters) => FileExists(parameters.Paths.Files.TestCoverageOutputFilePath)) - .WithCriteria((context, parameters) => !parameters.IsLocalBuild) - .WithCriteria((context, parameters) => !parameters.IsPullRequest) - .WithCriteria((context, parameters) => parameters.IsMainCakeRepo) - .IsDependentOn("Run-Unit-Tests") - .Does((context, parameters) => -{ - CoverallsIo(parameters.Paths.Files.TestCoverageOutputFilePath, new CoverallsIoSettings() - { - RepoToken = parameters.Coveralls.RepoToken - }); -}); - Task("Publish-MyGet") .IsDependentOn("Sign-Binaries") .IsDependentOn("Package") @@ -455,13 +242,15 @@ Task("Publish-MyGet") throw new InvalidOperationException("Could not resolve MyGet API url."); } - foreach(var package in parameters.Packages.All) + foreach(var package in parameters.Packages.NuGet) { // Push the package. - NuGetPush(package.PackagePath, new NuGetPushSettings { - Source = apiUrl, - ApiKey = apiKey - }); + var settings = new DotNetNuGetPushSettings { + ApiKey = apiKey, + Source = apiUrl + }; + + DotNetNuGetPush(package.PackagePath.FullPath, settings); } }) .OnError((exception, parameters) => @@ -491,10 +280,12 @@ Task("Publish-NuGet") foreach(var package in parameters.Packages.NuGet) { // Push the package. - NuGetPush(package.PackagePath, new NuGetPushSettings { - ApiKey = apiKey, - Source = apiUrl - }); + var settings = new DotNetNuGetPushSettings { + ApiKey = apiKey, + Source = apiUrl + }; + + DotNetNuGetPush(package.PackagePath.FullPath, settings); } }) .OnError((exception, parameters) => @@ -503,60 +294,15 @@ Task("Publish-NuGet") parameters.PublishingError = true; }); -Task("Publish-Chocolatey") - .IsDependentOn("Sign-Binaries") - .IsDependentOn("Create-Chocolatey-Packages") +Task("Publish-GitHub-Release") .WithCriteria((context, parameters) => parameters.ShouldPublish) .Does((context, parameters) => { - // Resolve the API key. - var apiKey = EnvironmentVariable("CHOCOLATEY_API_KEY"); - if(string.IsNullOrEmpty(apiKey)) { - throw new InvalidOperationException("Could not resolve Chocolatey API key."); - } - - // Resolve the API url. - var apiUrl = EnvironmentVariable("CHOCOLATEY_API_URL"); - if(string.IsNullOrEmpty(apiUrl)) { - throw new InvalidOperationException("Could not resolve Chocolatey API url."); - } - - foreach(var package in parameters.Packages.Chocolatey) + foreach(var package in GetFiles(parameters.Paths.Directories.NuGetRoot + "/*")) { - // Push the package. - ChocolateyPush(package.PackagePath, new ChocolateyPushSettings { - ApiKey = apiKey, - Source = apiUrl - }); + GitReleaseManagerAddAssets(parameters.GitHub.Token, "cake-build", "cake", parameters.Version.Milestone, package.FullPath); } -}) -.OnError((exception, parameters) => -{ - Information("Publish-Chocolatey Task failed, but continuing with next Task..."); - parameters.PublishingError = true; -}); - -Task("Publish-HomeBrew") - .IsDependentOn("Sign-Binaries") - .IsDependentOn("Zip-Files") - .WithCriteria((context, parameters) => parameters.ShouldPublish) - .Does((context, parameters) => -{ - var hash = CalculateFileHash(parameters.Paths.Files.ZipArtifactPathDesktop).ToHex(); - Information("Hash for creating HomeBrew PullRequest: {0}", hash); -}) -.OnError((exception, parameters) => -{ - Information("Publish-HomeBrew Task failed, but continuing with next Task..."); - parameters.PublishingError = true; -}); -Task("Publish-GitHub-Release") - .WithCriteria((context, parameters) => parameters.ShouldPublish) - .Does((context, parameters) => -{ - GitReleaseManagerAddAssets(parameters.GitHub.Token, "cake-build", "cake", parameters.Version.Milestone, parameters.Paths.Files.ZipArtifactPathDesktop.ToString()); - GitReleaseManagerAddAssets(parameters.GitHub.Token, "cake-build", "cake", parameters.Version.Milestone, parameters.Paths.Files.ZipArtifactPathCoreClr.ToString()); GitReleaseManagerClose(parameters.GitHub.Token, "cake-build", "cake", parameters.Version.Milestone); }) .OnError((exception, parameters) => @@ -582,38 +328,106 @@ Task("Prepare-Integration-Tests") { Unzip(parameters.Paths.Directories.NuGetRoot.CombineWithFilePath($"Cake.Tool.{parameters.Version.SemVersion}.nupkg"), parameters.Paths.Directories.IntegrationTestsBinTool); - - CopyDirectory(parameters.Paths.Directories.ArtifactsBinFullFx, parameters.Paths.Directories.IntegrationTestsBinFullFx); - CopyDirectory(parameters.Paths.Directories.ArtifactsBinNetCore, parameters.Paths.Directories.IntegrationTestsBinNetCore); }); +Task("Frosting-Integration-Tests") + .DeferOnError() + .DoesForEach( + (parameters, context) => { + var project = context.MakeAbsolute( + new FilePath("tests/integration/Cake.Frosting/build/Build.csproj") + ); + + DotNetBuild(project.FullPath, + new DotNetBuildSettings + { + Verbosity = DotNetVerbosity.Quiet, + Configuration = parameters.Configuration, + MSBuildSettings = parameters.MSBuildSettings + }); + + context.Verbose("Peeking into {0}...", project); + + var targetFrameworks = context.XmlPeek( + project, + "/Project/PropertyGroup/TargetFrameworks" + ); + + return targetFrameworks?.Split(';') + .Select(targetFramework => (targetFramework, project)) + .ToArray(); + }, + (parameters, test, context) => +{ + try + { + Information("Testing: {0}", test.Framework); + + DotNetRun(test.Project.FullPath, + new ProcessArgumentBuilder() + .AppendSwitchQuoted("--verbosity", "=", "quiet"), + new DotNetRunSettings + { + Configuration = parameters.Configuration, + Framework = test.Framework, + NoRestore = true, + NoBuild = true + }); + } + catch(Exception ex) + { + Error("While testing: {0}\r\n{1}", test.Framework, ex); + throw new Exception($"Exception while testing: {test.Framework}", ex); + } + finally + { + Information("Done testing: {0}", test.Framework); + } +}); Task("Run-Integration-Tests") .IsDependentOn("Prepare-Integration-Tests") + .IsDependentOn("Frosting-Integration-Tests") .DeferOnError() .DoesForEach( parameters => new[] { - GetFiles($"{parameters.Paths.Directories.IntegrationTestsBinTool.FullPath}/**/netcoreapp2.1/**/Cake.dll").Single(), - GetFiles($"{parameters.Paths.Directories.IntegrationTestsBinTool.FullPath}/**/netcoreapp3.0/**/Cake.dll").Single(), - parameters.Paths.Directories.IntegrationTestsBinFullFx.CombineWithFilePath("Cake.exe"), - parameters.Paths.Directories.IntegrationTestsBinNetCore.CombineWithFilePath("Cake.dll") + GetFiles($"{parameters.Paths.Directories.IntegrationTestsBinTool.FullPath}/**/netcoreapp3.1/**/Cake.dll").Single(), + GetFiles($"{parameters.Paths.Directories.IntegrationTestsBinTool.FullPath}/**/net5.0/**/Cake.dll").Single(), + GetFiles($"{parameters.Paths.Directories.IntegrationTestsBinTool.FullPath}/**/net6.0/**/Cake.dll").Single() }, (parameters, cakeAssembly, context) => { - Information("Testing: {0}", cakeAssembly); - CakeExecuteScript("./tests/integration/build.cake", - new CakeSettings { - ToolPath = cakeAssembly, - EnvironmentVariables = { - ["MyEnvironmentVariable"] = "Hello World", - ["CAKE_INTEGRATION_TEST_ROOT"] = "../.." - }, - Arguments = { - ["target"] = Argument("integration-tests-target", "Run-All-Tests"), - ["verbosity"] = "quiet", - ["platform"] = parameters.IsRunningOnWindows ? "windows" : "posix", - ["customarg"] = "hello" - } - }); + try + { + Information("Testing: {0}", cakeAssembly); + CakeExecuteScript("./tests/integration/build.cake", + new CakeSettings { + ToolPath = cakeAssembly, + EnvironmentVariables = { + ["MyEnvironmentVariable"] = "Hello World", + ["CAKE_INTEGRATION_TEST_ROOT"] = "../.." + }, + ArgumentCustomization = args => args + .AppendSwitchQuoted("--target", " ", Argument("integration-tests-target", "Run-All-Tests")) + .AppendSwitchQuoted("--verbosity", " ", "quiet") + .AppendSwitchQuoted("--platform", " ", parameters.IsRunningOnWindows ? "windows" : "posix") + .AppendSwitchQuoted("--customarg", " ", "hello") + .AppendSwitchQuoted("--multipleargs", "=", "a") + .AppendSwitchQuoted("--multipleargs", "=", "b") + .AppendSwitchQuoted("--testAssemblyDirectoryPath", "=", cakeAssembly.GetDirectory().FullPath) + .AppendSwitchQuoted("--testAssemblyFilePath", "=", cakeAssembly.FullPath) + .AppendSwitchQuoted("--testDotNetCoreVerbosity", "=", "Diagnostic") + .AppendSwitchQuoted("--testDotNetRollForward", "=", "LatestMajor") + }); + } + catch(Exception ex) + { + Error("While testing: {0}\r\n{1}", cakeAssembly, ex); + throw new Exception($"Exception while testing: {cakeAssembly}", ex); + } + finally + { + Information("Done testing: {0}", cakeAssembly); + } }); @@ -622,7 +436,6 @@ Task("Run-Integration-Tests") ////////////////////////////////////////////////////////////////////// Task("Package") - .IsDependentOn("Zip-Files") .IsDependentOn("Create-NuGet-Packages"); Task("Default") @@ -630,11 +443,8 @@ Task("Default") Task("AppVeyor") .IsDependentOn("Upload-AppVeyor-Artifacts") - .IsDependentOn("Upload-Coverage-Report") .IsDependentOn("Publish-MyGet") .IsDependentOn("Publish-NuGet") - .IsDependentOn("Publish-Chocolatey") - .IsDependentOn("Publish-HomeBrew") .IsDependentOn("Publish-GitHub-Release") .Does((context, parameters) => { @@ -651,7 +461,7 @@ Task("ReleaseNotes") .IsDependentOn("Create-Release-Notes"); Task("AzureDevOps") - .IsDependentOn(IsRunningOnWindows() ? "Create-Chocolatey-Packages" : "Package"); + .IsDependentOn("Package"); ////////////////////////////////////////////////////////////////////// // EXECUTION diff --git a/build.config b/build.config deleted file mode 100644 index 97cc6a05f1..0000000000 --- a/build.config +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -CAKE_VERSION=0.38.4 -DOTNET_VERSION=3.1.301 diff --git a/build.ps1 b/build.ps1 index e48d09a09c..b8737c0052 100755 --- a/build.ps1 +++ b/build.ps1 @@ -1,27 +1,8 @@ #!/usr/bin/env pwsh $DotNetInstallerUri = 'https://dot.net/v1/dotnet-install.ps1'; $DotNetUnixInstallerUri = 'https://dot.net/v1/dotnet-install.sh' -$DotNetChannel = 'LTS' $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent -[string] $CakeVersion = '' -[string] $DotNetVersion= '' -foreach($line in Get-Content (Join-Path $PSScriptRoot 'build.config')) -{ - if ($line -like 'CAKE_VERSION=*') { - $CakeVersion = $line.SubString(13) - } - elseif ($line -like 'DOTNET_VERSION=*') { - $DotNetVersion =$line.SubString(15) - } -} - - -if ([string]::IsNullOrEmpty($CakeVersion) -or [string]::IsNullOrEmpty($DotNetVersion)) { - 'Failed to parse Cake / .NET Core SDK Version' - exit 1 -} - # Make sure tools folder exists $ToolPath = Join-Path $PSScriptRoot "tools" if (!(Test-Path $ToolPath)) { @@ -77,78 +58,39 @@ Function Remove-PathVariable([string]$VariableToRemove) } } -# Get .NET Core CLI path if installed. -$FoundDotNetCliVersion = $null; -if (Get-Command dotnet -ErrorAction SilentlyContinue) { - $FoundDotNetCliVersion = dotnet --version; +$InstallPath = Join-Path $PSScriptRoot ".dotnet" +$GlobalJsonPath = Join-Path $PSScriptRoot "global.json" +if (!(Test-Path $InstallPath)) { + New-Item -Path $InstallPath -ItemType Directory -Force | Out-Null; } -if($FoundDotNetCliVersion -ne $DotNetVersion) { - $InstallPath = Join-Path $PSScriptRoot ".dotnet" - if (!(Test-Path $InstallPath)) { - New-Item -Path $InstallPath -ItemType Directory -Force | Out-Null; - } +if ($IsMacOS -or $IsLinux) { + $ScriptPath = Join-Path $InstallPath 'dotnet-install.sh' + (New-Object System.Net.WebClient).DownloadFile($DotNetUnixInstallerUri, $ScriptPath); + & bash $ScriptPath --jsonfile "$GlobalJsonPath" --install-dir "$InstallPath" --no-path - if ($IsMacOS -or $IsLinux) { - $ScriptPath = Join-Path $InstallPath 'dotnet-install.sh' - (New-Object System.Net.WebClient).DownloadFile($DotNetUnixInstallerUri, $ScriptPath); - & bash $ScriptPath --version "$DotNetVersion" --install-dir "$InstallPath" --channel "$DotNetChannel" --no-path - - Remove-PathVariable "$InstallPath" - $env:PATH = "$($InstallPath):$env:PATH" - } - else { - $ScriptPath = Join-Path $InstallPath 'dotnet-install.ps1' - (New-Object System.Net.WebClient).DownloadFile($DotNetInstallerUri, $ScriptPath); - & $ScriptPath -Channel $DotNetChannel -Version $DotNetVersion -InstallDir $InstallPath; + Remove-PathVariable "$InstallPath" + $env:PATH = "$($InstallPath):$env:PATH" +} +else { + $ScriptPath = Join-Path $InstallPath 'dotnet-install.ps1' + (New-Object System.Net.WebClient).DownloadFile($DotNetInstallerUri, $ScriptPath); + & $ScriptPath -JSonFile $GlobalJsonPath -InstallDir $InstallPath; - Remove-PathVariable "$InstallPath" - $env:PATH = "$InstallPath;$env:PATH" - } - $env:DOTNET_ROOT=$InstallPath + Remove-PathVariable "$InstallPath" + $env:PATH = "$InstallPath;$env:PATH" } +$env:DOTNET_ROOT=$InstallPath ########################################################################### # INSTALL CAKE ########################################################################### -# Make sure Cake has been installed. -[string] $CakeExePath = '' -[string] $CakeInstalledVersion = Get-Command dotnet-cake -ErrorAction SilentlyContinue | % {&$_.Source --version} - -if ($CakeInstalledVersion -eq $CakeVersion) { - # Cake found locally - $CakeExePath = (Get-Command dotnet-cake).Source -} -else { - $CakePath = [System.IO.Path]::Combine($ToolPath,'.store', 'cake.tool', $CakeVersion) # Old PowerShell versions Join-Path only supports one child path - - $CakeExePath = (Get-ChildItem -Path $ToolPath -Filter "dotnet-cake*" -File| ForEach-Object FullName | Select-Object -First 1) - - - if ((!(Test-Path -Path $CakePath -PathType Container)) -or (!(Test-Path $CakeExePath -PathType Leaf))) { - - if ((![string]::IsNullOrEmpty($CakeExePath)) -and (Test-Path $CakeExePath -PathType Leaf)) - { - & dotnet tool uninstall --tool-path $ToolPath Cake.Tool - } - - & dotnet tool install --tool-path $ToolPath --version $CakeVersion Cake.Tool - if ($LASTEXITCODE -ne 0) - { - 'Failed to install cake' - exit 1 - } - $CakeExePath = (Get-ChildItem -Path $ToolPath -Filter "dotnet-cake*" -File| ForEach-Object FullName | Select-Object -First 1) - } -} +& dotnet tool restore ########################################################################### # RUN BUILD SCRIPT ########################################################################### -& "$CakeExePath" ./build.cake --bootstrap -if ($LASTEXITCODE -eq 0) -{ - & "$CakeExePath" ./build.cake $args -} +& dotnet cake ./build.cake $args + exit $LASTEXITCODE \ No newline at end of file diff --git a/build.sh b/build.sh index 06bcee8070..0759a8b4c1 100755 --- a/build.sh +++ b/build.sh @@ -1,15 +1,8 @@ #!/usr/bin/env bash # Define varibles SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) -source $SCRIPT_DIR/build.config TOOLS_DIR=$SCRIPT_DIR/tools -CAKE_EXE=$TOOLS_DIR/dotnet-cake -CAKE_PATH=$TOOLS_DIR/.store/cake.tool/$CAKE_VERSION -if [ "$CAKE_VERSION" = "" ] || [ "$DOTNET_VERSION" = "" ]; then - echo "An error occured while parsing Cake / .NET Core SDK version." - exit 1 -fi # Make sure the tools folder exist. if [ ! -d "$TOOLS_DIR" ]; then @@ -25,51 +18,22 @@ export DOTNET_CLI_TELEMETRY_OPTOUT=1 export DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0 export DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=2 -DOTNET_INSTALLED_VERSION=$(dotnet --version 2>&1) - -if [ "$DOTNET_VERSION" != "$DOTNET_INSTALLED_VERSION" ]; then - echo "Installing .NET CLI..." - if [ ! -d "$SCRIPT_DIR/.dotnet" ]; then - mkdir "$SCRIPT_DIR/.dotnet" - fi - curl -Lsfo "$SCRIPT_DIR/.dotnet/dotnet-install.sh" https://dot.net/v1/dotnet-install.sh - bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --version $DOTNET_VERSION --install-dir .dotnet --no-path - export PATH="$SCRIPT_DIR/.dotnet":$PATH - export DOTNET_ROOT="$SCRIPT_DIR/.dotnet" +if [ ! -d "$SCRIPT_DIR/.dotnet" ]; then + mkdir "$SCRIPT_DIR/.dotnet" fi +curl -Lsfo "$SCRIPT_DIR/.dotnet/dotnet-install.sh" https://dot.net/v1/dotnet-install.sh +bash "$SCRIPT_DIR/.dotnet/dotnet-install.sh" --jsonfile ./global.json --install-dir .dotnet --no-path +export PATH="$SCRIPT_DIR/.dotnet":$PATH +export DOTNET_ROOT="$SCRIPT_DIR/.dotnet" ########################################################################### # INSTALL CAKE ########################################################################### -CAKE_INSTALLED_VERSION=$(dotnet-cake --version 2>&1) - -if [ "$CAKE_VERSION" != "$CAKE_INSTALLED_VERSION" ]; then - if [ ! -f "$CAKE_EXE" ] || [ ! -d "$CAKE_PATH" ]; then - if [ -f "$CAKE_EXE" ]; then - dotnet tool uninstall --tool-path $TOOLS_DIR Cake.Tool - fi - - echo "Installing Cake $CAKE_VERSION..." - dotnet tool install --tool-path $TOOLS_DIR --version $CAKE_VERSION Cake.Tool - if [ $? -ne 0 ]; then - echo "An error occured while installing Cake." - exit 1 - fi - fi - - # Make sure that Cake has been installed. - if [ ! -f "$CAKE_EXE" ]; then - echo "Could not find Cake.exe at '$CAKE_EXE'." - exit 1 - fi -else - CAKE_EXE="dotnet-cake" -fi +dotnet tool restore ########################################################################### # RUN BUILD SCRIPT ########################################################################### -# Start Cake -(exec "$CAKE_EXE" build.cake --bootstrap) && (exec "$CAKE_EXE" build.cake "$@") \ No newline at end of file +dotnet cake "$@" \ No newline at end of file diff --git a/build/credentials.cake b/build/credentials.cake index f097c19020..3cfdb1ffe0 100644 --- a/build/credentials.cake +++ b/build/credentials.cake @@ -1,12 +1,5 @@ -public class BuildCredentials +public record BuildCredentials(string Token) { - public string Token { get; private set; } - - public BuildCredentials(string token) - { - Token = token; - } - public static BuildCredentials GetGitHubCredentials(ICakeContext context) { return new BuildCredentials( @@ -14,37 +7,13 @@ public class BuildCredentials } } -public class CoverallsCredentials +public record TwitterCredentials( + string ConsumerKey, + string ConsumerSecret, + string AccessToken, + string AccessTokenSecret +) { - public string RepoToken { get; private set; } - - public CoverallsCredentials(string repoToken) - { - RepoToken = repoToken; - } - - public static CoverallsCredentials GetCoverallsCredentials(ICakeContext context) - { - return new CoverallsCredentials( - context.EnvironmentVariable("COVERALLS_REPO_TOKEN")); - } -} - -public class TwitterCredentials -{ - public string ConsumerKey { get; private set; } - public string ConsumerSecret { get; private set; } - public string AccessToken { get; private set; } - public string AccessTokenSecret { get; private set; } - - public TwitterCredentials(string consumerKey, string consumerSecret, string accessToken, string accessTokenSecret) - { - ConsumerKey = consumerKey; - ConsumerSecret = consumerSecret; - AccessToken = accessToken; - AccessTokenSecret = accessTokenSecret; - } - public static TwitterCredentials GetTwitterCredentials(ICakeContext context) { return new TwitterCredentials( @@ -55,17 +24,8 @@ public class TwitterCredentials } } -public class GitterCredentials +public record GitterCredentials(string Token, string RoomId) { - public string Token { get; private set; } - public string RoomId { get; private set; } - - public GitterCredentials(string token, string roomId) - { - Token = token; - RoomId = roomId; - } - public static GitterCredentials GetGitterCredentials(ICakeContext context) { return new GitterCredentials( diff --git a/build/packages.cake b/build/packages.cake index 3eba2e3703..0f5e8485f3 100644 --- a/build/packages.cake +++ b/build/packages.cake @@ -1,56 +1,30 @@ -public class BuildPackages +public record BuildPackages( + ICollection NuGet +) { - public ICollection All { get; private set; } - public ICollection NuGet { get; private set; } - public ICollection Chocolatey { get; private set; } - public static BuildPackages GetPackages( DirectoryPath nugetRooPath, string semVersion, - string[] packageIds, - string[] chocolateyPackageIds) + string[] packageIds) { var toNuGetPackage = BuildPackage(nugetRooPath, semVersion); - var toChocolateyPackage = BuildPackage(nugetRooPath, semVersion, isChocolateyPackage: true); var nugetPackages = packageIds.Select(toNuGetPackage).ToArray(); - var chocolateyPackages = chocolateyPackageIds.Select(toChocolateyPackage).ToArray(); - - return new BuildPackages { - All = nugetPackages.Union(chocolateyPackages).ToArray(), - NuGet = nugetPackages, - Chocolatey = chocolateyPackages - }; + + return new BuildPackages(nugetPackages); } private static Func BuildPackage( - DirectoryPath nugetRooPath, - string semVersion, - bool isChocolateyPackage = false) + DirectoryPath nugetRooPath, + string semVersion) { return package => new BuildPackage( - id: package, - nuspecPath: string.Concat("./nuspec/", package, ".nuspec"), - packagePath: nugetRooPath.CombineWithFilePath(string.Concat(package, ".", semVersion, ".nupkg")), - isChocolateyPackage: isChocolateyPackage); + Id: package, + PackagePath: nugetRooPath.CombineWithFilePath(string.Concat(package, ".", semVersion, ".nupkg")) + ); } } -public class BuildPackage -{ - public string Id { get; private set; } - public FilePath NuspecPath { get; private set; } - public FilePath PackagePath { get; private set; } - public bool IsChocolateyPackage { get; private set; } - - public BuildPackage( - string id, - FilePath nuspecPath, - FilePath packagePath, - bool isChocolateyPackage) - { - Id = id; - NuspecPath = nuspecPath; - PackagePath = packagePath; - IsChocolateyPackage = isChocolateyPackage; - } -} \ No newline at end of file +public record BuildPackage( + string Id, + FilePath PackagePath +); \ No newline at end of file diff --git a/build/parameters.cake b/build/parameters.cake index 4393ca96b3..41add05c47 100644 --- a/build/parameters.cake +++ b/build/parameters.cake @@ -19,10 +19,8 @@ public class BuildParameters public bool IsPublishBuild { get; } public bool IsReleaseBuild { get; } public bool SkipGitVersion { get; } - public bool SkipOpenCover { get; } public bool SkipSigning { get; } public BuildCredentials GitHub { get; } - public CoverallsCredentials Coveralls { get; } public TwitterCredentials Twitter { get; } public GitterCredentials Gitter { get; } public ReleaseNotes ReleaseNotes { get; } @@ -30,7 +28,7 @@ public class BuildParameters public BuildPaths Paths { get; } public BuildPackages Packages { get; } public bool PublishingError { get; set; } - public DotNetCoreMSBuildSettings MSBuildSettings { get; } + public DotNetMSBuildSettings MSBuildSettings { get; } public bool ShouldPublish { @@ -90,7 +88,6 @@ public class BuildParameters IsDevelopCakeBranch = StringComparer.OrdinalIgnoreCase.Equals("develop", buildSystem.AppVeyor.Environment.Repository.Branch); IsTagged = IsBuildTagged(buildSystem); GitHub = BuildCredentials.GetGitHubCredentials(context); - Coveralls = CoverallsCredentials.GetCoverallsCredentials(context); Twitter = TwitterCredentials.GetTwitterCredentials(context); Gitter = GitterCredentials.GetGitterCredentials(context); ReleaseNotes = context.ParseReleaseNotes("./ReleaseNotes.md"); @@ -98,21 +95,40 @@ public class BuildParameters IsReleaseBuild = IsReleasing(context.TargetTask.Name); SkipSigning = StringComparer.OrdinalIgnoreCase.Equals("True", context.Argument("skipsigning", "False")); SkipGitVersion = StringComparer.OrdinalIgnoreCase.Equals("True", context.EnvironmentVariable("CAKE_SKIP_GITVERSION")); - SkipOpenCover = true; //StringComparer.OrdinalIgnoreCase.Equals("True", context.EnvironmentVariable("CAKE_SKIP_OPENCOVER")); Version = BuildVersion.Calculate(context, this); Paths = BuildPaths.GetPaths(context, Configuration, Version.SemVersion); Packages = BuildPackages.GetPackages( Paths.Directories.NuGetRoot, Version.SemVersion, - new [] { "Cake", "Cake.Core", "Cake.Common", "Cake.Testing", "Cake.Testing.Xunit", "Cake.CoreCLR", "Cake.NuGet", "Cake.Tool" }, - new [] { "cake.portable" }); + new [] { + "Cake.Core", + "Cake.Common", + "Cake.Testing", + "Cake.Testing.Xunit", + "Cake.NuGet", + "Cake.Tool", + "Cake.Frosting", + "Cake.Frosting.Template", + "Cake.Cli", + "Cake.DotNetTool.Module" + }); - var releaseNotes = string.Join("\n", ReleaseNotes.Notes.ToArray()).Replace("\"", "\"\""); - MSBuildSettings = new DotNetCoreMSBuildSettings() - .WithProperty("Version", Version.SemVersion) - .WithProperty("AssemblyVersion", Version.Version) - .WithProperty("FileVersion", Version.Version) - .WithProperty("PackageReleaseNotes", string.Concat("\"", releaseNotes, "\"")); + var releaseNotes = string.Join( + System.Environment.NewLine, + ReleaseNotes.Notes.ToArray() + ); + + MSBuildSettings = new DotNetMSBuildSettings { + Version = Version.SemVersion, + AssemblyVersion = Version.Version, + FileVersion = Version.Version, + PackageReleaseNotes = releaseNotes + }; + + if (!IsLocalBuild) + { + MSBuildSettings.WithProperty("TemplateVersion", Version.SemVersion); + } } private static bool IsBuildTagged(BuildSystem buildSystem) @@ -123,7 +139,7 @@ public class BuildParameters private static bool IsReleasing(string target) { - var targets = new [] { "Publish", "Publish-NuGet", "Publish-Chocolatey", "Publish-HomeBrew", "Publish-GitHub-Release" }; + var targets = new [] { "Publish", "Publish-NuGet", "Publish-GitHub-Release" }; return targets.Any(t => StringComparer.OrdinalIgnoreCase.Equals(t, target)); } diff --git a/build/paths.cake b/build/paths.cake index 00bd3c292e..bed3f9b0ec 100644 --- a/build/paths.cake +++ b/build/paths.cake @@ -1,9 +1,8 @@ -public class BuildPaths +public record BuildPaths( + BuildDirectories Directories, + FilePath SignClientPath +) { - public BuildFiles Files { get; private set; } - public BuildDirectories Directories { get; private set; } - public FilePath SignClientPath { get; private set; } - public static BuildPaths GetPaths( ICakeContext context, string configuration, @@ -24,20 +23,12 @@ public class BuildPaths } var artifactsDir = (DirectoryPath)(context.Directory("./artifacts") + context.Directory("v" + semVersion)); - var artifactsBinDir = artifactsDir.Combine("bin"); - var artifactsBinFullFx = artifactsBinDir.Combine("net461"); - var artifactsBinNetCore = artifactsBinDir.Combine("netcoreapp2.0"); var testResultsDir = artifactsDir.Combine("test-results"); var nugetRoot = artifactsDir.Combine("nuget"); - var zipArtifactPathCoreClr = artifactsDir.CombineWithFilePath("Cake-bin-coreclr-v" + semVersion + ".zip"); - var zipArtifactPathDesktop = artifactsDir.CombineWithFilePath("Cake-bin-net461-v" + semVersion + ".zip"); - var testCoverageOutputFilePath = testResultsDir.CombineWithFilePath("OpenCover.xml"); var integrationTestsBin = context.MakeAbsolute(context.Directory("./tests/integration/tools")); - var integrationTestsBinFullFx = integrationTestsBin.Combine("Cake"); - var integrationTestsBinNetCore = integrationTestsBin.Combine("Cake.CoreCLR"); var integrationTestsBinTool = integrationTestsBin.Combine("Cake.Tool"); // Directories @@ -45,94 +36,28 @@ public class BuildPaths artifactsDir, testResultsDir, nugetRoot, - artifactsBinDir, - artifactsBinFullFx, - artifactsBinNetCore, - integrationTestsBinFullFx, - integrationTestsBinNetCore, integrationTestsBinTool); - // Files - var buildFiles = new BuildFiles( - context, - zipArtifactPathCoreClr, - zipArtifactPathDesktop, - testCoverageOutputFilePath); - var signClientPath = context.Tools.Resolve("SignClient.exe") ?? context.Tools.Resolve("SignClient") ?? throw new Exception("Failed to locate sign tool"); - return new BuildPaths - { - Files = buildFiles, - Directories = buildDirectories, - SignClientPath = signClientPath - }; + return new BuildPaths( + Directories: buildDirectories, + SignClientPath: signClientPath + ); } } -public class BuildFiles -{ - public FilePath ZipArtifactPathCoreClr { get; private set; } - public FilePath ZipArtifactPathDesktop { get; private set; } - public FilePath TestCoverageOutputFilePath { get; private set; } - - public BuildFiles( - ICakeContext context, - FilePath zipArtifactPathCoreClr, - FilePath zipArtifactPathDesktop, - FilePath testCoverageOutputFilePath +public record BuildDirectories( + DirectoryPath Artifacts, + DirectoryPath TestResults, + DirectoryPath NuGetRoot, + DirectoryPath IntegrationTestsBinTool ) - { - ZipArtifactPathCoreClr = zipArtifactPathCoreClr; - ZipArtifactPathDesktop = zipArtifactPathDesktop; - TestCoverageOutputFilePath = testCoverageOutputFilePath; - } -} - -public class BuildDirectories { - public DirectoryPath Artifacts { get; } - public DirectoryPath TestResults { get; } - public DirectoryPath NuGetRoot { get; } - public DirectoryPath ArtifactsBin { get; } - public DirectoryPath ArtifactsBinFullFx { get; } - public DirectoryPath ArtifactsBinNetCore { get; } - public DirectoryPath IntegrationTestsBinFullFx { get; } - public DirectoryPath IntegrationTestsBinNetCore { get; } - public DirectoryPath IntegrationTestsBinTool { get; } - public ICollection ToClean { get; } - - public BuildDirectories( - DirectoryPath artifactsDir, - DirectoryPath testResultsDir, - DirectoryPath nugetRoot, - DirectoryPath artifactsBinDir, - DirectoryPath artifactsBinFullFx, - DirectoryPath artifactsBinNetCore, - DirectoryPath integrationTestsBinFullFx, - DirectoryPath integrationTestsBinNetCore, - DirectoryPath integrationTestsBinTool - ) - { - Artifacts = artifactsDir; - TestResults = testResultsDir; - NuGetRoot = nugetRoot; - ArtifactsBin = artifactsBinDir; - ArtifactsBinFullFx = artifactsBinFullFx; - ArtifactsBinNetCore = artifactsBinNetCore; - IntegrationTestsBinFullFx = integrationTestsBinFullFx; - IntegrationTestsBinNetCore = integrationTestsBinNetCore; - IntegrationTestsBinTool = integrationTestsBinTool; - ToClean = new[] { + public ICollection ToClean { get; } = new[] { Artifacts, TestResults, NuGetRoot, - ArtifactsBin, - ArtifactsBinFullFx, - ArtifactsBinNetCore, - IntegrationTestsBinFullFx, - IntegrationTestsBinNetCore, IntegrationTestsBinTool }; - } } \ No newline at end of file diff --git a/build/version.cake b/build/version.cake index 15d9c0877e..abfb448178 100644 --- a/build/version.cake +++ b/build/version.cake @@ -1,11 +1,11 @@ -public class BuildVersion +public record BuildVersion( + string Version, + string SemVersion, + string DotNetAsterix, + string Milestone, + string CakeVersion +) { - public string Version { get; private set; } - public string SemVersion { get; private set; } - public string DotNetAsterix { get; private set; } - public string Milestone { get; private set; } - public string CakeVersion { get; private set; } - public static BuildVersion Calculate(ICakeContext context, BuildParameters parameters) { if (context == null) @@ -22,7 +22,7 @@ public class BuildVersion // Temp Workaround GitVersion Azure Pipelines var azurePipelines = context.AzurePipelines(); string sourceBranch = string.Empty; - if ((azurePipelines.IsRunningOnAzurePipelinesHosted || azurePipelines.IsRunningOnAzurePipelines) && azurePipelines.Environment.PullRequest.Number > 0) + if (azurePipelines.IsRunningOnAzurePipelines && azurePipelines.Environment.PullRequest.Number > 0) { sourceBranch = $"PullRequest{azurePipelines.Environment.PullRequest.Number}"; context.Information("Overriding Azure Pipelines branch name with: {0}", sourceBranch); @@ -59,7 +59,7 @@ public class BuildVersion semVersion = assertedVersions.LegacySemVerPadded; milestone = string.Concat("v", version); - context.Information("Calculated Semantic Version: {0}", semVersion); + context.Information("Calculated Semantic Version: {0} (Version: {1}, Milestone: {2})", semVersion, version, milestone); } if (string.IsNullOrEmpty(version) || string.IsNullOrEmpty(semVersion)) @@ -68,18 +68,19 @@ public class BuildVersion version = ReadSolutionInfoVersion(context); semVersion = version; milestone = string.Concat("v", version); + + context.Information("Fetched Semantic Version: {0} (Version: {1}, Milestone: {2})", semVersion, version, milestone); } var cakeVersion = typeof(ICakeContext).Assembly.GetName().Version.ToString(); - return new BuildVersion - { - Version = version, - SemVersion = semVersion, - DotNetAsterix = semVersion.Substring(version.Length).TrimStart('-'), - Milestone = milestone, - CakeVersion = cakeVersion - }; + return new BuildVersion( + Version: version, + SemVersion: semVersion, + DotNetAsterix: semVersion.Substring(version.Length).TrimStart('-'), + Milestone: milestone, + CakeVersion: cakeVersion + ); } public static string ReadSolutionInfoVersion(ICakeContext context) diff --git a/global.json b/global.json index ccd078f926..c0d1b00472 100644 --- a/global.json +++ b/global.json @@ -3,6 +3,7 @@ "src" ], "sdk": { - "version": "3.1.301" + "version": "6.0.102", + "rollForward": "latestFeature" } } \ No newline at end of file diff --git a/nuspec/Cake.CoreCLR.nuspec b/nuspec/Cake.CoreCLR.nuspec deleted file mode 100644 index ecd807bb6c..0000000000 --- a/nuspec/Cake.CoreCLR.nuspec +++ /dev/null @@ -1,19 +0,0 @@ - - - - Cake.CoreCLR - 0.0.0 - Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio and contributors - The Cake script runner. - Cake (C# Make) is a build automation system with a C# DSL to do things like compiling code, copy files/folders, running unit tests, compress files and build NuGet packages. - MIT - https://cakebuild.net - cake-medium.png - false - - Copyright (c) .NET Foundation and contributors - Cake Script Build - - - - diff --git a/nuspec/Cake.Portable.nuspec b/nuspec/Cake.Portable.nuspec deleted file mode 100644 index 12027819bb..0000000000 --- a/nuspec/Cake.Portable.nuspec +++ /dev/null @@ -1,23 +0,0 @@ - - - - - cake.portable - Cake.Portable - 0.0.0 - Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio and contributors - Cake (C# Make) is a build automation system with a C# DSL to do things like compiling code, copy files/folders, running unit tests, compress files and build NuGet packages. - The Cake script runner. - https://cakebuild.net/ - https://github.com/cake-build/cake - https://github.com/cake-build/cake - https://cakebuild.net/docs - https://github.com/cake-build/cake/issues - Cake Script Build - Copyright (c) .NET Foundation and contributors - https://github.com/cake-build/cake/blob/develop/LICENSE - false - https://raw.githubusercontent.com/cake-build/graphics/master/png/cake-medium.png - - - diff --git a/nuspec/Cake.nuspec b/nuspec/Cake.nuspec deleted file mode 100644 index cd69bf6e4d..0000000000 --- a/nuspec/Cake.nuspec +++ /dev/null @@ -1,19 +0,0 @@ - - - - Cake - 0.0.0 - Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio and contributors - The Cake script runner. - Cake (C# Make) is a build automation system with a C# DSL to do things like compiling code, copy files/folders, running unit tests, compress files and build NuGet packages. - MIT - https://cakebuild.net - cake-medium.png - false - - Copyright (c) .NET Foundation and contributors - Cake Script Build - - - - diff --git a/nuspec/NuGet.org.md b/nuspec/NuGet.org.md new file mode 100644 index 0000000000..f65fa220ef --- /dev/null +++ b/nuspec/NuGet.org.md @@ -0,0 +1,74 @@ +# Cake + +Cake (C# Make) is a build automation system with a C# DSL to do things like compiling code, copy files/folders, running unit tests, compress files and build NuGet packages. + +## Table of Contents + +1. [Documentation](https://github.com/cake-build/cake#documentation) +2. [Contributing](https://github.com/cake-build/cake#contributing) +3. [Get in touch](https://github.com/cake-build/cake#get-in-touch) +4. [License](https://github.com/cake-build/cake#license) + +## Documentation + +You can read the latest documentation at [https://cakebuild.net/](https://cakebuild.net/). + +For a simple example to get started see [Setting up a new project](https://cakebuild.net/docs/getting-started/setting-up-a-new-project). + +## Contributing + +So you’re thinking about contributing to Cake? Great! It’s **really** appreciated. + +Make sure you've read the [contribution guidelines](https://cakebuild.net/docs/contributing/contribution-guidelines) before sending that epic pull request. You'll also need to sign the [contribution license agreement](https://cla.dotnetfoundation.org/cake-build/cake) (CLA) for anything other than a trivial change. **NOTE:** The .NET Foundation CLA Bot will provide a link to this CLA within the PR that you submit if it is deemed as required. + +* Fork the repository. +* Create a branch to work in. +* Make your feature addition or bug fix. +* Don't forget the unit tests. +* Send a pull request. + +## Get in touch + +[![Follow @cakebuildnet](https://img.shields.io/badge/Twitter-Follow%20%40cakebuildnet-blue.svg)](https://twitter.com/intent/follow?screen_name=cakebuildnet) + +[![Join the chat at https://github.com/cake-build/cake/discussions](https://img.shields.io/badge/discussions-join%20chat-brightgreen)](https://github.com/cake-build/cake/discussions?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +## License + +Copyright © .NET Foundation, Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio, C. Augusto Proiete, Nils Andresen, and contributors. + +Cake is provided as-is under the MIT license. For more information see [LICENSE](https://github.com/cake-build/cake/blob/develop/LICENSE). + +* For Roslyn, see https://github.com/dotnet/roslyn/blob/master/License.txt +* For Autofac, see https://github.com/autofac/Autofac/blob/master/LICENSE +* For NuGet.Core, see https://github.com/NuGet/Home/blob/dev/LICENSE.txt + +## Thanks + +A big thank you has to go to [JetBrains](https://www.jetbrains.com) who provide each of the Cake Developers with an [Open Source License](https://www.jetbrains.com/community/opensource/#support) for [ReSharper](https://www.jetbrains.com/resharper/) that helps with the development of Cake. + +### Sponsors + +Our wonderful sponsors: + +[![Sponsors](https://opencollective.com/cake/sponsors.svg)](https://opencollective.com/cake) + +### Backers + +Our wonderful backers: + +[![Backers](https://opencollective.com/cake/backers.svg)](https://opencollective.com/cake) + +## Code of Conduct + +This project has adopted the code of conduct defined by the [Contributor Covenant](http://contributor-covenant.org/) +to clarify expected behavior in our community. +For more information see the [.NET Foundation Code of Conduct](http://www.dotnetfoundation.org/code-of-conduct). + +## Contribution License Agreement + +By signing the [CLA](https://cla.dotnetfoundation.org/cake-build/cake), the community is free to use your contribution to .NET Foundation projects. + +## .NET Foundation + +This project is supported by the [.NET Foundation](http://www.dotnetfoundation.org). diff --git a/nuspec/VERIFICATION.txt b/nuspec/VERIFICATION.txt deleted file mode 100644 index 5db9afe09b..0000000000 --- a/nuspec/VERIFICATION.txt +++ /dev/null @@ -1,7 +0,0 @@ -VERIFICATION -Verification is intended to assist the Chocolatey moderators and community -in verifying that this package's contents are trustworthy. - -This package is published by the Cake Project itself. The binaries are -identical to other package types published by the project, in particular -the Cake nuget package. \ No newline at end of file diff --git a/src/Cake.Cli/Cake.Cli.csproj b/src/Cake.Cli/Cake.Cli.csproj new file mode 100644 index 0000000000..28ee02e248 --- /dev/null +++ b/src/Cake.Cli/Cake.Cli.csproj @@ -0,0 +1,24 @@ + + + Cake.Cli + Library + AnyCpu + true + + + + + The Cake CLI library. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Cake.Cli/Features/InfoFeature.cs b/src/Cake.Cli/Features/InfoFeature.cs new file mode 100644 index 0000000000..70b0abacb4 --- /dev/null +++ b/src/Cake.Cli/Features/InfoFeature.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Core; + +namespace Cake.Cli +{ + /// + /// Represents a feature that writes information about Cake to the console. + /// + public interface ICakeInfoFeature + { + /// + /// Runs the feature. + /// + /// The console to write to. + void Run(IConsole console); + } + + /// + /// Writes information about Cake to the console. + /// + public sealed class InfoFeature : ICakeInfoFeature + { + private readonly IVersionResolver _resolver; + + /// + /// Initializes a new instance of the class. + /// + /// The version resolver. + public InfoFeature(IVersionResolver resolver) + { + _resolver = resolver; + } + + /// + public void Run(IConsole console) + { + var version = _resolver.GetVersion(); + var product = _resolver.GetProductVersion(); + + console.WriteLine(); + console.WriteLine(@" +## #;;'"); + console.WriteLine(@" #;;# .+;;;;+,"); + console.WriteLine(@" '+;;#;,+';;;;;'#."); + console.WriteLine(@" ++'''';;;;;;;;;;# ;#;"); + console.WriteLine(@" ##';;;;++'+#;;;;;'. `#:"); + console.WriteLine(@" ;# '+'';;;;;;;;;'#` #."); + console.WriteLine(@" `#, .'++;;;;;':..........#"); + console.WriteLine(@" '+ `.........';;;;':.........#"); + console.WriteLine(@" #..................+;;;;;':........#"); + console.WriteLine(@" #..................#';;;;;'+''''''.#"); + console.WriteLine(@" #.......,:;''''''''##';;;;;'+'''''#,"); + console.WriteLine(@" #''''''''''''''''''###';;;;;;+''''#"); + console.WriteLine(@" #''''''''''''''''''####';;;;;;#'''#"); + console.WriteLine(@" #''''''''''''''''''#####';;;;;;#''#"); + console.WriteLine(@" #''''''''''''''''''######';;;;;;#'#"); + console.WriteLine(@" #''''''''''''''''''#######';;;;;;##"); + console.WriteLine(@" #''''''''''''''''''########';;;;;;#"); + console.WriteLine(@" #''''''''''''++####+;#######';;;;;;#"); + console.WriteLine(@" #+####':,` ,#####';;;;;;'"); + console.WriteLine(@" +##'''''+."); + + console.ForegroundColor = System.ConsoleColor.Yellow; + console.WriteLine(@" ___ _ ___ _ _ _ "); + console.WriteLine(@" / __\__ _| | _____ / __\_ _(_) | __| |"); + console.WriteLine(@" / / / _` | |/ / _ \/__\// | | | | |/ _` |"); + console.WriteLine(@"/ /___ (_| | < __/ \/ \ |_| | | | (_| |"); + console.WriteLine(@"\____/\__,_|_|\_\___\_____/\__,_|_|_|\__,_|"); + console.ResetColor(); + + console.WriteLine(); + console.WriteLine(@"Version: {0}", version); + console.WriteLine(@"Details: {0}", string.Join("\n ", product.Split('/'))); + console.WriteLine(); + } + } +} diff --git a/src/Cake.Cli/Features/VersionFeature.cs b/src/Cake.Cli/Features/VersionFeature.cs new file mode 100644 index 0000000000..fc71345b5c --- /dev/null +++ b/src/Cake.Cli/Features/VersionFeature.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Cake.Core; + +namespace Cake.Cli +{ + /// + /// Represents a feature that writes the Cake version to the console. + /// + public interface ICakeVersionFeature + { + /// + /// Writes the Cake version to the console. + /// + /// The console to write to. + void Run(IConsole console); + } + + /// + /// Writes the Cake version to the console. + /// + public sealed class VersionFeature : ICakeVersionFeature + { + private readonly IVersionResolver _resolver; + + /// + /// Initializes a new instance of the class. + /// + /// The version resolver. + public VersionFeature(IVersionResolver resolver) + { + _resolver = resolver; + } + + /// + public void Run(IConsole console) + { + if (console is null) + { + throw new ArgumentNullException(nameof(console)); + } + + console.WriteLine(_resolver.GetVersion()); + } + } +} diff --git a/src/Cake.Cli/Features/VersionResolver.cs b/src/Cake.Cli/Features/VersionResolver.cs new file mode 100644 index 0000000000..cc91351749 --- /dev/null +++ b/src/Cake.Cli/Features/VersionResolver.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Reflection; + +namespace Cake.Cli +{ + /// + /// Represents a version resolver. + /// + public interface IVersionResolver + { + /// + /// Gets the version. + /// + /// The version. + string GetVersion(); + + /// + /// Gets the product version. + /// + /// The product version. + string GetProductVersion(); + } + + /// + /// The Cake version resolver. + /// + public sealed class VersionResolver : IVersionResolver + { + /// + public string GetVersion() + { + var assembly = Assembly.GetEntryAssembly(); + var version = FileVersionInfo.GetVersionInfo(assembly.Location).Comments; + + if (string.IsNullOrWhiteSpace(version)) + { + version = "Unknown"; + } + + return version; + } + + /// + public string GetProductVersion() + { + var assembly = Assembly.GetEntryAssembly(); + var version = FileVersionInfo.GetVersionInfo(assembly.Location).ProductVersion; + + if (string.IsNullOrWhiteSpace(version)) + { + version = "Unknown"; + } + + return version; + } + } +} diff --git a/src/Cake.Cli/Hosts/BuildScriptHost.cs b/src/Cake.Cli/Hosts/BuildScriptHost.cs new file mode 100644 index 0000000000..ba7e6c9151 --- /dev/null +++ b/src/Cake.Cli/Hosts/BuildScriptHost.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Cake.Core; +using Cake.Core.Diagnostics; +using Cake.Core.Scripting; + +namespace Cake.Cli +{ + /// + /// The script host used to execute Cake scripts. + /// + public sealed class BuildScriptHost : BuildScriptHost + { + /// + /// Initializes a new instance of the class. + /// + /// The engine. + /// The execution strategy. + /// The context. + /// The report printer. + /// The log. + public BuildScriptHost( + ICakeEngine engine, + IExecutionStrategy executionStrategy, + ICakeContext context, + ICakeReportPrinter reportPrinter, + ICakeLog log) : base(engine, executionStrategy, context, reportPrinter, log) + { + } + } + + /// + /// The script host used to execute Cake scripts. + /// + /// The context type. + public class BuildScriptHost : ScriptHost + where TContext : ICakeContext + { + private readonly ICakeReportPrinter _reportPrinter; + private readonly ICakeLog _log; + private readonly IExecutionStrategy _executionStrategy; + private readonly TContext _context; + + /// + /// Initializes a new instance of the class. + /// + /// The engine. + /// The execution strategy. + /// The context. + /// The report printer. + /// The log. + public BuildScriptHost( + ICakeEngine engine, + IExecutionStrategy executionStrategy, + TContext context, + ICakeReportPrinter reportPrinter, + ICakeLog log) : base(engine, context) + { + _executionStrategy = executionStrategy; + _context = context; + _reportPrinter = reportPrinter; + _log = log; + } + + /// + public override async Task RunTargetAsync(string target) + { + Settings.SetTarget(target); + + var report = await Engine.RunTargetAsync(_context, _executionStrategy, Settings).ConfigureAwait(false); + if (report != null && !report.IsEmpty) + { + _reportPrinter.Write(report); + } + + return report; + } + } +} \ No newline at end of file diff --git a/src/Cake/Scripting/DescriptionScriptHost.cs b/src/Cake.Cli/Hosts/DescriptionScriptHost.cs similarity index 81% rename from src/Cake/Scripting/DescriptionScriptHost.cs rename to src/Cake.Cli/Hosts/DescriptionScriptHost.cs index 76c70596d8..a6845ed13e 100644 --- a/src/Cake/Scripting/DescriptionScriptHost.cs +++ b/src/Cake.Cli/Hosts/DescriptionScriptHost.cs @@ -4,17 +4,16 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Cake.Core; using Cake.Core.Scripting; -namespace Cake.Scripting +namespace Cake.Cli { /// /// The script host used for showing task descriptions. /// - public sealed class DescriptionScriptHost : ScriptHost + public class DescriptionScriptHost : ScriptHost { private readonly IConsole _console; private readonly Dictionary _descriptions; @@ -28,19 +27,11 @@ public sealed class DescriptionScriptHost : ScriptHost public DescriptionScriptHost(ICakeEngine engine, ICakeContext context, IConsole console) : base(engine, context) { - if (console == null) - { - throw new ArgumentNullException(nameof(console)); - } - _console = console; + _console = console ?? throw new ArgumentNullException(nameof(console)); _descriptions = new Dictionary(StringComparer.OrdinalIgnoreCase); } - /// - /// Runs the specified target. - /// - /// The target to run. - /// The resulting report. + /// public override Task RunTargetAsync(string target) { var maxTaskNameLength = 29; diff --git a/src/Cake/Scripting/DryRunExecutionStrategy.cs b/src/Cake.Cli/Hosts/DryRunExecutionStrategy.cs similarity index 98% rename from src/Cake/Scripting/DryRunExecutionStrategy.cs rename to src/Cake.Cli/Hosts/DryRunExecutionStrategy.cs index 115ac62491..e8331f2334 100644 --- a/src/Cake/Scripting/DryRunExecutionStrategy.cs +++ b/src/Cake.Cli/Hosts/DryRunExecutionStrategy.cs @@ -7,7 +7,7 @@ using Cake.Core; using Cake.Core.Diagnostics; -namespace Cake.Scripting +namespace Cake.Cli { internal sealed class DryRunExecutionStrategy : IExecutionStrategy { diff --git a/src/Cake/Scripting/DryRunScriptHost.cs b/src/Cake.Cli/Hosts/DryRunScriptHost.cs similarity index 65% rename from src/Cake/Scripting/DryRunScriptHost.cs rename to src/Cake.Cli/Hosts/DryRunScriptHost.cs index 34fdb12e5d..92baff08ae 100644 --- a/src/Cake/Scripting/DryRunScriptHost.cs +++ b/src/Cake.Cli/Hosts/DryRunScriptHost.cs @@ -8,15 +8,13 @@ using Cake.Core.Diagnostics; using Cake.Core.Scripting; -namespace Cake.Scripting +namespace Cake.Cli { /// /// The script host used to dry run Cake scripts. /// - public sealed class DryRunScriptHost : ScriptHost + public sealed class DryRunScriptHost : DryRunScriptHost { - private readonly ICakeLog _log; - /// /// Initializes a new instance of the class. /// @@ -24,20 +22,33 @@ public sealed class DryRunScriptHost : ScriptHost /// The context. /// The log. public DryRunScriptHost(ICakeEngine engine, ICakeContext context, ICakeLog log) - : base(engine, context) + : base(engine, context, log) { - if (log == null) - { - throw new ArgumentNullException(nameof(log)); - } - _log = log; } + } + + /// + /// The script host used to dry run Cake scripts. + /// + /// The context. + public class DryRunScriptHost : ScriptHost + where TContext : ICakeContext + { + private readonly ICakeLog _log; /// - /// Runs the specified target. + /// Initializes a new instance of the class. /// - /// The target to run. - /// The resulting report. + /// The engine. + /// The context. + /// The log. + public DryRunScriptHost(ICakeEngine engine, TContext context, ICakeLog log) + : base(engine, context) + { + _log = log ?? throw new ArgumentNullException(nameof(log)); + } + + /// public override async Task RunTargetAsync(string target) { _log.Information("Performing dry run..."); diff --git a/src/Cake/Scripting/TaskTreeScriptHost.cs b/src/Cake.Cli/Hosts/TreeScriptHost.cs similarity index 85% rename from src/Cake/Scripting/TaskTreeScriptHost.cs rename to src/Cake.Cli/Hosts/TreeScriptHost.cs index ee096550e9..b31048c201 100644 --- a/src/Cake/Scripting/TaskTreeScriptHost.cs +++ b/src/Cake.Cli/Hosts/TreeScriptHost.cs @@ -10,12 +10,12 @@ using Cake.Core.Graph; using Cake.Core.Scripting; -namespace Cake.Scripting +namespace Cake.Cli { /// /// The script host used for showing task descriptions. /// - public sealed class TaskTreeScriptHost : ScriptHost + public sealed class TreeScriptHost : ScriptHost { private const int _maxDepth = 0; private const string _cross = "├─"; @@ -24,26 +24,18 @@ public sealed class TaskTreeScriptHost : ScriptHost private readonly IConsole _console; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The engine. /// The context. /// The console. - public TaskTreeScriptHost(ICakeEngine engine, ICakeContext context, IConsole console) + public TreeScriptHost(ICakeEngine engine, ICakeContext context, IConsole console) : base(engine, context) { - if (console == null) - { - throw new ArgumentNullException(nameof(console)); - } - _console = console; + _console = console ?? throw new ArgumentNullException(nameof(console)); } - /// - /// Runs the specified target. - /// - /// The target to run. - /// The resulting report. + /// public override Task RunTargetAsync(string target) { var topLevelTasks = GetTopLevelTasks(); diff --git a/src/Cake.Cli/Infrastructure/ExceptionLogger.cs b/src/Cake.Cli/Infrastructure/ExceptionLogger.cs new file mode 100644 index 0000000000..b72d3b32d2 --- /dev/null +++ b/src/Cake.Cli/Infrastructure/ExceptionLogger.cs @@ -0,0 +1,56 @@ +using System; +using System.Linq; +using Cake.Core; +using Cake.Core.Diagnostics; + +namespace Cake.Cli +{ + /// + /// Exception logging extension methods for the ICakeLog. + /// + public static class ExceptionLogger + { + /// + /// Logs exception and returns exit code if available in exception. + /// + /// The exception type. + /// The log. + /// The exception. + /// 1 or exit code provided by . + public static int LogException(this ICakeLog log, T ex) + where T : Exception + { + log = log ?? new CakeBuildLog( + new CakeConsole(new CakeEnvironment(new CakePlatform(), new CakeRuntime()))); + + if (log.Verbosity == Verbosity.Diagnostic) + { + log.Error("Error: {0}", ex); + } + else + { + log.Error("Error: {0}", ex.Message); + if (ex is AggregateException aex) + { + foreach (var exception in aex.Flatten().InnerExceptions) + { + log.Error("\t{0}", exception.Message); + } + } + } + + var exitCode = ex switch + { + CakeException cex => cex.ExitCode, + AggregateException aex => aex + .InnerExceptions + .OfType() + .Select(cex => cex.ExitCode as int?) + .FirstOrDefault() ?? 1, + _ => 1 + }; + + return exitCode; + } + } +} diff --git a/src/Cake.Cli/Infrastructure/FilePathConverter.cs b/src/Cake.Cli/Infrastructure/FilePathConverter.cs new file mode 100644 index 0000000000..f8932244f2 --- /dev/null +++ b/src/Cake.Cli/Infrastructure/FilePathConverter.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Globalization; +using Cake.Core.IO; + +namespace Cake.Cli +{ + /// + /// A type converter for . + /// + public sealed class FilePathConverter : TypeConverter + { + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string stringValue) + { + return new FilePath(stringValue); + } + + throw new NotSupportedException("Can't convert value to file path."); + } + } + + /// + /// A type converter for . + /// + public sealed class DirectoryPathConverter : TypeConverter + { + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string stringValue) + { + return new DirectoryPath(stringValue); + } + + throw new NotSupportedException("Can't convert value to file path."); + } + } +} diff --git a/src/Cake/Arguments/VerbosityParser.cs b/src/Cake.Cli/Infrastructure/VerbosityConverter.cs similarity index 53% rename from src/Cake/Arguments/VerbosityParser.cs rename to src/Cake.Cli/Infrastructure/VerbosityConverter.cs index 8d0fa19991..7ee38940c6 100644 --- a/src/Cake/Arguments/VerbosityParser.cs +++ b/src/Cake.Cli/Infrastructure/VerbosityConverter.cs @@ -4,26 +4,25 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; +using Cake.Core; using Cake.Core.Diagnostics; -namespace Cake.Arguments +namespace Cake.Cli { /// - /// Responsible for parsing . + /// A type converter for . /// - internal sealed class VerbosityParser + public sealed class VerbosityConverter : TypeConverter { - private readonly ICakeLog _log; private readonly Dictionary _lookup; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The log. - public VerbosityParser(ICakeLog log) + public VerbosityConverter() { - _log = log; _lookup = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "q", Verbosity.Quiet }, @@ -39,22 +38,21 @@ public VerbosityParser(ICakeLog log) }; } - /// - /// Parses the provided string to a . - /// - /// The string to parse. - /// The verbosity. - /// true if parsing succeeded; otherwise false. - public bool TryParse(string value, out Verbosity verbosity) + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - var result = _lookup.TryGetValue(value, out verbosity); - if (!result) + if (value is string stringValue) { - const string format = "The value '{0}' is not a valid verbosity."; - var message = string.Format(CultureInfo.InvariantCulture, format, value); - _log.Error(message); + var result = _lookup.TryGetValue(stringValue, out var verbosity); + if (!result) + { + const string format = "The value '{0}' is not a valid verbosity."; + var message = string.Format(CultureInfo.InvariantCulture, format, value); + throw new CakeException(message); + } + return verbosity; } - return result; + throw new NotSupportedException("Can't convert value to verbosity."); } } -} \ No newline at end of file +} diff --git a/src/Cake.Common.Tests/Cake.Common.Tests.csproj b/src/Cake.Common.Tests/Cake.Common.Tests.csproj index 71591132e2..44ca7c116c 100644 --- a/src/Cake.Common.Tests/Cake.Common.Tests.csproj +++ b/src/Cake.Common.Tests/Cake.Common.Tests.csproj @@ -1,7 +1,6 @@  Cake.Common.Tests - net461;netcoreapp2.1;netcoreapp3.1 true true @@ -17,17 +16,16 @@ - + - - + + all + runtime; build; native; contentfiles; analyzers + + - - - - PreserveNewest diff --git a/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture.cs b/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture.cs index b7c587c71f..56a5fa470d 100644 --- a/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture.cs @@ -34,6 +34,7 @@ internal sealed class AssemblyInfoParserFixture public FilePath Path { get; set; } public bool CreateAssemblyInfo { get; set; } + public bool ExtraWhiteSpaces { get; set; } public AssemblyInfoParserFixture() { @@ -118,7 +119,16 @@ private void CreateAssemblyInfoOnDisk(FilePath path) } var creator = new AssemblyInfoCreator(FileSystem, Environment, Substitute.For()); - creator.Create(path, settings); + if (ExtraWhiteSpaces) + { + creator.Create(path, settings, "[assembly: {0} ]", + "[assembly: {0}( {1} )]", + "[assembly: {0}( {1}, {2} )]"); + } + else + { + creator.Create(path, settings); + } } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture_VB.cs b/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture_VB.cs index d83bf25c78..4b780eb997 100644 --- a/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture_VB.cs +++ b/src/Cake.Common.Tests/Fixtures/AssemblyInfoParserFixture_VB.cs @@ -34,6 +34,7 @@ internal sealed class AssemblyInfoParserFixture_VB public FilePath Path { get; set; } public bool CreateAssemblyInfo { get; set; } + public bool ExtraWhiteSpaces { get; set; } public AssemblyInfoParserFixture_VB() { @@ -118,7 +119,16 @@ private void CreateAssemblyInfoOnDisk(FilePath path) } var creator = new AssemblyInfoCreator(FileSystem, Environment, Substitute.For()); - creator.Create(path, settings); + if (ExtraWhiteSpaces) + { + creator.Create(path, settings, vbAttributeFormat: "", + vbAttributeWithValueFormat: "", + vbAttributeWithKeyValueFormat: ""); + } + else + { + creator.Create(path, settings); + } } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/Build/AzurePipelinesFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/AzurePipelinesFixture.cs index 7a9ee563f2..dacc1cc813 100644 --- a/src/Cake.Common.Tests/Fixtures/Build/AzurePipelinesFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Build/AzurePipelinesFixture.cs @@ -26,20 +26,9 @@ public AzurePipelinesFixture() Writer = new FakeBuildSystemServiceMessageWriter(); } - public void IsRunningOnTFS() => IsRunningOnAzurePipelines(); - - public void IsRunningOnVSTS() => IsRunningOnAzurePipelinesHosted(); - public void IsRunningOnAzurePipelines() { Environment.GetEnvironmentVariable("TF_BUILD").Returns("True"); - Environment.GetEnvironmentVariable("AGENT_NAME").Returns("On Premises"); - } - - public void IsRunningOnAzurePipelinesHosted(string agentHostName = "Hosted Agent") - { - Environment.GetEnvironmentVariable("TF_BUILD").Returns("True"); - Environment.GetEnvironmentVariable("AGENT_NAME").Returns(agentHostName); } public AzurePipelinesProvider CreateAzurePipelinesService() => new AzurePipelinesProvider(Environment, Writer); diff --git a/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsCommandsFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsCommandsFixture.cs new file mode 100644 index 0000000000..9c28bd8e6b --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsCommandsFixture.cs @@ -0,0 +1,288 @@ +using System; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Cake.Common.Build.GitHubActions.Commands; +using Cake.Common.Build.GitHubActions.Data; +using Cake.Core; +using Cake.Core.IO; +using Cake.Testing; +using NSubstitute; + +namespace Cake.Common.Tests.Fixtures.Build +{ + internal sealed class GitHubActionsCommandsFixture : HttpMessageHandler + { + private const string ApiVersion = "6.0-preview"; + private const string AcceptHeader = "application/json; api-version=" + ApiVersion; + private const string AcceptGzip = "application/octet-stream; api-version=" + ApiVersion; + private const string AcceptEncodingGzip = "gzip"; + private const string CreateArtifactUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + + "_apis/pipelines/workflows/34058136/artifacts?api-version=" + ApiVersion + "&artifactName=artifact"; + private const string CreateArtifactsUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + + "_apis/pipelines/workflows/34058136/artifacts?api-version=" + ApiVersion + "&artifactName=artifacts"; + private const string PutFileUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + + "_apis/resources/Containers/942031?itemPath=artifact%2Fartifact.txt"; + private const string CreateArtifactResponse = @"{ + ""containerId"": 942031, + ""size"": -1, + ""signedContent"": null, + ""fileContainerResourceUrl"": """ + GitHubActionsInfoFixture.ActionRuntimeUrl + @"_apis/resources/Containers/942031"", + ""type"": ""actions_storage"", + ""name"": ""artifact"", + ""url"": """ + GitHubActionsInfoFixture.ActionRuntimeUrl + @"_apis/pipelines/1/runs/7/artifacts?artifactName=artifact"", + ""expiresOn"": ""2021-12-14T18:43:29.7431144Z"", + ""items"": null +}"; + private const string CreateArtifactsResponse = @"{ + ""containerId"": 942031, + ""size"": -1, + ""signedContent"": null, + ""fileContainerResourceUrl"": """ + GitHubActionsInfoFixture.ActionRuntimeUrl + @"_apis/resources/Containers/942031"", + ""type"": ""actions_storage"", + ""name"": ""artifact"", + ""url"": """ + GitHubActionsInfoFixture.ActionRuntimeUrl + @"_apis/pipelines/1/runs/7/artifacts?artifactName=artifacts"", + ""expiresOn"": ""2021-12-14T18:43:29.7431144Z"", + ""items"": null +}"; + + private const string PutDirectoryRootUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + + "_apis/resources/Containers/942031?itemPath=artifacts%2Fartifact.txt"; + private const string PutDirectoryFolderAUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + + "_apis/resources/Containers/942031?itemPath=artifacts%2Ffolder_a%2Fartifact.txt"; + private const string PutDirectoryFolderBUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + + "_apis/resources/Containers/942031?itemPath=artifacts%2Ffolder_b%2Fartifact.txt"; + private const string PutDirectoryFolderBFolderCUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + + "_apis/resources/Containers/942031?itemPath=artifacts%2Ffolder_b%2Ffolder_c%2Fartifact.txt"; + + private const string GetArtifactResourceUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + + "_apis/pipelines/workflows/34058136/artifacts?api-version=6.0-preview&artifactName=artifact"; + private const string FileContainerResourceUrl = GitHubActionsInfoFixture.ActionRuntimeUrl + @"_apis/resources/Containers/4794789"; + private const string GetArtifactResourceResponse = @"{ + ""count"": 1, + ""value"": [ + { + ""containerId"": 4794789, + ""size"": 4, + ""signedContent"": null, + ""fileContainerResourceUrl"": """ + FileContainerResourceUrl + @""", + ""type"": ""actions_storage"", + ""name"": ""artifact"", + ""url"": """ + GitHubActionsInfoFixture.ActionRuntimeUrl + @"_apis/pipelines/1/runs/7/artifacts?artifactName=artifact"", + ""expiresOn"": ""2022-03-16T08:22:01.5699067Z"", + ""items"": null + } + ] +}"; + + private const string GetContainerItemResourcesUrl = FileContainerResourceUrl + "?itemPath=artifact"; + private const string GetContainerItemResourcesResponse = @"{ + ""count"": 1, + ""value"": [ + { + ""containerId"": 4794789, + ""scopeIdentifier"": ""00000000-0000-0000-0000-000000000000"", + ""path"": ""artifact/test.txt"", + ""itemType"": ""file"", + ""status"": ""created"", + ""fileLength"": 4, + ""fileEncoding"": 1, + ""fileType"": 1, + ""dateCreated"": ""2021-12-16T09:05:18.803Z"", + ""dateLastModified"": ""2021-12-16T09:05:18.907Z"", + ""createdBy"": ""2daeb16b-86ae-4e46-ba89-92a8aa076e52"", + ""lastModifiedBy"": ""2daeb16b-86ae-4e46-ba89-92a8aa076e52"", + ""itemLocation"": """ + GetContainerItemResourcesUrl + @"%2Ftest.txt&metadata=True"", + ""contentLocation"": """ + GetContainerItemResourcesUrl + @"%2Ftest.txt"", + ""fileId"": 1407, + ""contentId"": """" + } + ] +}"; + + private const string DownloadItemResourceUrl = GetContainerItemResourcesUrl + "%2Ftest.txt"; + private const string DownloadItemResourceResponse = "Cake"; + + private GitHubActionsInfoFixture GitHubActionsInfoFixture { get; } + private ICakeEnvironment Environment { get; } + public FakeFileSystem FileSystem { get; } + + public GitHubActionsCommandsFixture() + { + GitHubActionsInfoFixture = new GitHubActionsInfoFixture(); + FileSystem = new FakeFileSystem(GitHubActionsInfoFixture.Environment); + FileSystem.CreateDirectory("/opt"); + Environment = GitHubActionsInfoFixture.Environment; + } + + public GitHubActionsCommands CreateGitHubActionsCommands() + { + return new GitHubActionsCommands(Environment, FileSystem, GitHubActionsInfoFixture.CreateEnvironmentInfo(), CreateClient); + } + + public GitHubActionsCommandsFixture WithWorkingDirectory(DirectoryPath workingDirectory) + { + Environment.WorkingDirectory = workingDirectory; + return this; + } + + public GitHubActionsCommandsFixture WithNoGitHubEnv() + { + Environment.GetEnvironmentVariable("GITHUB_ENV").Returns(null as string); + return this; + } + + public GitHubActionsCommandsFixture WithNoGitHubPath() + { + Environment.GetEnvironmentVariable("GITHUB_PATH").Returns(null as string); + return this; + } + + private HttpClient CreateClient(string name) => new HttpClient(this); + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + if (request.Headers.Authorization is null || request.Headers.Authorization.Scheme != "Bearer" || request.Headers.Authorization.Parameter != GitHubActionsInfoFixture.ActionRuntimeToken) + { + return new HttpResponseMessage + { + StatusCode = HttpStatusCode.Unauthorized + }; + } + + if ( + !request.Headers.TryGetValues("Accept", out var values) + || !values.Contains(AcceptHeader)) + { + if (request.RequestUri.AbsoluteUri != DownloadItemResourceUrl + || !values.Contains(AcceptGzip) + || !request.Headers.TryGetValues("Accept-Encoding", out var encodingValues) + || !encodingValues.Contains(AcceptEncodingGzip)) + { + return new HttpResponseMessage + { + StatusCode = HttpStatusCode.BadRequest + }; + } + } + + switch (request) + { +#pragma warning disable SA1013 + // Create Artifact FilePath + case + { + RequestUri: { AbsoluteUri: CreateArtifactUrl }, + Method: { Method: "POST" }, + }: + { + return Ok(new StringContent(CreateArtifactResponse)); + } + + // Create Artifact DirectoryPath + case + { + RequestUri: { AbsoluteUri: CreateArtifactsUrl }, + Method: { Method: "POST" }, + }: + { + return Ok(new StringContent(CreateArtifactsResponse)); + } + + // Download Artifact - Get Artifact Container Resource + case + { + RequestUri: { AbsoluteUri: GetArtifactResourceUrl }, + Method: { Method: "GET" } + }: + { + return Ok(new StringContent(GetArtifactResourceResponse)); + } + + // Download Artifact - Get Artifact Container Item Resource + case + { + RequestUri: { AbsoluteUri: GetContainerItemResourcesUrl }, + Method: { Method: "GET" } + }: + { + return Ok(new StringContent(GetContainerItemResourcesResponse)); + } + + // Download Artifact - DownloadItemResource + case + { + RequestUri: { AbsoluteUri: DownloadItemResourceUrl }, + Method: { Method: "GET" } + }: + { + return Ok(new StringContent(DownloadItemResourceResponse)); + } + + // Put FilePath + case + { + RequestUri: { AbsoluteUri: PutFileUrl }, + Method: { Method: "PUT" } + }: + case + { + RequestUri: { AbsoluteUri: CreateArtifactUrl }, + Method: { Method: "PATCH" }, + }: + + // Put DirectoryPath + case + { + RequestUri: { AbsoluteUri: PutDirectoryRootUrl }, + Method: { Method: "PUT" } + }: + case + { + RequestUri: { AbsoluteUri: PutDirectoryFolderAUrl }, + Method: { Method: "PUT" } + }: + case + { + RequestUri: { AbsoluteUri: PutDirectoryFolderBUrl }, + Method: { Method: "PUT" } + }: + case + { + RequestUri: { AbsoluteUri: PutDirectoryFolderBFolderCUrl }, + Method: { Method: "PUT" } + }: + case + { + RequestUri: { AbsoluteUri: CreateArtifactsUrl }, + Method: { Method: "PATCH" }, + }: + { + return Ok(); + } +#pragma warning restore SA1013 + + default: + { + await Task.Delay(1, cancellationToken); + return new HttpResponseMessage + { + StatusCode = HttpStatusCode.NotFound + }; + } + } + } + + private static HttpResponseMessage Ok(HttpContent content = null) + { + return new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + ReasonPhrase = "OK", + Content = content + }; + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsFixture.cs index 42da53ad35..02ae8ab82f 100644 --- a/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsFixture.cs @@ -4,18 +4,23 @@ using Cake.Common.Build.GitHubActions; using Cake.Core; +using Cake.Core.IO; +using Cake.Testing; using NSubstitute; namespace Cake.Common.Tests.Fixtures.Build { internal sealed class GitHubActionsFixture { - public ICakeEnvironment Environment { get; set; } + public ICakeEnvironment Environment { get; } + public IFileSystem FileSystem { get; } public GitHubActionsFixture() { Environment = Substitute.For(); Environment.GetEnvironmentVariable("GITHUB_ACTIONS").Returns((string)null); + Environment.WorkingDirectory.Returns("/home/cake"); + FileSystem = new FakeFileSystem(Environment); } public void IsRunningOnGitHubActions() @@ -25,7 +30,7 @@ public void IsRunningOnGitHubActions() public GitHubActionsProvider CreateGitHubActionsService() { - return new GitHubActionsProvider(Environment); + return new GitHubActionsProvider(Environment, FileSystem); } } } diff --git a/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsInfoFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsInfoFixture.cs index d6818533e1..ae0c6d04bb 100644 --- a/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsInfoFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Build/GitHubActionsInfoFixture.cs @@ -10,7 +10,9 @@ namespace Cake.Common.Tests.Fixtures.Build { internal sealed class GitHubActionsInfoFixture { - public ICakeEnvironment Environment { get; set; } + public const string ActionRuntimeToken = "zht1j5NeW2T5ZsOxncX4CUEiWYhD4ZRwoDghkARk"; + public const string ActionRuntimeUrl = "https://pipelines.actions.githubusercontent.com/ip0FyYnZXxdEOcOwPHkRsZJd2x6G5XoT486UsAb0/"; + public ICakeEnvironment Environment { get; } public GitHubActionsInfoFixture() { @@ -19,16 +21,23 @@ public GitHubActionsInfoFixture() Environment.GetEnvironmentVariable("GITHUB_ACTIONS").Returns("true"); Environment.GetEnvironmentVariable("HOME").Returns("/home/runner"); + Environment.GetEnvironmentVariable("RUNNER_NAME").Returns("RunnerName"); Environment.GetEnvironmentVariable("RUNNER_OS").Returns("Linux"); Environment.GetEnvironmentVariable("RUNNER_TEMP").Returns("/home/runner/work/_temp"); Environment.GetEnvironmentVariable("RUNNER_TOOL_CACHE").Returns("/opt/hostedtoolcache"); Environment.GetEnvironmentVariable("RUNNER_WORKSPACE").Returns("/home/runner/work/cake"); + Environment.GetEnvironmentVariable("ImageOS").Returns("ubuntu20"); + Environment.GetEnvironmentVariable("ImageVersion").Returns("20211209.3"); + Environment.GetEnvironmentVariable("RUNNER_USER").Returns("runner"); Environment.GetEnvironmentVariable("GITHUB_ACTION").Returns("run1"); + Environment.GetEnvironmentVariable("GITHUB_ACTION_PATH").Returns("/path/to/action"); Environment.GetEnvironmentVariable("GITHUB_ACTOR").Returns("dependabot"); + Environment.GetEnvironmentVariable("GITHUB_API_URL").Returns("https://api.github.com"); Environment.GetEnvironmentVariable("GITHUB_BASE_REF").Returns("master"); Environment.GetEnvironmentVariable("GITHUB_EVENT_NAME").Returns("pull_request"); Environment.GetEnvironmentVariable("GITHUB_EVENT_PATH").Returns("/home/runner/work/_temp/_github_workflow/event.json"); + Environment.GetEnvironmentVariable("GITHUB_GRAPHQL_URL").Returns("https://api.github.com/graphql"); Environment.GetEnvironmentVariable("GITHUB_HEAD_REF").Returns("dependabot/nuget/Microsoft.SourceLink.GitHub-1.0.0"); Environment.GetEnvironmentVariable("GITHUB_JOB").Returns("job"); Environment.GetEnvironmentVariable("GITHUB_REF").Returns("refs/pull/1/merge"); @@ -36,18 +45,30 @@ public GitHubActionsInfoFixture() Environment.GetEnvironmentVariable("GITHUB_REPOSITORY_OWNER").Returns("cake-build"); Environment.GetEnvironmentVariable("GITHUB_RUN_ID").Returns("34058136"); Environment.GetEnvironmentVariable("GITHUB_RUN_NUMBER").Returns("60"); + Environment.GetEnvironmentVariable("GITHUB_SERVER_URL").Returns("https://github.com"); Environment.GetEnvironmentVariable("GITHUB_SHA").Returns("d1e4f990f57349334368c8253382abc63be02d73"); Environment.GetEnvironmentVariable("GITHUB_WORKFLOW").Returns("Build"); Environment.GetEnvironmentVariable("GITHUB_WORKSPACE").Returns("/home/runner/work/cake/cake"); + Environment.GetEnvironmentVariable("GITHUB_RUN_ATTEMPT").Returns("2"); + Environment.GetEnvironmentVariable("GITHUB_REF_PROTECTED").Returns("true"); + Environment.GetEnvironmentVariable("GITHUB_REF_NAME").Returns("main"); + + Environment.GetEnvironmentVariable("ACTIONS_RUNTIME_TOKEN").Returns(ActionRuntimeToken); + Environment.GetEnvironmentVariable("ACTIONS_RUNTIME_URL").Returns(ActionRuntimeUrl); + Environment.GetEnvironmentVariable("GITHUB_ENV").Returns("/opt/github.env"); + Environment.GetEnvironmentVariable("GITHUB_PATH").Returns("/opt/github.path"); + Environment.WorkingDirectory.Returns("/home/runner/work/cake/cake"); } - public GitHubActionsRunnerInfo CreateRunnerInfo() + public GitHubActionsRunnerInfo CreateRunnerInfo(string architecture = null) { + Environment.GetEnvironmentVariable("RUNNER_ARCH").Returns(architecture); return new GitHubActionsRunnerInfo(Environment); } - public GitHubActionsWorkflowInfo CreateWorkflowInfo() + public GitHubActionsWorkflowInfo CreateWorkflowInfo(string refType = null) { + Environment.GetEnvironmentVariable("GITHUB_REF_TYPE").Returns(refType); return new GitHubActionsWorkflowInfo(Environment); } @@ -60,5 +81,10 @@ public GitHubActionsEnvironmentInfo CreateEnvironmentInfo() { return new GitHubActionsEnvironmentInfo(Environment); } + + public GitHubActionsRuntimeInfo CreateRuntimeInfo() + { + return new GitHubActionsRuntimeInfo(Environment); + } } } diff --git a/src/Cake.Common.Tests/Fixtures/Build/MyGetFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/MyGetFixture.cs new file mode 100644 index 0000000000..4619d39380 --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/Build/MyGetFixture.cs @@ -0,0 +1,34 @@ +using Cake.Common.Build.MyGet; +using Cake.Common.Tests.Fakes; +using Cake.Core; +using NSubstitute; + +namespace Cake.Common.Tests.Fixtures.Build +{ + internal sealed class MyGetFixture + { + public ICakeEnvironment Environment { get; set; } + + public FakeBuildSystemServiceMessageWriter Writer { get; set; } + + public MyGetFixture() + { + Environment = Substitute.For(); + Environment.GetEnvironmentVariable("BuildRunner").Returns((string)null); + Writer = new FakeBuildSystemServiceMessageWriter(); + } + + public void IsRunningOnMyGet(bool? capitalCase = default) + { + var buildRunnerValue = "MyGet"; + if (capitalCase.HasValue) + { + buildRunnerValue = capitalCase.Value ? "MYGET" : "myget"; + } + + Environment.GetEnvironmentVariable("BuildRunner").Returns(buildRunnerValue); + } + + public MyGetProvider CreateMyGetProvider() => new MyGetProvider(Environment, Writer); + } +} diff --git a/src/Cake.Common.Tests/Fixtures/Build/TFBuildFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/TFBuildFixture.cs deleted file mode 100644 index 2591a86600..0000000000 --- a/src/Cake.Common.Tests/Fixtures/Build/TFBuildFixture.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Common.Build.TFBuild; -using Cake.Common.Tests.Fakes; -using Cake.Core; -using Cake.Core.IO; -using NSubstitute; - -namespace Cake.Common.Tests.Fixtures.Build -{ - internal sealed class TFBuildFixture - { - public ICakeEnvironment Environment { get; set; } - - public FakeBuildSystemServiceMessageWriter Writer { get; set; } - - public TFBuildFixture() - { - Environment = Substitute.For(); - Environment.WorkingDirectory.Returns("C:\\build\\CAKE-CAKE-JOB1"); - Environment.GetEnvironmentVariable("TF_BUILD").Returns((string)null); - Environment.Platform.Family.Returns(PlatformFamily.Windows); - Writer = new FakeBuildSystemServiceMessageWriter(); - } - - public void IsRunningOnTFS() => IsRunningOnAzurePipelines(); - - public void IsRunningOnVSTS() => IsRunningOnAzurePipelinesHosted(); - - public void IsRunningOnAzurePipelines() - { - Environment.GetEnvironmentVariable("TF_BUILD").Returns("True"); - Environment.GetEnvironmentVariable("AGENT_NAME").Returns("On Premises"); - } - - public void IsRunningOnAzurePipelinesHosted(string agentHostName = "Hosted Agent") - { - Environment.GetEnvironmentVariable("TF_BUILD").Returns("True"); - Environment.GetEnvironmentVariable("AGENT_NAME").Returns(agentHostName); - } - - public TFBuildProvider CreateTFBuildService() => new TFBuildProvider(Environment, Writer); - - public TFBuildProvider CreateTFBuildService(PlatformFamily platformFamily, DirectoryPath workingDirectory) - { - Environment.Platform.Family.Returns(platformFamily); - Environment.WorkingDirectory.Returns(workingDirectory); - return CreateTFBuildService(); - } - } -} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/Build/TFBuildInfoFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/TFBuildInfoFixture.cs deleted file mode 100644 index d12477eaff..0000000000 --- a/src/Cake.Common.Tests/Fixtures/Build/TFBuildInfoFixture.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Common.Build.TFBuild.Data; -using Cake.Core; -using NSubstitute; - -namespace Cake.Common.Tests.Fixtures.Build -{ - public sealed class TFBuildInfoFixture - { - public ICakeEnvironment Environment { get; set; } - - public TFBuildInfoFixture() - { - Environment = Substitute.For(); - - // TFBuild RepositoryInfo - Environment.GetEnvironmentVariable("BUILD_SOURCEVERSION").Returns("4efbc1ffb993dfbcf024e6a9202865cc0b6d9c50"); - Environment.GetEnvironmentVariable("BUILD_SOURCETFVCSHELVESET").Returns("Shelveset1"); - Environment.GetEnvironmentVariable("BUILD_REPOSITORY_NAME").Returns("cake"); - Environment.GetEnvironmentVariable("BUILD_REPOSITORY_PROVIDER").Returns("GitHub"); - Environment.GetEnvironmentVariable("BUILD_SOURCEBRANCHNAME").Returns("develop"); - Environment.GetEnvironmentVariable("BUILD_SOURCEBRANCH").Returns("refs/heads/develop"); - Environment.GetEnvironmentVariable("BUILD_SOURCEVERSIONMESSAGE").Returns("A commit message"); - Environment.GetEnvironmentVariable("BUILD_REPOSITORY_GIT_SUBMODULECHECKOUT").Returns("A commit message"); - - // TFBuild AgentInfo - Environment.GetEnvironmentVariable("AGENT_BUILDDIRECTORY").Returns(@"c:\agent\_work\1"); - Environment.GetEnvironmentVariable("AGENT_HOMEDIRECTORY").Returns(@"c:\agent"); - Environment.GetEnvironmentVariable("AGENT_WORKFOLDER").Returns(@"c:\agent\_work"); - Environment.GetEnvironmentVariable("AGENT_ID").Returns("71"); - Environment.GetEnvironmentVariable("AGENT_NAME").Returns("Agent-1"); - Environment.GetEnvironmentVariable("AGENT_MACHINENAME").Returns("BuildServer"); - Environment.GetEnvironmentVariable("AGENT_JOBNAME").Returns("Job"); - Environment.GetEnvironmentVariable("AGENT_JOBSTATUS").Returns("SucceededWithIssues"); - Environment.GetEnvironmentVariable("AGENT_TOOLSDIRECTORY").Returns(@"C:/hostedtoolcache/windows"); - - // TFBuild BuildInfo - Environment.GetEnvironmentVariable("SYSTEM_ACCESSTOKEN").Returns("f662dbe218144c86bdecb1e9b2eb336c"); - Environment.GetEnvironmentVariable("SYSTEM_DEBUG").Returns("true"); - Environment.GetEnvironmentVariable("BUILD_BUILDID").Returns("100234"); - Environment.GetEnvironmentVariable("BUILD_BUILDNUMBER").Returns("Build-20160927.1"); - Environment.GetEnvironmentVariable("BUILD_BUILDURI").Returns("vstfs:///Build/Build/1430"); - Environment.GetEnvironmentVariable("BUILD_QUEUEDBY") - .Returns(@"[DefaultCollection]\Project Collection Service Accounts"); - Environment.GetEnvironmentVariable("BUILD_REQUESTEDFOR").Returns("Alistair Chapman"); - Environment.GetEnvironmentVariable("BUILD_REQUESTEDFOREMAIL").Returns("author@mail.com"); - Environment.GetEnvironmentVariable("BUILD_ARTIFACTSTAGINGDIRECTORY").Returns(@"c:\agent\_work\1\a"); - Environment.GetEnvironmentVariable("BUILD_BINARIESDIRECTORY").Returns(@"c:\agent\_work\1\b"); - Environment.GetEnvironmentVariable("BUILD_REASON").Returns("PullRequest"); - Environment.GetEnvironmentVariable("BUILD_SOURCESDIRECTORY").Returns(@"c:\agent\_work\1\s"); - Environment.GetEnvironmentVariable("BUILD_STAGINGDIRECTORY").Returns(@"c:\agent\_work\1\a"); - Environment.GetEnvironmentVariable("COMMON_TESTRESULTSDIRECTORY").Returns(@"c:\agent\_work\1\TestResults"); - - // VSTS Build TriggeredBy - Environment.GetEnvironmentVariable("BUILD_TRIGGEREDBY_BUILDID").Returns(@"1"); - Environment.GetEnvironmentVariable("BUILD_TRIGGEREDBY_DEFINITIONID").Returns(@"1"); - Environment.GetEnvironmentVariable("BUILD_TRIGGEREDBY_DEFINITIONNAME").Returns(@"Build"); - Environment.GetEnvironmentVariable("BUILD_TRIGGEREDBY_BUILDNUMBER").Returns(@"123"); - Environment.GetEnvironmentVariable("BUILD_TRIGGEREDBY_PROJECTID").Returns(@"456"); - - // TFBuild PullRequestInfo - Environment.GetEnvironmentVariable("SYSTEM_PULLREQUEST_PULLREQUESTID").Returns("1"); - Environment.GetEnvironmentVariable("SYSTEM_PULLREQUEST_PULLREQUESTNUMBER").Returns("1"); - Environment.GetEnvironmentVariable("SYSTEM_PULLREQUEST_ISFORK").Returns(@"False"); - Environment.GetEnvironmentVariable("SYSTEM_PULLREQUEST_SOURCEBRANCH").Returns(@"refs/heads/FeatureBranch"); - Environment.GetEnvironmentVariable("SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI").Returns(@"https://fabrikamfiber.visualstudio.com/Project/_git/ProjectRepo"); - Environment.GetEnvironmentVariable("SYSTEM_PULLREQUEST_TARGETBRANCH").Returns(@"refs/heads/master"); - - // TFBuild DefinitionInfo - Environment.GetEnvironmentVariable("SYSTEM_DEFINITIONID").Returns("1855"); - Environment.GetEnvironmentVariable("BUILD_DEFINITIONNAME").Returns("Cake-CI"); - Environment.GetEnvironmentVariable("BUILD_DEFINITIONVERSION").Returns("47"); - - // TFBuild TeamProjectInfo - Environment.GetEnvironmentVariable("SYSTEM_TEAMPROJECT").Returns("TeamProject"); - Environment.GetEnvironmentVariable("SYSTEM_TEAMPROJECTID").Returns("D0A3B6B8-499B-4D4B-BD46-DB70C19E6D33"); - Environment.GetEnvironmentVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI") - .Returns("https://fabrikamfiber.visualstudio.com/"); - } - - public TFBuildEnvironmentInfo CreateEnvironmentInfo() - { - return new TFBuildEnvironmentInfo(Environment); - } - - public TFBuildRepositoryInfo CreateRepositoryInfo() - { - return new TFBuildRepositoryInfo(Environment); - } - - public TFBuildRepositoryInfo CreateRepositoryInfo(string repoType) - { - Environment.GetEnvironmentVariable("BUILD_REPOSITORY_PROVIDER").Returns(repoType); - return CreateRepositoryInfo(); - } - - public TFBuildAgentInfo CreateAgentInfo() - { - return new TFBuildAgentInfo(Environment); - } - - public TFBuildAgentInfo CreateHostedAgentInfo() - { - Environment.GetEnvironmentVariable("AGENT_NAME").Returns("Hosted Agent"); - return new TFBuildAgentInfo(Environment); - } - - public TFBuildInfo CreateBuildInfo() - { - return new TFBuildInfo(Environment); - } - - public TFBuildPullRequestInfo CreatePullRequestInfo() - { - return new TFBuildPullRequestInfo(Environment); - } - - public TFBuildDefinitionInfo CreateDefinitionInfo() - { - return new TFBuildDefinitionInfo(Environment); - } - - public TFBuildTeamProjectInfo CreateTeamProjectInfo() - { - return new TFBuildTeamProjectInfo(Environment); - } - } -} diff --git a/src/Cake.Common.Tests/Fixtures/Build/TeamCityFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/TeamCityFixture.cs index d557ecbe3d..6d4ea07887 100644 --- a/src/Cake.Common.Tests/Fixtures/Build/TeamCityFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Build/TeamCityFixture.cs @@ -5,7 +5,7 @@ using Cake.Common.Build.TeamCity; using Cake.Common.Tests.Fakes; using Cake.Core; -using Cake.Testing; +using Cake.Core.IO; using NSubstitute; namespace Cake.Common.Tests.Fixtures.Build @@ -13,6 +13,7 @@ namespace Cake.Common.Tests.Fixtures.Build internal sealed class TeamCityFixture { public ICakeEnvironment Environment { get; set; } + public IFileSystem FileSystem { get; set; } public FakeBuildSystemServiceMessageWriter Writer { get; set; } public TeamCityFixture() @@ -20,6 +21,7 @@ public TeamCityFixture() Environment = Substitute.For(); Environment.WorkingDirectory.Returns("C:\\build\\CAKE-CAKE-JOB1"); Environment.GetEnvironmentVariable("TEAMCITY_VERSION").Returns((string)null); + FileSystem = Substitute.For(); Writer = new FakeBuildSystemServiceMessageWriter(); } @@ -30,7 +32,7 @@ public void IsRunningOnTeamCity() public TeamCityProvider CreateTeamCityService() { - return new TeamCityProvider(Environment, Writer); + return new TeamCityProvider(Environment, FileSystem, Writer); } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/Build/TeamCityInfoFixture.cs b/src/Cake.Common.Tests/Fixtures/Build/TeamCityInfoFixture.cs index acdcba2b58..18439f72ff 100644 --- a/src/Cake.Common.Tests/Fixtures/Build/TeamCityInfoFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Build/TeamCityInfoFixture.cs @@ -4,39 +4,74 @@ using Cake.Common.Build.TeamCity.Data; using Cake.Core; -using NSubstitute; +using Cake.Core.IO; +using Cake.Testing; namespace Cake.Common.Tests.Fixtures.Build { internal sealed class TeamCityInfoFixture { + public IFileSystem FileSystem { get; set; } public ICakeEnvironment Environment { get; set; } public TeamCityInfoFixture() { - Environment = Substitute.For(); + Environment = FakeEnvironment.CreateUnixEnvironment(); + FileSystem = new FakeFileSystem(Environment); + ((FakeFileSystem)FileSystem).CreateDirectory("/Working"); - Environment.GetEnvironmentVariable("TEAMCITY_BUILDCONF_NAME").Returns(@"Cake Build"); - Environment.GetEnvironmentVariable("BUILD_NUMBER").Returns("10-Foo"); + ((FakeEnvironment)Environment).SetEnvironmentVariable("TEAMCITY_BUILDCONF_NAME", @"Cake Build"); + ((FakeEnvironment)Environment).SetEnvironmentVariable("BUILD_NUMBER", "10-Foo"); + ((FakeEnvironment)Environment).SetEnvironmentVariable("TEAMCITY_PROJECT_NAME", "Cake"); + ((FakeEnvironment)Environment).SetEnvironmentVariable("TEAMCITY_BUILD_PROPERTIES_FILE", "/Working/teamcity.build.properties"); + ((FakeEnvironment)Environment).SetEnvironmentVariable("Git_Branch", "refs/pull-requests/7/from"); + ((FakeEnvironment)Environment).SetEnvironmentVariable("BUILD_START_DATE", "20200822"); + ((FakeEnvironment)Environment).SetEnvironmentVariable("BUILD_START_TIME", "123456"); + } + + public void SetBuildPropertiesContent(string xml) + { + ((FakeFileSystem)FileSystem).GetFile("/Working/teamcity.build.properties.xml").SetContent(xml); + } + + public void SetConfigPropertiesContent(string xml) + { + ((FakeFileSystem)FileSystem).GetFile("/Working/teamcity.config.configuration.xml").SetContent(xml); + } + + public void SetRunnerPropertiesContent(string xml) + { + ((FakeFileSystem)FileSystem).GetFile("/Working/teamcity.runner.configuration.xml").SetContent(xml); + } + + public void SetGitBranch(string branch) + { + ((FakeEnvironment)Environment).SetEnvironmentVariable("Git_Branch", branch); + } - Environment.GetEnvironmentVariable("TEAMCITY_PROJECT_NAME").Returns("Cake"); + public void SetBuildStartDate(string startDate) + { + ((FakeEnvironment)Environment).SetEnvironmentVariable("BUILD_START_DATE", startDate); + } - Environment.GetEnvironmentVariable("Git_Branch").Returns("refs/pull-requests/7/from"); + public void SetBuildStartTime(string startTime) + { + ((FakeEnvironment)Environment).SetEnvironmentVariable("BUILD_START_TIME", startTime); } public TeamCityPullRequestInfo CreatePullRequestInfo() { - return new TeamCityPullRequestInfo(Environment); + return new TeamCityPullRequestInfo(Environment, CreateBuildInfo()); } public TeamCityEnvironmentInfo CreateEnvironmentInfo() { - return new TeamCityEnvironmentInfo(Environment); + return new TeamCityEnvironmentInfo(Environment, FileSystem); } public TeamCityBuildInfo CreateBuildInfo() { - return new TeamCityBuildInfo(Environment); + return new TeamCityBuildInfo(Environment, FileSystem); } public TeamCityProjectInfo CreateProjectInfo() diff --git a/src/Cake.Common.Tests/Fixtures/IO/FileCopierFixture.cs b/src/Cake.Common.Tests/Fixtures/IO/FileCopierFixture.cs new file mode 100644 index 0000000000..1c19381102 --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/IO/FileCopierFixture.cs @@ -0,0 +1,49 @@ +using System; +using Cake.Core; +using Cake.Core.IO; +using Cake.Core.Tests.Fixtures; +using Cake.Testing; + +namespace Cake.Common.Tests.Fixtures.IO +{ + internal sealed class FileCopierFixture + { + private readonly FakeEnvironment _environment; + private readonly FakeFileSystem _fileSystem; + private readonly IGlobber _globber; + + public FileCopierFixture() + { + _environment = FakeEnvironment.CreateUnixEnvironment(); + _environment.WorkingDirectory = "/working"; + _fileSystem = new FakeFileSystem(_environment); + _globber = new Globber(_fileSystem, _environment); + Context = new CakeContextFixture { Environment = _environment, FileSystem = _fileSystem, Globber = _globber }.CreateContext(); + } + + public CakeContext Context { get; } + + public bool ExistsFile(FilePath path) + { + var file = _fileSystem.GetFile(path.MakeAbsolute(Context.Environment)); + return file != null; + } + + public FilePath MakeAbsolute(FilePath inputPath) + { + return inputPath.MakeAbsolute(Context.Environment); + } + + public void EnsureFileExists(FilePath filePath) + { + var fullPath = filePath.MakeAbsolute(Context.Environment); + _fileSystem.CreateFile(fullPath).SetContent(Guid.NewGuid().ToString("D")); + } + + public void EnsureDirectoryExists(DirectoryPath directoryPath) + { + var fullPath = directoryPath.MakeAbsolute(Context.Environment); + _fileSystem.CreateDirectory(fullPath); + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/Tools/Chocolatey/Export/ChocolateyExportFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/Chocolatey/Export/ChocolateyExportFixture.cs new file mode 100644 index 0000000000..dbadd8771a --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/Tools/Chocolatey/Export/ChocolateyExportFixture.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.Chocolatey.Export; + +namespace Cake.Common.Tests.Fixtures.Tools.Chocolatey.Export +{ + internal sealed class ChocolateyExportFixture : ChocolateyFixture + { + public ChocolateyExportFixture() + { + } + + protected override void RunTool() + { + var tool = new ChocolateyExporter(FileSystem, Environment, ProcessRunner, Tools, Resolver); + tool.Export(Settings); + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/Tools/DotNet/DotNetFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/DotNet/DotNetFixture.cs new file mode 100644 index 0000000000..3fa46ee699 --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/Tools/DotNet/DotNetFixture.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNet; +using Cake.Core.IO; +using Cake.Testing.Fixtures; + +namespace Cake.Common.Tests.Fixtures.Tools.DotNet +{ + internal abstract class DotNetFixture : ToolFixture + where TSettings : DotNetSettings, new() + { + protected DotNetFixture() + : base("dotnet.exe") + { + ProcessRunner.Process.SetStandardOutput(new string[] { }); + } + + protected override ToolFixtureResult CreateResult(FilePath path, ProcessSettings process) + { + return new ToolFixtureResult(path, process); + } + } +} diff --git a/src/Cake.Common.Tests/Fixtures/Tools/DotNet/Format/DotNetFormatterFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/DotNet/Format/DotNetFormatterFixture.cs new file mode 100644 index 0000000000..f7d678036d --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/Tools/DotNet/Format/DotNetFormatterFixture.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNet.Format; + +namespace Cake.Common.Tests.Fixtures.Tools.DotNet.Format +{ + internal sealed class DotNetFormatterFixture : DotNetFixture + { + public string Root { get; set; } + + public string Subcommand { get; set; } + + protected override void RunTool() + { + var tool = new DotNetFormatter(FileSystem, Environment, ProcessRunner, Tools); + tool.Format(Root, Subcommand, Settings); + } + } +} diff --git a/src/Cake.Common.Tests/Fixtures/Tools/DotNet/SDKCheck/DotNetSDKCheckerFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/DotNet/SDKCheck/DotNetSDKCheckerFixture.cs new file mode 100644 index 0000000000..bcbff5010e --- /dev/null +++ b/src/Cake.Common.Tests/Fixtures/Tools/DotNet/SDKCheck/DotNetSDKCheckerFixture.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNet.SDKCheck; + +namespace Cake.Common.Tests.Fixtures.Tools.DotNet.SDKCheck +{ + internal sealed class DotNetSDKCheckerFixture : DotNetFixture + { + protected override void RunTool() + { + var tool = new DotNetSDKChecker(FileSystem, Environment, ProcessRunner, Tools); + tool.Check(); + } + } +} diff --git a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Build/DotNetCoreBuilderFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Build/DotNetCoreBuilderFixture.cs index 5371e0dac6..44b431f3c6 100644 --- a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Build/DotNetCoreBuilderFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Build/DotNetCoreBuilderFixture.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.Build; using Cake.Common.Tools.DotNetCore.Build; namespace Cake.Common.Tests.Fixtures.Tools.DotNetCore.Build { - internal sealed class DotNetCoreBuilderFixture : DotNetCoreFixture + internal sealed class DotNetCoreBuilderFixture : DotNetCoreFixture { public string Project { get; set; } diff --git a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerFixture.cs index ad95e31829..c32030ee07 100644 --- a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerFixture.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.BuildServer; using Cake.Common.Tools.DotNetCore.BuildServer; namespace Cake.Common.Tests.Fixtures.Tools.DotNetCore.Build { - internal sealed class DotNetCoreBuildServerFixture : DotNetCoreFixture + internal sealed class DotNetCoreBuildServerFixture : DotNetCoreFixture { protected override void RunTool() { diff --git a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Clean/DotNetCoreCleanerFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Clean/DotNetCoreCleanerFixture.cs index e8b1621727..3b6e3a25d7 100644 --- a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Clean/DotNetCoreCleanerFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Clean/DotNetCoreCleanerFixture.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.Clean; using Cake.Common.Tools.DotNetCore.Clean; namespace Cake.Common.Tests.Fixtures.Tools.DotNetCore.Clean { - internal sealed class DotNetCoreCleanerFixture : DotNetCoreFixture + internal sealed class DotNetCoreCleanerFixture : DotNetCoreFixture { public string Project { get; set; } diff --git a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/DotNetCoreFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/DotNetCoreFixture.cs index 4bb1c669d2..84b5075b37 100644 --- a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/DotNetCoreFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/DotNetCoreFixture.cs @@ -2,24 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Cake.Common.Tools.DotNetCore; -using Cake.Core.IO; -using Cake.Testing.Fixtures; +using Cake.Common.Tests.Fixtures.Tools.DotNet; +using Cake.Common.Tools.DotNet; namespace Cake.Common.Tests.Fixtures.Tools.DotNetCore { - internal abstract class DotNetCoreFixture : ToolFixture - where TSettings : DotNetCoreSettings, new() + internal abstract class DotNetCoreFixture : DotNetFixture + where TSettings : DotNetSettings, new() { - protected DotNetCoreFixture() - : base("dotnet.exe") - { - ProcessRunner.Process.SetStandardOutput(new string[] { }); - } - - protected override ToolFixtureResult CreateResult(FilePath path, ProcessSettings process) - { - return new ToolFixtureResult(path, process); - } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Execute/DotNetCoreExecutorFixture.cs b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Execute/DotNetCoreExecutorFixture.cs index dbde2e3992..86b222121e 100644 --- a/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Execute/DotNetCoreExecutorFixture.cs +++ b/src/Cake.Common.Tests/Fixtures/Tools/DotNetCore/Execute/DotNetCoreExecutorFixture.cs @@ -11,7 +11,7 @@ internal sealed class DotNetCoreExecutorFixture : DotNetCoreFixture + /// Looks up a localized string similar to Microsoft Visual Studio Solution File, Format Version 12.00 + ///# Visual Studio 14 + ///VisualStudioVersion = 14.0.25123.0 + ///MinimumVisualStudioVersion = 10.0.40219.1 + ///Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2400A22B-695E-4BDF-93CB-8757F5FB3FB7}" + ///EndProject + ///Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{69930DD1-1688-4407-B4AB-B9E2C0BFB284}" + ///EndProject + ///Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dummy", "src\dummy\dummy.csproj", "{ADCB37DA-2469-462F-99 [rest of string was truncated]";. + /// + public static string Solution_WithProjectsAndFoldersAndMissingLine { + get { + return ResourceManager.GetString("Solution_WithProjectsAndFoldersAndMissingLine", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Microsoft Visual Studio Solution File, Format Version 12.00 + ///# Visual Studio Version 16 + ///VisualStudioVersion = 16.0.31702.278 + ///MinimumVisualStudioVersion = 10.0.40219.1 + ///Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dummy", "C:\project\dummy\src\dummy\dummy.csproj", "{A651D04F-DF2B-44C4-A1A2-2ED31CC3F128}" + ///EndProject + ///Global + /// GlobalSection(SolutionConfigurationPlatforms) = preSolution + /// Debug|Any CPU = Debug|Any CPU + /// Release|Any CPU = Release|Any CPU + /// EndGlobalSection + /// GlobalSection(ProjectCon [rest of string was truncated]";. + /// + public static string Solution_WithProjectUsingAbsolutePath { + get { + return ResourceManager.GetString("Solution_WithProjectUsingAbsolutePath", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" standalone="no"?> + ///<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> + ///<properties> + ///<comment>TeamCity build properties without 'system.' prefix</comment> + ///<entry key="teamcity.build.properties.file">/Working/teamcity.build.configuration</entry> + ///<entry key="teamcity.configuration.properties.file">/Working/teamcity.config.configuration</entry> + ///<entry key="teamcity.runner.properties.file">/Working/teamcity.runner.configuration</entry> + ///</properties>. + /// + public static string TeamCity_Build_Properties_Xml { + get { + return ResourceManager.GetString("TeamCity_Build_Properties_Xml", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" standalone="no"?> + ///<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> + ///<properties> + ///<comment>TeamCity configuration parameters for build with id 812869</comment> + ///<entry key="build.counter">414</entry> + ///<entry key="build.number">3246</entry> + ///<entry key="teamcity.build.branch">pull/5</entry> + ///<entry key="teamcity.build.branch.is_default">true</entry> + ///<entry key="teamcity.build.vcs.branch.MyVcsRootName">refs/pull/5/merge</entry> + ///</properties>. + /// + public static string TeamCity_Config_Properties_Xml { + get { + return ResourceManager.GetString("TeamCity_Config_Properties_Xml", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" standalone="no"?> + ///<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> + ///<properties> + ///<comment>TeamCity configuration parameters for build with id 812869</comment> + ///<entry key="command.executable">run.cmd</entry> + ///</properties>. + /// + public static string TeamCity_Runner_Properties_Xml { + get { + return ResourceManager.GetString("TeamCity_Runner_Properties_Xml", resourceCulture); + } + } /// /// Looks up a localized string similar to using System.Reflection; @@ -888,5 +973,44 @@ public static string XmlTransformation_Xsl { return ResourceManager.GetString("XmlTransformation_Xsl", resourceCulture); } } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8"?> + ///<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + ///<xsl:output method="html" encoding="utf-8"/> + ///<xsl:param name="BackgroundColor"></xsl:param> + ///<xsl:param name="Color"></xsl:param> + /// + ///<xsl:template match="/"> + ///<html> + /// <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE"> + /// <xsl:for-each select="breakfast_menu/food"> + /// <div style="background-color:{$BackgroundColor};color:{$Color};padding:4px"> + /// [rest of string was truncated]";. + /// + public static string XmlTransformationWithArguments_Xsl { + get { + return ResourceManager.GetString("XmlTransformationWithArguments_Xsl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8"?> + ///<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:input="http://example.com" exclude-result-prefixes="input" version="1.0"> + ///<xsl:output method="html" encoding="utf-8"/> + ///<xsl:param name="input:BackgroundColor"></xsl:param> + ///<xsl:param name="input:Color"></xsl:param> + /// + ///<xsl:template match="/"> + ///<html> + /// <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE"> + /// <xsl:for-each select="breakfast_menu/food"> + /// <di [rest of string was truncated]";. + /// + public static string XmlTransformationWithArgumentsAndNamespace_Xsl { + get { + return ResourceManager.GetString("XmlTransformationWithArgumentsAndNamespace_Xsl", resourceCulture); + } + } } } diff --git a/src/Cake.Common.Tests/Properties/Resources.resx b/src/Cake.Common.Tests/Properties/Resources.resx index 9274332092..69d086648b 100644 --- a/src/Cake.Common.Tests/Properties/Resources.resx +++ b/src/Cake.Common.Tests/Properties/Resources.resx @@ -299,6 +299,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -331,6 +332,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -367,6 +369,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -399,6 +402,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -794,6 +798,11 @@ Line #3]]></releaseNotes> <Project>{ABC3F1CB-F84E-43ED-A120-0CCFE344D250}</Project> <Name>Cake.Common</Name> </ProjectReference> + <ProjectReference Include="..\Cake.Common\Cake.Core.csproj"> + <Project>{6C54B9D8-A47D-45D8-82EF-3ADAF7FDD530}</Project> + <Name>Cake.Core</Name> + <Private>True</Private> + </ProjectReference> </ItemGroup> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> </Project> @@ -896,6 +905,50 @@ Global {5D553DC6-36AB-4823-85BD-A33F57C81381} = {69930DD1-1688-4407-B4AB-B9E2C0BFB284} EndGlobalSection EndGlobal + + + Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2400A22B-695E-4BDF-93CB-8757F5FB3FB7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{69930DD1-1688-4407-B4AB-B9E2C0BFB284}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dummy", "src\dummy\dummy.csproj", "{ADCB37DA-2469-462F-99F6-9D4FB7691A3B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dummy.Tests", "test\dummy.Tests\dummy.Tests.csproj", "{5D553DC6-36AB-4823-85BD-A33F57C81381}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "executable", "executable\executable.csproj", "{CF305C72-F3E0-44AA-9474-6F12C5276F9F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ADCB37DA-2469-462F-99F6-9D4FB7691A3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADCB37DA-2469-462F-99F6-9D4FB7691A3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADCB37DA-2469-462F-99F6-9D4FB7691A3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADCB37DA-2469-462F-99F6-9D4FB7691A3B}.Release|Any CPU.Build.0 = Release|Any CPU + {5D553DC6-36AB-4823-85BD-A33F57C81381}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D553DC6-36AB-4823-85BD-A33F57C81381}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D553DC6-36AB-4823-85BD-A33F57C81381}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D553DC6-36AB-4823-85BD-A33F57C81381}.Release|Any CPU.Build.0 = Release|Any CPU + {CF305C72-F3E0-44AA-9474-6F12C5276F9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF305C72-F3E0-44AA-9474-6F12C5276F9F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF305C72-F3E0-44AA-9474-6F12C5276F9F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF305C72-F3E0-44AA-9474-6F12C5276F9F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + + {ADCB37DA-2469-462F-99F6-9D4FB7691A3B} = {2400A22B-695E-4BDF-93CB-8757F5FB3FB7} + {5D553DC6-36AB-4823-85BD-A33F57C81381} = {69930DD1-1688-4407-B4AB-B9E2C0BFB284} + EndGlobalSection +EndGlobal <?xml version="1.0" encoding="utf-8"?> @@ -929,6 +982,7 @@ EndGlobal <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -968,6 +1022,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -1059,6 +1114,7 @@ Imports System.Runtime.CompilerServices; <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -1115,6 +1171,7 @@ using System.Reflection; <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -1150,6 +1207,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -1182,6 +1240,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -1217,6 +1276,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -1252,6 +1312,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -1287,6 +1348,7 @@ Line #3]]></releaseNotes> <owners>Owner #1,Owner #2</owners> <licenseUrl>https://license.com</licenseUrl> <projectUrl>https://project.com</projectUrl> + <icon>images\icon.png</icon> <iconUrl>https://icon.com</iconUrl> <requireLicenseAcceptance>true</requireLicenseAcceptance> <developmentDependency>true</developmentDependency> @@ -1315,4 +1377,128 @@ Line #3]]></releaseNotes> </files> </package> + + <?xml version="1.0" encoding="utf-8" standalone="no"?> +<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> +<properties> +<comment>TeamCity configuration parameters for build with id 812869</comment> +<entry key="build.counter">414</entry> +<entry key="build.number">3246</entry> +<entry key="teamcity.build.branch">pull/5</entry> +<entry key="teamcity.build.branch.is_default">true</entry> +<entry key="teamcity.build.vcs.branch.MyVcsRootName">refs/pull/5/merge</entry> +</properties> + + + <?xml version="1.0" encoding="utf-8" standalone="no"?> +<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> +<properties> +<comment>TeamCity build properties without 'system.' prefix</comment> +<entry key="teamcity.build.properties.file">/Working/teamcity.build.configuration</entry> +<entry key="teamcity.configuration.properties.file">/Working/teamcity.config.configuration</entry> +<entry key="teamcity.runner.properties.file">/Working/teamcity.runner.configuration</entry> +</properties> + + + <?xml version="1.0" encoding="utf-8" standalone="no"?> +<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> +<properties> +<comment>TeamCity configuration parameters for build with id 812869</comment> +<entry key="command.executable">run.cmd</entry> +</properties> + + + Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31702.278 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dummy", "C:\project\dummy\src\dummy\dummy.csproj", "{A651D04F-DF2B-44C4-A1A2-2ED31CC3F128}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A651D04F-DF2B-44C4-A1A2-2ED31CC3F128}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A651D04F-DF2B-44C4-A1A2-2ED31CC3F128}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A651D04F-DF2B-44C4-A1A2-2ED31CC3F128}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A651D04F-DF2B-44C4-A1A2-2ED31CC3F128}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E70E9E11-7FE4-43FA-8552-347EDAF69F86} + EndGlobalSection +EndGlobal + + + <?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> +<xsl:output method="html" encoding="utf-8"/> +<xsl:param name="BackgroundColor"></xsl:param> +<xsl:param name="Color"></xsl:param> + +<xsl:template match="/"> +<html> + <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE"> + <xsl:for-each select="breakfast_menu/food"> + <div style="background-color:{$BackgroundColor};color:{$Color};padding:4px"> + <span style="font-weight:bold"> + <xsl:value-of select="name" /> + - + </span> + <xsl:value-of select="price" /> + </div> + <div style="margin-left:20px;margin-bottom:1em;font-size:10pt"> + <p> + <xsl:value-of select="description" /> + <span style="font-style:italic"> + ( + <xsl:value-of select="calories" /> + calories per serving) + </span> + </p> + </div> + </xsl:for-each> + </body> +</html> +</xsl:template> +</xsl:stylesheet> + + + <?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:input="http://example.com" exclude-result-prefixes="input" version="1.0"> +<xsl:output method="html" encoding="utf-8"/> +<xsl:param name="input:BackgroundColor"></xsl:param> +<xsl:param name="input:Color"></xsl:param> + +<xsl:template match="/"> +<html> + <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE"> + <xsl:for-each select="breakfast_menu/food"> + <div style="background-color:{$input:BackgroundColor};color:{$input:Color};padding:4px"> + <span style="font-weight:bold"> + <xsl:value-of select="name" /> + - + </span> + <xsl:value-of select="price" /> + </div> + <div style="margin-left:20px;margin-bottom:1em;font-size:10pt"> + <p> + <xsl:value-of select="description" /> + <span style="font-style:italic"> + ( + <xsl:value-of select="calories" /> + calories per serving) + </span> + </p> + </div> + </xsl:for-each> + </body> +</html> +</xsl:template> +</xsl:stylesheet> + \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/ArgumentAliasesTests.cs b/src/Cake.Common.Tests/Unit/ArgumentAliasesTests.cs new file mode 100644 index 0000000000..0d58f75a09 --- /dev/null +++ b/src/Cake.Common.Tests/Unit/ArgumentAliasesTests.cs @@ -0,0 +1,130 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Cake.Core; +using Cake.Core.IO; +using NSubstitute; +using Xunit; + +namespace Cake.Common.Tests.Unit +{ + public sealed class ArgumentAliases + { + private const string WorkingDirectoryArgumentName = "workdir"; + private const string WorkingDirectoryArgumentValue = "c:/data/work"; + private const string OutputFileArgumentName = "outputFile"; + private const string OutputFileArgumentValue = "c:/data/work/output.txt"; + private const string VerboseArgumentName = "verbose"; + private const string VerboseArgumentValueOne = "enabled"; + private const string VerboseArgumentValueTwo = "full"; + + public sealed class TheArgumentOfDirectoryPathMethod + { + [Fact] + public void Should_Convert_A_String_Value_To_A_DirectoryPath_If_Argument_Exist() + { + var context = Substitute.For(); + context.Arguments.GetArguments(WorkingDirectoryArgumentName) + .Returns(new[] { WorkingDirectoryArgumentValue }); + + var result = context.Argument(WorkingDirectoryArgumentName); + + Assert.Equal(WorkingDirectoryArgumentValue, result.FullPath); + } + } + + public sealed class TheArgumentOfFilePathMethod + { + [Fact] + public void Should_Convert_A_String_Value_To_A_FilePath_If_Argument_Exist() + { + var context = Substitute.For(); + context.Arguments.GetArguments(OutputFileArgumentName) + .Returns(new[] { OutputFileArgumentValue }); + + var result = context.Argument(OutputFileArgumentName); + + Assert.Equal(OutputFileArgumentValue, result.FullPath); + } + } + + public sealed class TheArgumentCollectionMethod + { + [Fact] + public void Should_Return_An_Arguments_Dictionary() + { + var context = Substitute.For(); + context.Arguments.GetArguments() + .Returns(new Dictionary> + { + { WorkingDirectoryArgumentName, new[] { WorkingDirectoryArgumentValue } }, + { VerboseArgumentName, new[] { VerboseArgumentValueOne, VerboseArgumentValueTwo } }, + }); + + var result = context.Arguments(); + var wdValues = result[WorkingDirectoryArgumentName]; + var vValues = result[VerboseArgumentName]; + + Assert.Equal(WorkingDirectoryArgumentValue, wdValues.First()); + Assert.Equal(2, vValues.Count); + Assert.Equal(VerboseArgumentValueOne, vValues.ElementAt(0)); + Assert.Equal(VerboseArgumentValueTwo, vValues.ElementAt(1)); + } + + [Fact] + public void Should_Return_An_Arguments_With_Single_DefaultValue() + { + var context = Substitute.For(); + context.Arguments.GetArguments(Arg.Any()) + .Returns(Array.Empty()); + + // Given + var expect = new[] { "a" }; + + // When + var arg = context.Arguments("nonexistingmultipleargs", expect[0]); + + // Then + Assert.Equal(expect, arg); + } + + [Fact] + public void Should_Return_An_Arguments_With_Multiple_DefaultValue() + { + var context = Substitute.For(); + context.Arguments.GetArguments(Arg.Any()) + .Returns(Array.Empty()); + + // Given + var expect = new[] { "a", "b" }; + + // When + var arg = context.Arguments("nonexistingmultipleargs", expect); + + // Then + Assert.Equal(expect, arg); + } + + [Fact] + public void Should_Return_An_Arguments_With_Lazy_DefaultValue() + { + var context = Substitute.For(); + context.Arguments.GetArguments(Arg.Any()) + .Returns(Array.Empty()); + + // Given + var expect = new[] { "a", "b" }; + + // When + var arg = context.Arguments("nonexistingmultipleargs", _ => expect); + + // Then + Assert.Equal(expect, arg); + } + } + } +} diff --git a/src/Cake.Common.Tests/Unit/Build/AzurePipelines/AzurePipelinesCommandTests.cs b/src/Cake.Common.Tests/Unit/Build/AzurePipelines/AzurePipelinesCommandTests.cs index 70cb8b07c9..c57c4ba62a 100644 --- a/src/Cake.Common.Tests/Unit/Build/AzurePipelines/AzurePipelinesCommandTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/AzurePipelines/AzurePipelinesCommandTests.cs @@ -255,6 +255,20 @@ public void Should_Set_Secret_Variable() Assert.Contains(fixture.Writer.Entries, m => m == "##vso[task.setvariable variable=Secret Variable;issecret=true;]Secret Value"); } + [Fact] + public void Should_Set_Output_Variable() + { + // Given + var fixture = new AzurePipelinesFixture(); + var service = fixture.CreateAzurePipelinesService(); + + // When + service.Commands.SetOutputVariable("Output Variable", "Output Value"); + + // Then + Assert.Contains(fixture.Writer.Entries, m => m == "##vso[task.setvariable variable=Output Variable;isOutput=true;]Output Value"); + } + [Fact] public void Should_Upload_Task_Summary() { diff --git a/src/Cake.Common.Tests/Unit/Build/AzurePipelines/AzurePipelinesProviderTests.cs b/src/Cake.Common.Tests/Unit/Build/AzurePipelines/AzurePipelinesProviderTests.cs index fc4353835b..1ea0a99195 100644 --- a/src/Cake.Common.Tests/Unit/Build/AzurePipelines/AzurePipelinesProviderTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/AzurePipelines/AzurePipelinesProviderTests.cs @@ -65,55 +65,6 @@ public void Should_Return_False_If_Not_Running_On_AzurePipelines() } } - public sealed class TheIsRunningOnAzurePipelinesHostedProperty - { - [Fact] - public void Should_Return_True_If_Running_On_AzurePipelinesHosted() - { - // Given - var fixture = new AzurePipelinesFixture(); - fixture.IsRunningOnAzurePipelinesHosted(); - var tfBuild = fixture.CreateAzurePipelinesService(); - - // When - var result = tfBuild.IsRunningOnAzurePipelinesHosted; - - // Then - Assert.True(result); - } - - [Fact] - public void Should_Return_False_If_Not_Running_On_AzurePipelinesHosted() - { - // Given - var fixture = new AzurePipelinesFixture(); - var tfBuild = fixture.CreateAzurePipelinesService(); - - // When - var result = tfBuild.IsRunningOnAzurePipelinesHosted; - - // Then - Assert.False(result); - } - - [Theory] - [InlineData("Hosted Agent 2")] - [InlineData("Azure Pipelines 3")] - public void Should_Return_True_If_Running_On_AzurePipelinesExtraAgent(string agentName) - { - // Given - var fixture = new AzurePipelinesFixture(); - fixture.IsRunningOnAzurePipelinesHosted(agentName); - var tfBuild = fixture.CreateAzurePipelinesService(); - - // When - var result = tfBuild.IsRunningOnAzurePipelinesHosted; - - // Then - Assert.True(result); - } - } - public sealed class TheEnvironmentProperty { [Fact] diff --git a/src/Cake.Common.Tests/Unit/Build/BuildSystemTests.cs b/src/Cake.Common.Tests/Unit/Build/BuildSystemTests.cs index 942c9f53de..9dd8f51de3 100644 --- a/src/Cake.Common.Tests/Unit/Build/BuildSystemTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/BuildSystemTests.cs @@ -15,7 +15,6 @@ using Cake.Common.Build.Jenkins; using Cake.Common.Build.MyGet; using Cake.Common.Build.TeamCity; -using Cake.Common.Build.TFBuild; using Cake.Common.Build.TravisCI; using Cake.Common.Tests.Fixtures.Build; using NSubstitute; @@ -41,12 +40,11 @@ public void Should_Throw_If_AppVeyor_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(null, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(null, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "appVeyorProvider"); @@ -66,12 +64,11 @@ public void Should_Throw_If_TeamCity_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, null, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, null, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "teamCityProvider"); @@ -91,12 +88,11 @@ public void Should_Throw_If_MyGet_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, null, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, null, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "myGetProvider"); @@ -116,12 +112,11 @@ public void Should_Throw_If_Bamboo_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, null, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, null, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "bambooProvider"); @@ -141,12 +136,11 @@ public void Should_Throw_If_ContinuaCI_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, null, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, null, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "continuaCIProvider"); @@ -166,12 +160,11 @@ public void Should_Throw_If_Jenkins_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, null, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, null, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "jenkinsProvider"); @@ -191,12 +184,11 @@ public void Should_Throw_If_Bitrise_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, null, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, null, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "bitriseProvider"); @@ -216,12 +208,11 @@ public void Should_Throw_If_TravisCI_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, null, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, null, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "travisCIProvider"); @@ -241,12 +232,11 @@ public void Should_Throw_If_BitbucketPipelines_Is_Null() var travisCIProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, null, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, null, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "bitbucketPipelinesProvider"); @@ -266,12 +256,11 @@ public void Should_Throw_If_GoCD_Is_Null() var travisCIProvider = Substitute.For(); var bitbucketPipelinesProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, null, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, null, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "goCDProvider"); @@ -291,42 +280,16 @@ public void Should_Throw_If_GitLabCI_Is_Null() var travisCIProvider = Substitute.For(); var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, null, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, null, gitHubActionsProvider, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "gitLabCIProvider"); } - [Fact] - public void Should_Throw_If_TFBuild_Is_Null() - { - // Given - var appVeyorProvider = Substitute.For(); - var teamCityProvider = Substitute.For(); - var myGetProvider = Substitute.For(); - var bambooProvider = Substitute.For(); - var continuaCIProvider = Substitute.For(); - var jenkinsProvider = Substitute.For(); - var bitriseProvider = Substitute.For(); - var travisCIProvider = Substitute.For(); - var bitbucketPipelinesProvider = Substitute.For(); - var goCDProvider = Substitute.For(); - var gitLabCIProvider = Substitute.For(); - var gitHubActionsProvider = Substitute.For(); - var azurePipelinesProvider = Substitute.For(); - - // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, null, gitHubActionsProvider, azurePipelinesProvider)); - - // Then - AssertEx.IsArgumentNullException(result, "tfBuildProvider"); - } - [Fact] public void Should_Throw_If_AzurePipelines_Is_Null() { @@ -343,10 +306,9 @@ public void Should_Throw_If_AzurePipelines_Is_Null() var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, null)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, null)); // Then AssertEx.IsArgumentNullException(result, "azurePipelinesProvider"); @@ -367,11 +329,10 @@ public void Should_Throw_If_GitHubActions_Is_Null() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); // When - var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, null, azurePipelinesProvider)); + var result = Record.Exception(() => new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, null, azurePipelinesProvider)); // Then AssertEx.IsArgumentNullException(result, "gitHubActionsProvider"); @@ -396,7 +357,6 @@ public void Should_Return_True_If_Running_On_AppVeyor() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); @@ -404,7 +364,7 @@ public void Should_Return_True_If_Running_On_AppVeyor() appVeyorProvider.Environment.Returns(appVeyorEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnAppVeyor); @@ -429,7 +389,6 @@ public void Should_Return_True_If_Running_On_TeamCity() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); @@ -437,7 +396,7 @@ public void Should_Return_True_If_Running_On_TeamCity() teamCityProvider.Environment.Returns(teamCityEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnTeamCity); @@ -461,14 +420,13 @@ public void Should_Return_True_If_Running_On_MyGet() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); myGetProvider.IsRunningOnMyGet.Returns(true); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnMyGet); @@ -492,14 +450,13 @@ public void Should_Return_True_If_Running_On_Bamboo() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); bambooProvider.IsRunningOnBamboo.Returns(true); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnBamboo); @@ -523,14 +480,13 @@ public void Should_Return_True_If_Running_On_ContinuaCI() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); continuaCIProvider.IsRunningOnContinuaCI.Returns(true); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnContinuaCI); @@ -555,7 +511,6 @@ public void Should_Return_True_If_Running_On_Jenkins() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); @@ -563,7 +518,7 @@ public void Should_Return_True_If_Running_On_Jenkins() jenkinsProvider.Environment.Returns(jenkinsEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnJenkins); @@ -588,7 +543,6 @@ public void Should_Return_True_If_Running_On_Bitrise() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); @@ -596,7 +550,7 @@ public void Should_Return_True_If_Running_On_Bitrise() bitriseProvider.Environment.Returns(bitriseEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnBitrise); @@ -621,7 +575,6 @@ public void Should_Return_True_If_Running_On_TravisCI() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); @@ -629,7 +582,7 @@ public void Should_Return_True_If_Running_On_TravisCI() travisCIProvider.Environment.Returns(travisCIEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnTravisCI); @@ -654,7 +607,6 @@ public void Should_Return_True_If_Running_On_BitbucketPipelines() var bitbucketPipelinesEnvironment = new BitbucketPipelinesInfoFixture().CreateEnvironmentInfo(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); @@ -662,7 +614,7 @@ public void Should_Return_True_If_Running_On_BitbucketPipelines() bitbucketPipelinesProvider.Environment.Returns(bitbucketPipelinesEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnBitbucketPipelines); @@ -686,14 +638,13 @@ public void Should_Return_True_If_Running_On_GoCD() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); goCDProvider.IsRunningOnGoCD.Returns(true); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnGoCD); @@ -718,7 +669,6 @@ public void Should_Return_True_If_Running_On_GitLabCI() var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); var gitLabCIEnvironment = new GitLabCIInfoFixture().CreateEnvironmentInfo(); - var tfBuildProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); @@ -726,83 +676,13 @@ public void Should_Return_True_If_Running_On_GitLabCI() gitLabCIProvider.Environment.Returns(gitLabCIEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnGitLabCI); } } - public sealed class TheIsRunningOnTFSProperty - { - [Fact] - public void Should_Return_True_If_Running_On_TFS() - { - // Given - var appVeyorProvider = Substitute.For(); - var teamCityProvider = Substitute.For(); - var myGetProvider = Substitute.For(); - var bambooProvider = Substitute.For(); - var continuaCIProvider = Substitute.For(); - var jenkinsProvider = Substitute.For(); - var bitriseProvider = Substitute.For(); - var travisCIProvider = Substitute.For(); - var bitbucketPipelinesProvider = Substitute.For(); - var goCDProvider = Substitute.For(); - var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); - var tfBuildEnvironment = new TFBuildInfoFixture().CreateEnvironmentInfo(); - var gitHubActionsProvider = Substitute.For(); - var azurePipelinesProvider = Substitute.For(); - -#pragma warning disable 618 - tfBuildProvider.IsRunningOnTFS.Returns(true); - tfBuildProvider.Environment.Returns(tfBuildEnvironment); - - // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); - - // Then - Assert.True(buildSystem.IsRunningOnTFS); -#pragma warning restore 618 - } - } - - public sealed class TheIsRunningOnVSTSProperty - { - [Fact] - public void Should_Return_True_If_Running_On_VSTS() - { - // Given - var appVeyorProvider = Substitute.For(); - var teamCityProvider = Substitute.For(); - var myGetProvider = Substitute.For(); - var bambooProvider = Substitute.For(); - var continuaCIProvider = Substitute.For(); - var jenkinsProvider = Substitute.For(); - var bitriseProvider = Substitute.For(); - var travisCIProvider = Substitute.For(); - var bitbucketPipelinesProvider = Substitute.For(); - var goCDProvider = Substitute.For(); - var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); - var tfBuildEnvironment = new TFBuildInfoFixture().CreateEnvironmentInfo(); - var gitHubActionsProvider = Substitute.For(); - var azurePipelinesProvider = Substitute.For(); - -#pragma warning disable 618 - tfBuildProvider.IsRunningOnVSTS.Returns(true); - tfBuildProvider.Environment.Returns(tfBuildEnvironment); - - // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); - - // Then - Assert.True(buildSystem.IsRunningOnVSTS); -#pragma warning restore 618 - } - } - public sealed class TheIsRunningOnAzurePipelinesProperty { [Fact] @@ -820,61 +700,21 @@ public void Should_Return_True_If_Running_On_AzurePipelines() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); - var tfBuildEnvironment = new TFBuildInfoFixture().CreateEnvironmentInfo(); var gitHubActionsProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); var azurePipelinesEnvironment = new AzurePipelinesInfoFixture().CreateEnvironmentInfo(); azurePipelinesProvider.IsRunningOnAzurePipelines.Returns(true); azurePipelinesProvider.Environment.Returns(azurePipelinesEnvironment); - tfBuildProvider.IsRunningOnAzurePipelines.Returns(true); - tfBuildProvider.Environment.Returns(tfBuildEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnAzurePipelines); } } - public sealed class TheIsRunningOnAzurePipelinesHostedProperty - { - [Fact] - public void Should_Return_True_If_Running_On_AzurePipelinesHosted() - { - // Given - var appVeyorProvider = Substitute.For(); - var teamCityProvider = Substitute.For(); - var myGetProvider = Substitute.For(); - var bambooProvider = Substitute.For(); - var continuaCIProvider = Substitute.For(); - var jenkinsProvider = Substitute.For(); - var bitriseProvider = Substitute.For(); - var travisCIProvider = Substitute.For(); - var bitbucketPipelinesProvider = Substitute.For(); - var goCDProvider = Substitute.For(); - var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); - var tfBuildEnvironment = new TFBuildInfoFixture().CreateEnvironmentInfo(); - var gitHubActionsProvider = Substitute.For(); - var azurePipelinesProvider = Substitute.For(); - var azurePipelinesEnvironment = new AzurePipelinesInfoFixture().CreateEnvironmentInfo(); - - azurePipelinesProvider.IsRunningOnAzurePipelinesHosted.Returns(true); - azurePipelinesProvider.Environment.Returns(azurePipelinesEnvironment); - tfBuildProvider.IsRunningOnAzurePipelinesHosted.Returns(true); - tfBuildProvider.Environment.Returns(tfBuildEnvironment); - - // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); - - // Then - Assert.True(buildSystem.IsRunningOnAzurePipelinesHosted); - } - } - public sealed class TheIsRunningOnGitHubActionsProperty { [Fact] @@ -892,7 +732,6 @@ public void Should_Return_True_If_Running_On_GitHubActions() var bitbucketPipelinesProvider = Substitute.For(); var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); - var tfBuildProvider = Substitute.For(); var azurePipelinesProvider = Substitute.For(); var gitHubActionsProvider = Substitute.For(); var gitHubActionsEnvironment = new GitHubActionsInfoFixture().CreateEnvironmentInfo(); @@ -901,7 +740,7 @@ public void Should_Return_True_If_Running_On_GitHubActions() gitHubActionsProvider.Environment.Returns(gitHubActionsEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.True(buildSystem.IsRunningOnGitHubActions); @@ -911,24 +750,21 @@ public void Should_Return_True_If_Running_On_GitHubActions() public sealed class TheProviderProperty { [Theory] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.Local)] - [InlineData(true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.AppVeyor)] - [InlineData(false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.TeamCity)] - [InlineData(false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.MyGet)] - [InlineData(false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.Bamboo)] - [InlineData(false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.ContinuaCI)] - [InlineData(false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, BuildProvider.Jenkins)] - [InlineData(false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, BuildProvider.Bitrise)] - [InlineData(false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, BuildProvider.TravisCI)] - [InlineData(false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, BuildProvider.BitbucketPipelines)] - [InlineData(false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, BuildProvider.GoCD)] - [InlineData(false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, BuildProvider.GitLabCI)] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, BuildProvider.AzurePipelines)] // tfs - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, BuildProvider.AzurePipelinesHosted)] // vsts - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, BuildProvider.AzurePipelines)] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, false, BuildProvider.AzurePipelinesHosted)] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, BuildProvider.GitHubActions)] - public void Should_Return_Provider_If_Running_On_Provider(bool appVeyor, bool teamCity, bool myGet, bool bamboo, bool continuaCI, bool jenkins, bool bitrise, bool travisCI, bool bitbucketPipelines, bool goCD, bool gitLabCI, bool tfs, bool vsts, bool azurePipelines, bool azurePipelinesHosted, bool gitHubActions, BuildProvider provider) + [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.Local)] + [InlineData(true, false, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.AppVeyor)] + [InlineData(false, true, false, false, false, false, false, false, false, false, false, false, false, BuildProvider.TeamCity)] + [InlineData(false, false, true, false, false, false, false, false, false, false, false, false, false, BuildProvider.MyGet)] + [InlineData(false, false, false, true, false, false, false, false, false, false, false, false, false, BuildProvider.Bamboo)] + [InlineData(false, false, false, false, true, false, false, false, false, false, false, false, false, BuildProvider.ContinuaCI)] + [InlineData(false, false, false, false, false, true, false, false, false, false, false, false, false, BuildProvider.Jenkins)] + [InlineData(false, false, false, false, false, false, true, false, false, false, false, false, false, BuildProvider.Bitrise)] + [InlineData(false, false, false, false, false, false, false, true, false, false, false, false, false, BuildProvider.TravisCI)] + [InlineData(false, false, false, false, false, false, false, false, true, false, false, false, false, BuildProvider.BitbucketPipelines)] + [InlineData(false, false, false, false, false, false, false, false, false, true, false, false, false, BuildProvider.GoCD)] + [InlineData(false, false, false, false, false, false, false, false, false, false, true, false, false, BuildProvider.GitLabCI)] + [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, BuildProvider.AzurePipelines)] + [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, true, BuildProvider.GitHubActions)] + public void Should_Return_Provider_If_Running_On_Provider(bool appVeyor, bool teamCity, bool myGet, bool bamboo, bool continuaCI, bool jenkins, bool bitrise, bool travisCI, bool bitbucketPipelines, bool goCD, bool gitLabCI, bool azurePipelines, bool gitHubActions, BuildProvider provider) { // Given var appVeyorProvider = Substitute.For(); @@ -949,8 +785,6 @@ public void Should_Return_Provider_If_Running_On_Provider(bool appVeyor, bool te var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); var gitLabCIEnvironment = new GitLabCIInfoFixture().CreateEnvironmentInfo(); - var tfBuildProvider = Substitute.For(); - var tfBuildEnvironment = new TFBuildInfoFixture().CreateEnvironmentInfo(); var gitHubActionsProvider = Substitute.For(); var gitHubActionsEnvironment = new GitHubActionsInfoFixture().CreateEnvironmentInfo(); var azurePipelinesProvider = Substitute.For(); @@ -974,21 +808,13 @@ public void Should_Return_Provider_If_Running_On_Provider(bool appVeyor, bool te goCDProvider.IsRunningOnGoCD.Returns(goCD); gitLabCIProvider.IsRunningOnGitLabCI.Returns(gitLabCI); gitLabCIProvider.Environment.Returns(gitLabCIEnvironment); -#pragma warning disable 618 - tfBuildProvider.IsRunningOnTFS.Returns(tfs); - tfBuildProvider.IsRunningOnVSTS.Returns(vsts); -#pragma warning restore 618 - tfBuildProvider.IsRunningOnAzurePipelines.Returns(azurePipelines); - tfBuildProvider.IsRunningOnAzurePipelinesHosted.Returns(azurePipelinesHosted); - tfBuildProvider.Environment.Returns(tfBuildEnvironment); gitHubActionsProvider.IsRunningOnGitHubActions.Returns(gitHubActions); gitHubActionsProvider.Environment.Returns(gitHubActionsEnvironment); azurePipelinesProvider.IsRunningOnAzurePipelines.Returns(azurePipelines); - azurePipelinesProvider.IsRunningOnAzurePipelinesHosted.Returns(azurePipelinesHosted); azurePipelinesProvider.Environment.Returns(azurePipelinesEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.Equal(provider, buildSystem.Provider); @@ -998,24 +824,21 @@ public void Should_Return_Provider_If_Running_On_Provider(bool appVeyor, bool te public sealed class TheIsLocalBuildProperty { [Theory] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true)] - [InlineData(true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false)] - [InlineData(false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false)] - [InlineData(false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false)] - [InlineData(false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false)] - [InlineData(false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false)] - [InlineData(false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false)] - [InlineData(false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false)] - [InlineData(false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false)] - [InlineData(false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false)] - [InlineData(false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false)] - [InlineData(false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false)] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, false)] // tfs - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false)] // vsts - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false)] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, false, false)] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false)] - public void Should_Return_False_If_Running_On_Provider(bool appVeyor, bool teamCity, bool myGet, bool bamboo, bool continuaCI, bool jenkins, bool bitrise, bool travisCI, bool bitbucketPipelines, bool goCD, bool gitLabCI, bool tfs, bool vsts, bool azurePipelines, bool azurePipelinesHosted, bool gitHubActions, bool isLocalBuild) + [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, true)] + [InlineData(true, false, false, false, false, false, false, false, false, false, false, false, false, false)] + [InlineData(false, true, false, false, false, false, false, false, false, false, false, false, false, false)] + [InlineData(false, false, true, false, false, false, false, false, false, false, false, false, false, false)] + [InlineData(false, false, false, true, false, false, false, false, false, false, false, false, false, false)] + [InlineData(false, false, false, false, true, false, false, false, false, false, false, false, false, false)] + [InlineData(false, false, false, false, false, true, false, false, false, false, false, false, false, false)] + [InlineData(false, false, false, false, false, false, true, false, false, false, false, false, false, false)] + [InlineData(false, false, false, false, false, false, false, true, false, false, false, false, false, false)] + [InlineData(false, false, false, false, false, false, false, false, true, false, false, false, false, false)] + [InlineData(false, false, false, false, false, false, false, false, false, true, false, false, false, false)] + [InlineData(false, false, false, false, false, false, false, false, false, false, true, false, false, false)] + [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, false)] + [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, true, false)] + public void Should_Return_Whether_Or_Not_Running_On_Provider(bool appVeyor, bool teamCity, bool myGet, bool bamboo, bool continuaCI, bool jenkins, bool bitrise, bool travisCI, bool bitbucketPipelines, bool goCD, bool gitLabCI, bool azurePipelines, bool gitHubActions, bool isLocalBuild) { // Given var appVeyorProvider = Substitute.For(); @@ -1036,8 +859,6 @@ public void Should_Return_False_If_Running_On_Provider(bool appVeyor, bool teamC var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); var gitLabCIEnvironment = new GitLabCIInfoFixture().CreateEnvironmentInfo(); - var tfBuildProvider = Substitute.For(); - var tfBuildEnvironment = new TFBuildInfoFixture().CreateEnvironmentInfo(); var gitHubActionsProvider = Substitute.For(); var gitHubActionsEnvironment = new GitHubActionsInfoFixture().CreateEnvironmentInfo(); var azurePipelinesProvider = Substitute.For(); @@ -1061,22 +882,14 @@ public void Should_Return_False_If_Running_On_Provider(bool appVeyor, bool teamC goCDProvider.IsRunningOnGoCD.Returns(goCD); gitLabCIProvider.IsRunningOnGitLabCI.Returns(gitLabCI); gitLabCIProvider.Environment.Returns(gitLabCIEnvironment); -#pragma warning disable 618 - tfBuildProvider.IsRunningOnTFS.Returns(tfs); - tfBuildProvider.IsRunningOnVSTS.Returns(vsts); -#pragma warning restore 618 - tfBuildProvider.IsRunningOnAzurePipelines.Returns(azurePipelines); - tfBuildProvider.IsRunningOnAzurePipelinesHosted.Returns(azurePipelinesHosted); - tfBuildProvider.Environment.Returns(tfBuildEnvironment); gitHubActionsProvider.IsRunningOnGitHubActions.Returns(gitHubActions); gitHubActionsProvider.Environment.Returns(gitHubActionsEnvironment); azurePipelinesProvider.IsRunningOnAzurePipelines.Returns(azurePipelines); - azurePipelinesProvider.IsRunningOnAzurePipelinesHosted.Returns(azurePipelinesHosted); azurePipelinesProvider.Environment.Returns(azurePipelinesEnvironment); // When System.Console.WriteLine(jenkinsProvider); - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.Equal(isLocalBuild, buildSystem.IsLocalBuild); @@ -1086,24 +899,21 @@ public void Should_Return_False_If_Running_On_Provider(bool appVeyor, bool teamC public sealed class TheIsPullRequestProperty { [Theory] - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false)] // none - [InlineData(true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true)] // appveyor - [InlineData(false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true)] // teamcity - [InlineData(false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false)] // myget - [InlineData(false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false)] // bamboo - [InlineData(false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false)] // continua - [InlineData(false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, true)] // jenkins - [InlineData(false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true)] // bitrise - [InlineData(false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, true)] // travis - [InlineData(false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true)] // bitbucket - [InlineData(false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false)] // gocd - [InlineData(false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, true)] // gitlab - [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, true)] // tfs - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, true)] // vsts - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true)] // az pipelines - [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, false, true)] // az pipelines hosted - [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true)] // gh actions - public void Should_Return_True_If_Running_On_Supported_Provider(bool appVeyor, bool teamCity, bool myGet, bool bamboo, bool continuaCI, bool jenkins, bool bitrise, bool travisCI, bool bitbucketPipelines, bool goCD, bool gitLabCI, bool tfs, bool vsts, bool azurePipelines, bool azurePipelinesHosted, bool gitHubActions, bool isPullRequest) + [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, false, false)] // none + [InlineData(true, false, false, false, false, false, false, false, false, false, false, false, false, true)] // appveyor + [InlineData(false, true, false, false, false, false, false, false, false, false, false, false, false, true)] // teamcity + [InlineData(false, false, true, false, false, false, false, false, false, false, false, false, false, false)] // myget + [InlineData(false, false, false, true, false, false, false, false, false, false, false, false, false, false)] // bamboo + [InlineData(false, false, false, false, true, false, false, false, false, false, false, false, false, false)] // continua + [InlineData(false, false, false, false, false, true, false, false, false, false, false, false, false, true)] // jenkins + [InlineData(false, false, false, false, false, false, true, false, false, false, false, false, false, true)] // bitrise + [InlineData(false, false, false, false, false, false, false, true, false, false, false, false, false, true)] // travis + [InlineData(false, false, false, false, false, false, false, false, true, false, false, false, false, true)] // bitbucket + [InlineData(false, false, false, false, false, false, false, false, false, true, false, false, false, false)] // gocd + [InlineData(false, false, false, false, false, false, false, false, false, false, true, false, false, true)] // gitlab + [InlineData(false, false, false, false, false, false, false, false, false, false, false, true, false, true)] // az pipelines + [InlineData(false, false, false, false, false, false, false, false, false, false, false, false, true, true)] // gh actions + public void Should_Return_True_If_Running_On_Supported_Provider(bool appVeyor, bool teamCity, bool myGet, bool bamboo, bool continuaCI, bool jenkins, bool bitrise, bool travisCI, bool bitbucketPipelines, bool goCD, bool gitLabCI, bool azurePipelines, bool gitHubActions, bool isPullRequest) { // Given var appVeyorProvider = Substitute.For(); @@ -1124,8 +934,6 @@ public void Should_Return_True_If_Running_On_Supported_Provider(bool appVeyor, b var goCDProvider = Substitute.For(); var gitLabCIProvider = Substitute.For(); var gitLabCIEnvironment = new GitLabCIInfoFixture().CreateEnvironmentInfo(); - var tfBuildProvider = Substitute.For(); - var tfBuildEnvironment = new TFBuildInfoFixture().CreateEnvironmentInfo(); var gitHubActionsProvider = Substitute.For(); var gitHubActionsEnvironment = new GitHubActionsInfoFixture().CreateEnvironmentInfo(); var azurePipelinesProvider = Substitute.For(); @@ -1149,21 +957,13 @@ public void Should_Return_True_If_Running_On_Supported_Provider(bool appVeyor, b goCDProvider.IsRunningOnGoCD.Returns(goCD); gitLabCIProvider.IsRunningOnGitLabCI.Returns(gitLabCI); gitLabCIProvider.Environment.Returns(gitLabCIEnvironment); -#pragma warning disable 618 - tfBuildProvider.IsRunningOnTFS.Returns(tfs); - tfBuildProvider.IsRunningOnVSTS.Returns(vsts); -#pragma warning restore 618 - tfBuildProvider.IsRunningOnAzurePipelines.Returns(azurePipelines); - tfBuildProvider.IsRunningOnAzurePipelinesHosted.Returns(azurePipelinesHosted); - tfBuildProvider.Environment.Returns(tfBuildEnvironment); gitHubActionsProvider.IsRunningOnGitHubActions.Returns(gitHubActions); gitHubActionsProvider.Environment.Returns(gitHubActionsEnvironment); azurePipelinesProvider.IsRunningOnAzurePipelines.Returns(azurePipelines); - azurePipelinesProvider.IsRunningOnAzurePipelinesHosted.Returns(azurePipelinesHosted); azurePipelinesProvider.Environment.Returns(azurePipelinesEnvironment); // When - var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + var buildSystem = new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); // Then Assert.Equal(isPullRequest, buildSystem.IsPullRequest); diff --git a/src/Cake.Common.Tests/Unit/Build/GitHubActions/Commands/GitHubActionsCommandsTests.cs b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Commands/GitHubActionsCommandsTests.cs new file mode 100644 index 0000000000..6661c123de --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Commands/GitHubActionsCommandsTests.cs @@ -0,0 +1,418 @@ +using System.IO; +using System.Threading.Tasks; +using Cake.Common.Build.GitHubActions.Commands; +using Cake.Common.Tests.Fixtures.Build; +using Cake.Core; +using Cake.Core.IO; +using Cake.Testing; +using NSubstitute; +using Xunit; + +namespace Cake.Common.Tests.Unit.Build.GitHubActions.Commands +{ + public sealed class GitHubActionsCommandsTests + { + public sealed class TheConstructor + { + [Fact] + public void Should_Throw_If_Environment_Is_Null() + { + // Given, When + var result = Record.Exception(() => new GitHubActionsCommands(null, null, null, null)); + + // Then + AssertEx.IsArgumentNullException(result, "environment"); + } + + [Fact] + public void Should_Throw_If_FileSystem_Is_Null() + { + // Given + var environment = Substitute.For(); + + // When + var result = Record.Exception(() => new GitHubActionsCommands(environment, null, null, null)); + + // Then + AssertEx.IsArgumentNullException(result, "fileSystem"); + } + + [Fact] + public void Should_Throw_If_ActionsEnvironment_Is_Null() + { + // Given + var environment = Substitute.For(); + var filesystem = Substitute.For(); + + // When + var result = Record.Exception(() => new GitHubActionsCommands(environment, filesystem, null, null)); + + // Then + AssertEx.IsArgumentNullException(result, "actionsEnvironment"); + } + + [Fact] + public void Should_Throw_If_CreateHttpClient_Is_Null() + { + // Given + var environment = Substitute.For(); + var filesystem = Substitute.For(); + var actionsEnvironment = new GitHubActionsInfoFixture().CreateEnvironmentInfo(); + + // When + var result = Record.Exception(() => new GitHubActionsCommands(environment, filesystem, actionsEnvironment, null)); + + // Then + AssertEx.IsArgumentNullException(result, "createHttpClient"); + } + } + + public sealed class TheAddPathMethod + { + [Fact] + public void Should_Throw_If_Path_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + + // When + var result = Record.Exception(() => commands.AddPath(null)); + + // Then + AssertEx.IsArgumentNullException(result, "path"); + } + + [Fact] + public void Should_Throw_If_SystemPath_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture() + .WithNoGitHubPath() + .CreateGitHubActionsCommands(); + + var path = "/temp/dev/bin"; + + // When + var result = Record.Exception(() => commands.AddPath(path)); + + // Then + AssertEx.IsCakeException(result, "GitHub Actions Runtime SystemPath missing."); + } + + [Fact] + public void Should_AddPath() + { + // Given + var gitHubActionsCommandsFixture = new GitHubActionsCommandsFixture(); + var commands = gitHubActionsCommandsFixture.CreateGitHubActionsCommands(); + var path = "/temp/dev/bin"; + + // When + commands.AddPath(path); + + // Then + Assert.Equal( + (path + System.Environment.NewLine).NormalizeLineEndings(), + gitHubActionsCommandsFixture.FileSystem.GetFile("/opt/github.path").GetTextContent().NormalizeLineEndings()); + } + } + + public sealed class TheSetEnvironmentVariableMethod + { + [Fact] + public void Should_Throw_If_Key_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + + // When + var result = Record.Exception(() => commands.SetEnvironmentVariable(null, null)); + + // Then + AssertEx.IsArgumentNullException(result, "key"); + } + + [Fact] + public void Should_Throw_If_Value_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + var key = "Key"; + + // When + var result = Record.Exception(() => commands.SetEnvironmentVariable(key, null)); + + // Then + AssertEx.IsArgumentNullException(result, "value"); + } + + [Fact] + public void Should_Throw_If_EnvPath_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture() + .WithNoGitHubEnv() + .CreateGitHubActionsCommands(); + + var key = "Key"; + var value = "Value"; + + // When + var result = Record.Exception(() => commands.SetEnvironmentVariable(key, value)); + + // Then + AssertEx.IsCakeException(result, "GitHub Actions Runtime EnvPath missing."); + } + + [Fact] + public void Should_SetEnvironmentVariable() + { + // Given + var gitHubActionsCommandsFixture = new GitHubActionsCommandsFixture(); + var commands = gitHubActionsCommandsFixture.CreateGitHubActionsCommands(); + var key = "Key"; + var value = "Value"; + + // When + commands.SetEnvironmentVariable(key, value); + + // Then + Assert.Equal( + @"Key< commands.UploadArtifact(path, null)); + + // Then + AssertEx.IsArgumentNullException(result, "path"); + } + + [Fact] + public async Task Should_Throw_If_ArtifactName_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + var path = FilePath.FromString("/artifacts/artifact.zip"); + + // When + var result = await Record.ExceptionAsync(() => commands.UploadArtifact(path, null)); + + // Then + AssertEx.IsArgumentNullException(result, "artifactName"); + } + + [Fact] + public async Task Should_Throw_If_File_Missing() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + var path = FilePath.FromString("/artifacts/artifact.zip"); + var artifactName = "artifact"; + + // When + var result = await Record.ExceptionAsync(() => commands.UploadArtifact(path, artifactName)); + + // Then + AssertEx.IsExceptionWithMessage(result, "Artifact file not found."); + } + + [Theory] + [InlineData("/", "/artifacts/artifact.txt")] + [InlineData("/artifacts", "artifact.txt")] + public async Task Should_Upload(string workingDirectory, string testPath) + { + // Given + var gitHubActionsCommandsFixture = new GitHubActionsCommandsFixture() + .WithWorkingDirectory(workingDirectory); + var testFilePath = FilePath.FromString(testPath); + var artifactName = "artifact"; + gitHubActionsCommandsFixture + .FileSystem + .CreateFile("/artifacts/artifact.txt") + .SetContent(artifactName); + var commands = gitHubActionsCommandsFixture.CreateGitHubActionsCommands(); + + // When + await commands.UploadArtifact(testFilePath, artifactName); + } + } + + public sealed class Directory + { + [Fact] + public async Task Should_Throw_If_Path_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + DirectoryPath path = null; + + // When + var result = await Record.ExceptionAsync(() => commands.UploadArtifact(path, null)); + + // Then + AssertEx.IsArgumentNullException(result, "path"); + } + + [Fact] + public async Task Should_Throw_If_ArtifactName_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + var path = DirectoryPath.FromString("/artifacts"); + + // When + var result = await Record.ExceptionAsync(() => commands.UploadArtifact(path, null)); + + // Then + AssertEx.IsArgumentNullException(result, "artifactName"); + } + + [Fact] + public async Task Should_Throw_If_Directory_Missing() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + var path = DirectoryPath.FromString("/artifacts"); + var artifactName = "artifact"; + + // When + var result = await Record.ExceptionAsync(() => commands.UploadArtifact(path, artifactName)); + + // Then + AssertEx.IsExceptionWithMessage(result, "Artifact directory /artifacts not found."); + } + + [Theory] + [InlineData("/", "/src/artifacts")] + [InlineData("/src", "artifacts")] + public async Task Should_Upload(string workingDirectory, string testPath) + { + // Given + var gitHubActionsCommandsFixture = new GitHubActionsCommandsFixture() + .WithWorkingDirectory(workingDirectory); + var testDirectoryPath = DirectoryPath.FromString(testPath); + var artifactName = "artifacts"; + var directory = DirectoryPath.FromString("/src/artifacts"); + + gitHubActionsCommandsFixture + .FileSystem + .CreateFile(directory.CombineWithFilePath("artifact.txt")) + .SetContent(artifactName); + + gitHubActionsCommandsFixture + .FileSystem + .CreateFile(directory.Combine("folder_a").CombineWithFilePath("artifact.txt")) + .SetContent(artifactName); + + gitHubActionsCommandsFixture + .FileSystem + .CreateFile(directory.Combine("folder_b").CombineWithFilePath("artifact.txt")) + .SetContent(artifactName); + + gitHubActionsCommandsFixture + .FileSystem + .CreateFile(directory.Combine("folder_b").Combine("folder_c").CombineWithFilePath("artifact.txt")) + .SetContent(artifactName); + + var commands = gitHubActionsCommandsFixture.CreateGitHubActionsCommands(); + + // When + await commands.UploadArtifact(testDirectoryPath, artifactName); + } + } + } + + public sealed class TheDownloadArtifactMethod + { + [Fact] + public async Task Should_Throw_If_ArtifactName_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + var path = DirectoryPath.FromString("/artifacts"); + + // When + var result = await Record.ExceptionAsync(() => commands.DownloadArtifact(null, path)); + + // Then + AssertEx.IsArgumentNullException(result, "artifactName"); + } + + [Fact] + public async Task Should_Throw_If_Path_Is_Null() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + var artifactName = "artifactName"; + + // When + var result = await Record.ExceptionAsync(() => commands.DownloadArtifact(artifactName, null)); + + // Then + AssertEx.IsArgumentNullException(result, "path"); + } + + [Fact] + public async Task Should_Throw_If_Directory_Missing() + { + // Given + var commands = new GitHubActionsCommandsFixture().CreateGitHubActionsCommands(); + var path = DirectoryPath.FromString("/artifacts"); + var artifactName = "artifact"; + + // When + var result = await Record.ExceptionAsync(() => commands.DownloadArtifact(artifactName, path)); + + // Then + AssertEx.IsExceptionWithMessage(result, "Local directory /artifacts not found."); + } + + [Theory] + [InlineData("/", "/src/artifacts")] + [InlineData("/src", "artifacts")] + public async Task Should_Download(string workingDirectory, string testPath) + { + // Given + var gitHubActionsCommandsFixture = new GitHubActionsCommandsFixture() + .WithWorkingDirectory(workingDirectory); + var testDirectoryPath = DirectoryPath.FromString(testPath); + var artifactName = "artifact"; + var directory = DirectoryPath.FromString("/src/artifacts"); + var filePath = directory.CombineWithFilePath("test.txt"); + + gitHubActionsCommandsFixture + .FileSystem + .CreateDirectory(directory); + + var commands = gitHubActionsCommandsFixture.CreateGitHubActionsCommands(); + + // When + await commands.DownloadArtifact(artifactName, testDirectoryPath); + var file = gitHubActionsCommandsFixture + .FileSystem + .GetFile(filePath); + + // Then + Assert.True(file.Exists, $"{filePath.FullPath} doesn't exist."); + Assert.Equal("Cake", file.GetTextContent()); + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsEnvironmentInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsEnvironmentInfoTests.cs index f147ee0d65..27c6815b0a 100644 --- a/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsEnvironmentInfoTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsEnvironmentInfoTests.cs @@ -18,7 +18,7 @@ public void Should_Return_Correct_Values() var info = new GitHubActionsInfoFixture().CreateEnvironmentInfo(); // When - var result = info.Home; + var result = info.Home.FullPath; // Then Assert.Equal("/home/runner", result); diff --git a/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsRunnerInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsRunnerInfoTests.cs index 236c8e3a81..bca1252fa3 100644 --- a/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsRunnerInfoTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsRunnerInfoTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Build.GitHubActions.Data; using Cake.Common.Tests.Fixtures.Build; using Xunit; @@ -9,6 +10,22 @@ namespace Cake.Common.Tests.Unit.Build.GitHubActions.Data { public sealed class GitHubActionsRunnerInfoTests { + public sealed class TheNameProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRunnerInfo(); + + // When + var result = info.Name; + + // Then + Assert.Equal("RunnerName", result); + } + } + // ReSharper disable once InconsistentNaming public sealed class TheOSProperty { @@ -35,7 +52,7 @@ public void Should_Return_Correct_Value() var info = new GitHubActionsInfoFixture().CreateRunnerInfo(); // When - var result = info.Temp; + var result = info.Temp.FullPath; // Then Assert.Equal("/home/runner/work/_temp", result); @@ -51,7 +68,7 @@ public void Should_Return_Correct_Value() var info = new GitHubActionsInfoFixture().CreateRunnerInfo(); // When - var result = info.ToolCache; + var result = info.ToolCache.FullPath; // Then Assert.Equal("/opt/hostedtoolcache", result); @@ -67,11 +84,80 @@ public void Should_Return_Correct_Value() var info = new GitHubActionsInfoFixture().CreateRunnerInfo(); // When - var result = info.Workspace; + var result = info.Workspace.FullPath; // Then Assert.Equal("/home/runner/work/cake", result); } } + + public sealed class TheImageOSProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRunnerInfo(); + + // When + var result = info.ImageOS; + + // Then + Assert.Equal("ubuntu20", result); + } + } + + public sealed class TheImageVersionProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRunnerInfo(); + + // When + var result = info.ImageVersion; + + // Then + Assert.Equal("20211209.3", result); + } + } + + public sealed class TheUserProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRunnerInfo(); + + // When + var result = info.User; + + // Then + Assert.Equal("runner", result); + } + } + + public sealed class TheArchitectureProperty + { + [Theory] + [InlineData("X86", GitHubActionsArchitecture.X86)] + [InlineData("X64", GitHubActionsArchitecture.X64)] + [InlineData("ARM", GitHubActionsArchitecture.ARM)] + [InlineData("ARM64", GitHubActionsArchitecture.ARM64)] + [InlineData("", GitHubActionsArchitecture.Unknown)] + public void Should_Return_Correct_Value(string value, GitHubActionsArchitecture expected) + { + // Given + var info = new GitHubActionsInfoFixture().CreateRunnerInfo(architecture: value); + + // When + var result = info.Architecture; + + // Then + Assert.Equal(expected, result); + } + } } } diff --git a/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsRuntimeInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsRuntimeInfoTests.cs new file mode 100644 index 0000000000..f9a966960f --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsRuntimeInfoTests.cs @@ -0,0 +1,88 @@ +using Cake.Common.Tests.Fixtures.Build; +using Xunit; + +namespace Cake.Common.Tests.Unit.Build.GitHubActions.Data +{ + public sealed class GitHubActionsRuntimeInfoTests + { + public sealed class TheIsRuntimeAvailableProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRuntimeInfo(); + + // When + var result = info.IsRuntimeAvailable; + + // Then + Assert.Equal(true, result); + } + } + + public sealed class TheTokenProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRuntimeInfo(); + + // When + var result = info.Token; + + // Then + Assert.Equal("zht1j5NeW2T5ZsOxncX4CUEiWYhD4ZRwoDghkARk", result); + } + } + + public sealed class TheUrlProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRuntimeInfo(); + + // When + var result = info.Url; + + // Then + Assert.Equal("https://pipelines.actions.githubusercontent.com/ip0FyYnZXxdEOcOwPHkRsZJd2x6G5XoT486UsAb0/", result); + } + } + + public sealed class TheEnvPathProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRuntimeInfo(); + + // When + var result = info.EnvPath.FullPath; + + // Then + Assert.Equal("/opt/github.env", result); + } + } + + public sealed class TheSystemPathProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateRuntimeInfo(); + + // When + var result = info.SystemPath.FullPath; + + // Then + Assert.Equal("/opt/github.path", result); + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsWorkflowInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsWorkflowInfoTests.cs index 2d878e60b1..fa523ba95a 100644 --- a/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsWorkflowInfoTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/GitHubActions/Data/GitHubActionsWorkflowInfoTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Build.GitHubActions.Data; using Cake.Common.Tests.Fixtures.Build; using Xunit; @@ -25,6 +26,22 @@ public void Should_Return_Correct_Value() } } + public sealed class TheActionPathProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); + + // When + var result = info.ActionPath.FullPath; + + // Then + Assert.Equal("/path/to/action", result); + } + } + public sealed class TheActorProperty { [Fact] @@ -41,6 +58,22 @@ public void Should_Return_Correct_Value() } } + public sealed class TheApiUrlProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); + + // When + var result = info.ApiUrl; + + // Then + Assert.Equal("https://api.github.com", result); + } + } + public sealed class TheBaseRefProperty { [Fact] @@ -82,13 +115,29 @@ public void Should_Return_Correct_Value() var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); // When - var result = info.EventPath; + var result = info.EventPath.FullPath; // Then Assert.Equal("/home/runner/work/_temp/_github_workflow/event.json", result); } } + public sealed class TheGraphQLUrlProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); + + // When + var result = info.GraphQLUrl; + + // Then + Assert.Equal("https://api.github.com/graphql", result); + } + } + public sealed class TheHeadRefProperty { [Fact] @@ -201,6 +250,22 @@ public void Should_Return_Correct_Value() } } + public sealed class TheServerUrlProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); + + // When + var result = info.ServerUrl; + + // Then + Assert.Equal("https://github.com", result); + } + } + public sealed class TheShaProperty { [Fact] @@ -242,11 +307,78 @@ public void Should_Return_Correct_Value() var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); // When - var result = info.Workspace; + var result = info.Workspace.FullPath; // Then Assert.Equal("/home/runner/work/cake/cake", result); } } + + public sealed class TheAttemptProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); + + // When + var result = info.Attempt; + + // Then + Assert.Equal(2, result); + } + } + + public sealed class TheRefProtectedProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); + + // When + var result = info.RefProtected; + + // Then + Assert.True(result); + } + } + + public sealed class TheRefNameProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(); + + // When + var result = info.RefName; + + // Then + Assert.Equal("main", result); + } + } + + public sealed class TheRefTypeProperty + { + [Theory] + [InlineData("branch", GitHubActionsRefType.Branch)] + [InlineData("tag", GitHubActionsRefType.Tag)] + [InlineData("", GitHubActionsRefType.Unknown)] + public void Should_Return_Correct_Value(string value, GitHubActionsRefType expected) + { + // Given + var info = new GitHubActionsInfoFixture().CreateWorkflowInfo(refType: value); + + // When + var result = info.RefType; + + // Then + Assert.Equal(expected, result); + } + } } } diff --git a/src/Cake.Common.Tests/Unit/Build/GitHubActions/GitHubActionsProviderTests.cs b/src/Cake.Common.Tests/Unit/Build/GitHubActions/GitHubActionsProviderTests.cs index 1c19960527..cb5e387e2e 100644 --- a/src/Cake.Common.Tests/Unit/Build/GitHubActions/GitHubActionsProviderTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/GitHubActions/GitHubActionsProviderTests.cs @@ -4,6 +4,8 @@ using Cake.Common.Build.GitHubActions; using Cake.Common.Tests.Fixtures.Build; +using Cake.Core; +using NSubstitute; using Xunit; namespace Cake.Common.Tests.Unit.Build.GitHubActions @@ -16,11 +18,24 @@ public sealed class TheConstructor public void Should_Throw_If_Environment_Is_Null() { // Given, When - var result = Record.Exception(() => new GitHubActionsProvider(null)); + var result = Record.Exception(() => new GitHubActionsProvider(null, null)); // Then AssertEx.IsArgumentNullException(result, "environment"); } + + [Fact] + public void Should_Throw_If_FileSystem_Is_Null() + { + // Given + var environment = Substitute.For(); + + // When + var result = Record.Exception(() => new GitHubActionsProvider(environment, null)); + + // Then + AssertEx.IsArgumentNullException(result, "fileSystem"); + } } public sealed class TheIsRunningOnGitHubActionsProperty diff --git a/src/Cake.Common.Tests/Unit/Build/MyGet/MyGetProviderTests.cs b/src/Cake.Common.Tests/Unit/Build/MyGet/MyGetProviderTests.cs new file mode 100644 index 0000000000..c6e7c3cb16 --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Build/MyGet/MyGetProviderTests.cs @@ -0,0 +1,179 @@ +using Cake.Common.Build.MyGet; +using Cake.Common.Tests.Fakes; +using Cake.Common.Tests.Fixtures.Build; +using Cake.Core; +using Cake.Testing; +using Xunit; + +namespace Cake.Common.Tests.Unit.Build.MyGet +{ + public sealed class MyGetProviderTests + { + public sealed class TheConstructor + { + [Fact] + public void Should_Throw_If_Environment_Is_Null() + { + // Given, When + var writer = new FakeBuildSystemServiceMessageWriter(); + var result = Record.Exception(() => new MyGetProvider(null, writer)); + + // Then + AssertEx.IsArgumentNullException(result, "environment"); + } + + [Fact] + public void Should_Throw_If_Writer_Is_Null() + { + // Given, When + var result = Record.Exception(() => new MyGetProvider(new FakeEnvironment(PlatformFamily.Unknown), null)); + + // Then + AssertEx.IsArgumentNullException(result, "writer"); + } + } + + public sealed class IsRunningOnMyGet + { + [Theory] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public void Should_Return_True_If_Running_On_MyGet(bool? capitalCase) + { + // Given + var fixture = new MyGetFixture(); + fixture.IsRunningOnMyGet(capitalCase); + var provider = fixture.CreateMyGetProvider(); + + // When + var result = provider.IsRunningOnMyGet; + + // Then + Assert.True(result); + } + + [Fact] + public void Should_Return_False_If_Not_Running_On_MyGet() + { + // Given + var fixture = new MyGetFixture(); + var provider = fixture.CreateMyGetProvider(); + + // When + var result = provider.IsRunningOnMyGet; + + // Then + Assert.False(result); + } + } + + public sealed class BuildProblem + { + [Theory] + [InlineData("Test build problem", "Test build problem")] + [InlineData("", "")] + [InlineData(null, "")] + [InlineData("[Special characters:\r\n\"\'test|split\'\"]", "|[Special characters:|r|n\"|\'test||split|\'\"|]")] + public void Should_Log_Description(string description, string expectedOutput) + { + // Given + var fixture = new MyGetFixture(); + var provider = fixture.CreateMyGetProvider(); + + // When + provider.BuildProblem(description); + + // Then + var entry = Assert.Single(fixture.Writer.Entries); + Assert.Equal($"##myget[buildProblem description='{expectedOutput}']", entry); + } + } + + public sealed class SetParameter + { + [Theory] + [InlineData("Parameter", "Value", "Parameter", "Value")] + [InlineData("", "", "", "")] + [InlineData(null, null, "", "")] + [InlineData("Special [param] \'name\'", "test\n|\r||value||", "Special |[param|] |\'name|\'", "test|n|||r||||value||||")] + public void Should_Log_Parameter_Value(string name, string value, string expectedName, string expectedValue) + { + // Given + var fixture = new MyGetFixture(); + var provider = fixture.CreateMyGetProvider(); + + // When + provider.SetParameter(name, value); + + // Then + var entry = Assert.Single(fixture.Writer.Entries); + Assert.Equal($"##myget[setParameter name='{expectedName}' value='{expectedValue}']", entry); + } + } + + public sealed class WriteStatus + { + [Theory] + [InlineData("M", MyGetBuildStatus.Normal, "M", "NORMAL")] + [InlineData(null, MyGetBuildStatus.Warning, "", "WARNING")] + [InlineData("Message \n text", MyGetBuildStatus.Error, "Message |n text", "ERROR")] + [InlineData("[Failure]|status", MyGetBuildStatus.Failure, "|[Failure|]||status", "FAILURE")] + public void Should_Log_Status(string message, MyGetBuildStatus status, string expectedMessage, string expectedStatus) + { + // Given + var fixture = new MyGetFixture(); + var provider = fixture.CreateMyGetProvider(); + + // When + provider.WriteStatus(message, status); + + // Then + var entry = Assert.Single(fixture.Writer.Entries); + Assert.Equal($"##myget[message text='{expectedMessage}' status='{expectedStatus}']", entry); + } + + [Theory] + [InlineData("Hello, World!", MyGetBuildStatus.Normal, "", "Hello, World!", "NORMAL", "")] + [InlineData("My custom message", MyGetBuildStatus.Warning, "Hello, World!", "My custom message", "WARNING", "Hello, World!")] + [InlineData("Test", MyGetBuildStatus.Error, "r = (a - b) * c + (s1 & s2)", "Test", "ERROR", "r = (a - b) * c + (s1 & s2)")] + [InlineData("T", MyGetBuildStatus.Failure, "i = (b << 4) | c;\r\nr = a[i] / c;", "T", "FAILURE", "i = (b << 4) || c;|r|nr = a|[i|] / c;")] + public void Should_Log_Status_With_Error_Details(string message, MyGetBuildStatus status, string errorDetails, string expectedMessage, string expectedStatus, string expectedDetails) + { + // Given + var fixture = new MyGetFixture(); + var provider = fixture.CreateMyGetProvider(); + + // When + provider.WriteStatus(message, status, errorDetails); + + // Then + var entry = Assert.Single(fixture.Writer.Entries); + Assert.Equal($"##myget[message text='{expectedMessage}' status='{expectedStatus}' errorDetails='{expectedDetails}']", entry); + } + } + + public sealed class SetBuildNumber + { + [Theory] + [InlineData("2.3.1", "2.3.1")] + [InlineData("", "")] + [InlineData(null, "")] + [InlineData("99.4-beta", "99.4-beta")] + [InlineData("[net5.0\r\n\"\'beta|preview\'\"]", "|[net5.0|r|n\"|\'beta||preview|\'\"|]")] + public void Should_Log_Build_Number(string buildNumber, string expectedOutput) + { + // Given + var fixture = new MyGetFixture(); + var provider = fixture.CreateMyGetProvider(); + + // When + provider.SetBuildNumber(buildNumber); + + // Then + var entry = Assert.Single(fixture.Writer.Entries); + Assert.Equal($"##myget[buildNumber '{expectedOutput}']", entry); + } + } + } +} diff --git a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildAgentInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildAgentInfoTests.cs deleted file mode 100644 index 2724959a39..0000000000 --- a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildAgentInfoTests.cs +++ /dev/null @@ -1,185 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Common.Tests.Fixtures.Build; -using Xunit; - -namespace Cake.Common.Tests.Unit.Build.TFBuild.Data -{ - public sealed class TFBuildAgentInfoTests - { - public sealed class TheBuildDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.BuildDirectory; - - // Then - Assert.Equal("c:/agent/_work/1", result.FullPath); - } - } - - public sealed class TheHomeDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.HomeDirectory; - - // Then - Assert.Equal("c:/agent", result.FullPath); - } - } - - public sealed class TheWorkingDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.WorkingDirectory; - - // Then - Assert.Equal("c:/agent/_work", result.FullPath); - } - } - - public sealed class TheIdProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.Id; - - // Then - Assert.Equal(71, result); - } - } - - public sealed class TheNameProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.Name; - - // Then - Assert.Equal("Agent-1", result); - } - } - - public sealed class TheMachineNameProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.MachineName; - - // Then - Assert.Equal("BuildServer", result); - } - } - - public sealed class TheToolsDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.ToolsDirectory; - - // Then - Assert.Equal("C:/hostedtoolcache/windows", result.FullPath); - } - } - - public sealed class TheJobNameProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.JobName; - - // Then - Assert.Equal("Job", result); - } - } - - public sealed class TheJobStatusProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.JobStatus; - - // Then - Assert.Equal("SucceededWithIssues", result); - } - } - - public sealed class TheIsHostedProperty - { - [Fact] - public void Should_Return_True_On_Hosted_Agent() - { - // Given - var info = new TFBuildInfoFixture().CreateHostedAgentInfo(); - - // When - var result = info.IsHosted; - - // Then - Assert.True(result); - } - - [Fact] - public void Should_Return_False_On_Other_Agent() - { - // Given - var info = new TFBuildInfoFixture().CreateAgentInfo(); - - // When - var result = info.IsHosted; - - // Then - Assert.False(result); - } - } - } -} diff --git a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildDefinitionInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildDefinitionInfoTests.cs deleted file mode 100644 index 6447ffeb12..0000000000 --- a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildDefinitionInfoTests.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Common.Tests.Fixtures.Build; -using Xunit; - -namespace Cake.Common.Tests.Unit.Build.TFBuild.Data -{ - public sealed class TFBuildDefinitionInfoTests - { - public sealed class TheIdProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateDefinitionInfo(); - - // When - var result = info.Id; - - // Then - Assert.Equal(1855, result); - } - } - - public sealed class TheNameProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateDefinitionInfo(); - - // When - var result = info.Name; - - // Then - Assert.Equal("Cake-CI", result); - } - } - - public sealed class TheVersionProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateDefinitionInfo(); - - // When - var result = info.Version; - - // Then - Assert.Equal(47, result); - } - } - } -} diff --git a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildInfoTests.cs deleted file mode 100644 index 51b2189631..0000000000 --- a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildInfoTests.cs +++ /dev/null @@ -1,318 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Common.Tests.Fixtures.Build; -using Xunit; - -namespace Cake.Common.Tests.Unit.Build.TFBuild.Data -{ - public sealed class TFBuildInfoTests - { - public sealed class TheIdProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.Id; - - // Then - Assert.Equal(100234, result); - } - } - - public sealed class TheNumberProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.Number; - - // Then - Assert.Equal("Build-20160927.1", result); - } - } - - public sealed class TheUriProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.Uri; - - // Then - var uri = new Uri("vstfs:///Build/Build/1430"); - Assert.Equal(uri, result); - } - } - - public sealed class TheQueuedByProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.QueuedBy; - - // Then - Assert.Equal(@"[DefaultCollection]\Project Collection Service Accounts", result); - } - } - - public sealed class TheRequestedForProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.RequestedFor; - - // Then - Assert.Equal("Alistair Chapman", result); - } - } - - public sealed class TheRequestedForEmailProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.RequestedForEmail; - - // Then - Assert.Equal("author@mail.com", result); - } - } - - public sealed class TheAccessTokenProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.AccessToken; - - // Then - Assert.Equal("f662dbe218144c86bdecb1e9b2eb336c", result); - } - } - - public sealed class TheDebugProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.Debug; - - // Then - Assert.Equal(true, result); - } - } - - public sealed class TheArtifactStagingDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.ArtifactStagingDirectory; - - // Then - Assert.Equal(@"c:/agent/_work/1/a", result.FullPath); - } - } - - public sealed class TheBinariesDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.BinariesDirectory; - - // Then - Assert.Equal(@"c:/agent/_work/1/b", result.FullPath); - } - } - - public sealed class TheSourcesDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.SourcesDirectory; - - // Then - Assert.Equal(@"c:/agent/_work/1/s", result.FullPath); - } - } - - public sealed class TheStagingDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.StagingDirectory; - - // Then - Assert.Equal(@"c:/agent/_work/1/a", result.FullPath); - } - } - - public sealed class TheTestResultsDirectoryProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.TestResultsDirectory; - - // Then - Assert.Equal(@"c:/agent/_work/1/TestResults", result.FullPath); - } - } - - public sealed class TheReasonProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.Reason; - - // Then - Assert.Equal(@"PullRequest", result); - } - } - - public sealed class TheTriggeredByBuildIdProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.TriggeredBy.BuildId; - - // Then - Assert.Equal(1, result); - } - } - - public sealed class TheTriggeredByDefinitionIdProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.TriggeredBy.DefinitionId; - - // Then - Assert.Equal(1, result); - } - } - - public sealed class TheTriggeredByDefinitionNameProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.TriggeredBy.DefinitionName; - - // Then - Assert.Equal(@"Build", result); - } - } - - public sealed class TheTriggeredByBuildNumberProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.TriggeredBy.BuildNumber; - - // Then - Assert.Equal(@"123", result); - } - } - - public sealed class TheTriggeredByProjectIdProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateBuildInfo(); - - // When - var result = info.TriggeredBy.ProjectId; - - // Then - Assert.Equal(@"456", result); - } - } - } -} diff --git a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildPullRequestInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildPullRequestInfoTests.cs deleted file mode 100644 index be2cc07fec..0000000000 --- a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildPullRequestInfoTests.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Common.Tests.Fixtures.Build; -using NSubstitute; -using Xunit; - -namespace Cake.Common.Tests.Unit.Build.TFBuild.Data -{ - public sealed class TFBuildPullRequestInfoTests - { - public sealed class TheIsPullRequestProperty - { - [Theory] - [InlineData("1", true)] - [InlineData("0", false)] - public void Should_Return_Correct_Value(string value, bool expected) - { - // Given - var fixture = new TFBuildInfoFixture(); - fixture.Environment.GetEnvironmentVariable("SYSTEM_PULLREQUEST_PULLREQUESTID").Returns(value); - var info = fixture.CreatePullRequestInfo(); - - // When - var result = info.IsPullRequest; - - // Then - Assert.Equal(expected, result); - } - } - - public sealed class TheIdProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreatePullRequestInfo(); - - // When - var result = info.Id; - - // Then - Assert.Equal(1, result); - } - } - - public sealed class TheNumberProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreatePullRequestInfo(); - - // When - var result = info.Number; - - // Then - Assert.Equal(1, result); - } - } - - public sealed class ThePullRequestIsForkProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreatePullRequestInfo(); - - // When - var result = info.IsFork; - - // Then - Assert.Equal(false, result); - } - } - - public sealed class ThePullRequestSourceBranchProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreatePullRequestInfo(); - - // When - var result = info.SourceBranch; - - // Then - Assert.Equal(@"refs/heads/FeatureBranch", result); - } - } - - public sealed class ThePullRequestSourceRepositoryUriProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreatePullRequestInfo(); - - // When - var result = info.SourceRepositoryUri; - - // Then - Assert.Equal(new Uri(@"https://fabrikamfiber.visualstudio.com/Project/_git/ProjectRepo"), result); - } - } - - public sealed class ThePullRequestTargetBranchProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreatePullRequestInfo(); - - // When - var result = info.TargetBranch; - - // Then - Assert.Equal(@"refs/heads/master", result); - } - } - } -} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildRepositoryInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildRepositoryInfoTests.cs deleted file mode 100644 index ef6783bbf7..0000000000 --- a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildRepositoryInfoTests.cs +++ /dev/null @@ -1,116 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Common.Build.TFBuild.Data; -using Cake.Common.Tests.Fixtures.Build; -using Xunit; - -namespace Cake.Common.Tests.Unit.Build.TFBuild.Data -{ - public sealed class TFBuildRepositoryInfoTests - { - public sealed class TheBranchProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateRepositoryInfo(); - - // When -#pragma warning disable 618 - var result = info.Branch; -#pragma warning restore 618 - - // Then - Assert.Equal("develop", result); - } - } - - public sealed class TheSourceBranchNameProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateRepositoryInfo(); - - // When - var result = info.SourceBranchName; - - // Then - Assert.Equal("develop", result); - } - } - - public sealed class TheSourceVersionProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateRepositoryInfo(); - - // When - var result = info.SourceVersion; - - // Then - Assert.Equal("4efbc1ffb993dfbcf024e6a9202865cc0b6d9c50", result); - } - } - - public sealed class TheShelvesetProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateRepositoryInfo(); - - // When - var result = info.Shelveset; - - // Then - Assert.Equal("Shelveset1", result); - } - } - - public sealed class TheRepoNameProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateRepositoryInfo(); - - // When - var result = info.RepoName; - - // Then - Assert.Equal("cake", result); - } - } - - public sealed class TheProviderProperty - { - [Theory] - [InlineData("Git", TFRepositoryType.Git)] - [InlineData("GitHub", TFRepositoryType.GitHub)] - [InlineData("Svn", TFRepositoryType.Svn)] - [InlineData("TfsGit", TFRepositoryType.TfsGit)] - [InlineData("TfsVersionControl", TFRepositoryType.TfsVersionControl)] - public void Should_Return_Correct_Value(string type, TFRepositoryType provider) - { - // Given - var info = new TFBuildInfoFixture().CreateRepositoryInfo(type); - - // When - var result = info.Provider; - - // Then - Assert.Equal(provider, result); - } - } - } -} diff --git a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildTeamProjectInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildTeamProjectInfoTests.cs deleted file mode 100644 index d66c617c1f..0000000000 --- a/src/Cake.Common.Tests/Unit/Build/TFBuild/Data/TFBuildTeamProjectInfoTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Common.Tests.Fixtures.Build; -using Xunit; - -namespace Cake.Common.Tests.Unit.Build.TFBuild.Data -{ - public sealed class TFBuildTeamProjectInfoTests - { - public sealed class TheNameProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateTeamProjectInfo(); - - // When - var result = info.Name; - - // Then - Assert.Equal("TeamProject", result); - } - } - - public sealed class TheIdProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateTeamProjectInfo(); - - // When - var result = info.Id; - - // Then - Assert.Equal("D0A3B6B8-499B-4D4B-BD46-DB70C19E6D33", result); - } - } - - public sealed class TheCollectionUriProperty - { - [Fact] - public void Should_Return_Correct_Value() - { - // Given - var info = new TFBuildInfoFixture().CreateTeamProjectInfo(); - - // When - var result = info.CollectionUri; - - // Then - var uri = new Uri("https://fabrikamfiber.visualstudio.com/"); - Assert.Equal(uri, result); - } - } - } -} diff --git a/src/Cake.Common.Tests/Unit/Build/TFBuild/TFBuildCommandTests.cs b/src/Cake.Common.Tests/Unit/Build/TFBuild/TFBuildCommandTests.cs deleted file mode 100644 index de71fe1655..0000000000 --- a/src/Cake.Common.Tests/Unit/Build/TFBuild/TFBuildCommandTests.cs +++ /dev/null @@ -1,666 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Linq; -using Cake.Common.Build.TFBuild; -using Cake.Common.Build.TFBuild.Data; -using Cake.Common.Tests.Fakes; -using Cake.Common.Tests.Fixtures.Build; -using Cake.Core; -using Cake.Core.Diagnostics; -using Cake.Core.IO; -using Cake.Testing; -using Cake.Testing.Xunit; -using NSubstitute; -using Xunit; - -namespace Cake.Common.Tests.Unit.Build.TFBuild -{ - public sealed class TFBuildCommandTests - { - public sealed class TheConstructor - { - [Fact] - public void Should_Throw_If_Environment_Is_Null() - { - // Given, When - var result = Record.Exception(() => new TFBuildCommands(null, new FakeBuildSystemServiceMessageWriter())); - - // Then - AssertEx.IsArgumentNullException(result, "environment"); - } - - [Fact] - public void Should_Throw_If_Writer_Is_Null() - { - // Given, When - var result = Record.Exception(() => new TFBuildCommands(new FakeEnvironment(PlatformFamily.Unknown), null)); - - // Then - AssertEx.IsArgumentNullException(result, "writer"); - } - } - - public sealed class TheCommands - { - [Fact] - public void Should_Not_Be_Null() - { - // Given - var fixture = new TFBuildFixture(); - - // When - var service = fixture.CreateTFBuildService(); - - // Then - Assert.NotNull(service.Commands); - } - - [Theory] - [InlineData("warning")] - [InlineData("message")] - public void Should_Log_Warning_Message(string msg) - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.WriteWarning(msg); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.logissue type=warning;]{msg}"); - } - - [Fact] - public void Should_Log_Warning_Message_With_Data() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.WriteWarning("build warning", new TFBuildMessageData - { - SourcePath = "./code file.cs", - LineNumber = 5, - ColumnNumber = 12, - ErrorCode = 9 - }); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.logissue sourcepath=./code file.cs;linenumber=5;columnnumber=12;code=9;type=warning;]build warning"); - } - - [Theory] - [InlineData("error")] - [InlineData("message")] - public void Should_Log_Error_Message(string msg) - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.WriteError(msg); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.logissue type=error;]{msg}"); - } - - [Fact] - public void Should_Log_Error_Message_With_Data() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.WriteError("build error", new TFBuildMessageData - { - SourcePath = "./code.cs", - LineNumber = 1, - ColumnNumber = 2, - ErrorCode = 3 - }); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.logissue sourcepath=./code.cs;linenumber=1;columnnumber=2;code=3;type=error;]build error"); - } - - [Fact] - public void Should_Set_Current_Progress() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.SetProgress(75, "Testing Provider"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.setprogress value=75;]Testing Provider"); - } - - [Fact] - public void Should_Complete_Current_Task() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.CompleteCurrentTask(); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.complete ]DONE"); - } - - [Fact] - public void Should_Complete_Current_Task_With_Status() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.CompleteCurrentTask(TFBuildTaskResult.Failed); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.complete result=Failed;]DONE"); - } - - [Fact] - public void Should_Create_New_Record() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - var guid = service.Commands.CreateNewRecord("New record", "build", 1); - - // Then - Assert.NotNull(guid); - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.logdetail id={guid.ToString()};name=New record;type=build;order=1;]create new timeline record"); - } - - [Fact] - public void Should_Create_New_Record_With_Data() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var date = DateTime.UtcNow; - - // When - var guid = service.Commands.CreateNewRecord("New record", "build", 2, new TFBuildRecordData - { - StartTime = date, - Progress = 75, - Status = TFBuildTaskStatus.Initialized - }); - - // Then - Assert.NotNull(guid); - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.logdetail starttime={date.ToString()};progress=75;state=Initialized;id={guid.ToString()};name=New record;type=build;order=2;]create new timeline record"); - } - - [Fact] - public void Should_Update_Existing_Record() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var guid = Guid.NewGuid(); - var parent = Guid.NewGuid(); - - // When - service.Commands.UpdateRecord(guid, new TFBuildRecordData - { - Progress = 95, - Status = TFBuildTaskStatus.InProgress, - ParentRecord = parent - }); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.logdetail parentid={parent.ToString()};progress=95;state=InProgress;id={guid.ToString()};]update"); - } - - [Fact] - public void Should_Set_Variable() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.SetVariable("varname", "VarValue"); - - // Then - Assert.Contains(fixture.Writer.Entries, - m => m == $"##vso[task.setvariable variable=varname;]VarValue"); - } - - [Fact] - public void Should_Set_Secret_Variable() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.SetSecretVariable("Secret Variable", "Secret Value"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == "##vso[task.setvariable variable=Secret Variable;issecret=true;]Secret Value"); - } - - [Fact] - public void Should_Upload_Task_Summary() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var path = FilePath.FromString("./summary.md").MakeAbsolute(fixture.Environment); - - // When - service.Commands.UploadTaskSummary("./summary.md"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.uploadsummary ]{path}"); - } - - [Fact] - public void Should_Upload_Task_Log() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var path = FilePath.FromString("./logs/task.log").MakeAbsolute(fixture.Environment); - - // When - service.Commands.UploadTaskLogFile("./logs/task.log"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[task.uploadfile ]{path}"); - } - - [Theory] - [InlineData("drop", TFBuildArtifactType.Container, "./drop")] - [InlineData("artifact", TFBuildArtifactType.FilePath, "./dist/build/artifact.file")] - [InlineData("ref", TFBuildArtifactType.GitRef, "895a00ec66af875c1593a7563beb0edee400aba0")] - public void Should_Link_Build_Artifacts(string name, TFBuildArtifactType type, string location) - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.LinkArtifact(name, type, location); - - // Then - Assert.Contains(fixture.Writer.Entries, - m => m == $"##vso[artifact.associate artifactname={name};type={type};]{location}"); - } - - [Fact] - public void Should_Upload_To_Container() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var path = FilePath.FromString("./dist/package.nupkg").MakeAbsolute(fixture.Environment).FullPath; - - // When - service.Commands.UploadArtifact("packages", "./dist/package.nupkg"); - - // Then - Assert.Contains(fixture.Writer.Entries, - m => m == $"##vso[artifact.upload containerfolder=packages;]{path}"); - } - - [Fact] - public void Should_Upload_To_Container_Artifact() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var path = FilePath.FromString("./artifacts/results.trx").MakeAbsolute(fixture.Environment).FullPath; - - // When - service.Commands.UploadArtifact("tests", "./artifacts/results.trx", "Test Results"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[artifact.upload containerfolder=tests;artifactname=Test Results;]{path}"); - } - - [Fact] - public void UploadArtifactDirectory_Should_Throw_If_Directory_Is_Null() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - var result = Record.Exception(() => service.Commands.UploadArtifactDirectory(null)); - - // Then - AssertEx.IsArgumentNullException(result, "directory"); - } - - [Fact] - public void Should_Upload_Directory_As_Container() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var path = DirectoryPath.FromString("./artifacts/Packages").MakeAbsolute(fixture.Environment).FullPath; - - // When - service.Commands.UploadArtifactDirectory("./artifacts/Packages"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[artifact.upload containerfolder=Packages;artifactname=Packages;]{path}"); - } - - [Fact] - public void UploadArtifactDirectory_With_ArtifactName_Should_Throw_If_Directory_Is_Null() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - var result = Record.Exception(() => service.Commands.UploadArtifactDirectory(null, "Packages")); - - // Then - AssertEx.IsArgumentNullException(result, "directory"); - } - - [Fact] - public void UploadArtifactDirectory_Should_Throw_If_ArtifactName_Is_Null() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - var result = Record.Exception(() => service.Commands.UploadArtifactDirectory("./artifacts/Packages", null)); - - // Then - AssertEx.IsArgumentNullException(result, "artifactName"); - } - - [Fact] - public void Should_Upload_Directory_As_Container_Artifact() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var path = DirectoryPath.FromString("./artifacts/Packages").MakeAbsolute(fixture.Environment).FullPath; - - // When - service.Commands.UploadArtifactDirectory("./artifacts/Packages", "NuGet"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[artifact.upload containerfolder=NuGet;artifactname=NuGet;]{path}"); - } - - [Fact] - public void Should_Upload_Build_Log() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var path = FilePath.FromString("./dist/buildlog.txt").MakeAbsolute(fixture.Environment).FullPath; - - // When - service.Commands.UploadBuildLogFile("./dist/buildlog.txt"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == $"##vso[build.uploadlog ]{path}"); - } - - [Fact] - public void Should_Update_Build_Number() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.UpdateBuildNumber("CIBuild_1"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == "##vso[build.updatebuildnumber ]CIBuild_1"); - } - - [Fact] - public void Should_Add_Build_Tag() - { - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.AddBuildTag("Stable"); - - // Then - Assert.Contains(fixture.Writer.Entries, m => m == "##vso[build.addbuildtag ]Stable"); - } - - [Fact] - public void Should_Publish_Test_Results() - { - const string expected = @"##vso[results.publish type=XUnit;mergeResults=true;platform=x86;config=Debug;runTitle='Cake Test Run 1 [master]';publishRunAttachments=true;resultFiles=C:\build\CAKE-CAKE-JOB1\artifacts\resultsXUnit.trx,C:\build\CAKE-CAKE-JOB1\artifacts\resultsJs.trx;]"; - - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var data = new TFBuildPublishTestResultsData - { - Configuration = "Debug", - MergeTestResults = true, - Platform = "x86", - PublishRunAttachments = true, - TestRunner = TFTestRunnerType.XUnit, - TestRunTitle = "Cake Test Run 1 [master]", - TestResultsFiles = new FilePath[] - { - "./artifacts/resultsXUnit.trx", - "./artifacts/resultsJs.trx" - } - }; - - // When - service.Commands.PublishTestResults(data); - - // Then - Assert.Equal(expected.Replace('\\', System.IO.Path.DirectorySeparatorChar), fixture.Writer.Entries.FirstOrDefault()); - } - - [Fact] - public void Should_Publish_Test_Results_If_File_Path_Is_Relative() - { - const string expected = @"##vso[results.publish type=XUnit;mergeResults=true;platform=x86;config=Debug;runTitle='Cake Test Run 1 [master]';publishRunAttachments=true;resultFiles=C:\build\CAKE-CAKE-JOB1\artifacts\resultsXUnit.trx,C:\build\CAKE-CAKE-JOB1\artifacts\resultsJs.trx;]"; - - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var data = new TFBuildPublishTestResultsData - { - Configuration = "Debug", - MergeTestResults = true, - Platform = "x86", - PublishRunAttachments = true, - TestRunner = TFTestRunnerType.XUnit, - TestRunTitle = "Cake Test Run 1 [master]", - TestResultsFiles = new FilePath[] - { - "./artifacts/resultsXUnit.trx", - "./artifacts/resultsJs.trx" - } - }; - - // When - service.Commands.PublishTestResults(data); - - // Then - Assert.Equal(expected.Replace('\\', System.IO.Path.DirectorySeparatorChar), fixture.Writer.Entries.FirstOrDefault()); - } - - [Fact] - public void Should_Publish_Test_Results_If_File_Path_Is_Absolute() - { - const string expected = @"##vso[results.publish type=XUnit;mergeResults=true;platform=x86;config=Debug;runTitle='Cake Test Run 1 [master]';publishRunAttachments=true;resultFiles=/build/CAKE-CAKE-JOB1/artifacts/resultsXUnit.trx,/build/CAKE-CAKE-JOB1/artifacts/resultsJs.trx;]"; - - // Given - var fixture = new TFBuildFixture(); - fixture.Environment.WorkingDirectory.Returns("/build/CAKE-CAKE-JOB1"); - fixture.Environment.Platform.Family.Returns(PlatformFamily.OSX); - var service = fixture.CreateTFBuildService(); - var data = new TFBuildPublishTestResultsData - { - Configuration = "Debug", - MergeTestResults = true, - Platform = "x86", - PublishRunAttachments = true, - TestRunner = TFTestRunnerType.XUnit, - TestRunTitle = "Cake Test Run 1 [master]", - TestResultsFiles = new FilePath[] - { - "/build/CAKE-CAKE-JOB1/artifacts/resultsXUnit.trx", - "/build/CAKE-CAKE-JOB1/artifacts/resultsJs.trx" - } - }; - - // When - service.Commands.PublishTestResults(data); - - // Then - Assert.Equal(expected.Replace('/', System.IO.Path.DirectorySeparatorChar), fixture.Writer.Entries.FirstOrDefault()); - } - - [WindowsFact] - public void Should_Publish_Test_Results_If_File_Path_Is_Absolute_Windows() - { - const string expected = @"##vso[results.publish type=XUnit;mergeResults=true;platform=x86;config=Debug;runTitle='Cake Test Run 1 [master]';publishRunAttachments=true;resultFiles=C:\build\CAKE-CAKE-JOB1\artifacts\resultsXUnit.trx,C:\build\CAKE-CAKE-JOB1\artifacts\resultsJs.trx;]"; - - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var data = new TFBuildPublishTestResultsData - { - Configuration = "Debug", - MergeTestResults = true, - Platform = "x86", - PublishRunAttachments = true, - TestRunner = TFTestRunnerType.XUnit, - TestRunTitle = "Cake Test Run 1 [master]", - TestResultsFiles = new FilePath[] - { - "C:\\build\\CAKE-CAKE-JOB1\\artifacts\\resultsXUnit.trx", - "C:\\build\\CAKE-CAKE-JOB1\\artifacts\\resultsJs.trx" - } - }; - - // When - service.Commands.PublishTestResults(data); - - // Then - Assert.Equal(expected.Replace('/', System.IO.Path.DirectorySeparatorChar), fixture.Writer.Entries.FirstOrDefault()); - } - - // TODO: Windows Fact, OSX Fact - // TODO: TestResultFilePaths - [Fact] - public void Should_Publish_Code_Coverage() - { - const string expected = @"##vso[codecoverage.publish codecoveragetool=Cobertura;summaryfile=/build/CAKE-CAKE-JOB1/coverage/cobertura-coverage.xml;reportdirectory=/build/CAKE-CAKE-JOB1/coverage/report;]"; - - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(PlatformFamily.OSX, "/build/CAKE-CAKE-JOB1"); - var data = new TFBuildPublishCodeCoverageData - { - CodeCoverageTool = TFCodeCoverageToolType.Cobertura, - SummaryFileLocation = "./coverage/cobertura-coverage.xml", - ReportDirectory = "./coverage/report" - }; - - // When - service.Commands.PublishCodeCoverage(data); - - // Then - Assert.Equal(expected.Replace('/', System.IO.Path.DirectorySeparatorChar), fixture.Writer.Entries.FirstOrDefault()); - } - - [WindowsFact] - public void Should_Publish_Code_Coverage_Windows() - { - const string expected = @"##vso[codecoverage.publish codecoveragetool=Cobertura;summaryfile=C:\build\CAKE-CAKE-JOB1\coverage\cobertura-coverage.xml;reportdirectory=C:\build\CAKE-CAKE-JOB1\coverage\report;]"; - - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var data = new TFBuildPublishCodeCoverageData - { - CodeCoverageTool = TFCodeCoverageToolType.Cobertura, - SummaryFileLocation = "./coverage/cobertura-coverage.xml", - ReportDirectory = "./coverage/report" - }; - - // When - service.Commands.PublishCodeCoverage(data); - - // Then - Assert.Equal(expected.Replace('\\', System.IO.Path.DirectorySeparatorChar), fixture.Writer.Entries.FirstOrDefault()); - } - - [Fact] - public void Should_Publish_Code_Coverage_If_File_Path_Provided() - { - const string expected = @"##vso[codecoverage.publish codecoveragetool=Cobertura;summaryfile=C:\build\CAKE-CAKE-JOB1\coverage\cobertura-coverage.xml;reportdirectory=C:\build\CAKE-CAKE-JOB1\coverage\report;]"; - - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - var data = new TFBuildPublishCodeCoverageData - { - CodeCoverageTool = TFCodeCoverageToolType.Cobertura, - ReportDirectory = "./coverage/report" - }; - - // When - service.Commands.PublishCodeCoverage("./coverage/cobertura-coverage.xml", data); - - // Then - Assert.Equal(expected.Replace('\\', System.IO.Path.DirectorySeparatorChar), fixture.Writer.Entries.FirstOrDefault()); - } - - [Fact] - public void Should_Publish_Code_Coverage_If_File_Path_And_Action_Provided() - { - const string expected = @"##vso[codecoverage.publish codecoveragetool=Cobertura;summaryfile=C:\build\CAKE-CAKE-JOB1\coverage\cobertura-coverage.xml;reportdirectory=C:\build\CAKE-CAKE-JOB1\coverage\report;]"; - - // Given - var fixture = new TFBuildFixture(); - var service = fixture.CreateTFBuildService(); - - // When - service.Commands.PublishCodeCoverage("./coverage/cobertura-coverage.xml", - data => - { - data.CodeCoverageTool = TFCodeCoverageToolType.Cobertura; - data.ReportDirectory = "./coverage/report"; - }); - - // Then - Assert.Equal(expected.Replace('\\', System.IO.Path.DirectorySeparatorChar), fixture.Writer.Entries.FirstOrDefault()); - } - } - } -} diff --git a/src/Cake.Common.Tests/Unit/Build/TFBuild/TFBuildProviderTests.cs b/src/Cake.Common.Tests/Unit/Build/TFBuild/TFBuildProviderTests.cs deleted file mode 100644 index 6f1980ca4f..0000000000 --- a/src/Cake.Common.Tests/Unit/Build/TFBuild/TFBuildProviderTests.cs +++ /dev/null @@ -1,210 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Common.Build.TFBuild; -using Cake.Common.Tests.Fakes; -using Cake.Common.Tests.Fixtures.Build; -using Cake.Core; -using Cake.Core.Diagnostics; -using Cake.Testing; -using Xunit; - -namespace Cake.Common.Tests.Unit.Build.TFBuild -{ - public sealed class TFBuildProviderTests - { - public sealed class TheConstructor - { - [Fact] - public void Should_Throw_If_Environment_Is_Null() - { - // Given, When - var result = Record.Exception(() => new TFBuildProvider(null, new FakeBuildSystemServiceMessageWriter())); - - // Then - AssertEx.IsArgumentNullException(result, "environment"); - } - - [Fact] - public void Should_Throw_If_Writer_Is_Null() - { - // Given, When - var result = Record.Exception(() => new TFBuildProvider(new FakeEnvironment(PlatformFamily.Unknown), null)); - - // Then - AssertEx.IsArgumentNullException(result, "writer"); - } - } - - public sealed class TheIsRunningOnTFSProperty - { - [Fact] - public void Should_Return_True_If_Running_On_TFS() - { - // Given - var fixture = new TFBuildFixture(); - fixture.IsRunningOnTFS(); - var tfBuild = fixture.CreateTFBuildService(); - - // When -#pragma warning disable 618 - var result = tfBuild.IsRunningOnTFS; -#pragma warning restore 618 - - // Then - Assert.True(result); - } - - [Fact] - public void Should_Return_False_If_Not_Running_On_TFS() - { - // Given - var fixture = new TFBuildFixture(); - var tfBuild = fixture.CreateTFBuildService(); - - // When -#pragma warning disable 618 - var result = tfBuild.IsRunningOnTFS; -#pragma warning restore 618 - - // Then - Assert.False(result); - } - } - - public sealed class TheIsRunningOnVSTSProperty - { - [Fact] - public void Should_Return_True_If_Running_On_VSTS() - { - // Given - var fixture = new TFBuildFixture(); - fixture.IsRunningOnVSTS(); - var tfBuild = fixture.CreateTFBuildService(); - - // When -#pragma warning disable 618 - var result = tfBuild.IsRunningOnVSTS; -#pragma warning restore 618 - - // Then - Assert.True(result); - } - - [Fact] - public void Should_Return_False_If_Not_Running_On_VSTS() - { - // Given - var fixture = new TFBuildFixture(); - var tfBuild = fixture.CreateTFBuildService(); - - // When -#pragma warning disable 618 - var result = tfBuild.IsRunningOnVSTS; -#pragma warning restore 618 - - // Then - Assert.False(result); - } - } - - public sealed class TheIsRunningOnAzurePipelinesProperty - { - [Fact] - public void Should_Return_True_If_Running_On_AzurePipelines() - { - // Given - var fixture = new TFBuildFixture(); - fixture.IsRunningOnAzurePipelines(); - var tfBuild = fixture.CreateTFBuildService(); - - // When - var result = tfBuild.IsRunningOnAzurePipelines; - - // Then - Assert.True(result); - } - - [Fact] - public void Should_Return_False_If_Not_Running_On_AzurePipelines() - { - // Given - var fixture = new TFBuildFixture(); - var tfBuild = fixture.CreateTFBuildService(); - - // When - var result = tfBuild.IsRunningOnAzurePipelines; - - // Then - Assert.False(result); - } - } - - public sealed class TheIsRunningOnAzurePipelinesHostedProperty - { - [Fact] - public void Should_Return_True_If_Running_On_AzurePipelinesHosted() - { - // Given - var fixture = new TFBuildFixture(); - fixture.IsRunningOnAzurePipelinesHosted(); - var tfBuild = fixture.CreateTFBuildService(); - - // When - var result = tfBuild.IsRunningOnAzurePipelinesHosted; - - // Then - Assert.True(result); - } - - [Fact] - public void Should_Return_False_If_Not_Running_On_AzurePipelinesHosted() - { - // Given - var fixture = new TFBuildFixture(); - var tfBuild = fixture.CreateTFBuildService(); - - // When - var result = tfBuild.IsRunningOnAzurePipelinesHosted; - - // Then - Assert.False(result); - } - - [Theory] - [InlineData("Hosted Agent 2")] - [InlineData("Azure Pipelines 3")] - public void Should_Return_True_If_Running_On_AzurePipelinesExtraAgent(string agentName) - { - // Given - var fixture = new TFBuildFixture(); - fixture.IsRunningOnAzurePipelinesHosted(agentName); - var tfBuild = fixture.CreateTFBuildService(); - - // When - var result = tfBuild.IsRunningOnAzurePipelinesHosted; - - // Then - Assert.True(result); - } - } - - public sealed class TheEnvironmentProperty - { - [Fact] - public void Should_Return_Non_Null_Reference() - { - // Given - var fixture = new TFBuildFixture(); - var tfBuild = fixture.CreateTFBuildService(); - - // When - var result = tfBuild.Environment; - - // Then - Assert.NotNull(result); - } - } - } -} diff --git a/src/Cake.Common.Tests/Unit/Build/TeamCity/Data/TeamCityBuildInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/TeamCity/Data/TeamCityBuildInfoTests.cs index 18820e468c..a35afcc383 100644 --- a/src/Cake.Common.Tests/Unit/Build/TeamCity/Data/TeamCityBuildInfoTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/TeamCity/Data/TeamCityBuildInfoTests.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Globalization; using Cake.Common.Tests.Fixtures.Build; using Xunit; @@ -40,5 +42,226 @@ public void Should_Return_Correct_Value() Assert.Equal("10-Foo", result); } } + + public sealed class TheStartDateTimeProperty + { + [Fact] + public void Should_Return_Correct_Value() + { + // Given + var info = new TeamCityInfoFixture().CreateBuildInfo(); + + // When + var result = info.StartDateTime; + + // Then + var expected = new DateTimeOffset?(new DateTime(2020, 08, 22, 12, 34, 56, DateTimeKind.Local)); + Assert.Equal(expected, result); + } + + [Fact] + public void Should_Use_Build_Server_Local_Time() + { + // Given + var now = DateTime.Now; + var startDate = now.ToString("yyyyMMdd", CultureInfo.InvariantCulture); + var startTime = now.ToString("HHmmss", CultureInfo.InvariantCulture); + + var fixture = new TeamCityInfoFixture(); + fixture.SetBuildStartDate(startDate); + fixture.SetBuildStartTime(startTime); + + var info = fixture.CreateBuildInfo(); + + // When + var result = info.StartDateTime; + + // Then + var expected = new DateTimeOffset?(new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, DateTimeKind.Local)); + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(null, null)] + [InlineData("Cake", null)] + [InlineData(null, "Build")] + [InlineData("Cake", "Build")] + [InlineData("Cake", "123456")] + [InlineData("20200822", "Build")] + public void Should_Return_Null_If_Cannot_Parse_Values(string startDate, string startTime) + { + // Given + var fixture = new TeamCityInfoFixture(); + fixture.SetBuildStartDate(startDate); + fixture.SetBuildStartTime(startTime); + + var info = fixture.CreateBuildInfo(); + + // When + var result = info.StartDateTime; + + // Then + Assert.Equal(null, result); + } + } + + public sealed class TheBranchProperty + { + [Fact] + public void Should_Return_Empty_When_No_Properties() + { + // Given + var info = new TeamCityInfoFixture().CreateBuildInfo(); + + // When + var result = info.BranchName; + + // Then + Assert.Equal(string.Empty, result); + } + + [Fact] + public void Should_Return_Value_From_Properties() + { + // Given + var fixture = new TeamCityInfoFixture(); + fixture.SetBuildPropertiesContent(Properties.Resources.TeamCity_Build_Properties_Xml); + fixture.SetConfigPropertiesContent(Properties.Resources.TeamCity_Config_Properties_Xml); + var info = fixture.CreateBuildInfo(); + + // When + var result = info.BranchName; + + // Then + Assert.Equal("pull/5", result); + } + } + + public sealed class TheVcsBranchProperty + { + [Fact] + public void Should_Return_Empty_When_No_Properties() + { + // Given + var info = new TeamCityInfoFixture().CreateBuildInfo(); + + // When + var result = info.VcsBranchName; + + // Then + Assert.Equal(string.Empty, result); + } + + [Fact] + public void Should_Return_Value_From_Properties() + { + // Given + var fixture = new TeamCityInfoFixture(); + fixture.SetBuildPropertiesContent(Properties.Resources.TeamCity_Build_Properties_Xml); + fixture.SetConfigPropertiesContent(Properties.Resources.TeamCity_Config_Properties_Xml); + var info = fixture.CreateBuildInfo(); + + // When + var result = info.VcsBranchName; + + // Then + Assert.Equal("refs/pull/5/merge", result); + } + } + + public sealed class ThePropertiesProperties + { + [Fact] + public void Should_Return_Empty_ForAll_When_File_Not_Created() + { + // Given + var fixture = new TeamCityInfoFixture(); + var info = fixture.CreateBuildInfo(); + + // When + var buildProperties = info.BuildProperties; + var configProperties = info.ConfigProperties; + var runnerProperties = info.RunnerProperties; + + // Then + Assert.Empty(buildProperties); + Assert.Empty(configProperties); + Assert.Empty(runnerProperties); + } + + [Fact] + public void Should_Return_Empty_When_Config_Properties_File_Not_Created() + { + // Given + var fixture = new TeamCityInfoFixture(); + fixture.SetBuildPropertiesContent(Properties.Resources.TeamCity_Build_Properties_Xml); + var info = fixture.CreateBuildInfo(); + + // When + var buildProperties = info.BuildProperties; + var configProperties = info.ConfigProperties; + + // Then + Assert.NotEmpty(buildProperties); + Assert.Empty(configProperties); + } + + [Fact] + public void Should_Return_Config_Values_When_Files_Exist() + { + // Given + var fixture = new TeamCityInfoFixture(); + fixture.SetBuildPropertiesContent(Properties.Resources.TeamCity_Build_Properties_Xml); + fixture.SetConfigPropertiesContent(Properties.Resources.TeamCity_Config_Properties_Xml); + var info = fixture.CreateBuildInfo(); + + // When + var buildProperties = info.BuildProperties; + var configProperties = info.ConfigProperties; + + // Then + Assert.NotEmpty(buildProperties); + Assert.NotEmpty(configProperties); + Assert.Equal(5, configProperties.Count); + Assert.Equal("3246", configProperties["build.number"]); + } + + [Fact] + public void Should_Return_Empty_When_Runner_Properties_File_Not_Created() + { + // Given + var fixture = new TeamCityInfoFixture(); + fixture.SetBuildPropertiesContent(Properties.Resources.TeamCity_Build_Properties_Xml); + var info = fixture.CreateBuildInfo(); + + // When + var buildProperties = info.BuildProperties; + var runnerProperties = info.RunnerProperties; + + // Then + Assert.NotEmpty(buildProperties); + Assert.Empty(runnerProperties); + } + + [Fact] + public void Should_Return_Runner_Values_When_Files_Exist() + { + // Given + var fixture = new TeamCityInfoFixture(); + fixture.SetBuildPropertiesContent(Properties.Resources.TeamCity_Build_Properties_Xml); + fixture.SetRunnerPropertiesContent(Properties.Resources.TeamCity_Runner_Properties_Xml); + var info = fixture.CreateBuildInfo(); + + // When + var buildProperties = info.BuildProperties; + var runnerProperties = info.RunnerProperties; + + // Then + Assert.NotEmpty(buildProperties); + Assert.NotEmpty(runnerProperties); + Assert.Single(runnerProperties); + Assert.Equal("run.cmd", runnerProperties["command.executable"]); + } + } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Build/TeamCity/Data/TeamCityPullRequestInfoTests.cs b/src/Cake.Common.Tests/Unit/Build/TeamCity/Data/TeamCityPullRequestInfoTests.cs index 242a365461..508d108952 100644 --- a/src/Cake.Common.Tests/Unit/Build/TeamCity/Data/TeamCityPullRequestInfoTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/TeamCity/Data/TeamCityPullRequestInfoTests.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using Cake.Common.Tests.Fixtures.Build; -using NSubstitute; using Xunit; namespace Cake.Common.Tests.Unit.Build.TeamCity.Data @@ -19,11 +18,14 @@ public sealed class TheIsPullRequestProperty [InlineData("refs/pull/1/merge", true)] [InlineData("refs/changes/1/head", true)] [InlineData("refs/heads/master", false)] + [InlineData("", true)] public void Should_Return_Correct_Value(string value, bool expected) { // Given var fixture = new TeamCityInfoFixture(); - fixture.Environment.GetEnvironmentVariable("Git_Branch").Returns(value); + fixture.SetGitBranch(value); + fixture.SetBuildPropertiesContent(Properties.Resources.TeamCity_Build_Properties_Xml); + fixture.SetConfigPropertiesContent(Properties.Resources.TeamCity_Config_Properties_Xml); var info = fixture.CreatePullRequestInfo(); // When @@ -42,11 +44,14 @@ public sealed class TheNumberProperty [InlineData("refs/changes/3/merge", 3)] [InlineData("refs/merge-requests/4/merge", 4)] [InlineData("refs/heads/master", null)] + [InlineData("", 5)] public void Should_Return_Correct_Value(string value, int? expected) { // Given var fixture = new TeamCityInfoFixture(); - fixture.Environment.GetEnvironmentVariable("Git_Branch").Returns(value); + fixture.SetGitBranch(value); + fixture.SetBuildPropertiesContent(Properties.Resources.TeamCity_Build_Properties_Xml); + fixture.SetConfigPropertiesContent(Properties.Resources.TeamCity_Config_Properties_Xml); var info = fixture.CreatePullRequestInfo(); // When diff --git a/src/Cake.Common.Tests/Unit/Build/TeamCity/TeamCityProviderTests.cs b/src/Cake.Common.Tests/Unit/Build/TeamCity/TeamCityProviderTests.cs index a4a763d76b..c025ec0794 100644 --- a/src/Cake.Common.Tests/Unit/Build/TeamCity/TeamCityProviderTests.cs +++ b/src/Cake.Common.Tests/Unit/Build/TeamCity/TeamCityProviderTests.cs @@ -6,7 +6,6 @@ using Cake.Common.Build.TeamCity; using Cake.Common.Tests.Fixtures.Build; using Cake.Core.IO; -using Cake.Testing.Extensions; using Xunit; namespace Cake.Common.Tests.Unit.Build.TeamCity @@ -19,12 +18,25 @@ public sealed class TheConstructor public void Should_Throw_If_Environment_Is_Null() { // Given, When - var result = Record.Exception(() => new TeamCityProvider(null, null)); + var result = Record.Exception(() => new TeamCityProvider(null, null, null)); // Then AssertEx.IsArgumentNullException(result, "environment"); } + [Fact] + public void Should_Throw_If_FileSystem_Is_Null() + { + // Given + var fixture = new TeamCityFixture(); + + // When + var result = Record.Exception(() => new TeamCityProvider(fixture.Environment, null, null)); + + // Then + AssertEx.IsArgumentNullException(result, "fileSystem"); + } + [Fact] public void Should_Throw_If_Writer_Is_Null() { @@ -32,7 +44,7 @@ public void Should_Throw_If_Writer_Is_Null() var fixture = new TeamCityFixture(); // When - var result = Record.Exception(() => new TeamCityProvider(fixture.Environment, null)); + var result = Record.Exception(() => new TeamCityProvider(fixture.Environment, fixture.FileSystem, null)); // Then AssertEx.IsArgumentNullException(result, "writer"); diff --git a/src/Cake.Common.Tests/Unit/EnvironmentAliasesTests.cs b/src/Cake.Common.Tests/Unit/EnvironmentAliasesTests.cs index b19a96b1db..2a4fdeec22 100644 --- a/src/Cake.Common.Tests/Unit/EnvironmentAliasesTests.cs +++ b/src/Cake.Common.Tests/Unit/EnvironmentAliasesTests.cs @@ -226,5 +226,65 @@ public void Should_Return_Correct_Value(PlatformFamily family, bool expected) Assert.Equal(expected, result); } } + + public sealed class TheIsRunningOnLinuxMethod + { + [Fact] + public void Should_Throw_If_Context_Is_Null() + { + // Given, When + var result = Record.Exception(() => EnvironmentAliases.IsRunningOnLinux(null)); + + // Then + AssertEx.IsArgumentNullException(result, "context"); + } + + [Theory] + [InlineData(PlatformFamily.Linux, true)] + [InlineData(PlatformFamily.OSX, false)] + [InlineData(PlatformFamily.Windows, false)] + public void Should_Return_Correct_Value(PlatformFamily family, bool expected) + { + // Given + var context = Substitute.For(); + context.Environment.Returns(new FakeEnvironment(family)); + + // When + var result = EnvironmentAliases.IsRunningOnLinux(context); + + // Then + Assert.Equal(expected, result); + } + } + + public sealed class TheIsRunningOnMacMethod + { + [Fact] + public void Should_Throw_If_Context_Is_Null() + { + // Given, When + var result = Record.Exception(() => EnvironmentAliases.IsRunningOnMacOs(null)); + + // Then + AssertEx.IsArgumentNullException(result, "context"); + } + + [Theory] + [InlineData(PlatformFamily.Linux, false)] + [InlineData(PlatformFamily.OSX, true)] + [InlineData(PlatformFamily.Windows, false)] + public void Should_Return_Correct_Value(PlatformFamily family, bool expected) + { + // Given + var context = Substitute.For(); + context.Environment.Returns(new FakeEnvironment(family)); + + // When + var result = EnvironmentAliases.IsRunningOnMacOs(context); + + // Then + Assert.Equal(expected, result); + } + } } -} \ No newline at end of file +} diff --git a/src/Cake.Common.Tests/Unit/IO/DirectoryAliasesTests.cs b/src/Cake.Common.Tests/Unit/IO/DirectoryAliasesTests.cs index 75fc1ab2f5..0598b82e88 100644 --- a/src/Cake.Common.Tests/Unit/IO/DirectoryAliasesTests.cs +++ b/src/Cake.Common.Tests/Unit/IO/DirectoryAliasesTests.cs @@ -12,6 +12,7 @@ using Cake.Core; using Cake.Core.IO; using Cake.Testing; +using Cake.Testing.Xunit; using NSubstitute; using Xunit; @@ -598,15 +599,17 @@ public void Should_Make_Relative_Path_Absolute() } } - public sealed class TheDeleteDirectoryMethod + public sealed class TheEnsureDoNotExistsMethod { [Fact] public void Should_Throw_If_Context_Is_Null() { - // Given, When -#pragma warning disable CS0618 - var result = Record.Exception(() => DirectoryAliases.DeleteDirectory(null, "/Temp/DoNotExist")); -#pragma warning restore CS0618 + // Given + var path = new DirectoryPath("/Temp"); + + // When + var result = Record.Exception(() => + DirectoryAliases.EnsureDirectoryDoesNotExist(null, path)); // Then AssertEx.IsArgumentNullException(result, "context"); @@ -616,90 +619,55 @@ public void Should_Throw_If_Context_Is_Null() public void Should_Throw_If_Directory_Is_Null() { // Given - var fixture = new FileSystemFixture(); var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); // When -#pragma warning disable CS0618 - var result = Record.Exception(() => context.DeleteDirectory(null)); -#pragma warning restore CS0618 + var result = Record.Exception(() => + DirectoryAliases.EnsureDirectoryDoesNotExist(context, null)); // Then AssertEx.IsArgumentNullException(result, "path"); } [Fact] - public void Should_Throw_If_Directory_Do_Not_Exist() + public void Should_Not_Throw_Exception_Or_Fail_For_Non_Existing_Directory() { // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - // When -#pragma warning disable CS0618 - var result = Record.Exception(() => context.DeleteDirectory("/Temp/DoNotExist")); -#pragma warning restore CS0618 - - // Then - Assert.IsType(result); - Assert.Equal("The directory '/Temp/DoNotExist' does not exist.", result?.Message); - } + var fileSystem = Substitute.For(); - [Fact] - public void Should_Throw_When_Deleting_Directory_With_Sub_Directories_If_Non_Recursive() - { - // Given - var fixture = new FileSystemFixture(); var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); + context.FileSystem.Returns(fileSystem); // When -#pragma warning disable CS0618 - var result = Record.Exception(() => context.DeleteDirectory("/Temp/HasDirectories")); -#pragma warning restore CS0618 + var result = Record.Exception(() => + DirectoryAliases.EnsureDirectoryDoesNotExist(context, "/Temp")); // Then - Assert.IsType(result); - Assert.Equal("Cannot delete directory '/Temp/HasDirectories' without recursion since it's not empty.", result?.Message); + Assert.Null(result); } [Fact] - public void Should_Throw_When_Deleting_Directory_With_Files_If_Non_Recursive() + public void Should_Delete_Directory_If_It_Exists() { // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - // When -#pragma warning disable CS0618 - var result = Record.Exception(() => context.DeleteDirectory("/Temp/HasFiles")); -#pragma warning restore CS0618 - - // Then - Assert.IsType(result); - Assert.Equal("Cannot delete directory '/Temp/HasFiles' without recursion since it's not empty.", result?.Message); - } + var fileSystem = Substitute.For(); + var directory = Substitute.For(); + directory.Exists.Returns(true); + fileSystem.GetDirectory(Arg.Is(p => p.FullPath == "/Temp")).Returns(directory); - [Fact] - public void Should_Delete_Empty_Directory_If_Non_Recursive() - { - // Given - var fixture = new FileSystemFixture(); var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); + context.FileSystem.Returns(fileSystem); // When -#pragma warning disable CS0618 - context.DeleteDirectory("/Temp/Hello/Empty"); -#pragma warning restore CS0618 + DirectoryAliases.EnsureDirectoryDoesNotExist(context, "/Temp"); // Then - Assert.False(fixture.FileSystem.GetDirectory("/Temp/Hello/Empty").Exists); + directory.Received(1).Delete(true); } + } + public sealed class TheDeleteDirectoryMethod + { [Fact] public void Should_Delete_Directory_With_Content_If_Recursive() { @@ -751,120 +719,6 @@ public sealed class TheDeleteDirectoriesMethod { public sealed class WithPaths { - [Fact] - public void Should_Throw_If_Context_Is_Null() - { - // Given - var paths = new DirectoryPath[] { "/Temp/DoNotExist" }; - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - DirectoryAliases.DeleteDirectories(null, paths)); -#pragma warning restore CS0618 - - // Then - AssertEx.IsArgumentNullException(result, "context"); - } - - [Fact] - public void Should_Throw_If_Directories_Are_Null() - { - // Given - var context = Substitute.For(); - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - context.DeleteDirectories((IEnumerable)null)); -#pragma warning restore CS0618 - - // Then - AssertEx.IsArgumentNullException(result, "directories"); - } - - [Fact] - public void Should_Throw_If_Any_Directory_Do_Not_Exist() - { - // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - var paths = new DirectoryPath[] { "/Temp/DoNotExist" }; - - // When -#pragma warning disable CS0618 - var result = Record.Exception(() => context.DeleteDirectories(paths)); -#pragma warning restore CS0618 - - // Then - Assert.IsType(result); - Assert.Equal("The directory '/Temp/DoNotExist' does not exist.", result?.Message); - } - - [Fact] - public void Should_Throw_When_Deleting_Directory_With_Sub_Directories_If_Non_Recursive() - { - // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - var paths = new DirectoryPath[] { "/Temp/HasDirectories" }; - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - context.DeleteDirectories(paths)); -#pragma warning restore CS0618 - - // Then - Assert.IsType(result); - Assert.Equal("Cannot delete directory '/Temp/HasDirectories' without recursion since it's not empty.", result?.Message); - } - - [Fact] - public void Should_Throw_When_Deleting_Directory_With_Files_If_Non_Recursive() - { - // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - var paths = new DirectoryPath[] { "/Temp/HasFiles" }; - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - context.DeleteDirectories(paths)); -#pragma warning restore CS0618 - - // Then - Assert.IsType(result); - Assert.Equal("Cannot delete directory '/Temp/HasFiles' without recursion since it's not empty.", result?.Message); - } - - [Fact] - public void Should_Delete_Empty_Directory_If_Non_Recursive() - { - // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - var paths = new DirectoryPath[] { "/Temp/Hello/Empty", "/Temp/Hello/More/Empty" }; - - // When -#pragma warning disable CS0618 - context.DeleteDirectories(paths); -#pragma warning restore CS0618 - - // Then - Assert.False(fixture.FileSystem.GetDirectory("/Temp/Hello/Empty").Exists); - Assert.False(fixture.FileSystem.GetDirectory("/Temp/Hello/More/Empty").Exists); - } - [Fact] public void Should_Delete_Directory_With_Content_If_Recursive() { @@ -921,121 +775,6 @@ public void Should_Delete_Directories_With_Readonly_Files_If_Force() public sealed class WithStrings { - [Fact] - public void Should_Throw_If_Context_Is_Null() - { - // Given - var paths = new[] { "/Temp/DoNotExist" }; - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - DirectoryAliases.DeleteDirectories(null, paths)); -#pragma warning restore CS0618 - - // Then - AssertEx.IsArgumentNullException(result, "context"); - } - - [Fact] - public void Should_Throw_If_Directories_Are_Null() - { - // Given - var context = Substitute.For(); - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - context.DeleteDirectories((IEnumerable)null)); -#pragma warning restore CS0618 - - // Then - AssertEx.IsArgumentNullException(result, "directories"); - } - - [Fact] - public void Should_Throw_If_Any_Directory_Do_Not_Exist() - { - // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - var paths = new[] { "/Temp/DoNotExist" }; - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - context.DeleteDirectories(paths)); -#pragma warning restore CS0618 - - // Then - Assert.IsType(result); - Assert.Equal("The directory '/Temp/DoNotExist' does not exist.", result?.Message); - } - - [Fact] - public void Should_Throw_When_Deleting_Directory_With_Sub_Directories_If_Non_Recursive() - { - // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - var paths = new[] { "/Temp/HasDirectories" }; - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - context.DeleteDirectories(paths)); -#pragma warning restore CS0618 - - // Then - Assert.IsType(result); - Assert.Equal("Cannot delete directory '/Temp/HasDirectories' without recursion since it's not empty.", result?.Message); - } - - [Fact] - public void Should_Throw_When_Deleting_Directory_With_Files_If_Non_Recursive() - { - // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - var paths = new[] { "/Temp/HasFiles" }; - - // When - var result = Record.Exception(() => -#pragma warning disable CS0618 - context.DeleteDirectories(paths)); -#pragma warning restore CS0618 - - // Then - Assert.IsType(result); - Assert.Equal("Cannot delete directory '/Temp/HasFiles' without recursion since it's not empty.", result?.Message); - } - - [Fact] - public void Should_Delete_Empty_Directory_If_Non_Recursive() - { - // Given - var fixture = new FileSystemFixture(); - var context = Substitute.For(); - context.FileSystem.Returns(fixture.FileSystem); - - var paths = new[] { "/Temp/Hello/Empty", "/Temp/Hello/More/Empty" }; - - // When -#pragma warning disable CS0618 - context.DeleteDirectories(paths); -#pragma warning restore CS0618 - - // Then - Assert.False(fixture.FileSystem.GetDirectory("/Temp/Hello/Empty").Exists); - Assert.False(fixture.FileSystem.GetDirectory("/Temp/Hello/More/Empty").Exists); - } - [Fact] public void Should_Delete_Directory_With_Content_If_Recursive() { @@ -1345,6 +1084,127 @@ public void Should_Return_Absolute_Directory_Path() } } + public sealed class TheMakeRelativeMethod + { + [Fact] + public void Should_Throw_For_DirectoryPath_If_Context_Is_Null() + { + // Given, When + var result = Record.Exception(() => DirectoryAliases.MakeRelative(null, new DirectoryPath("./build"))); + + // Then + AssertEx.IsArgumentNullException(result, "context"); + } + + [Fact] + public void Should_Throw_For_FilePath_If_Context_Is_Null() + { + // Given, When + var result = Record.Exception(() => DirectoryAliases.MakeRelative(null, new FilePath("./build"))); + + // Then + AssertEx.IsArgumentNullException(result, "context"); + } + + [Fact] + public void Should_Throw_If_DirectoryPath_Is_Null() + { + // Given + var context = Substitute.For(); + DirectoryPath path = null; + + // When + var result = Record.Exception(() => DirectoryAliases.MakeRelative(context, path)); + + // Then + AssertEx.IsArgumentNullException(result, "path"); + } + + [Fact] + public void Should_Throw_If_FilePath_Is_Null() + { + // Given + var context = Substitute.For(); + FilePath path = null; + + // When + var result = Record.Exception(() => DirectoryAliases.MakeRelative(context, path)); + + // Then + AssertEx.IsArgumentNullException(result, "path"); + } + + [WindowsTheory] + [InlineData(@"\Working", @"\Working\build", "build")] + [InlineData(@"\Working", @"\Working", ".")] + [InlineData("C:/Working/build/core", "C:/Working/stage/core", "../../stage/core")] + [InlineData("C:/Working/build/core", "C:/Working", "../..")] + public void Should_Return_Relative_Directory_Path_For_Working_Directory(string rootPath, string path, string expected) + { + // Given + var context = Substitute.For(); + context.Environment.WorkingDirectory.Returns(d => rootPath); + + // When + var result = DirectoryAliases.MakeRelative(context, new DirectoryPath(path)); + + // Then + Assert.Equal(expected, result.FullPath); + } + + [WindowsTheory] + [InlineData(@"\Working", @"\Working\build", "build")] + [InlineData(@"\Working", @"\Working", ".")] + [InlineData("C:/Working/build/core", "C:/Working/stage/core", "../../stage/core")] + [InlineData("C:/Working/build/core", "C:/Working", "../..")] + public void Should_Return_Relative_Directory_Path_For_Defined_Root_Directory(string rootPath, string path, string expected) + { + // Given + var context = Substitute.For(); + + // When + var result = DirectoryAliases.MakeRelative(context, new DirectoryPath(path), new DirectoryPath(rootPath)); + + // Then + Assert.Equal(expected, result.FullPath); + } + + [WindowsTheory] + [InlineData(@"\Working", @"\Working\build\file.cake", "build/file.cake")] + [InlineData(@"\Working", @"\Working\file.cake", "file.cake")] + [InlineData("C:/Working/build/core", "C:/Working/stage/core/file.cake", "../../stage/core/file.cake")] + [InlineData("C:/Working/build/core", "C:/Working/file.cake", "../../file.cake")] + public void Should_Return_Relative_File_Path_For_Working_Directory(string rootPath, string path, string expected) + { + // Given + var context = Substitute.For(); + context.Environment.WorkingDirectory.Returns(d => rootPath); + + // When + var result = DirectoryAliases.MakeRelative(context, new FilePath(path)); + + // Then + Assert.Equal(expected, result.FullPath); + } + + [WindowsTheory] + [InlineData(@"\Working", @"\Working\build\file.cake", "build/file.cake")] + [InlineData(@"\Working", @"\Working\file.cake", "file.cake")] + [InlineData("C:/Working/build/core", "C:/Working/stage/core/file.cake", "../../stage/core/file.cake")] + [InlineData("C:/Working/build/core", "C:/Working/file.cake", "../../file.cake")] + public void Should_Return_Relative_File_Path_For_Defined_Root_Directory(string rootPath, string path, string expected) + { + // Given + var context = Substitute.For(); + + // When + var result = DirectoryAliases.MakeRelative(context, new FilePath(path), new DirectoryPath(rootPath)); + + // Then + Assert.Equal(expected, result.FullPath); + } + } + public sealed class TheMoveDirectoryMethod { [Fact] diff --git a/src/Cake.Common.Tests/Unit/IO/FileCopierTests.cs b/src/Cake.Common.Tests/Unit/IO/FileCopierTests.cs new file mode 100644 index 0000000000..5ab9a39eea --- /dev/null +++ b/src/Cake.Common.Tests/Unit/IO/FileCopierTests.cs @@ -0,0 +1,201 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Cake.Common.IO; +using Cake.Common.Tests.Fixtures.IO; +using Cake.Core.IO; +using Xunit; + +namespace Cake.Common.Tests.Unit.IO +{ + public sealed class FileCopierTests + { + public sealed class FileCopierTestsMethod + { + [Fact] + public void Should_Copy_Single_File_Relative_Path() + { + const string filePath = "./src/a/a.txt"; + const string dstPath = "./dst"; + + // Given + var fixture = new FileCopierFixture(); + fixture.EnsureFileExists(filePath); + fixture.EnsureDirectoryExists(dstPath); + + // When + FileCopier.CopyFiles( + fixture.Context, + new FilePath[] + { + filePath + }, + new DirectoryPath(dstPath), + true); + + // Then + Assert.True(fixture.ExistsFile($"{dstPath}/a/a.txt")); + } + + [Fact] + public void Should_Copy_Single_File_Absolute_Path() + { + const string filePath = "./src/a/a.txt"; + const string dstPath = "./dst"; + + // Given + var fixture = new FileCopierFixture(); + fixture.EnsureFileExists(filePath); + fixture.EnsureDirectoryExists(dstPath); + + // When + FileCopier.CopyFiles( + fixture.Context, + new[] { fixture.MakeAbsolute(filePath) }, + new DirectoryPath(dstPath), + true); + + // Then + Assert.True(fixture.ExistsFile($"{dstPath}/a/a.txt")); + } + + [Fact] + public void Should_Copy_Multiple_Files_Relative_Path() + { + const string filePath1 = "./src/a/a.txt"; + const string filePath2 = "./src/b/b.txt"; + const string dstPath = "./dst"; + + // Given + var fixture = new FileCopierFixture(); + fixture.EnsureFileExists(filePath1); + fixture.EnsureFileExists(filePath2); + fixture.EnsureDirectoryExists(dstPath); + + // When + FileCopier.CopyFiles( + fixture.Context, + new FilePath[] + { + filePath1, + filePath2 + }, + new DirectoryPath(dstPath), + true); + + // Then + Assert.True(fixture.ExistsFile($"{dstPath}/a/a.txt")); + Assert.True(fixture.ExistsFile($"{dstPath}/b/b.txt")); + } + + [Fact] + public void Should_Copy_Multiple_Files_Absolute_Path() + { + const string filePath1 = "./src/a/a.txt"; + const string filePath2 = "./src/b/b.txt"; + const string dstPath = "./dst"; + + // Given + var fixture = new FileCopierFixture(); + fixture.EnsureFileExists(filePath1); + fixture.EnsureFileExists(filePath2); + fixture.EnsureDirectoryExists(dstPath); + + // When + FileCopier.CopyFiles( + fixture.Context, + new[] + { + fixture.MakeAbsolute(filePath1), + fixture.MakeAbsolute(filePath2) + }, + new DirectoryPath(dstPath), + true); + + // Then + Assert.True(fixture.ExistsFile($"{dstPath}/a/a.txt")); + Assert.True(fixture.ExistsFile($"{dstPath}/b/b.txt")); + } + + [Fact] + public void Should_Copy_Multiple_Files_Mixed_Path() + { + const string filePath1 = "./src/a/a.txt"; + const string filePath2 = "./src/b/b.txt"; + const string dstPath = "./dst"; + + // Given + var fixture = new FileCopierFixture(); + fixture.EnsureFileExists(filePath1); + fixture.EnsureFileExists(filePath2); + fixture.EnsureDirectoryExists(dstPath); + + // When + FileCopier.CopyFiles( + fixture.Context, + new[] + { + filePath1, + fixture.MakeAbsolute(filePath2) + }, + new DirectoryPath(dstPath), + true); + + // Then + Assert.True(fixture.ExistsFile($"{dstPath}/a/a.txt")); + Assert.True(fixture.ExistsFile($"{dstPath}/b/b.txt")); + } + + [Fact] + public void Should_Throw_If_Context_Is_Null() + { + // When + var result = Record.Exception(() => FileCopier.CopyFiles(null, Enumerable.Empty(), new DirectoryPath(""), true)); + + // Then + AssertEx.IsArgumentNullException(result, "context"); + } + + [Fact] + public void Should_Throw_If_File_Paths_Is_Null() + { + // Given + var fixture = new FileCopierFixture(); + + // When + var result = Record.Exception(() => FileCopier.CopyFiles(fixture.Context, (List)null, new DirectoryPath(""), true)); + + // Then + AssertEx.IsArgumentNullException(result, "filePaths"); + } + + [Fact] + public void Should_Throw_If_Target_Directory_Path_Is_Null() + { + // Given + var fixture = new FileCopierFixture(); + + // When + var result = Record.Exception(() => FileCopier.CopyFiles(fixture.Context, Enumerable.Empty(), null, true)); + + // Then + AssertEx.IsArgumentNullException(result, "targetDirectoryPath"); + } + + [Fact] + public void Should_Throw_If_Target_Directory_Does_Not_Exist() + { + const string dstPath = "/dst"; + + // Given + var fixture = new FileCopierFixture(); + + // When + var result = Record.Exception(() => FileCopier.CopyFiles(fixture.Context, Enumerable.Empty(), new DirectoryPath(dstPath), true)); + + // Then + AssertEx.IsExceptionWithMessage(result, $"The directory '{dstPath}' does not exist."); + } + } + } +} diff --git a/src/Cake.Common.Tests/Unit/IO/Paths/ConvertableDirectoryPathTests.cs b/src/Cake.Common.Tests/Unit/IO/Paths/ConvertableDirectoryPathTests.cs index d828167d6c..76ea669f86 100644 --- a/src/Cake.Common.Tests/Unit/IO/Paths/ConvertableDirectoryPathTests.cs +++ b/src/Cake.Common.Tests/Unit/IO/Paths/ConvertableDirectoryPathTests.cs @@ -144,6 +144,57 @@ public void Should_Throw_If_Right_Operand_Is_Null() } } + public sealed class AddingDirectoryPathAndConvertableDirectoryPath + { + [Fact] + public void Should_Combine_The_Two_Paths() + { + // Given + var path = new DirectoryPath("./root"); + + // When + var result = path + new ConvertableDirectoryPath("other"); + + // Then + Assert.Equal("root/other", result.Path.FullPath); + } + + [Fact] + public void Should_Return_A_New_Convertable_Directory_Path() + { + // Given + var path = new DirectoryPath("./root"); + + // When + var result = path + new ConvertableDirectoryPath("other"); + + // Then + Assert.IsType(result); + } + + [Fact] + public void Should_Throw_If_Left_Operand_Is_Null() + { + // Given, When + var result = Record.Exception(() => + (DirectoryPath)null + new ConvertableDirectoryPath("other")); + + // Then + AssertEx.IsArgumentNullException(result, "left"); + } + + [Fact] + public void Should_Throw_If_Right_Operand_Is_Null() + { + // Given, When + var result = Record.Exception(() => + new DirectoryPath("./root") + (ConvertableDirectoryPath)null); + + // Then + AssertEx.IsArgumentNullException(result, "right"); + } + } + public sealed class AddingConvertableFilePath { [Fact] diff --git a/src/Cake.Common.Tests/Unit/ReleaseNotesAliasesTests.cs b/src/Cake.Common.Tests/Unit/ReleaseNotesAliasesTests.cs index b24f3994b7..fca05ac075 100644 --- a/src/Cake.Common.Tests/Unit/ReleaseNotesAliasesTests.cs +++ b/src/Cake.Common.Tests/Unit/ReleaseNotesAliasesTests.cs @@ -61,6 +61,7 @@ public void Should_Read_Content_Of_File_And_Parse_It() // Then Assert.Equal("1.2.3", result[0].Version.ToString()); + Assert.Equal("1.2.3", result[0].SemVersion.ToString()); } } @@ -82,6 +83,7 @@ public void Should_Return_The_Latest_Release_Notes() // Then Assert.Equal("1.2.5", result.Version.ToString()); + Assert.Equal("1.2.5", result.SemVersion.ToString()); } } } diff --git a/src/Cake.Common.Tests/Unit/ReleaseNotesParserTests.cs b/src/Cake.Common.Tests/Unit/ReleaseNotesParserTests.cs index 0d6d0c29ff..364f12adf5 100644 --- a/src/Cake.Common.Tests/Unit/ReleaseNotesParserTests.cs +++ b/src/Cake.Common.Tests/Unit/ReleaseNotesParserTests.cs @@ -1,10 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - using Cake.Core; using Xunit; - namespace Cake.Common.Tests.Unit { public sealed class ReleaseNotesParserTests @@ -67,6 +65,7 @@ public void Should_Parse_Release_Note_Version() // Then Assert.Equal("0.1.9", result[0].Version.ToString()); + Assert.Equal("0.1.9", result[0].SemVersion.ToString()); } [Fact] @@ -129,6 +128,8 @@ public void Should_Return_Release_Notes_In_Descending_Order() Assert.Equal(2, result.Count); Assert.Equal("0.1.10", result[0].Version.ToString()); Assert.Equal("0.1.9", result[1].Version.ToString()); + Assert.Equal("0.1.10", result[0].SemVersion.ToString()); + Assert.Equal("0.1.9", result[1].SemVersion.ToString()); } [Fact] @@ -159,6 +160,40 @@ public void Should_Set_RawVersionLine_Property_To_Line_Containing_Version_Number // Then Assert.Equal("### New in 0.1.9-beta1 (Releases 2014/06/28)", result[0].RawVersionLine); } + + [Fact] + public void Should_Parse_Release_Note_Version_With_Prerelease() + { + // Given + var parser = new ReleaseNotesParser(); + const string content = "### New in 0.1.9-beta1 (Releases 2014/06/28)\nLine 1\n \n\t\n"; + + // When + var result = parser.Parse(content); + + // Then + Assert.Equal("0.1.9", result[0].Version.ToString()); + Assert.Equal("0.1.9-beta1", result[0].SemVersion.ToString()); + } + + [Fact] + public void Should_Return_Multiple_Release_Notes_With_Prerelease() + { + // Given + var parser = new ReleaseNotesParser(); + const string content = "### New in 0.1.9-alpha1 (Releases 2014/06/28)\n* Line 1\n" + + "###New in 0.1.10-gamma3\n* Line 2\n Line 3"; + + // When + var result = parser.Parse(content); + + // Then + Assert.Equal(2, result.Count); + Assert.Equal("0.1.10", result[0].Version.ToString()); + Assert.Equal("0.1.9", result[1].Version.ToString()); + Assert.Equal("0.1.10-gamma3", result[0].SemVersion.ToString()); + Assert.Equal("0.1.9-alpha1", result[1].SemVersion.ToString()); + } } public sealed class SimpleFormat @@ -190,6 +225,7 @@ public void Should_Parse_Release_Note_Version() // Then Assert.Equal("0.1.9", result[0].Version.ToString()); + Assert.Equal("0.1.9", result[0].SemVersion.ToString()); } [Fact] @@ -249,6 +285,8 @@ public void Should_Return_Release_Notes_In_Descending_Order() Assert.Equal(2, result.Count); Assert.Equal("0.1.10", result[0].Version.ToString()); Assert.Equal("0.1.9", result[1].Version.ToString()); + Assert.Equal("0.1.10", result[0].SemVersion.ToString()); + Assert.Equal("0.1.9", result[1].SemVersion.ToString()); } } } diff --git a/src/Cake.Common.Tests/Unit/ReleaseNotesTests.cs b/src/Cake.Common.Tests/Unit/ReleaseNotesTests.cs index 47946bc890..013870fe41 100644 --- a/src/Cake.Common.Tests/Unit/ReleaseNotesTests.cs +++ b/src/Cake.Common.Tests/Unit/ReleaseNotesTests.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - +using System; using System.Linq; using Xunit; @@ -15,11 +15,23 @@ public sealed class TheConstructor public void Should_Throw_If_Version_Is_Null() { // Given, When - var result = Record.Exception(() => new ReleaseNotes(null, Enumerable.Empty(), null)); + Version version = null; + var result = Record.Exception(() => new ReleaseNotes(version, Enumerable.Empty(), null)); // Then AssertEx.IsArgumentNullException(result, "version"); } + + [Fact] + public void Should_Throw_If_SemVersion_Is_Null() + { + // Given, When + SemVersion semVersion = null; + var result = Record.Exception(() => new ReleaseNotes(semVersion, Enumerable.Empty(), null)); + + // Then + AssertEx.IsArgumentNullException(result, "semVersion"); + } } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Security/DirectoryHashCalculatorTests.cs b/src/Cake.Common.Tests/Unit/Security/DirectoryHashCalculatorTests.cs new file mode 100644 index 0000000000..c60f1d6077 --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Security/DirectoryHashCalculatorTests.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Cake.Common.Security; +using Cake.Core; +using Cake.Core.IO; +using NSubstitute; +using Xunit; + +namespace Cake.Common.Tests.Unit.Security +{ + public sealed class DirectoryHashCalculatorTests + { + public sealed class TheCalculateMethod + { + [Fact] + public void Should_Throw_If_Directory_Path_Is_Null() + { + // Given + var hashAlgorithmBuilder = Substitute.For(); + var cakeContext = Substitute.For(); + var calculator = new DirectoryHashCalculator(cakeContext, hashAlgorithmBuilder); + + // When + var result = Record.Exception(() => calculator.Calculate(null, null as string[], HashAlgorithm.MD5)); + + // Then + AssertEx.IsArgumentNullException(result, "directoryPath"); + } + + [Fact] + public void Should_Throw_If_Directory_Does_Not_Exist() + { + // Given + var hashAlgorithmBuilder = Substitute.For(); + var fileSystem = Substitute.For(); + var file = Substitute.For(); + file.Exists.Returns(false); + fileSystem.GetFile(Arg.Any()).Returns(file); + var cakeContext = Substitute.For(); + cakeContext.FileSystem.Returns(fileSystem); + + var calculator = new DirectoryHashCalculator(cakeContext, hashAlgorithmBuilder); + + // When + var result = Record.Exception(() => calculator.Calculate("./non-existent-path", new List { "./**/*.cs" }, HashAlgorithm.MD5)); + + // Then + AssertEx.IsExceptionWithMessage(result, "Directory 'non-existent-path' does not exist."); + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Security/FileHashCalculatorTests.cs b/src/Cake.Common.Tests/Unit/Security/FileHashCalculatorTests.cs index 3b7f7e9325..586a1ca6b0 100644 --- a/src/Cake.Common.Tests/Unit/Security/FileHashCalculatorTests.cs +++ b/src/Cake.Common.Tests/Unit/Security/FileHashCalculatorTests.cs @@ -18,8 +18,9 @@ public sealed class TheCalculateMethod public void Should_Throw_If_File_Path_Is_Null() { // Given + var hashAlgorithmBuilder = Substitute.For(); var fileSystem = Substitute.For(); - var calculator = new FileHashCalculator(fileSystem); + var calculator = new FileHashCalculator(fileSystem, hashAlgorithmBuilder); // When var result = Record.Exception(() => calculator.Calculate(null, HashAlgorithm.MD5)); @@ -32,12 +33,13 @@ public void Should_Throw_If_File_Path_Is_Null() public void Should_Throw_If_File_Does_Not_Exist() { // Given + var hashAlgorithmBuilder = Substitute.For(); var fileSystem = Substitute.For(); var file = Substitute.For(); file.Exists.Returns(false); fileSystem.GetFile(Arg.Any()).Returns(file); - var calculator = new FileHashCalculator(fileSystem); + var calculator = new FileHashCalculator(fileSystem, hashAlgorithmBuilder); // When var result = Record.Exception(() => calculator.Calculate("./non-existent-path", HashAlgorithm.MD5)); diff --git a/src/Cake.Common.Tests/Unit/Security/HashAlgorithmBuilderTests.cs b/src/Cake.Common.Tests/Unit/Security/HashAlgorithmBuilderTests.cs new file mode 100644 index 0000000000..c00c4188e8 --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Security/HashAlgorithmBuilderTests.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Security; +using Xunit; + +namespace Cake.Common.Tests.Unit.Security +{ + public sealed class HashAlgorithmBuilderTests + { + public sealed class TheCreateHashAlgorithmMethod + { + [Fact] + public void Should_Return_MD5_Algorithm_Instance_If_Input_Is_Cake_HashAlgorithm_Enum_MD5() + { + // Given + var hashAlgorithmbuilder = new HashAlgorithmBuilder(); + + // When + var result = hashAlgorithmbuilder.CreateHashAlgorithm(HashAlgorithm.MD5); + + // Then + Assert.IsAssignableFrom(result); + } + + [Fact] + public void Should_Return_SHA256_Algorithm_Instance_If_Input_Is_Cake_HashAlgorithm_Enum_SHA256() + { + // Given + var hashAlgorithmbuilder = new HashAlgorithmBuilder(); + + // When + var result = hashAlgorithmbuilder.CreateHashAlgorithm(HashAlgorithm.SHA256); + + // Then + Assert.IsAssignableFrom(result); + } + + [Fact] + public void Should_Return_SHA512_Algorithm_Instance_If_Input_Is_Cake_HashAlgorithm_Enum_SHA512() + { + // Given + var hashAlgorithmbuilder = new HashAlgorithmBuilder(); + + // When + var result = hashAlgorithmbuilder.CreateHashAlgorithm(HashAlgorithm.SHA512); + + // Then + Assert.IsAssignableFrom(result); + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/SemVerTests.cs b/src/Cake.Common.Tests/Unit/SemVerTests.cs new file mode 100644 index 0000000000..62a1527f2f --- /dev/null +++ b/src/Cake.Common.Tests/Unit/SemVerTests.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace Cake.Common.Tests.Unit +{ + public sealed class SemVerTests + { + public sealed class TheTryParseMethod + { + [Fact] + public void Should_Return_False_If_Version_Is_Null() + { + // Given + string version = null; + + // When + var result = SemVersion.TryParse(version, out _); + + // Then + Assert.False(result); + } + + [Theory] + [InlineData(1, 2, 3, null, null, "1.2.3")] + [InlineData(1, 2, 3, "rc001", null, "1.2.3-rc001")] + [InlineData(1, 2, 3, "rc001", "meta1", "1.2.3-rc001+meta1")] + public void Should_Return_True_If_Version_Is_Valid(int major, int minor, int patch, string preRelease, string meta, string versionString) + { + // Given + var expect = new SemVersion(major, minor, patch, preRelease, meta); + + // When + var result = SemVersion.TryParse(versionString, out var parsedSemVersion); + + // Then + Assert.True(result, nameof(SemVersion.TryParse)); + Assert.Equal(expect, parsedSemVersion); + Assert.True(expect == parsedSemVersion, "expect == parsedSemVersion"); + Assert.Equal(versionString, parsedSemVersion.VersionString); + } + } + + public sealed class Operators + { + private const bool ExpectGreaterThanTrue = true; + private const bool ExpectGreaterThanFalse = false; + private const bool ExpectLessThanTrue = true; + private const bool ExpectLessThanFalse = false; + private const bool ExpectGreaterThanOrEqualTrue = true; + private const bool ExpectGreaterThanOrEqualFalse = false; + private const bool ExpectLesserThanOrEqualTrue = true; + private const bool ExpectLesserThanOrEqualFalse = false; + private const bool ExpectEqualToTrue = true; + private const bool ExpectEqualToFalse = false; + private const bool ExpectNotEqualToTrue = true; + private const bool ExpectNotEqualToFalse = false; + + [Theory] + [InlineData("1.2.3", "1.2.3", ExpectGreaterThanFalse, ExpectLessThanFalse, ExpectGreaterThanOrEqualTrue, ExpectLesserThanOrEqualTrue, ExpectEqualToTrue, ExpectNotEqualToFalse)] + [InlineData("1.2.4", "1.2.3", ExpectGreaterThanTrue, ExpectLessThanFalse, ExpectGreaterThanOrEqualTrue, ExpectLesserThanOrEqualFalse, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3", "1.2.4", ExpectGreaterThanFalse, ExpectLessThanTrue, ExpectGreaterThanOrEqualFalse, ExpectLesserThanOrEqualTrue, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3-rc001", "1.2.3-rc001", ExpectGreaterThanFalse, ExpectLessThanFalse, ExpectGreaterThanOrEqualTrue, ExpectLesserThanOrEqualTrue, ExpectEqualToTrue, ExpectNotEqualToFalse)] + [InlineData("1.2.4-rc001", "1.2.3-rc001", ExpectGreaterThanTrue, ExpectLessThanFalse, ExpectGreaterThanOrEqualTrue, ExpectLesserThanOrEqualFalse, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3-rc001", "1.2.4-rc001", ExpectGreaterThanFalse, ExpectLessThanTrue, ExpectGreaterThanOrEqualFalse, ExpectLesserThanOrEqualTrue, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3-rc001+meta001", "1.2.3-rc001+meta001", ExpectGreaterThanFalse, ExpectLessThanFalse, ExpectGreaterThanOrEqualTrue, ExpectLesserThanOrEqualTrue, ExpectEqualToTrue, ExpectNotEqualToFalse)] + [InlineData("1.2.4-rc001+meta001", "1.2.3-rc001+meta001", ExpectGreaterThanTrue, ExpectLessThanFalse, ExpectGreaterThanOrEqualTrue, ExpectLesserThanOrEqualFalse, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3-rc001+meta001", "1.2.4-rc001+meta001", ExpectGreaterThanFalse, ExpectLessThanTrue, ExpectGreaterThanOrEqualFalse, ExpectLesserThanOrEqualTrue, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3", "1.2.3-rc001", ExpectGreaterThanTrue, ExpectLessThanFalse, ExpectGreaterThanOrEqualTrue, ExpectLesserThanOrEqualFalse, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3-rc001", "1.2.3", ExpectGreaterThanFalse, ExpectLessThanTrue, ExpectGreaterThanOrEqualFalse, ExpectLesserThanOrEqualTrue, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3-rc001", "1.2.3-rc001+meta001", ExpectGreaterThanTrue, ExpectLessThanFalse, ExpectGreaterThanOrEqualTrue, ExpectLesserThanOrEqualFalse, ExpectEqualToFalse, ExpectNotEqualToTrue)] + [InlineData("1.2.3-rc001+meta001", "1.2.3-rc001", ExpectGreaterThanFalse, ExpectLessThanTrue, ExpectGreaterThanOrEqualFalse, ExpectLesserThanOrEqualTrue, ExpectEqualToFalse, ExpectNotEqualToTrue)] + public void Should_Return_Expected(string operand1string, string operand2string, bool expectGreaterThan, bool expectLessThan, bool expectGreaterThanOrEqual, bool expectLesserThanOrEqual, bool expectEqualTo, bool expectNotEqualTo) + { + // Given + var expect = new + { + ParsedOperand1 = true, + ParsedOperand2 = true, + GreaterThan = expectGreaterThan, + LessThan = expectLessThan, + GreaterThanOrEqual = expectGreaterThanOrEqual, + LesserThanOrEqual = expectLesserThanOrEqual, + EqualTo = expectEqualTo, + NotEqualTo = expectNotEqualTo + }; + + // When + var result = new + { + ParsedOperand1 = SemVersion.TryParse(operand1string, out var operand1), + ParsedOperand2 = SemVersion.TryParse(operand2string, out var operand2), + GreaterThan = operand1 > operand2, + LessThan = operand1 < operand2, + GreaterThanOrEqual = operand1 >= operand2, + LesserThanOrEqual = operand1 <= operand2, + EqualTo = operand1 == operand2, + NotEqualTo = operand1 != operand2, + }; + + // Then + Assert.Equal(expect, result); + } + + [Fact] + public void Should_Be_Able_To_Compare_Equals_Null() + { + // Given + SemVersion semVersion = null; + + // When / Then + Assert.True(semVersion == null); + } + + [Fact] + public void Should_Be_Able_To_Compare_Not_Equals_Null() + { + // Given + SemVersion semVersion = null; + + // When / Then + Assert.False(semVersion != null); + } + + [Fact] + public void Should_Be_Able_To_Compare_GreaterThan_Null() + { + // Given + SemVersion semVersion = null; + + // When / Then + Assert.False(semVersion > null); + } + + [Fact] + public void Should_Be_Able_To_Compare_LessThan_Null() + { + // Given + SemVersion semVersion = null; + + // When / Then + Assert.False(semVersion < null); + } + + [Fact] + public void Should_Be_Able_To_Compare_GreaterEqualThan_Null() + { + // Given + SemVersion semVersion = null; + + // When / Then + Assert.True(semVersion >= null); + } + + [Fact] + public void Should_Be_Able_To_Compare_LessEqualThan_Null() + { + // Given + SemVersion semVersion = null; + + // When / Then + Assert.True(semVersion <= null); + } + } + } +} diff --git a/src/Cake.Common.Tests/Unit/Solution/Project/ProjectParserTests.cs b/src/Cake.Common.Tests/Unit/Solution/Project/ProjectParserTests.cs index 99a7093c57..8e74972ac0 100644 --- a/src/Cake.Common.Tests/Unit/Solution/Project/ProjectParserTests.cs +++ b/src/Cake.Common.Tests/Unit/Solution/Project/ProjectParserTests.cs @@ -235,11 +235,13 @@ public void Should_Return_Project_References() var result = fixture.Parse(); // Then - Assert.Equal(1, result.ProjectReferences.Count); + Assert.Equal(2, result.ProjectReferences.Count); Assert.Equal("/Working/../Cake.Common/Cake.Common.csproj", result.ProjectReferences.First().FilePath.FullPath); Assert.Equal("..\\Cake.Common\\Cake.Common.csproj", result.ProjectReferences.First().RelativePath); Assert.Equal("{ABC3F1CB-F84E-43ED-A120-0CCFE344D250}", result.ProjectReferences.First().Project); Assert.Equal("Cake.Common", result.ProjectReferences.First().Name); + Assert.Equal(null, result.ProjectReferences.First().Private); + Assert.Equal(true, result.ProjectReferences.ElementAt(1).Private); } } } diff --git a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoParserTests.cs b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoParserTests.cs index 882290f33c..bb009c530f 100644 --- a/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoParserTests.cs +++ b/src/Cake.Common.Tests/Unit/Solution/Project/Properties/AssemblyInfoParserTests.cs @@ -77,13 +77,17 @@ public void Should_Throw_If_AssemblyInfo_File_Do_Not_Exist() } [Theory] - [InlineData(true, true)] - [InlineData(false, false)] - [InlineData(null, false)] - public void Should_Read_ClsCompliance(bool value, bool expected) + [InlineData(true, true, true)] + [InlineData(false, false, true)] + [InlineData(null, false, true)] + [InlineData(true, true, false)] + [InlineData(false, false, false)] + [InlineData(null, false, false)] + public void Should_Read_ClsCompliance(bool value, bool expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.ClsCompliant = value; // When @@ -94,12 +98,15 @@ public void Should_Read_ClsCompliance(bool value, bool expected) } [Theory] - [InlineData("CompanyA", "CompanyA")] - [InlineData(null, "")] - public void Should_Read_Company(string value, string expected) + [InlineData("CompanyA", "CompanyA", true)] + [InlineData("CompanyA", "CompanyA", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Company(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Company = value; // When @@ -110,13 +117,36 @@ public void Should_Read_Company(string value, string expected) } [Theory] - [InlineData(true, true)] - [InlineData(false, false)] - [InlineData(null, false)] - public void Should_Read_ComVisible(bool value, bool expected) + [InlineData("CompanyA", "CompanyA", true)] + [InlineData("CompanyA", "CompanyA", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Company_VB_AssemblyInfo_File(string value, string expected, bool extraWhiteSpaces) + { + // Given + var fixture = new AssemblyInfoParserFixture_VB(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; + fixture.Company = value; + + // When + var result = fixture.Parse(); + + // Then + Assert.Equal(expected, result.Company); + } + + [Theory] + [InlineData(true, true, true)] + [InlineData(false, false, true)] + [InlineData(null, false, true)] + [InlineData(true, true, false)] + [InlineData(false, false, false)] + [InlineData(null, false, false)] + public void Should_Read_ComVisible(bool value, bool expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.ComVisible = value; // When @@ -127,13 +157,17 @@ public void Should_Read_ComVisible(bool value, bool expected) } [Theory] - [InlineData("Debug", "Debug")] - [InlineData("Release", "Release")] - [InlineData(null, "")] - public void Should_Read_Configuration(string value, string expected) + [InlineData("Debug", "Debug", true)] + [InlineData("Debug", "Debug", false)] + [InlineData("Release", "Release", true)] + [InlineData("Release", "Release", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Configuration(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Configuration = value; // When @@ -144,12 +178,15 @@ public void Should_Read_Configuration(string value, string expected) } [Theory] - [InlineData("Copyright (c) Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio and contributors", "Copyright (c) Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio and contributors")] - [InlineData(null, "")] - public void Should_Read_Copyright(string value, string expected) + [InlineData("Copyright (c) Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio, C. Augusto Proiete, Nils Andresen, and contributors", "Copyright (c) Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio, C. Augusto Proiete, Nils Andresen, and contributors", true)] + [InlineData("Copyright (c) Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio, C. Augusto Proiete, Nils Andresen, and contributors", "Copyright (c) Patrik Svensson, Mattias Karlsson, Gary Ewan Park, Alistair Chapman, Martin Björkström, Dave Glick, Pascal Berger, Jérémie Desautels, Enrico Campidoglio, C. Augusto Proiete, Nils Andresen, and contributors", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Copyright(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Copyright = value; // When @@ -160,12 +197,15 @@ public void Should_Read_Copyright(string value, string expected) } [Theory] - [InlineData("Assembly Description", "Assembly Description")] - [InlineData(null, "")] - public void Should_Read_Description(string value, string expected) + [InlineData("Assembly Description", "Assembly Description", true)] + [InlineData("Assembly Description", "Assembly Description", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Description(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Description = value; // When @@ -176,13 +216,17 @@ public void Should_Read_Description(string value, string expected) } [Theory] - [InlineData("1.2.3.4", "1.2.3.4")] - [InlineData("1.2.*.*", "1.2.*.*")] - [InlineData(null, "1.0.0.0")] - public void Should_Read_AssemblyFileVersion(string value, string expected) + [InlineData("1.2.3.4", "1.2.3.4", true)] + [InlineData("1.2.3.4", "1.2.3.4", false)] + [InlineData("1.2.*.*", "1.2.*.*", true)] + [InlineData("1.2.*.*", "1.2.*.*", false)] + [InlineData(null, "1.0.0.0", true)] + [InlineData(null, "1.0.0.0", false)] + public void Should_Read_AssemblyFileVersion(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.FileVersion = value; // When @@ -193,12 +237,15 @@ public void Should_Read_AssemblyFileVersion(string value, string expected) } [Theory] - [InlineData("D394B7DB-0DDC-4D11-AD69-C408212E1E80", "D394B7DB-0DDC-4D11-AD69-C408212E1E80")] - [InlineData(null, "")] - public void Should_Read_Guid(string value, string expected) + [InlineData("D394B7DB-0DDC-4D11-AD69-C408212E1E80", "D394B7DB-0DDC-4D11-AD69-C408212E1E80", true)] + [InlineData("D394B7DB-0DDC-4D11-AD69-C408212E1E80", "D394B7DB-0DDC-4D11-AD69-C408212E1E80", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Guid(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Guid = value; // When @@ -209,14 +256,19 @@ public void Should_Read_Guid(string value, string expected) } [Theory] - [InlineData("1.2.3.4", "1.2.3.4")] - [InlineData("1.2.*.*", "1.2.*.*")] - [InlineData("1.2.3-rc1", "1.2.3-rc1")] - [InlineData(null, "1.0.0.0")] - public void Should_Read_AssemblyInformationalVersion(string value, string expected) + [InlineData("1.2.3.4", "1.2.3.4", true)] + [InlineData("1.2.3.4", "1.2.3.4", false)] + [InlineData("1.2.*.*", "1.2.*.*", true)] + [InlineData("1.2.*.*", "1.2.*.*", false)] + [InlineData("1.2.3-rc1", "1.2.3-rc1", true)] + [InlineData("1.2.3-rc1", "1.2.3-rc1", false)] + [InlineData(null, "1.0.0.0", true)] + [InlineData(null, "1.0.0.0", false)] + public void Should_Read_AssemblyInformationalVersion(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.InformationalVersion = value; // When @@ -226,11 +278,14 @@ public void Should_Read_AssemblyInformationalVersion(string value, string expect Assert.Equal(expected, result.AssemblyInformationalVersion); } - [Fact] - public void Should_Read_InternalsVisibleTo() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void Should_Read_InternalsVisibleTo(bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.InternalsVisibleTo = new List { "Cake.Core.Tests", @@ -247,12 +302,15 @@ public void Should_Read_InternalsVisibleTo() } [Theory] - [InlineData("Cake", "Cake")] - [InlineData(null, "")] - public void Should_Read_Product(string value, string expected) + [InlineData("Cake", "Cake", true)] + [InlineData("Cake", "Cake", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Product(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Product = value; // When @@ -263,12 +321,15 @@ public void Should_Read_Product(string value, string expected) } [Theory] - [InlineData("Cake.Common", "Cake.Common")] - [InlineData(null, "")] - public void Should_Read_Title(string value, string expected) + [InlineData("Cake.Common", "Cake.Common", true)] + [InlineData("Cake.Common", "Cake.Common", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Title(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Title = value; // When @@ -279,12 +340,15 @@ public void Should_Read_Title(string value, string expected) } [Theory] - [InlineData("Trademark Cake", "Trademark Cake")] - [InlineData(null, "")] - public void Should_Read_Trademark(string value, string expected) + [InlineData("Trademark Cake", "Trademark Cake", true)] + [InlineData("Trademark Cake", "Trademark Cake", false)] + [InlineData(null, "", true)] + [InlineData(null, "", false)] + public void Should_Read_Trademark(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Trademark = value; // When @@ -295,13 +359,17 @@ public void Should_Read_Trademark(string value, string expected) } [Theory] - [InlineData("1.2.3.4", "1.2.3.4")] - [InlineData("1.2.*.*", "1.2.*.*")] - [InlineData(null, "1.0.0.0")] - public void Should_Read_AssemblyVersion(string value, string expected) + [InlineData("1.2.3.4", "1.2.3.4", true)] + [InlineData("1.2.3.4", "1.2.3.4", false)] + [InlineData("1.2.*.*", "1.2.*.*", true)] + [InlineData("1.2.*.*", "1.2.*.*", false)] + [InlineData(null, "1.0.0.0", true)] + [InlineData(null, "1.0.0.0", false)] + public void Should_Read_AssemblyVersion(string value, string expected, bool extraWhiteSpaces) { // Given var fixture = new AssemblyInfoParserFixture(); + fixture.ExtraWhiteSpaces = extraWhiteSpaces; fixture.Version = value; // When diff --git a/src/Cake.Common.Tests/Unit/Solution/SolutionParserTests.cs b/src/Cake.Common.Tests/Unit/Solution/SolutionParserTests.cs index f35b221be3..ab18f8bc71 100644 --- a/src/Cake.Common.Tests/Unit/Solution/SolutionParserTests.cs +++ b/src/Cake.Common.Tests/Unit/Solution/SolutionParserTests.cs @@ -111,6 +111,44 @@ public void Should_Properly_Parse_Relation_Between_Project_And_Folder() Assert.Contains(dummyProject, srcFolder.Items); Assert.Equal(srcFolder, dummyProject.Parent); } + + [Fact] + public void Should_Properly_Parse_Projects_With_Empty_Lines() + { + // Given + var fixture = new SolutionParserFixture(); + var slnFilePath = fixture.WithSolutionFile(Resources.Solution_WithProjectsAndFoldersAndMissingLine); + var solutionParser = new SolutionParser(fixture.FileSystem, fixture.Environment); + + // When + var result = solutionParser.Parse(slnFilePath); + + // Then + Assert.NotNull(result); + Assert.NotNull(result.Projects); + Assert.Equal(5, result.Projects.Count); + var onlyProjects = result.Projects.Where(x => !(x is SolutionFolder)).ToList(); + Assert.Equal(3, onlyProjects.Count); + } + + [Fact] + public void Should_Properly_Parse_Projects_With_Absolute_Path() + { + // Given + var fixture = new SolutionParserFixture(); + var slnFilePath = fixture.WithSolutionFile(Resources.Solution_WithProjectUsingAbsolutePath); + var solutionParser = new SolutionParser(fixture.FileSystem, fixture.Environment); + + // When + var result = solutionParser.Parse(slnFilePath); + + // Then + Assert.NotNull(result); + Assert.NotNull(result.Projects); + Assert.Single(result.Projects); + var onlyProjects = result.Projects.Where(x => !(x is SolutionFolder)).ToList(); + Assert.Single(onlyProjects); + } } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/Cake/CakeRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/Cake/CakeRunnerTests.cs index 2188c54ea3..660bf299ca 100644 --- a/src/Cake.Common.Tests/Unit/Tools/Cake/CakeRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/Cake/CakeRunnerTests.cs @@ -118,7 +118,7 @@ public void Should_Add_Provided_Verbosity_To_Process_Arguments() var result = fixture.Run(); // Then - Assert.Equal("\"/Working/build.cake\" -verbosity=Diagnostic", result.Args); + Assert.Equal("\"/Working/build.cake\" --verbosity=Diagnostic", result.Args); } [Fact] @@ -135,8 +135,8 @@ public void Should_Add_Provided_Arguments_To_Process_Arguments() // Then Assert.Equal("\"/Working/build.cake\" " + - "-target=\"Build\" " + - "-configuration=\"Debug\"", result.Args); + "--target=\"Build\" " + + "--configuration=\"Debug\"", result.Args); } } } diff --git a/src/Cake.Common.Tests/Unit/Tools/Chocolatey/Export/ChocolateyExporterTests.cs b/src/Cake.Common.Tests/Unit/Tools/Chocolatey/Export/ChocolateyExporterTests.cs new file mode 100644 index 0000000000..bea2614454 --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Tools/Chocolatey/Export/ChocolateyExporterTests.cs @@ -0,0 +1,292 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tests.Fixtures.Tools.Chocolatey.Export; +using Cake.Testing; +using Cake.Testing.Xunit; +using Xunit; + +namespace Cake.Common.Tests.Unit.Tools.Chocolatey.Export +{ + public sealed class ChocolateyExporterTests + { + public sealed class TheExportMethod + { + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings = null; + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsArgumentNullException(result, "settings"); + } + + [Fact] + public void Should_Throw_If_Chocolatey_Executable_Was_Not_Found() + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.GivenDefaultToolDoNotExist(); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsCakeException(result, "Chocolatey: Could not locate executable."); + } + + [Theory] + [InlineData("/bin/chocolatey/choco.exe", "/bin/chocolatey/choco.exe")] + [InlineData("./chocolatey/choco.exe", "/Working/chocolatey/choco.exe")] + public void Should_Use_Chocolatey_Executable_From_Tool_Path_If_Provided(string toolPath, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.ToolPath = toolPath; + fixture.GivenSettingsToolPathExist(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Path.FullPath); + } + + [WindowsTheory] + [InlineData("C:/ProgramData/chocolatey/choco.exe", "C:/ProgramData/chocolatey/choco.exe")] + public void Should_Use_Chocolatey_Executable_From_Tool_Path_If_Provided_On_Windows(string toolPath, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.ToolPath = toolPath; + fixture.GivenSettingsToolPathExist(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Path.FullPath); + } + + [Fact] + public void Should_Throw_If_Process_Was_Not_Started() + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.GivenProcessCannotStart(); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsCakeException(result, "Chocolatey: Process was not started."); + } + + [Fact] + public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.GivenProcessExitsWithCode(1); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsCakeException(result, "Chocolatey: Process returned an error (exit code 1)."); + } + + [Fact] + public void Should_Find_Chocolatey_Executable_If_Tool_Path_Not_Provided() + { + // Given + var fixture = new ChocolateyExportFixture(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/Working/tools/choco.exe", result.Path.FullPath); + } + + [Fact] + public void Should_Add_Mandatory_Arguments() + { + // Given + var fixture = new ChocolateyExportFixture(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("export -y", result.Args); + } + + [Theory] + [InlineData(true, "export -d -y")] + [InlineData(false, "export -y")] + public void Should_Add_Debug_Flag_To_Arguments_If_Set(bool debug, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.Debug = debug; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(true, "export -v -y")] + [InlineData(false, "export -y")] + public void Should_Add_Verbose_Flag_To_Arguments_If_Set(bool verbose, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.Verbose = verbose; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(true, "export -y -f")] + [InlineData(false, "export -y")] + public void Should_Add_Force_Flag_To_Arguments_If_Set(bool force, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.Force = force; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(true, "export -y --noop")] + [InlineData(false, "export -y")] + public void Should_Add_Noop_Flag_To_Arguments_If_Set(bool noop, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.Noop = noop; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(true, "export -y -r")] + [InlineData(false, "export -y")] + public void Should_Add_LimitOutput_Flag_To_Arguments_If_Set(bool limitOutput, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.LimitOutput = limitOutput; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(5, "export -y --execution-timeout \"5\"")] + [InlineData(0, "export -y")] + public void Should_Add_ExecutionTimeout_To_Arguments_If_Set(int executionTimeout, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.ExecutionTimeout = executionTimeout; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(@"c:\temp", "export -y -c \"c:\\temp\"")] + [InlineData("", "export -y")] + public void Should_Add_CacheLocation_Flag_To_Arguments_If_Set(string cacheLocation, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.CacheLocation = cacheLocation; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(true, "export -y --allowunofficial")] + [InlineData(false, "export -y")] + public void Should_Add_AllowUnofficial_Flag_To_Arguments_If_Set(bool allowUnofficial, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.AllowUnofficial = allowUnofficial; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(@"c:\temp", "export -y --output-file-path \"c:/temp\"")] + [InlineData(null, "export -y")] + public void Should_Add_OutputFilePath_To_Arguments_If_Set(string outputFilePath, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.OutputFilePath = outputFilePath; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData(true, "export -y --include-version-numbers")] + [InlineData(false, "export -y")] + public void Should_Add_IncludeVersionNumbers_Flag_To_Arguments_If_Set(bool includeVersionNumbers, string expected) + { + // Given + var fixture = new ChocolateyExportFixture(); + fixture.Settings.IncludeVersionNumbers = includeVersionNumbers; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNet/Format/DotNetFormatTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNet/Format/DotNetFormatTests.cs new file mode 100644 index 0000000000..4921371013 --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Tools/DotNet/Format/DotNetFormatTests.cs @@ -0,0 +1,152 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tests.Fixtures.Tools.DotNet.Format; +using Cake.Common.Tools.DotNet.Format; +using Cake.Testing; +using Xunit; + +namespace Cake.Common.Tests.Unit.Tools.DotNet.Format +{ + public sealed class DotNetFormatTests + { + public sealed class TheFormatMethod + { + [Fact] + public void Should_Throw_If_Settings_Are_Null() + { + // Given + var fixture = new DotNetFormatterFixture(); + fixture.Root = "./src/project"; + fixture.Settings = null; + fixture.GivenDefaultToolDoNotExist(); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsArgumentNullException(result, "settings"); + } + + [Fact] + public void Should_Throw_If_Root_Is_Null() + { + // Given + var fixture = new DotNetFormatterFixture(); + fixture.Settings = new DotNetFormatSettings(); + fixture.GivenDefaultToolDoNotExist(); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsArgumentNullException(result, "root"); + } + + [Fact] + public void Should_Throw_If_Process_Was_Not_Started() + { + // Given + var fixture = new DotNetFormatterFixture(); + fixture.Root = "./src/project"; + fixture.GivenProcessCannotStart(); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); + } + + [Fact] + public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() + { + // Given + var fixture = new DotNetFormatterFixture(); + fixture.Root = "./src/project"; + fixture.GivenProcessExitsWithCode(1); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); + } + + [Fact] + public void Should_Add_Mandatory_Arguments() + { + // Given + var fixture = new DotNetFormatterFixture(); + fixture.Root = "./src/project"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("format \"./src/project\"", result.Args); + } + + [Fact] + public void Should_Add_Additional_Arguments() + { + // Given + var fixture = new DotNetFormatterFixture(); + fixture.Settings.Diagnostics.Add("CS123"); + fixture.Settings.Diagnostics.Add("CA555"); + fixture.Settings.Severity = DotNetFormatSeverity.Warning; + fixture.Settings.NoRestore = true; + fixture.Settings.VerifyNoChanges = true; + fixture.Settings.Include.Add("./src/"); + fixture.Settings.Include.Add("./tests/"); + fixture.Settings.Exclude.Add("./src/submodule-a/"); + fixture.Settings.IncludeGenerated = true; + fixture.Settings.Verbosity = Common.Tools.DotNet.DotNetVerbosity.Diagnostic; + fixture.Settings.BinaryLog = "./temp/b.log"; + fixture.Settings.Report = "./temp/report.json"; + fixture.Root = "./src/project"; + + // When + var result = fixture.Run(); + + // Then + var expected = "format \"./src/project\" --diagnostics CS123 CA555 --severity warn --no-restore --verify-no-changes --include ./src/ ./tests/ --exclude ./src/submodule-a/ --include-generated"; + expected += " --binarylog \"/Working/temp/b.log\" --report \"/Working/temp/report.json\" --verbosity diagnostic"; + Assert.Equal(expected, result.Args); + } + + [Theory] + [InlineData("./src/project", "format \"./src/project\"")] + [InlineData("./src/cake build/", "format \"./src/cake build/\"")] + [InlineData("./src/cake build/cake cli", "format \"./src/cake build/cake cli\"")] + public void Should_Quote_Root_Path(string text, string expected) + { + // Given + var fixture = new DotNetFormatterFixture(); + fixture.Root = text; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } + + [Fact] + public void Should_Add_Subcommand() + { + // Given + var fixture = new DotNetFormatterFixture(); + fixture.Root = "./src/project"; + fixture.Subcommand = "style"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("format style \"./src/project\"", result.Args); + } + } + } +} diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNet/SDKCheck/DotNetSDKCheckTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNet/SDKCheck/DotNetSDKCheckTests.cs new file mode 100644 index 0000000000..b902ddbe03 --- /dev/null +++ b/src/Cake.Common.Tests/Unit/Tools/DotNet/SDKCheck/DotNetSDKCheckTests.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tests.Fixtures.Tools.DotNet.SDKCheck; +using Cake.Testing; +using Xunit; + +namespace Cake.Common.Tests.Unit.Tools.DotNet.SDKCheck +{ + public sealed class DotNetSDKCheckTests + { + public sealed class TheSDKCheckMethod + { + [Fact] + public void Should_Throw_If_Process_Was_Not_Started() + { + // Given + var fixture = new DotNetSDKCheckerFixture(); + fixture.GivenProcessCannotStart(); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); + } + + [Fact] + public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() + { + // Given + var fixture = new DotNetSDKCheckerFixture(); + fixture.GivenProcessExitsWithCode(1); + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); + } + } + } +} diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetBuildSettingsExtensionsTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetBuildSettingsExtensionsTests.cs deleted file mode 100644 index 6a4aa4976f..0000000000 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetBuildSettingsExtensionsTests.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Common.Tools; -using Cake.Core.Diagnostics; -using Cake.Core.IO; -using Xunit; - -namespace Cake.Common.Tests.Unit.Tools -{ - public sealed class DotNetBuildSettingsExtensionsTests - { - public sealed class TheWithTargetMethod - { - [Fact] - public void Should_Add_Target_To_Configuration() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - settings.WithTarget("Target"); - - // Then - Assert.True(settings.Targets.Contains("Target")); - } - - [Fact] - public void Should_Return_The_Same_Configuration() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - var result = settings.WithTarget("Target"); - - // Then - Assert.Equal(settings, result); - } - } - - public sealed class TheWithPropertyMethod - { - [Fact] - public void Should_Add_Property_To_Configuration() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - settings.WithProperty("PropertyName", "Value"); - - // Then - Assert.True(settings.Properties.ContainsKey("PropertyName")); - } - - [Fact] - public void Should_Return_The_Same_Configuration() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - var result = settings.WithProperty("PropertyName", "Value"); - - // Then - Assert.Equal(settings, result); - } - } - - public sealed class TheSetConfigurationMethod - { - [Fact] - public void Should_Set_Configuration() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - settings.SetConfiguration("TheConfiguration"); - - // Then - Assert.Equal("TheConfiguration", settings.Configuration); - } - - [Fact] - public void Should_Return_The_Same_Configuration() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - var result = settings.SetConfiguration("TheConfiguration"); - - // Then - Assert.Equal(settings, result); - } - } - - public sealed class TheSetVerbosityMethod - { - [Theory] - [InlineData(Verbosity.Quiet)] - [InlineData(Verbosity.Minimal)] - [InlineData(Verbosity.Normal)] - [InlineData(Verbosity.Verbose)] - [InlineData(Verbosity.Diagnostic)] - public void Should_Set_Verbosity(Verbosity verbosity) - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - settings.SetVerbosity(verbosity); - - // Then - Assert.Equal(verbosity, settings.Verbosity); - } - - [Fact] - public void Should_Return_The_Same_Configuration() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - var result = settings.SetVerbosity(Verbosity.Normal); - - // Then - Assert.Equal(settings, result); - } - } - } -} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetBuildSettingsTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetBuildSettingsTests.cs deleted file mode 100644 index d5bb5c7076..0000000000 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetBuildSettingsTests.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Common.Tools; -using Cake.Core.Diagnostics; -using Cake.Core.IO; -using Xunit; - -namespace Cake.Common.Tests.Unit.Tools -{ - public sealed class DotNetBuildSettingsTests - { - public sealed class TheConstructor - { - [Fact] - public void Should_Set_Default_Verbosity_To_Normal() - { - // Given, When - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // Then - Assert.Equal(Verbosity.Normal, settings.Verbosity); - } - - [Fact] - public void Should_Throw_If_Solution_Is_Null() - { - // Given, When - var result = Record.Exception(() => new DotNetBuildSettings(null)); - - // Then - AssertEx.IsArgumentNullException(result, "solution"); - } - } - - public sealed class TheTargetsProperty - { - [Fact] - public void Should_Return_A_Set_That_Is_Case_Insensitive() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - settings.Targets.Add("TARGET"); - - // Then - Assert.True(settings.Targets.Contains("target")); - } - } - - public sealed class ThePropertiesProperty - { - [Fact] - public void Should_Return_A_Dictionary_That_Is_Case_Insensitive() - { - // Given - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // When - settings.Properties.Add("THEKEY", new[] { "THEVALUE" }); - - // Then - Assert.True(settings.Properties.ContainsKey("thekey")); - } - } - - public sealed class TheConfigurationProperty - { - [Fact] - public void Should_Be_Empty_By_Default() - { - // Given, When - var settings = new DotNetBuildSettings(new FilePath("./Test.sln")); - - // Then - Assert.Equal(string.Empty, settings.Configuration); - } - } - - public sealed class TheSolutionProperty - { - [Fact] - public void Should_Return_Passed_Constructor_Argument() - { - // Given - var solution = new FilePath("./Test.sln"); - - // When - var settings = new DotNetBuildSettings(solution); - - // Then - Assert.Equal(solution, settings.Solution); - } - } - } -} \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Build/DotNetCoreBuilderTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Build/DotNetCoreBuilderTests.cs index 5e909d4ed4..d9abf8fe8f 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Build/DotNetCoreBuilderTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Build/DotNetCoreBuilderTests.cs @@ -57,7 +57,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -72,7 +72,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -101,12 +101,13 @@ public void Should_Add_Additional_Arguments() fixture.Settings.NoLogo = true; fixture.Project = "./src/*"; fixture.Settings.Verbosity = DotNetCoreVerbosity.Minimal; + fixture.Settings.Sources = new[] { "https://api.nuget.org/v3/index.json" }; // When var result = fixture.Run(); // Then - Assert.Equal("build \"./src/*\" --runtime runtime1 --framework net451 --configuration Release --version-suffix rc1 --nologo --verbosity minimal", result.Args); + Assert.Equal("build \"./src/*\" --runtime runtime1 --framework net451 --configuration Release --version-suffix rc1 --nologo --source \"https://api.nuget.org/v3/index.json\" --verbosity minimal", result.Args); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerTests.cs index 63138e35a3..6bc2ade4da 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerTests.cs @@ -40,7 +40,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -54,7 +54,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Clean/DotNetCoreCleanTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Clean/DotNetCoreCleanTests.cs index f03be343b3..b8f3da7fa1 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Clean/DotNetCoreCleanTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Clean/DotNetCoreCleanTests.cs @@ -58,7 +58,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -73,7 +73,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Execute/DotNetCoreExecutorTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Execute/DotNetCoreExecutorTests.cs index aec2d1395d..c557748f71 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Execute/DotNetCoreExecutorTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Execute/DotNetCoreExecutorTests.cs @@ -44,7 +44,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -61,7 +61,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildBuilderTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildBuilderTests.cs index d51d3c0b91..870a0dfd0a 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildBuilderTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildBuilderTests.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Cake.Common.Tests.Fixtures.Tools.DotNetCore.MSBuild; +using Cake.Common.Tools.DotNet; using Cake.Common.Tools.DotNetCore; using Cake.Common.Tools.DotNetCore.MSBuild; using Cake.Common.Tools.MSBuild; @@ -64,7 +65,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -81,7 +82,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -607,6 +608,159 @@ public void Should_Add_NoLogo_If_Specified() Assert.Equal("msbuild /nologo", result.Args); } + [Fact] + public void Should_Add_Version_If_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.Version = "1.0.0-test"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:Version=1.0.0-test", result.Args); + } + + [Fact] + public void Should_Add_VersionPrefix_If_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.VersionPrefix = "1.0.0"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:VersionPrefix=1.0.0", result.Args); + } + + [Fact] + public void Should_Add_VersionSuffix_If_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.VersionSuffix = "test"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:VersionSuffix=test", result.Args); + } + + [Fact] + public void Should_Add_FileVersion_If_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.FileVersion = "1.0.0.0"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:FileVersion=1.0.0.0", result.Args); + } + + [Fact] + public void Should_Add_AssemblyVersion_If_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.AssemblyVersion = "1.0.0.0"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:AssemblyVersion=1.0.0.0", result.Args); + } + + [Fact] + public void Should_Add_InformationalVersion_If_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.InformationalVersion = "1.0.0-test+7ad03d0"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:InformationalVersion=1.0.0-test+7ad03d0", result.Args); + } + + [Fact] + public void Should_Add_PackageVersion_If_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.PackageVersion = "1.0.0-test"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:PackageVersion=1.0.0-test", result.Args); + } + + [Fact] + public void Should_Add_PackageReleaseNotes_If_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.PackageReleaseNotes = "https://"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:PackageReleaseNotes=https://", result.Args); + } + + [Fact] + public void Should_Add_ContinuousIntegrationBuild_If_Set_To_True() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.ContinuousIntegrationBuild = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:ContinuousIntegrationBuild=true", result.Args); + } + + [Fact] + public void Should_Add_ContinuousIntegrationBuild_If_Set_To_False() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + fixture.Settings.ContinuousIntegrationBuild = false; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("msbuild /property:ContinuousIntegrationBuild=false", result.Args); + } + + [Fact] + public void Should_Not_Add_ContinuousIntegrationBuild_If_Not_Set() + { + // Given + var fixture = new DotNetCoreMSBuildBuilderFixture(); + + // When + var result = fixture.Run(); + + // Then + Assert.DoesNotContain("/property:ContinuousIntegrationBuild=", result.Args); + } + [Fact] public void Should_Add_ResponseFile_Argument() { @@ -860,12 +1014,12 @@ public void Should_Append_DisableMultiprocessorLogging_If_Specified() } [Theory] - [InlineData(DotNetCoreVerbosity.Quiet)] - [InlineData(DotNetCoreVerbosity.Minimal)] - [InlineData(DotNetCoreVerbosity.Normal)] - [InlineData(DotNetCoreVerbosity.Detailed)] - [InlineData(DotNetCoreVerbosity.Diagnostic)] - public void Should_Append_Verbosity_If_Specified(DotNetCoreVerbosity verbosity) + [InlineData(DotNetVerbosity.Quiet)] + [InlineData(DotNetVerbosity.Minimal)] + [InlineData(DotNetVerbosity.Normal)] + [InlineData(DotNetVerbosity.Detailed)] + [InlineData(DotNetVerbosity.Diagnostic)] + public void Should_Append_Verbosity_If_Specified(DotNetVerbosity verbosity) { // Given var fixture = new DotNetCoreMSBuildBuilderFixture(); @@ -1117,12 +1271,12 @@ public void Should_Append_DisableMultiprocessorLogging_If_Specified() } [Theory] - [InlineData(DotNetCoreVerbosity.Quiet)] - [InlineData(DotNetCoreVerbosity.Minimal)] - [InlineData(DotNetCoreVerbosity.Normal)] - [InlineData(DotNetCoreVerbosity.Detailed)] - [InlineData(DotNetCoreVerbosity.Diagnostic)] - public void Should_Append_Verbosity_If_Specified(DotNetCoreVerbosity verbosity) + [InlineData(DotNetVerbosity.Quiet)] + [InlineData(DotNetVerbosity.Minimal)] + [InlineData(DotNetVerbosity.Normal)] + [InlineData(DotNetVerbosity.Detailed)] + [InlineData(DotNetVerbosity.Diagnostic)] + public void Should_Append_Verbosity_If_Specified(DotNetVerbosity verbosity) { // Given var fixture = new DotNetCoreMSBuildBuilderFixture(); @@ -1142,8 +1296,8 @@ public class TheBinaryLoggerProperty [InlineData(false, null, MSBuildBinaryLoggerImports.Unspecified, "msbuild")] [InlineData(true, null, MSBuildBinaryLoggerImports.Unspecified, "msbuild /binarylogger")] [InlineData(true, null, MSBuildBinaryLoggerImports.None, "msbuild /binarylogger:ProjectImports=None")] - [InlineData(true, "mylog.binlog", MSBuildBinaryLoggerImports.Unspecified, "msbuild /binarylogger:mylog.binlog")] - [InlineData(true, "mylog.binlog", MSBuildBinaryLoggerImports.Embed, "msbuild /binarylogger:mylog.binlog;ProjectImports=Embed")] + [InlineData(true, "mylog.binlog", MSBuildBinaryLoggerImports.Unspecified, "msbuild /binarylogger:\"mylog.binlog\"")] + [InlineData(true, "mylog.binlog", MSBuildBinaryLoggerImports.Embed, "msbuild /binarylogger:\"mylog.binlog\";ProjectImports=Embed")] public void Should_Append_Binary_Logging_If_Specified(bool enabled, string fileName, MSBuildBinaryLoggerImports imports, string args) { // Given @@ -1165,8 +1319,8 @@ public void Should_Append_Binary_Logging_If_Specified(bool enabled, string fileN [Theory] [InlineData(null, MSBuildBinaryLoggerImports.Unspecified, "msbuild /binarylogger")] [InlineData(null, MSBuildBinaryLoggerImports.None, "msbuild /binarylogger:ProjectImports=None")] - [InlineData("mylog.binlog", MSBuildBinaryLoggerImports.Unspecified, "msbuild /binarylogger:mylog.binlog")] - [InlineData("mylog.binlog", MSBuildBinaryLoggerImports.Embed, "msbuild /binarylogger:mylog.binlog;ProjectImports=Embed")] + [InlineData("mylog.binlog", MSBuildBinaryLoggerImports.Unspecified, "msbuild /binarylogger:\"mylog.binlog\"")] + [InlineData("mylog.binlog", MSBuildBinaryLoggerImports.Embed, "msbuild /binarylogger:\"mylog.binlog\";ProjectImports=Embed")] public void Should_Append_Binary_Logging_If_Enabled(string fileName, MSBuildBinaryLoggerImports imports, string args) { // Given diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsExtensionsTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsExtensionsTests.cs index aa49c2c5ff..5e445c62ad 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsExtensionsTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsExtensionsTests.cs @@ -228,6 +228,38 @@ public void Should_Return_The_Same_Configuration() } } + public sealed class TheSetContinuousIntegrationBuildMethod + { + [Theory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void Should_Set_ContinuousIntegrationBuild(bool? continuousIntegrationBuild) + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.SetContinuousIntegrationBuild(continuousIntegrationBuild); + + // Then + Assert.Equal(continuousIntegrationBuild, settings.ContinuousIntegrationBuild); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + var result = settings.SetContinuousIntegrationBuild(); + + // Then + Assert.Equal(settings, result); + } + } + public sealed class TheUseToolVersionMethod { [Fact] @@ -730,6 +762,7 @@ public void Should_Set_Version() // Then Assert.True(settings.Properties.ContainsKey(key)); Assert.Equal(Version, settings.Properties[key].FirstOrDefault()); + Assert.Equal(Version, settings.Version); } [Fact] @@ -779,6 +812,39 @@ public void Should_Return_The_Same_Configuration() } } + public sealed class TheSetAssemblyVersionMethod + { + private const string AssemblyVersion = "1.0.0.0"; + + [Fact] + public void Should_Set_AssemblyVersion() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + const string key = "AssemblyVersion"; + + // When + settings.SetAssemblyVersion(AssemblyVersion); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(AssemblyVersion, settings.Properties[key].FirstOrDefault()); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + var result = settings.SetAssemblyVersion(AssemblyVersion); + + // Then + Assert.Equal(settings, result); + } + } + public sealed class TheSetInformationalVersionMethod { private const string InformationalVersion = "1.0.0-test"; @@ -812,6 +878,72 @@ public void Should_Return_The_Same_Configuration() } } + public sealed class TheSetPackageVersionMethod + { + private const string PackageVersion = "1.0.0-test"; + + [Fact] + public void Should_Set_PackageVersion() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + const string key = "PackageVersion"; + + // When + settings.SetPackageVersion(PackageVersion); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(PackageVersion, settings.Properties[key].FirstOrDefault()); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + var result = settings.SetPackageVersion(PackageVersion); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetPackageReleaseNotesMethod + { + private const string PackageReleaseNotes = "https://"; + + [Fact] + public void Should_Set_PackageReleaseNotes() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + const string key = "PackageReleaseNotes"; + + // When + settings.SetPackageReleaseNotes(PackageReleaseNotes); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(PackageReleaseNotes, settings.Properties[key].FirstOrDefault()); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + var result = settings.SetPackageReleaseNotes(PackageReleaseNotes); + + // Then + Assert.Equal(settings, result); + } + } + public sealed class TheSuppressVersionRecommendedFormatWarningMethod { [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsTests.cs index e5685940f5..00fff0a273 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsTests.cs @@ -9,6 +9,222 @@ namespace Cake.Common.Tests.Unit.Tools.DotNetCore.MSBuild { public sealed class DotNetCoreMSBuildSettingsTests { + public sealed class TheVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // Then + Assert.Null(settings.Version); + } + + [Fact] + public void Should_Add_Version_Property_To_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.Version = "1.0.0-test"; + + // Then + Assert.True(settings.Properties.ContainsKey("Version")); + Assert.True(settings.Properties["Version"].Contains("1.0.0-test")); + } + } + + public sealed class TheVersionPrefixProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // Then + Assert.Null(settings.VersionPrefix); + } + + [Fact] + public void Should_Add_VersionPrefix_Property_To_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.VersionPrefix = "1.0.0"; + + // Then + Assert.True(settings.Properties.ContainsKey("VersionPrefix")); + Assert.True(settings.Properties["VersionPrefix"].Contains("1.0.0")); + } + } + + public sealed class TheVersionSuffixProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // Then + Assert.Null(settings.VersionSuffix); + } + + [Fact] + public void Should_Add_VersionSuffix_Property_To_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.VersionSuffix = "test"; + + // Then + Assert.True(settings.Properties.ContainsKey("VersionSuffix")); + Assert.True(settings.Properties["VersionSuffix"].Contains("test")); + } + } + + public sealed class TheFileVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // Then + Assert.Null(settings.FileVersion); + } + + [Fact] + public void Should_Add_FileVersion_Property_To_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.FileVersion = "1.0.0.0"; + + // Then + Assert.True(settings.Properties.ContainsKey("FileVersion")); + Assert.True(settings.Properties["FileVersion"].Contains("1.0.0.0")); + } + } + + public sealed class TheAssemblyVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // Then + Assert.Null(settings.AssemblyVersion); + } + + [Fact] + public void Should_Add_AssemblyVersion_Property_To_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.AssemblyVersion = "1.0.0.0"; + + // Then + Assert.True(settings.Properties.ContainsKey("AssemblyVersion")); + Assert.True(settings.Properties["AssemblyVersion"].Contains("1.0.0.0")); + } + } + + public sealed class TheInformationalVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // Then + Assert.Null(settings.InformationalVersion); + } + + [Fact] + public void Should_Add_InformationalVersion_Property_To_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.InformationalVersion = "1.0.0-test+7ad03d0"; + + // Then + Assert.True(settings.Properties.ContainsKey("InformationalVersion")); + Assert.True(settings.Properties["InformationalVersion"].Contains("1.0.0-test+7ad03d0")); + } + } + + public sealed class ThePackageVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // Then + Assert.Null(settings.PackageVersion); + } + + [Fact] + public void Should_Add_PackageVersion_Property_To_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.PackageVersion = "1.0.0-test"; + + // Then + Assert.True(settings.Properties.ContainsKey("PackageVersion")); + Assert.True(settings.Properties["PackageVersion"].Contains("1.0.0-test")); + } + } + + public sealed class ThePackageReleaseNotesProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // Then + Assert.Null(settings.PackageReleaseNotes); + } + + [Fact] + public void Should_Add_PackageReleaseNotes_Property_To_Configuration() + { + // Given + var settings = new DotNetCoreMSBuildSettings(); + + // When + settings.PackageReleaseNotes = "https://..."; + + // Then + Assert.True(settings.Properties.ContainsKey("PackageReleaseNotes")); + Assert.True(settings.Properties["PackageReleaseNotes"].Contains("https://...")); + } + } + public sealed class TheDistributedFileLoggerProperty { [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleterTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleterTests.cs index 62623d734f..b013f82e74 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleterTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleterTests.cs @@ -76,7 +76,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -90,7 +90,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPusherTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPusherTests.cs index 5ba3239f0a..2686e4b72f 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPusherTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPusherTests.cs @@ -58,7 +58,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -73,7 +73,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourcerTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourcerTests.cs index f799b52274..aee207d3f5 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourcerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourcerTests.cs @@ -73,7 +73,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -88,7 +88,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -185,7 +185,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -199,7 +199,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -274,7 +274,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -288,7 +288,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -363,7 +363,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -377,7 +377,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -459,7 +459,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -473,7 +473,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -562,7 +562,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -576,7 +576,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -651,7 +651,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -665,7 +665,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Pack/DotNetCorePackerTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Pack/DotNetCorePackerTests.cs index a869c9499d..878886bbda 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Pack/DotNetCorePackerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Pack/DotNetCorePackerTests.cs @@ -39,7 +39,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -53,7 +53,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -114,15 +114,17 @@ public void Should_Add_Settings() fixture.Settings.VersionSuffix = "rc1"; fixture.Settings.IncludeSource = true; fixture.Settings.IncludeSymbols = true; + fixture.Settings.SymbolPackageFormat = "snupkg"; fixture.Settings.Serviceable = true; fixture.Settings.Runtime = "win7-x86"; fixture.Settings.Verbosity = DotNetCoreVerbosity.Minimal; + fixture.Settings.Sources = new[] { "https://api.nuget.org/v3/index.json" }; // When var result = fixture.Run(); // Then - Assert.Equal("pack --output \"/Working/artifacts\" --no-build --no-dependencies --no-restore --nologo --include-symbols --include-source --configuration Release --version-suffix rc1 --serviceable --runtime win7-x86 --verbosity minimal", result.Args); + Assert.Equal("pack --output \"/Working/artifacts\" --no-build --no-dependencies --no-restore --nologo --include-symbols -p:SymbolPackageFormat=snupkg --include-source --configuration Release --version-suffix rc1 --serviceable --runtime win7-x86 --source \"https://api.nuget.org/v3/index.json\" --verbosity minimal", result.Args); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Publish/DotNetCorePublisherTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Publish/DotNetCorePublisherTests.cs index 9dfbc63c61..0752b251f1 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Publish/DotNetCorePublisherTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Publish/DotNetCorePublisherTests.cs @@ -39,7 +39,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -53,7 +53,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -233,6 +233,62 @@ public void Should_Add_PublishReadyToRun() // Then Assert.Equal("publish -p:PublishReadyToRun=true", result.Args); } + + [Fact] + public void Should_Add_PublishReadyToRunShowWarnings() + { + // Given + var fixture = new DotNetCorePublisherFixture(); + fixture.Settings.PublishReadyToRunShowWarnings = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("publish -p:PublishReadyToRunShowWarnings=true", result.Args); + } + + [Fact] + public void Should_Add_IncludeNativeLibrariesForSelfExtract() + { + // Given + var fixture = new DotNetCorePublisherFixture(); + fixture.Settings.IncludeNativeLibrariesForSelfExtract = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("publish -p:IncludeNativeLibrariesForSelfExtract=true", result.Args); + } + + [Fact] + public void Should_Add_IncludeAllContentForSelfExtract() + { + // Given + var fixture = new DotNetCorePublisherFixture(); + fixture.Settings.IncludeAllContentForSelfExtract = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("publish -p:IncludeAllContentForSelfExtract=true", result.Args); + } + + [Fact] + public void Should_Add_EnableCompressionInSingleFile() + { + // Given + var fixture = new DotNetCorePublisherFixture(); + fixture.Settings.EnableCompressionInSingleFile = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("publish -p:EnableCompressionInSingleFile=true", result.Args); + } } } } diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Restore/DotNetCoreRestorerTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Restore/DotNetCoreRestorerTests.cs index db3c8def41..fd6107a33e 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Restore/DotNetCoreRestorerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Restore/DotNetCoreRestorerTests.cs @@ -41,7 +41,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -55,7 +55,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Run/DotNetCoreRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Run/DotNetCoreRunnerTests.cs index 35a1d49da1..847c477ad7 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Run/DotNetCoreRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Run/DotNetCoreRunnerTests.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using Cake.Common.Tests.Fixtures.Tools.DotNetCore.Run; +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNetCore; using Cake.Testing; using Xunit; @@ -40,7 +42,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -55,7 +57,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -93,11 +95,14 @@ public void Should_Add_Additional_Settings() fixture.Settings.Framework = "dnxcore50"; fixture.Settings.Configuration = "Release"; fixture.Settings.Runtime = "win7-x86"; + fixture.Settings.Sources = new[] { "https://api.nuget.org/v3/index.json" }; + fixture.Settings.RollForward = DotNetCoreRollForward.Major; + // When var result = fixture.Run(); // Then - Assert.Equal("run --framework dnxcore50 --configuration Release --runtime win7-x86", result.Args); + Assert.Equal("run --framework dnxcore50 --configuration Release --runtime win7-x86 --source \"https://api.nuget.org/v3/index.json\" --roll-forward Major", result.Args); } [Fact] @@ -113,6 +118,26 @@ public void Should_Add_Host_Arguments() // Then Assert.Equal("--diagnostics run", result.Args); } + + [Theory] + [InlineData(DotNetRollForward.Minor, "run --roll-forward Minor")] + [InlineData(DotNetRollForward.LatestPatch, "run --roll-forward LatestPatch")] + [InlineData(DotNetRollForward.Major, "run --roll-forward Major")] + [InlineData(DotNetRollForward.LatestMinor, "run --roll-forward LatestMinor")] + [InlineData(DotNetRollForward.LatestMajor, "run --roll-forward LatestMajor")] + [InlineData(DotNetRollForward.Disable, "run --roll-forward Disable")] + public void Should_Add_RollForward_Arguments(DotNetRollForward rollForward, string expected) + { + // Given + var fixture = new DotNetCoreRunnerFixture(); + fixture.Settings.RollForward = rollForward; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Args); + } } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Test/DotNetCoreTesterTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Test/DotNetCoreTesterTests.cs index c9c5640999..eaed023794 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Test/DotNetCoreTesterTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Test/DotNetCoreTesterTests.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Cake.Common.Tests.Fixtures.Tools.DotNetCore.Test; +using Cake.Core; using Cake.Testing; using Xunit; @@ -40,7 +41,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -55,7 +56,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] @@ -102,6 +103,20 @@ public void Should_Quote_Project_Path(string text, string expected) Assert.Equal(expected, result.Args); } + [Fact] + public void Should_Add_RunSettings_Arguments() + { + // Given + var fixture = new DotNetCoreTesterFixture(); + fixture.Arguments = new[] { "MSTest.DeploymentEnabled=false", "MSTest.MapInconclusiveToFailed=true" }.ToProcessArguments(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("test -- MSTest.DeploymentEnabled=false MSTest.MapInconclusiveToFailed=true", result.Args); + } + [Fact] public void Should_Add_Additional_Settings() { @@ -112,21 +127,27 @@ public void Should_Add_Additional_Settings() fixture.Settings.NoLogo = true; fixture.Settings.Framework = "dnxcore50"; fixture.Settings.Configuration = "Release"; + fixture.Settings.Collectors = new[] { "XPlat Code Coverage" }; fixture.Settings.OutputDirectory = "./artifacts/"; fixture.Settings.Settings = "./demo.runsettings"; fixture.Settings.Filter = "Priority = 1"; fixture.Settings.TestAdapterPath = @"/Working/custom-test-adapter"; - fixture.Settings.Logger = @"trx;LogFileName=/Working/logfile.trx"; +#pragma warning disable CS0618 + fixture.Settings.Logger = "trx;LogFileName=/Working/logfile.trx"; +#pragma warning restore CS0618 + fixture.Settings.Loggers = new[] { "html;LogFileName=/Working/logfile.html" }; fixture.Settings.DiagnosticFile = "./artifacts/logging/diagnostics.txt"; fixture.Settings.ResultsDirectory = "./tests/"; fixture.Settings.VSTestReportPath = "./tests/TestResults.xml"; fixture.Settings.Runtime = "win-x64"; + fixture.Settings.Blame = true; + fixture.Settings.Sources = new[] { "https://api.nuget.org/v3/index.json" }; // When var result = fixture.Run(); // Then - Assert.Equal("test --settings \"/Working/demo.runsettings\" --filter \"Priority = 1\" --test-adapter-path \"/Working/custom-test-adapter\" --logger \"trx;LogFileName=/Working/logfile.trx\" --output \"/Working/artifacts\" --framework dnxcore50 --configuration Release --diag \"/Working/artifacts/logging/diagnostics.txt\" --no-build --no-restore --nologo --results-directory \"/Working/tests\" --logger trx;LogFileName=\"/Working/tests/TestResults.xml\" --runtime win-x64", result.Args); + Assert.Equal("test --settings \"/Working/demo.runsettings\" --filter \"Priority = 1\" --test-adapter-path \"/Working/custom-test-adapter\" --logger \"trx;LogFileName=/Working/logfile.trx\" --logger \"html;LogFileName=/Working/logfile.html\" --output \"/Working/artifacts\" --framework dnxcore50 --configuration Release --collect \"XPlat Code Coverage\" --diag \"/Working/artifacts/logging/diagnostics.txt\" --no-build --no-restore --nologo --results-directory \"/Working/tests\" --logger trx;LogFileName=\"/Working/tests/TestResults.xml\" --runtime win-x64 --source \"https://api.nuget.org/v3/index.json\" --blame", result.Args); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Tool/DotNetCoreToolTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Tool/DotNetCoreToolTests.cs index 2e2e1ffb49..d4126dcdc1 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Tool/DotNetCoreToolTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/Tool/DotNetCoreToolTests.cs @@ -77,7 +77,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -94,7 +94,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } } } diff --git a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/VSTest/DotNetCoreVSTesterTests.cs b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/VSTest/DotNetCoreVSTesterTests.cs index 190ba1e455..0d3295f796 100644 --- a/src/Cake.Common.Tests/Unit/Tools/DotNetCore/VSTest/DotNetCoreVSTesterTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/DotNetCore/VSTest/DotNetCoreVSTesterTests.cs @@ -44,7 +44,7 @@ public void Should_Throw_If_Process_Was_Not_Started() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process was not started."); + AssertEx.IsCakeException(result, ".NET CLI: Process was not started."); } [Fact] @@ -58,7 +58,7 @@ public void Should_Throw_If_Process_Has_A_Non_Zero_Exit_Code() var result = Record.Exception(() => fixture.Run()); // Then - AssertEx.IsCakeException(result, ".NET Core CLI: Process returned an error (exit code 1)."); + AssertEx.IsCakeException(result, ".NET CLI: Process returned an error (exit code 1)."); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/GitVersion/GitVersionRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/GitVersion/GitVersionRunnerTests.cs index 8904b59d05..bc31ab6428 100644 --- a/src/Cake.Common.Tests/Unit/Tools/GitVersion/GitVersionRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/GitVersion/GitVersionRunnerTests.cs @@ -356,11 +356,11 @@ public void Should_Tolerate_Bad_Json_Set() } [Theory] - [InlineData(GitVersionVerbosity.None, "None")] - [InlineData(GitVersionVerbosity.Debug, "Debug")] - [InlineData(GitVersionVerbosity.Info, "Info")] - [InlineData(GitVersionVerbosity.Warn, "Warn")] - [InlineData(GitVersionVerbosity.Error, "Error")] + [InlineData(GitVersionVerbosity.Quiet, nameof(GitVersionVerbosity.Quiet))] + [InlineData(GitVersionVerbosity.Diagnostic, nameof(GitVersionVerbosity.Diagnostic))] + [InlineData(GitVersionVerbosity.Verbose, nameof(GitVersionVerbosity.Verbose))] + [InlineData(GitVersionVerbosity.Normal, nameof(GitVersionVerbosity.Normal))] + [InlineData(GitVersionVerbosity.Minimal, nameof(GitVersionVerbosity.Minimal))] public void Should_Add_Verbosity_To_Arguments_If_Set(GitVersionVerbosity verbosity, string arg) { // Given @@ -375,10 +375,10 @@ public void Should_Add_Verbosity_To_Arguments_If_Set(GitVersionVerbosity verbosi } [Theory] - [InlineData(Verbosity.Quiet, "None")] - [InlineData(Verbosity.Diagnostic, "Debug")] - [InlineData(Verbosity.Verbose, "Debug")] - [InlineData(Verbosity.Minimal, "Error")] + [InlineData(Verbosity.Quiet, nameof(Verbosity.Quiet))] + [InlineData(Verbosity.Diagnostic, nameof(Verbosity.Diagnostic))] + [InlineData(Verbosity.Verbose, nameof(Verbosity.Verbose))] + [InlineData(Verbosity.Minimal, nameof(Verbosity.Minimal))] public void Should_Add_Default_Verbosity_To_Arguments_If_Not_Set(Verbosity verbosity, string arg) { // Given diff --git a/src/Cake.Common.Tests/Unit/Tools/InspectCode/InspectCodeRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/InspectCode/InspectCodeRunnerTests.cs index 28d8a534ad..5cedfad02e 100644 --- a/src/Cake.Common.Tests/Unit/Tools/InspectCode/InspectCodeRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/InspectCode/InspectCodeRunnerTests.cs @@ -408,6 +408,48 @@ public void Should_Use_Provided_Config_File() // Then Assert.Equal("\"/config=/Working/config.xml\"", result.Args); } + + [Fact] + public void Should_Not_Contain_Build_Or_NoBuild_If_Build_Is_Not_Set() + { + // Given + var fixture = new InspectCodeRunFixture(); + + // When + var result = fixture.Run(); + + // Then + Assert.DoesNotContain("--build", result.Args); + Assert.DoesNotContain("--no-build", result.Args); + } + + [Fact] + public void Should_Contain_Build_If_Build_Is_Set_To_True() + { + // Given + var fixture = new InspectCodeRunFixture(); + fixture.Settings.Build = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Contains("--build", result.Args); + } + + [Fact] + public void Should_Contain_NoBuild_If_Build_Is_Set_To_False() + { + // Given + var fixture = new InspectCodeRunFixture(); + fixture.Settings.Build = false; + + // When + var result = fixture.Run(); + + // Then + Assert.Contains("--no-build", result.Args); + } } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildRunnerTests.cs index 1c2fb64dbe..7481e95f7a 100644 --- a/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildRunnerTests.cs @@ -155,6 +155,82 @@ public void Should_Get_Correct_Path_To_MSBuild_Version_16(MSBuildToolVersion ver Assert.Equal(expected, result.Path.FullPath); } + [Theory] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x64, PlatformFamily.Windows, false, "/Program/Microsoft Visual Studio/2022/Enterprise/MSBuild/Current/Bin/amd64/MSBuild.exe")] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x86, PlatformFamily.Windows, false, "/Program/Microsoft Visual Studio/2022/Enterprise/MSBuild/Current/Bin/MSBuild.exe")] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x64, PlatformFamily.Linux, false, "/usr/bin/msbuild")] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x64, PlatformFamily.OSX, false, "/Library/Frameworks/Mono.framework/Versions/Current/Commands/msbuild")] + public void Should_Get_Correct_Path_To_MSBuild_Version_17(MSBuildToolVersion version, PlatformTarget target, PlatformFamily family, bool is64BitOperativeSystem, string expected) + { + // Given + var fixture = new MSBuildRunnerFixture(is64BitOperativeSystem, family); + fixture.Settings.ToolVersion = version; + fixture.Settings.PlatformTarget = target; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Path.FullPath); + } + + [Theory] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x64, PlatformFamily.Windows, false, "/Program86/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/amd64/MSBuild.exe")] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x86, PlatformFamily.Windows, false, "/Program86/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe")] + public void Should_Get_Correct_Path_To_MSBuild_Version_17_When_Only_Build_Tools_Are_Installed(MSBuildToolVersion version, PlatformTarget target, PlatformFamily family, bool is64BitOperativeSystem, string expected) + { + // Given + var fixture = new MSBuildRunnerFixture(is64BitOperativeSystem, family); + fixture.Settings.ToolVersion = version; + fixture.Settings.PlatformTarget = target; + + fixture.GivenDefaultToolDoNotExist(); + fixture.GivenMSBuildIsNotInstalled(); + fixture.FileSystem.CreateFile("/Program86/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/amd64/MSBuild.exe"); + fixture.FileSystem.CreateFile("/Program86/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe"); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(expected, result.Path.FullPath); + } + + [Theory] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x64, PlatformFamily.Windows, true)] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x86, PlatformFamily.Windows, true)] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x64, PlatformFamily.Windows, false)] + [InlineData(MSBuildToolVersion.VS2022, PlatformTarget.x86, PlatformFamily.Windows, false)] + public void Should_Get_Correct_Path_To_MSBuild_Version_17Preview_When_Preview_Is_Set(MSBuildToolVersion version, PlatformTarget target, PlatformFamily family, bool allowPreview) + { + // Given + var is64BitOperativeSystem = target == PlatformTarget.x64; + var fixture = new MSBuildRunnerFixture(is64BitOperativeSystem, family); + fixture.Settings.ToolVersion = version; + fixture.Settings.PlatformTarget = target; + fixture.Settings.AllowPreviewVersion = allowPreview; + + fixture.GivenDefaultToolDoNotExist(); + fixture.GivenMSBuildIsNotInstalled(); + fixture.FileSystem.CreateFile("/Program/Microsoft Visual Studio/2022/Enterprise/MSBuild/Current/Bin/amd64/MSBuild.exe"); + fixture.FileSystem.CreateFile("/Program/Microsoft Visual Studio/2022/Enterprise/MSBuild/Current/Bin/MSBuild.exe"); + fixture.FileSystem.CreateFile("/Program/Microsoft Visual Studio/2022/Preview/MSBuild/Current/Bin/amd64/MSBuild.exe"); + fixture.FileSystem.CreateFile("/Program/Microsoft Visual Studio/2022/Preview/MSBuild/Current/Bin/MSBuild.exe"); + + // When + var result = fixture.Run(); + + // Then + if (allowPreview) + { + Assert.Contains("2022/Preview", result.Path.FullPath); + } + else + { + Assert.DoesNotContain("2022/Preview", result.Path.FullPath); + } + } + [Theory] [InlineData(MSBuildToolVersion.NET40, PlatformTarget.MSIL, true, "/Windows/Microsoft.NET/Framework64/v4.0.30319/MSBuild.exe")] [InlineData(MSBuildToolVersion.NET40, PlatformTarget.MSIL, false, "/Windows/Microsoft.NET/Framework/v4.0.30319/MSBuild.exe")] @@ -903,6 +979,200 @@ public void Should_Throw_If_Verbosity_Is_Unknown() AssertEx.IsCakeException(result, "Encountered unknown MSBuild build log verbosity."); } + [Fact] + public void Should_Use_IncludeSymbols_If_Specified() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.IncludeSymbols = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:IncludeSymbols=true /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Use_SymbolPackageFormat_If_Specified() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.IncludeSymbols = true; + fixture.Settings.SymbolPackageFormat = "snupkg"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_Version_If_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.Version = "1.0.0-test"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:Version=1.0.0-test /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_VersionPrefix_If_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.VersionPrefix = "1.0.0"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:VersionPrefix=1.0.0 /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_VersionSuffix_If_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.VersionSuffix = "test"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:VersionSuffix=test /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_FileVersion_If_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.FileVersion = "1.0.0.0"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:FileVersion=1.0.0.0 /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_AssemblyVersion_If_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.AssemblyVersion = "1.0.0.0"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:AssemblyVersion=1.0.0.0 /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_InformationalVersion_If_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.InformationalVersion = "1.0.0-test+7ad03d0"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:InformationalVersion=1.0.0-test+7ad03d0 /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_PackageVersion_If_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.PackageVersion = "1.0.0-test"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:PackageVersion=1.0.0-test /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_PackageReleaseNotes_If_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.PackageReleaseNotes = "https://"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:PackageReleaseNotes=https:// /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_ContinuousIntegrationBuild_If_Set_To_True() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.ContinuousIntegrationBuild = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:ContinuousIntegrationBuild=true /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Add_ContinuousIntegrationBuild_If_Set_To_False() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.ContinuousIntegrationBuild = false; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /p:ContinuousIntegrationBuild=false /target:Build " + + "\"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Not_Add_ContinuousIntegrationBuild_If_Not_Set() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + + // When + var result = fixture.Run(); + + // Then + Assert.DoesNotContain("/p:ContinuousIntegrationBuild=", result.Args); + } + [Fact] public void Should_Append_Logger_To_Process_Arguments() { @@ -993,7 +1263,7 @@ public void Should_Use_Binary_Logging_If_Specified() var result = fixture.Run(); // Then - Assert.Equal("/v:normal /target:Build /bl:mylog.binlog;ProjectImports=ZipFile \"C:/Working/src/Solution.sln\"", result.Args); + Assert.Equal("/v:normal /target:Build /bl:\"mylog.binlog\";ProjectImports=ZipFile \"C:/Working/src/Solution.sln\"", result.Args); } [Fact] @@ -1007,7 +1277,25 @@ public void Should_Use_Binary_Logging_If_Enabled() var result = fixture.Run(); // Then - Assert.Equal("/v:normal /target:Build /bl:mylog.binlog;ProjectImports=ZipFile \"C:/Working/src/Solution.sln\"", result.Args); + Assert.Equal("/v:normal /target:Build /bl:\"mylog.binlog\";ProjectImports=ZipFile \"C:/Working/src/Solution.sln\"", result.Args); + } + + [Fact] + public void Should_Quote_Binary_Logging_FilePath() + { + // Given + var fixture = new MSBuildRunnerFixture(false, PlatformFamily.Windows); + fixture.Settings.BinaryLogger = new MSBuildBinaryLogSettings() + { + Enabled = true, + FileName = "C:/Working Directory/src folder/mylog.binlog" + }; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("/v:normal /target:Build /bl:\"C:/Working Directory/src folder/mylog.binlog\" \"C:/Working/src/Solution.sln\"", result.Args); } [Theory] diff --git a/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildSettingsExtensionsTests.cs b/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildSettingsExtensionsTests.cs index 5928341b9b..4fe7721a1e 100644 --- a/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildSettingsExtensionsTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildSettingsExtensionsTests.cs @@ -67,6 +67,79 @@ public void Should_Return_The_Same_Configuration() // Then Assert.Equal(settings, result); } + + [Fact] + public void Should_Set_Tool_Version_FromStringOverride() + { + // Given + var settings = new MSBuildSettings(); + + // When + settings.UseToolVersion("net20"); + + // Then + Assert.Equal(MSBuildToolVersion.NET20, settings.ToolVersion); + } + + [Fact] + public void Should_Return_The_Same_Configuration_FromStringOverride() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.UseToolVersion("net35"); + + // Then + Assert.Equal(settings, result); + } + + [Fact] + public void Should_ThrowArgumetnException_When_String_Is_Null() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Throws(() => settings.UseToolVersion(null)); + } + + [Fact] + public void Should_Return_Default_When_Input_Is_Bad() + { + // Given + var settings = new MSBuildSettings(); + + // When + settings.UseToolVersion("fjaldskjflaksdjflkas"); + + // Then + Assert.Equal(MSBuildToolVersion.Default, settings.ToolVersion); + } + + [Fact] + public void Should_Return_VSCustom_When_VsVersion_CantBeMatch() + { + var settings = new MSBuildSettings(); + + // When + settings.UseToolVersion("2022"); + + // Then + Assert.Equal(MSBuildToolVersion.VSCustom, settings.ToolVersion); + } + + [Fact] + public void Should_Return_VSCustom_When_NETFramework_CantBeMatch() + { + var settings = new MSBuildSettings(); + + // When + settings.UseToolVersion("5"); + + // Then + Assert.Equal(MSBuildToolVersion.NETCustom, settings.ToolVersion); + } } public sealed class TheSetPlatformTargetMethod @@ -98,6 +171,36 @@ public void Should_Return_The_Same_Configuration() } } + public sealed class TheSetPlatformTargetStringMethod + { + [Fact] + public void Should_Set_Platform_Target_Via_Property() + { + // Given + var settings = new MSBuildSettings(); + + // When + settings.SetPlatformTarget("Custom"); + + // Then + Assert.True(settings.Properties.ContainsKey("Platform")); + Assert.Equal("Custom", string.Join(string.Empty, settings.Properties["Platform"])); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetPlatformTarget("Custom"); + + // Then + Assert.Equal(settings, result); + } + } + public sealed class TheWithPropertyMethod { [Fact] @@ -322,6 +425,310 @@ public void Should_Return_The_Same_Configuration() } } + public sealed class TheSetVersionMethod + { + private const string Version = "1.0.0-test"; + + [Fact] + public void Should_Set_Version() + { + // Given + var settings = new MSBuildSettings(); + const string key = "Version"; + + // When + settings.SetVersion(Version); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(Version, settings.Properties[key].FirstOrDefault()); + Assert.Equal(Version, settings.Version); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetVersion(Version); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetVersionPrefixMethod + { + private const string VersionPrefix = "1.0.0"; + + [Fact] + public void Should_Set_VersionPrefix() + { + // Given + var settings = new MSBuildSettings(); + const string key = "VersionPrefix"; + + // When + settings.SetVersionPrefix(VersionPrefix); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(VersionPrefix, settings.Properties[key].FirstOrDefault()); + Assert.Equal(VersionPrefix, settings.VersionPrefix); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetVersionPrefix(VersionPrefix); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetVersionSuffixMethod + { + private const string VersionSuffix = "test"; + + [Fact] + public void Should_Set_VersionSuffix() + { + // Given + var settings = new MSBuildSettings(); + const string key = "VersionSuffix"; + + // When + settings.SetVersionSuffix(VersionSuffix); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(VersionSuffix, settings.Properties[key].FirstOrDefault()); + Assert.Equal(VersionSuffix, settings.VersionSuffix); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetVersionSuffix(VersionSuffix); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetFileVersionMethod + { + private const string FileVersion = "1.0.0.0"; + + [Fact] + public void Should_Set_FileVersion() + { + // Given + var settings = new MSBuildSettings(); + const string key = "FileVersion"; + + // When + settings.SetFileVersion(FileVersion); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(FileVersion, settings.Properties[key].FirstOrDefault()); + Assert.Equal(FileVersion, settings.FileVersion); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetFileVersion(FileVersion); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetAssemblyVersionMethod + { + private const string AssemblyVersion = "1.0.0.0"; + + [Fact] + public void Should_Set_AssemblyVersion() + { + // Given + var settings = new MSBuildSettings(); + const string key = "AssemblyVersion"; + + // When + settings.SetAssemblyVersion(AssemblyVersion); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(AssemblyVersion, settings.Properties[key].FirstOrDefault()); + Assert.Equal(AssemblyVersion, settings.AssemblyVersion); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetAssemblyVersion(AssemblyVersion); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetInformationalVersionMethod + { + private const string InformationalVersion = "1.0.0-test+7ad03d0"; + + [Fact] + public void Should_Set_InformationalVersion() + { + // Given + var settings = new MSBuildSettings(); + const string key = "InformationalVersion"; + + // When + settings.SetInformationalVersion(InformationalVersion); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(InformationalVersion, settings.Properties[key].FirstOrDefault()); + Assert.Equal(InformationalVersion, settings.InformationalVersion); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetInformationalVersion(InformationalVersion); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetPackageVersionMethod + { + private const string PackageVersion = "1.0.0-test"; + + [Fact] + public void Should_Set_PackageVersion() + { + // Given + var settings = new MSBuildSettings(); + const string key = "PackageVersion"; + + // When + settings.SetPackageVersion(PackageVersion); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(PackageVersion, settings.Properties[key].FirstOrDefault()); + Assert.Equal(PackageVersion, settings.PackageVersion); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetPackageVersion(PackageVersion); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetPackageReleaseNotesMethod + { + private const string PackageReleaseNotes = "1.0.0-test"; + + [Fact] + public void Should_Set_PackageReleaseNotes() + { + // Given + var settings = new MSBuildSettings(); + const string key = "PackageReleaseNotes"; + + // When + settings.SetPackageReleaseNotes(PackageReleaseNotes); + + // Then + Assert.True(settings.Properties.ContainsKey(key)); + Assert.Equal(PackageReleaseNotes, settings.Properties[key].FirstOrDefault()); + Assert.Equal(PackageReleaseNotes, settings.PackageReleaseNotes); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetPackageReleaseNotes(PackageReleaseNotes); + + // Then + Assert.Equal(settings, result); + } + } + + public sealed class TheSetContinuousIntegrationBuildMethod + { + [Theory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void Should_Set_ContinuousIntegrationBuild(bool? continuousIntegrationBuild) + { + // Given + var settings = new MSBuildSettings(); + + // When + settings.SetContinuousIntegrationBuild(continuousIntegrationBuild); + + // Then + Assert.Equal(continuousIntegrationBuild, settings.ContinuousIntegrationBuild); + } + + [Fact] + public void Should_Return_The_Same_Configuration() + { + // Given + var settings = new MSBuildSettings(); + + // When + var result = settings.SetContinuousIntegrationBuild(); + + // Then + Assert.Equal(settings, result); + } + } + public sealed class TheNoImplicitTargetMethod { [Theory] diff --git a/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildSettingsTests.cs b/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildSettingsTests.cs index 5a661ca488..5acf90d505 100644 --- a/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildSettingsTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/MSBuild/MSBuildSettingsTests.cs @@ -153,6 +153,110 @@ public void Should_Be_Null_By_Default() } } + public sealed class TheContinuousIntegrationBuildProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Null(settings.ContinuousIntegrationBuild); + } + } + + public sealed class TheVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Null(settings.Version); + } + } + + public sealed class TheVersionPrefixProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Null(settings.VersionPrefix); + } + } + + public sealed class TheVersionSuffixProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Null(settings.VersionSuffix); + } + } + + public sealed class TheFileVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Null(settings.FileVersion); + } + } + + public sealed class TheAssemblyVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Null(settings.AssemblyVersion); + } + } + + public sealed class ThePackageVersionProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Null(settings.PackageVersion); + } + } + + public sealed class ThePackageReleaseNotesProperty + { + [Fact] + public void Should_Be_Null_By_Default() + { + // Given + var settings = new MSBuildSettings(); + + // Then + Assert.Null(settings.PackageReleaseNotes); + } + } + public sealed class TheLoggersProperty { [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/MSTest/MSTestRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/MSTest/MSTestRunnerTests.cs index ff51f62295..d7e7d783d5 100644 --- a/src/Cake.Common.Tests/Unit/Tools/MSTest/MSTestRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/MSTest/MSTestRunnerTests.cs @@ -291,5 +291,57 @@ public void Should_Use_Available_Environment_Tool_Path(string existingToolPath, // Then Assert.Equal(existingToolPath, result.Path.FullPath); } + + [Theory] + [InlineData(SpecialPath.ProgramFilesX86, "2017", "Enterprise")] + [InlineData(SpecialPath.ProgramFilesX86, "2017", "Professional")] + [InlineData(SpecialPath.ProgramFilesX86, "2017", "Community")] + [InlineData(SpecialPath.ProgramFilesX86, "2019", "Enterprise")] + [InlineData(SpecialPath.ProgramFilesX86, "2019", "Professional")] + [InlineData(SpecialPath.ProgramFilesX86, "2019", "Community")] + [InlineData(SpecialPath.ProgramFiles, "2022", "Enterprise")] + [InlineData(SpecialPath.ProgramFiles, "2022", "Professional")] + [InlineData(SpecialPath.ProgramFiles, "2022", "Community")] + public void Should_Use_Tool_Path_For_YearAndEdition_Versions(SpecialPath programFiles, string year, string edition) + { + // Given + var fixture = new MSTestRunnerFixture(); + fixture.GivenDefaultToolDoNotExist(); + var toolPath = fixture.Environment.GetSpecialPath(programFiles) + .CombineWithFilePath($"Microsoft Visual Studio/{year}/{edition}/Common7/IDE/mstest.exe"); + fixture.FileSystem.CreateFile(toolPath); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(toolPath, result.Path.FullPath); + } + + [Theory] + [InlineData("2022", true)] + [InlineData("2022", false)] + public void Should_Use_Tool_Path_For_Preview_Version_Only_If_PreviewIsSet(string year, bool allowPreview) + { + // Given + var fixture = new MSTestRunnerFixture(); + var previewToolPath = fixture.Environment.GetSpecialPath(SpecialPath.ProgramFiles) + .CombineWithFilePath($"Microsoft Visual Studio/{year}/Preview/Common7/IDE/mstest.exe"); + fixture.FileSystem.CreateFile(previewToolPath); + fixture.Settings.AllowPreviewVersion = allowPreview; + + // When + var result = fixture.Run(); + + // Then + if (allowPreview) + { + Assert.Equal(previewToolPath, result.Path.FullPath); + } + else + { + Assert.NotEqual(previewToolPath, result.Path.FullPath); + } + } } } \ No newline at end of file diff --git a/src/Cake.Common.Tests/Unit/Tools/NUnit/NUnit3RunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/NUnit/NUnit3RunnerTests.cs index 98a36b0290..3b8a89f598 100644 --- a/src/Cake.Common.Tests/Unit/Tools/NUnit/NUnit3RunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/NUnit/NUnit3RunnerTests.cs @@ -219,10 +219,6 @@ public void Should_Set_Commandline_Switches() fixture.Settings.SkipNonTestAssemblies = true; fixture.Settings.Work = "out"; fixture.Settings.OutputFile = "stdout.txt"; - #pragma warning disable 0618 - fixture.Settings.ErrorOutputFile = "stderr.txt"; - fixture.Settings.Full = true; - #pragma warning restore 0618 fixture.Settings.Results = new[] { new NUnit3Result { FileName = "NewTestResult.xml", Format = "nunit2", Transform = "nunit2.xslt" }, @@ -232,9 +228,6 @@ public void Should_Set_Commandline_Switches() fixture.Settings.TeamCity = true; fixture.Settings.NoHeader = true; fixture.Settings.NoColor = true; - #pragma warning disable 0618 - fixture.Settings.Verbose = true; - #pragma warning restore 0618 fixture.Settings.Configuration = "Debug"; fixture.Settings.Process = NUnit3ProcessOption.InProcess; fixture.Settings.AppDomainUsage = NUnit3AppDomainUsage.Single; @@ -251,6 +244,12 @@ public void Should_Set_Commandline_Switches() ["two"] = "2", ["three"] = "3" }; + fixture.Settings.TestParams = new Dictionary + { + ["uno"] = "1", + ["dos"] = "2", + ["tres"] = "3" + }; // When var result = fixture.Run(); @@ -259,10 +258,9 @@ public void Should_Set_Commandline_Switches() Assert.Equal("\"/Working/Test1.dll\" --test=Test1,Test2 \"--testlist=/Working/Testlist.txt\" " + "--where \"cat==Data\" --timeout=5 --seed=6 --workers=7 " + "--stoponerror --skipnontestassemblies \"--work=/Working/out\" \"--out=/Working/stdout.txt\" " + - "\"--err=/Working/stderr.txt\" --full " + "\"--result=/Working/NewTestResult.xml;format=nunit2;transform=/Working/nunit2.xslt\" " + "\"--result=/Working/NewTestResult2.xml;format=nunit3\" " + - "--labels=All --teamcity --noheader --nocolor --verbose " + + "--labels=All --teamcity --noheader --nocolor " + "\"--config=Debug\" \"--framework=net3.5\" --x86 " + "--dispose-runners --shadowcopy --agents=3 " + "--process=InProcess --domain=Single " + @@ -270,7 +268,10 @@ public void Should_Set_Commandline_Switches() "\"--configfile=/Working/app.config\" " + "\"--params=one=1\" " + "\"--params=two=2\" " + - "\"--params=three=3\"", result.Args); + "\"--params=three=3\" " + + "\"--testparam:uno=1\" " + + "\"--testparam:dos=2\" " + + "\"--testparam:tres=3\"", result.Args); } [Fact] diff --git a/src/Cake.Common.Tests/Unit/Tools/NuGet/Pack/NuGetPackerTests.cs b/src/Cake.Common.Tests/Unit/Tools/NuGet/Pack/NuGetPackerTests.cs index be5c8358d4..afedbdd3fd 100644 --- a/src/Cake.Common.Tests/Unit/Tools/NuGet/Pack/NuGetPackerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/NuGet/Pack/NuGetPackerTests.cs @@ -280,6 +280,21 @@ public void Should_Add_Symbols_Flag_To_Arguments_If_Set() Assert.Equal("pack \"/Working/existing.temp.nuspec\" -Symbols", result.Args); } + [Fact] + public void Should_Add_SymbolPackageFormat_To_Arguments_If_Set() + { + // Given + var fixture = new NuGetPackerWithNuSpecFixture(); + fixture.Settings.Symbols = true; + fixture.Settings.SymbolPackageFormat = "snupkg"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("pack \"/Working/existing.temp.nuspec\" -Symbols -SymbolPackageFormat snupkg", result.Args); + } + [Theory] [InlineData(NuGetVerbosity.Detailed, "pack \"/Working/existing.temp.nuspec\" -Verbosity detailed")] [InlineData(NuGetVerbosity.Normal, "pack \"/Working/existing.temp.nuspec\" -Verbosity normal")] @@ -313,6 +328,7 @@ public void Should_Add_Metadata_Element_To_Nuspec_If_Missing() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -347,6 +363,7 @@ public void Should_Add_Repository_Element_To_Nuspec_If_Missing() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -381,6 +398,7 @@ public void Should_Add_License_Element_To_Nuspec_If_Missing() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -415,6 +433,7 @@ public void Should_Add_PackageTypes_Element_To_Nuspec_If_Missing() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -453,6 +472,7 @@ public void Should_Add_FrameworkAssemblies_Element_To_Nuspec_If_Missing() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -491,6 +511,7 @@ public void Should_Add_References_Element_To_Nuspec_If_Missing() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -529,6 +550,7 @@ public void Should_Add_References_With_TargetFramework_Element_To_Nuspec_If_Miss fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -567,6 +589,7 @@ public void Should_Add_ContentFiles_Element_To_Nuspec_If_Missing() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -605,6 +628,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -639,6 +663,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec_Without_Namespaces() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -672,6 +697,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec_With_Files() fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -718,6 +744,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec_With_Files_Without_Namespac fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -797,6 +824,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec_With_Files_And_DependencyTa fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -842,6 +870,7 @@ public void Should_Replace_Template_Tokens_In_Nuspec_With_Files_And_DependencyTa fixture.Settings.Summary = "The summary"; fixture.Settings.LicenseUrl = new Uri("https://license.com"); fixture.Settings.ProjectUrl = new Uri("https://project.com"); + fixture.Settings.Icon = @"images\icon.png"; fixture.Settings.IconUrl = new Uri("https://icon.com"); fixture.Settings.DevelopmentDependency = true; fixture.Settings.RequireLicenseAcceptance = true; @@ -1089,6 +1118,21 @@ public void Should_Add_Symbols_Flag_To_Arguments_If_Set() Assert.Equal("pack \"/Working/existing.csproj\" -Symbols", result.Args); } + [Fact] + public void Should_Add_SymbolPackageFormat_To_Arguments_If_Set() + { + // Given + var fixture = new NuGetPackerWithProjectFileFixture(); + fixture.Settings.Symbols = true; + fixture.Settings.SymbolPackageFormat = "snupkg"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("pack \"/Working/existing.csproj\" -Symbols -SymbolPackageFormat snupkg", result.Args); + } + [Theory] [InlineData(NuGetVerbosity.Detailed, "pack \"/Working/existing.csproj\" -Verbosity detailed")] [InlineData(NuGetVerbosity.Normal, "pack \"/Working/existing.csproj\" -Verbosity normal")] diff --git a/src/Cake.Common.Tests/Unit/Tools/OctopusDeploy/OctoCreateReleaseTests.cs b/src/Cake.Common.Tests/Unit/Tools/OctopusDeploy/OctoCreateReleaseTests.cs index 932cf9d5c0..f912050c12 100644 --- a/src/Cake.Common.Tests/Unit/Tools/OctopusDeploy/OctoCreateReleaseTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/OctopusDeploy/OctoCreateReleaseTests.cs @@ -442,12 +442,12 @@ public void Should_Add_Progress_To_Arguments_If_Specified() // Then Assert.Equal("create-release --project \"testProject\" " + "--server http://octopus --apiKey API-12345 " + - "--deployto \"SomeEnvironment\" " + - "--progress", result.Args); + "--progress " + + "--deployto \"SomeEnvironment\"", result.Args); } [Fact] - public void Should_Add_FocePackageDownload_To_Arguments_If_Specified() + public void Should_Add_ForcePackageDownload_To_Arguments_If_Specified() { // Given var fixture = new OctopusDeployReleaseCreatorFixture(); @@ -460,8 +460,8 @@ public void Should_Add_FocePackageDownload_To_Arguments_If_Specified() // Then Assert.Equal("create-release --project \"testProject\" " + "--server http://octopus --apiKey API-12345 " + - "--deployto \"SomeEnvironment\" " + - "--forcepackagedownload", result.Args); + "--forcepackagedownload " + + "--deployto \"SomeEnvironment\"", result.Args); } [Fact] @@ -478,8 +478,8 @@ public void Should_Add_WaitForDeployment_To_Arguments_If_Specified() // Then Assert.Equal("create-release --project \"testProject\" " + "--server http://octopus --apiKey API-12345 " + - "--deployto \"SomeEnvironment\" " + - "--waitfordeployment", result.Args); + "--waitfordeployment " + + "--deployto \"SomeEnvironment\"", result.Args); } [Fact] @@ -769,10 +769,10 @@ public void Should_Add_All_Deploymnet_Arguments() // Then Assert.Equal("create-release --project \"testProject\" " + "--server http://octopus --apiKey API-12345 " + - "--deployto \"SomeEnvironment\" " + "--progress " + "--forcepackagedownload " + "--waitfordeployment " + + "--deployto \"SomeEnvironment\" " + "--deploymenttimeout=\"00:01:00\" " + "--cancelontimeout " + "--deploymentchecksleepcycle=\"01:17:00\" " + @@ -871,6 +871,58 @@ public void Should_Add_Space_To_Arguments_If_Not_Null() "--server http://octopus --apiKey API-12345 " + "--space \"spacename\"", result.Args); } + + [Fact] + public void Should_Add_Multiple_Deployment_Environments_To_Arguments_If_Not_Null() + { + // Given + var fixture = new OctopusDeployReleaseCreatorFixture(); + fixture.Settings.DeployToMultiple = new string[] { @"someenvironment", @"someotherenvironment" }; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("create-release --project \"testProject\" " + + "--server http://octopus --apiKey API-12345 " + + "--deployto \"someenvironment\" " + + "--deployto \"someotherenvironment\"", result.Args); + } + + [Fact] + public void Should_Add_Deployment_Environments_From_Both_Properties_To_Arguments_If_Not_Null() + { + // Given + var fixture = new OctopusDeployReleaseCreatorFixture(); + fixture.Settings.DeployTo = @"someenvironment"; + fixture.Settings.DeployToMultiple = new string[] { @"someotherenvironment", @"someadditionalenvironment" }; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("create-release --project \"testProject\" " + + "--server http://octopus --apiKey API-12345 " + + "--deployto \"someenvironment\" " + + "--deployto \"someotherenvironment\" " + + "--deployto \"someadditionalenvironment\"", result.Args); + } + + [Fact] + public void Should_Add_Exclude_Machines_To_Arguments_If_Not_Null() + { + // Given + var fixture = new OctopusDeployReleaseCreatorFixture(); + fixture.Settings.ExcludeMachines = @"somemachine"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("create-release --project \"testProject\" " + + "--server http://octopus --apiKey API-12345 " + + "--excludemachines \"somemachine\"", result.Args); + } } } } diff --git a/src/Cake.Common.Tests/Unit/Tools/OctopusDeploy/OctoDeployReleaseTests.cs b/src/Cake.Common.Tests/Unit/Tools/OctopusDeploy/OctoDeployReleaseTests.cs index 8176aab3e2..5c9def646b 100644 --- a/src/Cake.Common.Tests/Unit/Tools/OctopusDeploy/OctoDeployReleaseTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/OctopusDeploy/OctoDeployReleaseTests.cs @@ -10,7 +10,7 @@ namespace Cake.Common.Tests.Unit.Tools.OctopusDeploy { public sealed class OctoDeployReleaseTests { - private const string MinimalParameters = "deploy-release --project=\"MyProject\" --deployto=\"Testing\" --releasenumber=\"0.15.1\" --server http://octopus --apiKey API-12345"; + private const string MinimalParameters = "deploy-release --project=\"MyProject\" --releasenumber=\"0.15.1\" --deployto=\"Testing\" --server http://octopus --apiKey API-12345"; public sealed class TheBaseArgumentBuilder { @@ -70,6 +70,48 @@ public void Should_Throw_If_DeployTo_Is_Null() AssertEx.IsArgumentNullException(result, "deployTo"); } + [Fact] + public void Should_Throw_If_DeployTo_Is_Empty() + { + // Given + var fixture = new OctopusDeployReleaseDeployerFixture(); + fixture.DeployTo = new string[] { }; + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsArgumentNullException(result, "deployTo"); + } + + [Fact] + public void Should_Throw_If_DeployTo_Contains_Null_Items() + { + // Given + var fixture = new OctopusDeployReleaseDeployerFixture(); + fixture.DeployTo = new string[] { "Testing", null }; + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsArgumentNullException(result, "deployTo"); + } + + [Fact] + public void Should_Throw_If_DeployTo_Contains_Empty_Items() + { + // Given + var fixture = new OctopusDeployReleaseDeployerFixture(); + fixture.DeployTo = new string[] { "Testing", string.Empty }; + + // When + var result = Record.Exception(() => fixture.Run()); + + // Then + AssertEx.IsArgumentNullException(result, "deployTo"); + } + [Fact] public void Should_Throw_If_ReleaseNumber_Is_Null() { @@ -457,6 +499,20 @@ public void Should_Add_Channel_To_Arguments_If_Not_Null() Assert.Equal(MinimalParameters + " --channel \"somechannel\"", result.Args); } + [Fact] + public void Should_Add_Exclude_Machines_To_Arguments_If_Not_Null() + { + // Given + var fixture = new OctopusDeployReleaseDeployerFixture(); + fixture.Settings.ExcludeMachines = @"somemachine"; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal(MinimalParameters + " --excludemachines \"somemachine\"", result.Args); + } + [Fact] public void Should_Add_Space_To_Arguments_If_Not_Null() { diff --git a/src/Cake.Common.Tests/Unit/Tools/OpenCover/OpenCoverTests.cs b/src/Cake.Common.Tests/Unit/Tools/OpenCover/OpenCoverTests.cs index 05f858c604..f73cc2218c 100644 --- a/src/Cake.Common.Tests/Unit/Tools/OpenCover/OpenCoverTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/OpenCover/OpenCoverTests.cs @@ -229,7 +229,7 @@ public void Should_Use_Specified_Register() { // Given var fixture = new OpenCoverFixture(); - fixture.Settings.Register = "Path32"; + fixture.Settings.Register = new OpenCoverRegisterOptionDll("Path32"); // When var result = fixture.Run(); @@ -240,6 +240,72 @@ public void Should_Use_Specified_Register() "-register:Path32 -output:\"/Working/result.xml\"", result.Args); } + [Fact] + public void Should_Use_No_Register() + { + // Given + var fixture = new OpenCoverFixture(); + fixture.Settings.Register = null; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("-target:\"/Working/tools/Test.exe\" " + + "-targetargs:\"-argument\" " + + "-output:\"/Working/result.xml\"", result.Args); + } + + [Fact] + public void Should_Use_Admin_Register() + { + // Given + var fixture = new OpenCoverFixture(); + fixture.Settings.Register = new OpenCoverRegisterOptionAdmin(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("-target:\"/Working/tools/Test.exe\" " + + "-targetargs:\"-argument\" " + + "-register -output:\"/Working/result.xml\"", result.Args); + } + + [Fact] + public void Should_Use_User_Register() + { + // Given + var fixture = new OpenCoverFixture(); + fixture.Settings.Register = new OpenCoverRegisterOptionUser(); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("-target:\"/Working/tools/Test.exe\" " + + "-targetargs:\"-argument\" " + + "-register:user -output:\"/Working/result.xml\"", result.Args); + } + + [Fact] + public void Should_Not_break_when_old_string_registrations_are_used() + { + // Given + var fixture = new OpenCoverFixture(); +#pragma warning disable CS0618 // Type or member is obsolete + fixture.Settings.Register = "Path64"; +#pragma warning restore CS0618 // Type or member is obsolete + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("-target:\"/Working/tools/Test.exe\" " + + "-targetargs:\"-argument\" " + + "-register:Path64 -output:\"/Working/result.xml\"", result.Args); + } + [Fact] public void Should_Add_ReturnTargetCode_If_ReturnTargetCodeOffset_Is_Set() { @@ -344,6 +410,27 @@ public void Should_Append_LogLevel() "-log:All", result.Args); } + [Fact] + public void Should_Append_HideSkipped() + { + // Given + var fixture = new OpenCoverFixture(); + fixture.Settings.HideSkippedOption = OpenCoverHideSkippedOption.File + | OpenCoverHideSkippedOption.MissingPdb + | OpenCoverHideSkippedOption.Filter + | OpenCoverHideSkippedOption.All + | OpenCoverHideSkippedOption.Attribute; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("-target:\"/Working/tools/Test.exe\" " + + "-targetargs:\"-argument\" " + + "-register:user -output:\"/Working/result.xml\" " + + "-hideskipped:All", result.Args); + } + [Fact] public void Should_Append_MergeByHash() { diff --git a/src/Cake.Common.Tests/Unit/Tools/ReportGenerator/ReportGeneratorRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/ReportGenerator/ReportGeneratorRunnerTests.cs index 84883c8114..6df45a28b2 100644 --- a/src/Cake.Common.Tests/Unit/Tools/ReportGenerator/ReportGeneratorRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/ReportGenerator/ReportGeneratorRunnerTests.cs @@ -175,6 +175,10 @@ public void Should_Set_Reports_And_Target_Directory() [InlineData("MHtml", 15)] [InlineData("SonarQube", 16)] [InlineData("HtmlInline_AzurePipelines_Dark", 17)] + [InlineData("Clover", 18)] + [InlineData("JsonSummary", 19)] + [InlineData("lcov", 20)] + [InlineData("TeamCitySummary", 21)] public void Should_Set_Report_Types(string expected, int enumValue) { // Given diff --git a/src/Cake.Common.Tests/Unit/Tools/VSTest/VSTestRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/VSTest/VSTestRunnerTests.cs index 5de2b656a3..d9b06f3882 100644 --- a/src/Cake.Common.Tests/Unit/Tools/VSTest/VSTestRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/VSTest/VSTestRunnerTests.cs @@ -91,16 +91,21 @@ public void Should_Use_VSTest_From_Tool_Path_If_Provided_On_Windows(string toolP } [Theory] - [InlineData("/ProgramFilesX86/Microsoft Visual Studio 15.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio 14.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio 12.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio 11.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2017/Enterprise/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2017/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2017/Community/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2017/BuildTools/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2019/Enterprise/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2019/Community/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2019/BuildTools/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFiles/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFiles/Microsoft Visual Studio/2022/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFiles/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] + [InlineData("/ProgramFilesX86/Microsoft Visual Studio/2022/BuildTools/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe")] public void Should_Use_Available_Tool_Path(string existingToolPath) { // Given @@ -115,6 +120,30 @@ public void Should_Use_Available_Tool_Path(string existingToolPath) Assert.Equal(existingToolPath, result.Path.FullPath); } + [Theory] + [InlineData("/ProgramFiles/Microsoft Visual Studio/2022/Preview/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe", true)] + [InlineData("/ProgramFiles/Microsoft Visual Studio/2022/Preview/Common7/IDE/CommonExtensions/Microsoft/TestWindow/vstest.console.exe", false)] + public void Should_Use_Available_Preview_Tool_Path_Only_If_Preview_Is_Set(string previewToolPath, bool allowPreview) + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.FileSystem.CreateFile(previewToolPath); + fixture.Settings.AllowPreviewVersion = allowPreview; + + // When + var result = fixture.Run(); + + // Then + if (allowPreview) + { + Assert.Equal(previewToolPath, result.Path.FullPath); + } + else + { + Assert.NotEqual(previewToolPath, result.Path.FullPath); + } + } + [Fact] public void Should_Set_Working_Directory() { @@ -255,6 +284,20 @@ public void Should_Use_Diag_If_Provided() Assert.Equal("\"/Working/Test1.dll\" /Diag:\"/Working/Path to/diag log.txt\"", result.Args); } + [Fact] + public void Should_Use_ResultsDirectory_If_Provided() + { + // Given + var fixture = new VSTestRunnerFixture(); + fixture.Settings.ResultsDirectory = new DirectoryPath("./Path to/"); + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("\"/Working/Test1.dll\" /ResultsDirectory:\"/Working/Path to\"", result.Args); + } + [Fact] public void Should_Use_SettingsFile_If_Provided() { diff --git a/src/Cake.Common.Tests/Unit/XML/XmlTransformationTests.cs b/src/Cake.Common.Tests/Unit/XML/XmlTransformationTests.cs index 710991d93a..72cf41db80 100644 --- a/src/Cake.Common.Tests/Unit/XML/XmlTransformationTests.cs +++ b/src/Cake.Common.Tests/Unit/XML/XmlTransformationTests.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Xml.Xsl; using Cake.Common.Tests.Fixtures; using Cake.Common.Tests.Properties; using Cake.Common.Xml; @@ -88,7 +89,7 @@ public void Should_Throw_If_Xml_Not_Exists() var result = Record.Exception(() => fixture.Transform()); // Then - AssertEx.IsExceptionWithMessage(result, "XML File not found."); + AssertEx.IsExceptionWithMessage(result, "XML file not found."); } [Fact] @@ -104,7 +105,7 @@ public void Should_Throw_If_Xsl_Not_Exists() var result = Record.Exception(() => fixture.Transform()); // Then - AssertEx.IsExceptionWithMessage(result, "Xsl File not found."); + AssertEx.IsExceptionWithMessage(result, "XSL file not found."); } [Fact] @@ -182,63 +183,108 @@ public void Should_Transform_Xml_String_And_Xsl_String_To_Result_String_With_Xml Assert.Equal(htm, result, ignoreLineEndingDifferences: true); } - // this feels wrong to be CLR only - [RuntimeFact(TestRuntime.Clr)] - public void Should_Transform_Xml_String_And_Xsl_String_To_Result_String_With_Utf32Xml_Declaration() + [Fact] + public void Should_Throw_If_Xml_Was_Null() + { + // Given + var xsl = Resources.XmlTransformation_Xsl; + + // When + var result = Record.Exception(() => XmlTransformation.Transform(xsl, null)); + + // Then + AssertEx.IsArgumentNullException(result, "xml"); + } + + [Fact] + public void Should_Throw_If_Xsl_Was_Null() + { + // Given + var xml = Resources.XmlTransformation_Xml; + + // When + var result = Record.Exception(() => XmlTransformation.Transform(null, xml)); + + // Then + AssertEx.IsArgumentNullException(result, "xsl"); + } + + [Fact] + public void Should_Throw_If_Xml_Transformation_Settings_Was_Null() { // Given var xml = Resources.XmlTransformation_Xml; var xsl = Resources.XmlTransformation_Xsl; - var settings = new XmlTransformationSettings - { - Encoding = new UTF32Encoding(false, false, true) - }; // When - var result = string.Concat(XmlTransformation.Transform(xsl, xml, settings).Take(39)); + var result = Record.Exception(() => XmlTransformation.Transform(xsl, xml, null)); // Then - Assert.Equal("", result); + AssertEx.IsArgumentNullException(result, "settings"); } [Fact] - public void Should_Throw_If_Xml_Was_Null() + public void Should_Not_Throw_If_Xsl_Argument_List_Was_Null() { // Given + var xml = Resources.XmlTransformation_Xml; var xsl = Resources.XmlTransformation_Xsl; + XmlTransformationSettings xmlTransformationSettings = new XmlTransformationSettings + { + XsltArgumentList = null + }; // When - var result = Record.Exception(() => XmlTransformation.Transform(xsl, null)); + var result = Record.Exception(() => XmlTransformation.Transform(xsl, xml, xmlTransformationSettings)); // Then - AssertEx.IsArgumentNullException(result, "xml"); + Assert.Null(result); } [Fact] - public void Should_Throw_If_Xsl_Was_Null() + public void Should_Transform_Xml_String_And_Xsl_String_WithArguments_To_Result_String() { // Given var xml = Resources.XmlTransformation_Xml; + var xsl = Resources.XmlTransformationWithArguments_Xsl; + var htm = Resources.XmlTransformation_Htm_NoXmlDeclaration; + XmlTransformationSettings xmlTransformationSettings = new XmlTransformationSettings + { + OmitXmlDeclaration = true, + Encoding = new UTF8Encoding(false), + XsltArgumentList = new XsltArgumentList() + }; + xmlTransformationSettings.XsltArgumentList.AddParam("BackgroundColor", string.Empty, "teal"); + xmlTransformationSettings.XsltArgumentList.AddParam("Color", string.Empty, "white"); // When - var result = Record.Exception(() => XmlTransformation.Transform(null, xml)); + var result = XmlTransformation.Transform(xsl, xml, xmlTransformationSettings); // Then - AssertEx.IsArgumentNullException(result, "xsl"); + Assert.Equal(htm, result, ignoreLineEndingDifferences: true); } [Fact] - public void Should_Throw_If_String_Settings_Was_Null() + public void Should_Transform_Xml_String_And_Xsl_String_WithArgumentsAndNamespace_To_Result_String() { // Given var xml = Resources.XmlTransformation_Xml; - var xsl = Resources.XmlTransformation_Xsl; + var xsl = Resources.XmlTransformationWithArgumentsAndNamespace_Xsl; + var htm = Resources.XmlTransformation_Htm_NoXmlDeclaration; + XmlTransformationSettings xmlTransformationSettings = new XmlTransformationSettings + { + OmitXmlDeclaration = true, + Encoding = new UTF8Encoding(false), + XsltArgumentList = new XsltArgumentList() + }; + xmlTransformationSettings.XsltArgumentList.AddParam("BackgroundColor", "http://example.com", "teal"); + xmlTransformationSettings.XsltArgumentList.AddParam("Color", "http://example.com", "white"); // When - var result = Record.Exception(() => XmlTransformation.Transform(xsl, xml, null)); + var result = XmlTransformation.Transform(xsl, xml, xmlTransformationSettings); // Then - AssertEx.IsArgumentNullException(result, "settings"); + Assert.Equal(htm, result, ignoreLineEndingDifferences: true); } } } diff --git a/src/Cake.Common/ArgumentAliases.cs b/src/Cake.Common/ArgumentAliases.cs index 51a5d935e9..42eb8bca4d 100644 --- a/src/Cake.Common/ArgumentAliases.cs +++ b/src/Cake.Common/ArgumentAliases.cs @@ -3,8 +3,10 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.ComponentModel; using System.Globalization; +using System.Linq; using Cake.Core; using Cake.Core.Annotations; @@ -26,12 +28,12 @@ public static class ArgumentAliases /// This sample shows how to call the method. /// /// var argumentName = "myArgument"; - /// //Cake.exe .\hasargument.cake -myArgument="is specified" + /// // Cake.exe .\hasargument.cake -myArgument="is specified" /// if (HasArgument(argumentName)) /// { /// Information("{0} is specified", argumentName); /// } - /// //Cake.exe .\hasargument.cake + /// // Cake.exe .\hasargument.cake /// else /// { /// Warning("{0} not specified", argumentName); @@ -57,7 +59,7 @@ public static bool HasArgument(this ICakeContext context, string name) /// The value of the argument. /// /// - /// //Cake.exe .\argument.cake -myArgument="is valid" -loopCount = 5 + /// // Cake.exe .\argument.cake --myArgument="is valid" --loopCount=5 /// Information("Argument {0}", Argument<string>("myArgument")); /// var loopCount = Argument<int>("loopCount"); /// for(var index = 0;index<loopCount; index++) @@ -76,16 +78,149 @@ public static T Argument(this ICakeContext context, string name) throw new ArgumentNullException(nameof(context)); } - var value = context.Arguments.GetArgument(name); + var value = context.Arguments.GetArguments(name).FirstOrDefault(); if (value == null) { const string format = "Argument '{0}' was not set."; var message = string.Format(CultureInfo.InvariantCulture, format, name); throw new CakeException(message); } + return Convert(value); } + /// + /// Gets all arguments with the specific name and throws if the argument is missing. + /// + /// The argument type. + /// The context. + /// The argument name. + /// The argument values. + /// + /// + /// // Cake.exe .\argument.cake --foo="foo" --foo="bar" + /// var arguments = Arguments<string>("foo"); + /// Information("Arguments: {0}", string.Join(", ", arguments)); + /// + /// + [CakeMethodAlias] + public static ICollection Arguments(this ICakeContext context, string name) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var values = context.Arguments.GetArguments(name); + if (values == null || values.Count == 0) + { + const string format = "Argument '{0}' was not set."; + var message = string.Format(CultureInfo.InvariantCulture, format, name); + throw new CakeException(message); + } + + return values.Select(value => Convert(value)).ToArray(); + } + + /// + /// Gets all arguments with the specific name and returns the + /// provided if the argument is missing. + /// + /// The argument type. + /// The context. + /// The argument name. + /// The value to return if the argument is missing. + /// The argument values. + /// + /// + /// // Cake.exe .\argument.cake --foo="foo" --foo="bar" + /// var arguments = Arguments<string>("foo", "default"); + /// Information("Arguments: {0}", string.Join(", ", arguments)); + /// + /// + [CakeMethodAlias] + public static ICollection Arguments(this ICakeContext context, string name, T defaultValue) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var values = context.Arguments.GetArguments(name); + if (values == null || values.Count == 0) + { + return new T[] { defaultValue }; + } + + return values.Select(value => Convert(value)).ToArray(); + } + + /// + /// Gets all arguments with the specific name and returns the + /// provided if the argument is missing. + /// + /// The argument type. + /// The context. + /// The argument name. + /// The values to return if the argument is missing. + /// The argument values. + /// + /// + /// // Cake.exe .\argument.cake --foo="foo" --foo="bar" + /// var arguments = Arguments<string>("foo", new [] { "default" }); + /// Information("Arguments: {0}", string.Join(", ", arguments)); + /// + /// + [CakeMethodAlias] + public static ICollection Arguments(this ICakeContext context, string name, ICollection defaultValues) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var values = context.Arguments.GetArguments(name); + if (values == null || values.Count == 0) + { + return defaultValues; + } + + return values.Select(value => Convert(value)).ToArray(); + } + + /// + /// Gets all arguments with the specific name, evaluates and returns the + /// provided if the argument is missing. + /// + /// The argument type. + /// The context. + /// The argument name. + /// The values to return if the argument is missing. + /// The argument values. + /// + /// + /// // Cake.exe .\argument.cake --foo="foo" --foo="bar" + /// var arguments = Arguments<string>("foo", ctx => new [] { "default" }); + /// Information("Arguments: {0}", string.Join(", ", arguments)); + /// + /// + [CakeMethodAlias] + public static ICollection Arguments(this ICakeContext context, string name, Func> defaultValues) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var values = context.Arguments.GetArguments(name); + if (values == null || values.Count == 0) + { + return defaultValues?.Invoke(context); + } + + return values.Select(value => Convert(value)).ToArray(); + } + /// /// Gets an argument and returns the provided if the argument is missing. /// @@ -96,7 +231,7 @@ public static T Argument(this ICakeContext context, string name) /// The value of the argument if it exist; otherwise . /// /// - /// //Cake.exe .\argument.cake -myArgument="is valid" -loopCount = 5 + /// // Cake.exe .\argument.cake --myArgument="is valid" --loopCount=5 /// Information("Argument {0}", Argument<string>("myArgument", "is NOT valid")); /// var loopCount = Argument<int>("loopCount", 10); /// for(var index = 0;index<loopCount; index++) @@ -113,8 +248,44 @@ public static T Argument(this ICakeContext context, string name, T defaultVal throw new ArgumentNullException(nameof(context)); } - var value = context.Arguments.GetArgument(name); - return value == null ? defaultValue : Convert(value); + var value = context.Arguments.GetArguments(name)?.FirstOrDefault(); + return value == null + ? defaultValue + : Convert(value); + } + + /// + /// Retrieves all command line arguments. + /// + /// + /// + /// var args = context.Arguments(); + /// + /// if (args.ContainsKey("verbose")) + /// { + /// Information("Verbose output enabled"); + /// } + /// + /// foreach(var arg in args) + /// { + /// Information( + /// "Key: {0}\tValue: \"{1}\"", + /// arg.Key, + /// string.Join(";", arg.Value) + /// ); + /// } + /// + /// + /// The context. + /// The command line arguments. + [CakeMethodAlias] + public static IDictionary> Arguments(this ICakeContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + return context.Arguments.GetArguments(); } private static T Convert(string value) diff --git a/src/Cake.Common/Build/AppVeyor/AppVeyorProvider.cs b/src/Cake.Common/Build/AppVeyor/AppVeyorProvider.cs index 2900e0d14c..d7d5d640dd 100644 --- a/src/Cake.Common/Build/AppVeyor/AppVeyorProvider.cs +++ b/src/Cake.Common/Build/AppVeyor/AppVeyorProvider.cs @@ -23,100 +23,10 @@ public sealed class AppVeyorProvider : IAppVeyorProvider private readonly IProcessRunner _processRunner; private readonly ICakeLog _log; - /// - /// Gets a value indicating whether the current build is running on AppVeyor. - /// - /// - /// true if the current build is running on AppVeyor.; otherwise, false. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.AppVeyor.IsRunningOnAppVeyor) - /// { - /// Information("Running on AppVeyor"); - /// } - /// else - /// { - /// Information("Not running on AppVeyor"); - /// } - /// - /// - /// Via AppVeyor. - /// - /// - /// if (AppVeyor.IsRunningOnAppVeyor) - /// { - /// Information("Running on AppVeyor"); - /// } - /// else - /// { - /// Information("Not running on AppVeyor"); - /// } - /// - /// + /// public bool IsRunningOnAppVeyor => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("APPVEYOR")); - /// - /// Gets the AppVeyor environment. - /// - /// - /// The AppVeyor environment. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.AppVeyor.IsRunningOnAppVeyor) - /// { - /// Information( - /// @"Environment: - /// ApiUrl: {0} - /// Configuration: {1} - /// JobId: {2} - /// JobName: {3} - /// Platform: {4} - /// ScheduledBuild: {5}", - /// BuildSystem.AppVeyor.Environment.ApiUrl, - /// BuildSystem.AppVeyor.Environment.Configuration, - /// BuildSystem.AppVeyor.Environment.JobId, - /// BuildSystem.AppVeyor.Environment.JobName, - /// BuildSystem.AppVeyor.Environment.Platform, - /// BuildSystem.AppVeyor.Environment.ScheduledBuild - /// ); - /// } - /// else - /// { - /// Information("Not running on AppVeyor"); - /// } - /// - /// - /// Via AppVeyor. - /// - /// - /// if (AppVeyor.IsRunningOnAppVeyor) - /// { - /// Information( - /// @"Environment: - /// ApiUrl: {0} - /// Configuration: {1} - /// JobId: {2} - /// JobName: {3} - /// Platform: {4} - /// ScheduledBuild: {5}", - /// AppVeyor.Environment.ApiUrl, - /// AppVeyor.Environment.Configuration, - /// AppVeyor.Environment.JobId, - /// AppVeyor.Environment.JobName, - /// AppVeyor.Environment.Platform, - /// AppVeyor.Environment.ScheduledBuild - /// ); - /// } - /// else - /// { - /// Information("Not running on AppVeyor"); - /// } - /// - /// + /// public AppVeyorEnvironmentInfo Environment { get; } /// @@ -133,20 +43,13 @@ public AppVeyorProvider(ICakeEnvironment environment, IProcessRunner processRunn Environment = new AppVeyorEnvironmentInfo(environment); } - /// - /// Uploads an AppVeyor artifact. - /// - /// The file path of the artifact to upload. + /// public void UploadArtifact(FilePath path) { UploadArtifact(path, settings => settings.SetArtifactType(AppVeyorUploadArtifactType.Auto)); } - /// - /// Uploads an AppVeyor artifact. - /// - /// The file path of the artifact to upload. - /// The settings to apply when uploading an artifact. + /// public void UploadArtifact(FilePath path, AppVeyorUploadArtifactsSettings settings) { if (path == null) @@ -185,11 +88,7 @@ public void UploadArtifact(FilePath path, AppVeyorUploadArtifactsSettings settin StartAppVeyor(arguments); } - /// - /// Uploads an AppVeyor artifact. - /// - /// The file path of the artifact to upload. - /// The settings to apply when uploading an artifact. + /// public void UploadArtifact(FilePath path, Action settingsAction) { if (settingsAction == null) @@ -202,11 +101,7 @@ public void UploadArtifact(FilePath path, Action - /// Uploads test results XML file to AppVeyor. Results type can be one of the following: mstest, xunit, nunit, nunit3, junit. - /// - /// The file path of the test results XML to upload. - /// The results type. Can be mstest, xunit, nunit, nunit3 or junit. + /// public void UploadTestResults(FilePath path, AppVeyorTestResultsType resultsType) { if (path == null) @@ -240,36 +135,7 @@ public void UploadTestResults(FilePath path, AppVeyorTestResultsType resultsType }).Wait(); } - /// - /// Updates the build version. - /// - /// The new build version. - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.AppVeyor.IsRunningOnAppVeyor) - /// { - /// BuildSystem.AppVeyor.UpdateBuildVersion("2.0.0.0"); - /// } - /// else - /// { - /// Information("Not running on AppVeyor"); - /// } - /// - /// - /// Via AppVeyor. - /// - /// - /// if (AppVeyor.IsRunningOnAppVeyor) - /// { - /// AppVeyor.UpdateBuildVersion("2.0.0.0"); - /// } - /// else - /// { - /// Information("Not running on AppVeyor"); - /// } - /// - /// + /// public void UpdateBuildVersion(string version) { if (version == null) @@ -295,70 +161,7 @@ public void UpdateBuildVersion(string version) StartAppVeyor(arguments); } - /// - /// Adds a message to the AppVeyor build. Messages can be categorised as: Information, Warning or Error. - /// - /// A short message to display. - /// The category of the message. - /// Additional message details. - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.AppVeyor.IsRunningOnAppVeyor) - /// { - /// BuildSystem.AppVeyor.AddMessage( - /// "This is a error message.", - /// AppVeyorMessageCategoryType.Error, - /// "Error details." - /// ); - /// - /// BuildSystem.AppVeyor.AddMessage( - /// "This is a information message.", - /// AppVeyorMessageCategoryType.Information, - /// "Information details." - /// ); - /// - /// BuildSystem.AppVeyor.AddMessage( - /// "This is a warning message.", - /// AppVeyorMessageCategoryType.Warning, - /// "Warning details." - /// ); - /// } - /// else - /// { - /// Information("Not running on AppVeyor"); - /// } - /// - /// - /// Via AppVeyor. - /// - /// - /// if (AppVeyor.IsRunningOnAppVeyor) - /// { - /// AppVeyor.AddMessage( - /// "This is a error message.", - /// AppVeyorMessageCategoryType.Error, - /// "Error details." - /// ); - /// - /// AppVeyor.AddMessage( - /// "This is a information message.", - /// AppVeyorMessageCategoryType.Information, - /// "Information details." - /// ); - /// - /// AppVeyor.AddMessage( - /// "This is a warning message.", - /// AppVeyorMessageCategoryType.Warning, - /// "Warning details." - /// ); - /// } - /// else - /// { - /// Information("Not running on AppVeyor"); - /// } - /// - /// + /// public void AddMessage(string message, AppVeyorMessageCategoryType category = AppVeyorMessageCategoryType.Information, string details = null) { if (message == null) diff --git a/src/Cake.Common/Build/AppVeyor/IAppVeyorProvider.cs b/src/Cake.Common/Build/AppVeyor/IAppVeyorProvider.cs index 051c878a9d..3e46f2d01b 100644 --- a/src/Cake.Common/Build/AppVeyor/IAppVeyorProvider.cs +++ b/src/Cake.Common/Build/AppVeyor/IAppVeyorProvider.cs @@ -140,6 +140,32 @@ public interface IAppVeyorProvider /// Updates the build version. /// /// The new build version. + /// Via BuildSystem. + /// + /// + /// if (BuildSystem.AppVeyor.IsRunningOnAppVeyor) + /// { + /// BuildSystem.AppVeyor.UpdateBuildVersion("2.0.0.0"); + /// } + /// else + /// { + /// Information("Not running on AppVeyor"); + /// } + /// + /// + /// Via AppVeyor. + /// + /// + /// if (AppVeyor.IsRunningOnAppVeyor) + /// { + /// AppVeyor.UpdateBuildVersion("2.0.0.0"); + /// } + /// else + /// { + /// Information("Not running on AppVeyor"); + /// } + /// + /// void UpdateBuildVersion(string version); /// diff --git a/src/Cake.Common/Build/AzurePipelines/AzurePipelinesCommands.cs b/src/Cake.Common/Build/AzurePipelines/AzurePipelinesCommands.cs index 5bfcb1daf9..ecef614c78 100644 --- a/src/Cake.Common/Build/AzurePipelines/AzurePipelinesCommands.cs +++ b/src/Cake.Common/Build/AzurePipelines/AzurePipelinesCommands.cs @@ -35,10 +35,7 @@ public AzurePipelinesCommands(ICakeEnvironment environment, IBuildSystemServiceM _writer = writer ?? throw new ArgumentNullException(nameof(writer)); } - /// - /// Log a warning issue to timeline record of current task. - /// - /// The warning message. + /// public void WriteWarning(string message) { WriteLoggingCommand("task.logissue", new Dictionary @@ -47,11 +44,7 @@ public void WriteWarning(string message) }, message); } - /// - /// Log a warning issue with detailed data to timeline record of current task. - /// - /// The warning message. - /// The message data. + /// public void WriteWarning(string message, AzurePipelinesMessageData data) { var properties = data.GetProperties(); @@ -59,10 +52,7 @@ public void WriteWarning(string message, AzurePipelinesMessageData data) WriteLoggingCommand("task.logissue", properties, message); } - /// - /// Log an error to timeline record of current task. - /// - /// The error message. + /// public void WriteError(string message) { WriteLoggingCommand("task.logissue", new Dictionary @@ -71,11 +61,7 @@ public void WriteError(string message) }, message); } - /// - /// Log an error with detailed data to timeline record of current task. - /// - /// The error message. - /// The message data. + /// public void WriteError(string message, AzurePipelinesMessageData data) { var properties = data.GetProperties(); @@ -83,11 +69,7 @@ public void WriteError(string message, AzurePipelinesMessageData data) WriteLoggingCommand("task.logissue", properties, message); } - /// - /// Set progress and current operation for current task. - /// - /// Current progress as percentage. - /// The current operation. + /// public void SetProgress(int progress, string currentOperation) { WriteLoggingCommand("task.setprogress", new Dictionary @@ -96,18 +78,13 @@ public void SetProgress(int progress, string currentOperation) }, currentOperation); } - /// - /// Finish timeline record for current task and set task result to succeeded. - /// + /// public void CompleteCurrentTask() { WriteLoggingCommand("task.complete", "DONE"); } - /// - /// Finish timeline record for current task and set task result. - /// - /// The task result status. + /// public void CompleteCurrentTask(AzurePipelinesTaskResult result) { WriteLoggingCommand("task.complete", new Dictionary @@ -116,13 +93,7 @@ public void CompleteCurrentTask(AzurePipelinesTaskResult result) }, "DONE"); } - /// - /// Create detail timeline record. - /// - /// Name of the new timeline record. - /// Type of the new timeline record. - /// Order of the timeline record. - /// The timeline record ID. + /// public Guid CreateNewRecord(string name, string type, int order) { var guid = Guid.NewGuid(); @@ -136,14 +107,7 @@ public Guid CreateNewRecord(string name, string type, int order) return guid; } - /// - /// Create detail timeline record. - /// - /// Name of the new timeline record. - /// Type of the new timeline record. - /// Order of the timeline record. - /// Additional data for the new timeline record. - /// The timeline record ID. + /// public Guid CreateNewRecord(string name, string type, int order, AzurePipelinesRecordData data) { var guid = Guid.NewGuid(); @@ -156,11 +120,7 @@ public Guid CreateNewRecord(string name, string type, int order, AzurePipelinesR return guid; } - /// - /// Update an existing detail timeline record. - /// - /// The ID of the existing timeline record. - /// Additional data for the timeline record. + /// public void UpdateRecord(Guid id, AzurePipelinesRecordData data) { var properties = data.GetProperties(); @@ -168,14 +128,7 @@ public void UpdateRecord(Guid id, AzurePipelinesRecordData data) WriteLoggingCommand("task.logdetail", properties, "update"); } - /// - /// Sets a variable in the variable service of the task context. - /// - /// - /// The variable is exposed to following tasks as an environment variable. - /// - /// The variable name. - /// The variable value. + /// public void SetVariable(string name, string value) { WriteLoggingCommand("task.setvariable", new Dictionary @@ -184,14 +137,17 @@ public void SetVariable(string name, string value) }, value); } - /// - /// Sets a secret variable in the variable service of the task context. - /// - /// - /// The variable is not exposed to following tasks as an environment variable, and must be passed as inputs. - /// - /// The variable name. - /// The variable value. + /// + public void SetOutputVariable(string name, string value) + { + WriteLoggingCommand("task.setvariable", new Dictionary + { + ["variable"] = name, + ["isOutput"] = "true" + }, value); + } + + /// public void SetSecretVariable(string name, string value) { WriteLoggingCommand("task.setvariable", new Dictionary @@ -201,41 +157,19 @@ public void SetSecretVariable(string name, string value) }, value); } - /// - /// Upload and attach summary markdown to current timeline record. - /// - /// - /// This summary is added to the build/release summary and is not available for download with logs. - /// - /// Path to the summary markdown file. + /// public void UploadTaskSummary(FilePath markdownPath) { WriteLoggingCommand("task.uploadsummary", markdownPath.MakeAbsolute(_environment).FullPath); } - /// - /// Upload file as additional log information to the current timeline record. - /// - /// - /// - /// The file shall be available for download along with task logs. - /// - /// - /// Requires agent version 1.101. - /// - /// - /// Path to the additional log file. + /// public void UploadTaskLogFile(FilePath logFile) { WriteLoggingCommand("task.uploadfile", logFile.MakeAbsolute(_environment).FullPath); } - /// - /// Create an artifact link, such as a file or folder path or a version control path. - /// - /// The artifact name.. - /// The artifact type. - /// The link path or value. + /// public void LinkArtifact(string name, AzurePipelinesArtifactType type, string location) { WriteLoggingCommand("artifact.associate", new Dictionary @@ -245,11 +179,7 @@ public void LinkArtifact(string name, AzurePipelinesArtifactType type, string lo }, location); } - /// - /// Upload local file into a file container folder. - /// - /// Folder that the file will upload to. - /// Path to the local file. + /// public void UploadArtifact(string folderName, FilePath file) { WriteLoggingCommand("artifact.upload", new Dictionary @@ -258,12 +188,7 @@ public void UploadArtifact(string folderName, FilePath file) }, file.MakeAbsolute(_environment).FullPath); } - /// - /// Upload local file into a file container folder, and create an artifact. - /// - /// Folder that the file will upload to. - /// Path to the local file. - /// The artifact name. + /// public void UploadArtifact(string folderName, FilePath file, string artifactName) { WriteLoggingCommand("artifact.upload", new Dictionary @@ -273,7 +198,7 @@ public void UploadArtifact(string folderName, FilePath file, string artifactName }, file.MakeAbsolute(_environment).FullPath); } - /// + /// public void UploadArtifactDirectory(DirectoryPath directory) { if (directory == null) @@ -284,7 +209,7 @@ public void UploadArtifactDirectory(DirectoryPath directory) UploadArtifactDirectory(directory, directory.GetDirectoryName()); } - /// + /// public void UploadArtifactDirectory(DirectoryPath directory, string artifactName) { if (directory == null) @@ -304,64 +229,39 @@ public void UploadArtifactDirectory(DirectoryPath directory, string artifactName }, directory.MakeAbsolute(_environment).FullPath); } - /// - /// Upload additional log to build container's logs/tool folder. - /// - /// The log file. + /// public void UploadBuildLogFile(FilePath logFile) { WriteLoggingCommand("build.uploadlog", logFile.MakeAbsolute(_environment).FullPath); } - /// - /// Update build number for current build. - /// - /// - /// Requires agent version 1.88. - /// - /// The build number. + /// public void UpdateBuildNumber(string buildNumber) { WriteLoggingCommand("build.updatebuildnumber", buildNumber); } - /// - /// Add a tag for current build. - /// - /// - /// Requires agent version 1.95. - /// - /// The tag. + /// public void AddBuildTag(string tag) { WriteLoggingCommand("build.addbuildtag", tag); } - /// - /// Publishes and uploads tests results. - /// - /// The publish test results data. + /// public void PublishTestResults(AzurePipelinesPublishTestResultsData data) { var properties = data.GetProperties(_environment); WriteLoggingCommand("results.publish", properties, string.Empty); } - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage data. + /// public void PublishCodeCoverage(AzurePipelinesPublishCodeCoverageData data) { var properties = data.GetProperties(_environment); WriteLoggingCommand("codecoverage.publish", properties, string.Empty); } - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage summary file path. - /// The code coverage data. + /// public void PublishCodeCoverage(FilePath summaryFilePath, AzurePipelinesPublishCodeCoverageData data) { if (summaryFilePath == null) @@ -373,11 +273,7 @@ public void PublishCodeCoverage(FilePath summaryFilePath, AzurePipelinesPublishC WriteLoggingCommand("codecoverage.publish", properties, string.Empty); } - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage summary file path. - /// The configuration action for the code coverage data. + /// public void PublishCodeCoverage(FilePath summaryFilePath, Action action) { if (action == null) diff --git a/src/Cake.Common/Build/AzurePipelines/AzurePipelinesProvider.cs b/src/Cake.Common/Build/AzurePipelines/AzurePipelinesProvider.cs index 5304bc5752..12097c1a48 100644 --- a/src/Cake.Common/Build/AzurePipelines/AzurePipelinesProvider.cs +++ b/src/Cake.Common/Build/AzurePipelines/AzurePipelinesProvider.cs @@ -28,38 +28,14 @@ public AzurePipelinesProvider(ICakeEnvironment environment, IBuildSystemServiceM Commands = new AzurePipelinesCommands(environment, writer); } - /// - /// Gets a value indicating whether the current build is running on Azure Pipelines. - /// - /// - /// true if the current build is running on Azure Pipelines; otherwise, false. - /// + /// public bool IsRunningOnAzurePipelines - => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("TF_BUILD")) && !IsHostedAgent; - - /// - /// Gets a value indicating whether the current build is running on hosted Azure Pipelines. - /// - /// - /// true if the current build is running on hosted Azure Pipelines; otherwise, false. - /// - public bool IsRunningOnAzurePipelinesHosted - => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("TF_BUILD")) && IsHostedAgent; + => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("TF_BUILD")); - /// - /// Gets the Azure Pipelines environment. - /// - /// - /// The Azure Pipelines environment. - /// + /// public AzurePipelinesEnvironmentInfo Environment { get; } - /// - /// Gets the Azure Pipelines commands provider. - /// - /// - /// The Azure Pipelines commands provider. - /// + /// public IAzurePipelinesCommands Commands { get; } /// diff --git a/src/Cake.Common/Build/AzurePipelines/Data/AzurePipelinesAgentInfo.cs b/src/Cake.Common/Build/AzurePipelines/Data/AzurePipelinesAgentInfo.cs index 6b5bb34251..879079c768 100644 --- a/src/Cake.Common/Build/AzurePipelines/Data/AzurePipelinesAgentInfo.cs +++ b/src/Cake.Common/Build/AzurePipelines/Data/AzurePipelinesAgentInfo.cs @@ -101,10 +101,10 @@ public AzurePipelinesAgentInfo(ICakeEnvironment environment) public FilePath ToolsDirectory => GetEnvironmentString("AGENT_TOOLSDIRECTORY"); /// - /// Gets a value indicating whether the current agent is a hosted agent. + /// Gets a value indicating whether the current agent is a Microsoft hosted agent. /// /// - /// true if the current agent is a hosted agent; otherwise, false. + /// true if the current agent is a Microsoft hosted agent. false if the current agent is a self hosted agent. /// public bool IsHosted => Name != null && (Name.StartsWith("Hosted") || Name.StartsWith("Azure Pipelines")); } diff --git a/src/Cake.Common/Build/AzurePipelines/Data/AzurePipelinesBuildInfo.cs b/src/Cake.Common/Build/AzurePipelines/Data/AzurePipelinesBuildInfo.cs index 87ff3b7c58..c28c3454b6 100644 --- a/src/Cake.Common/Build/AzurePipelines/Data/AzurePipelinesBuildInfo.cs +++ b/src/Cake.Common/Build/AzurePipelines/Data/AzurePipelinesBuildInfo.cs @@ -45,7 +45,7 @@ public AzurePipelinesBuildInfo(ICakeEnvironment environment) /// /// The path of the staging directory. /// - public FilePath ArtifactStagingDirectory => GetEnvironmentString("BUILD_ARTIFACTSTAGINGDIRECTORY"); + public DirectoryPath ArtifactStagingDirectory => GetEnvironmentString("BUILD_ARTIFACTSTAGINGDIRECTORY"); /// /// Gets the local path on the agent you can use as an output folder for compiled binaries. @@ -53,7 +53,7 @@ public AzurePipelinesBuildInfo(ICakeEnvironment environment) /// /// The path to the binaries directory. /// - public FilePath BinariesDirectory => GetEnvironmentString("BUILD_BINARIESDIRECTORY"); + public DirectoryPath BinariesDirectory => GetEnvironmentString("BUILD_BINARIESDIRECTORY"); /// /// Gets the ID of the record for the completed build. @@ -119,7 +119,7 @@ public AzurePipelinesBuildInfo(ICakeEnvironment environment) /// /// The source code directory. /// - public FilePath SourcesDirectory => GetEnvironmentString("BUILD_SOURCESDIRECTORY"); + public DirectoryPath SourcesDirectory => GetEnvironmentString("BUILD_SOURCESDIRECTORY"); /// /// Gets the local path on the agent where any artifacts are copied to before being pushed to their destination. @@ -127,7 +127,7 @@ public AzurePipelinesBuildInfo(ICakeEnvironment environment) /// /// The staging directory. /// - public FilePath StagingDirectory => GetEnvironmentString("BUILD_STAGINGDIRECTORY"); + public DirectoryPath StagingDirectory => GetEnvironmentString("BUILD_STAGINGDIRECTORY"); /// /// Gets local path on the agent where the test results are created. @@ -135,7 +135,7 @@ public AzurePipelinesBuildInfo(ICakeEnvironment environment) /// /// The test result directory. /// - public FilePath TestResultsDirectory => GetEnvironmentString("COMMON_TESTRESULTSDIRECTORY"); + public DirectoryPath TestResultsDirectory => GetEnvironmentString("COMMON_TESTRESULTSDIRECTORY"); /// /// Gets Azure Pipelines Build TriggeredBy information. diff --git a/src/Cake.Common/Build/AzurePipelines/IAzurePipelinesCommands.cs b/src/Cake.Common/Build/AzurePipelines/IAzurePipelinesCommands.cs index 4ba6d2af00..9adf93515b 100644 --- a/src/Cake.Common/Build/AzurePipelines/IAzurePipelinesCommands.cs +++ b/src/Cake.Common/Build/AzurePipelines/IAzurePipelinesCommands.cs @@ -93,6 +93,16 @@ public interface IAzurePipelinesCommands /// The variable value. void SetVariable(string name, string value); + /// + /// Sets a output variable in the variable service of the task context. + /// + /// + /// The variable is exposed to following tasks as an environment variable. + /// + /// The variable name. + /// The variable value. + void SetOutputVariable(string name, string value); + /// /// Sets a secret variable in the variable service of the task context. /// @@ -129,7 +139,7 @@ public interface IAzurePipelinesCommands /// /// Create an artifact link, such as a file or folder path or a version control path. /// - /// The artifact name.. + /// The artifact name. /// The artifact type. /// The link path or value. void LinkArtifact(string name, AzurePipelinesArtifactType type, string location); diff --git a/src/Cake.Common/Build/AzurePipelines/IAzurePipelinesProvider.cs b/src/Cake.Common/Build/AzurePipelines/IAzurePipelinesProvider.cs index 9ac035d975..05cc97546e 100644 --- a/src/Cake.Common/Build/AzurePipelines/IAzurePipelinesProvider.cs +++ b/src/Cake.Common/Build/AzurePipelines/IAzurePipelinesProvider.cs @@ -19,14 +19,6 @@ public interface IAzurePipelinesProvider /// bool IsRunningOnAzurePipelines { get; } - /// - /// Gets a value indicating whether the current build is running on hosted Azure Pipelines. - /// - /// - /// true if the current build is running on hosted Azure Pipelines; otherwise, false. - /// - bool IsRunningOnAzurePipelinesHosted { get; } - /// /// Gets the Azure Pipelines environment. /// diff --git a/src/Cake.Common/Build/Bamboo/BambooProvider.cs b/src/Cake.Common/Build/Bamboo/BambooProvider.cs index 1714a4ff02..84c58700e8 100644 --- a/src/Cake.Common/Build/Bamboo/BambooProvider.cs +++ b/src/Cake.Common/Build/Bamboo/BambooProvider.cs @@ -25,20 +25,10 @@ public BambooProvider(ICakeEnvironment environment) Environment = new BambooEnvironmentInfo(environment); } - /// - /// Gets a value indicating whether the current build is running on Bamboo. - /// - /// - /// true if the current build is running on Bamboo.; otherwise, false. - /// + /// public bool IsRunningOnBamboo => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("bamboo_buildNumber")); - /// - /// Gets the Bamboo environment. - /// - /// - /// The Bamboo environment. - /// + /// public BambooEnvironmentInfo Environment { get; } } } \ No newline at end of file diff --git a/src/Cake.Common/Build/BitbucketPipelines/BitbucketPipelinesProvider.cs b/src/Cake.Common/Build/BitbucketPipelines/BitbucketPipelinesProvider.cs index 1d58d5f38b..4ff799f03d 100644 --- a/src/Cake.Common/Build/BitbucketPipelines/BitbucketPipelinesProvider.cs +++ b/src/Cake.Common/Build/BitbucketPipelines/BitbucketPipelinesProvider.cs @@ -12,22 +12,12 @@ namespace Cake.Common.Build.BitbucketPipelines /// public sealed class BitbucketPipelinesProvider : IBitbucketPipelinesProvider { - /// - /// Gets a value indicating whether the current build is running on Pipelines. - /// - /// - /// true if the current build is running on Pipelines; otherwise, false. - /// + /// public bool IsRunningOnBitbucketPipelines => !string.IsNullOrWhiteSpace(Environment.Repository.RepoOwner) && !string.IsNullOrWhiteSpace(Environment.Repository.RepoSlug) && !string.IsNullOrWhiteSpace(Environment.Repository.Commit); - /// - /// Gets the Pipelines environment. - /// - /// - /// The Pipelines environment. - /// + /// public BitbucketPipelinesEnvironmentInfo Environment { get; } /// diff --git a/src/Cake.Common/Build/Bitrise/BitriseProvider.cs b/src/Cake.Common/Build/Bitrise/BitriseProvider.cs index f36eb8e124..054b73792a 100644 --- a/src/Cake.Common/Build/Bitrise/BitriseProvider.cs +++ b/src/Cake.Common/Build/Bitrise/BitriseProvider.cs @@ -17,20 +17,10 @@ public sealed class BitriseProvider : IBitriseProvider private readonly ICakeEnvironment _environment; private readonly IProcessRunner _processRunner; - /// - /// Gets a value indicating whether the current build is running on Bitrise. - /// - /// - /// true if the current build is running on Bitrise; otherwise, false. - /// + /// public bool IsRunningOnBitrise => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("BITRISE_BUILD_URL")); - /// - /// Gets the Bitrise environment. - /// - /// - /// The Bamboo environment. - /// + /// public BitriseEnvironmentInfo Environment { get; } /// @@ -45,11 +35,7 @@ public BitriseProvider(ICakeEnvironment environment, IProcessRunner processRunne Environment = new BitriseEnvironmentInfo(_environment); } - /// - /// Sets and environment variable that can be used in next steps on Bitrise. - /// - /// The variable. - /// The value. + /// public void SetEnvironmentString(string variable, string value) { var arguments = new ProcessArgumentBuilder() diff --git a/src/Cake.Common/Build/BuildProvider.cs b/src/Cake.Common/Build/BuildProvider.cs index 753a4c3028..5515b17f84 100644 --- a/src/Cake.Common/Build/BuildProvider.cs +++ b/src/Cake.Common/Build/BuildProvider.cs @@ -77,11 +77,6 @@ public enum BuildProvider /// AzurePipelines = 2048, - /// - /// AzurePipelinesHosted build provider. - /// - AzurePipelinesHosted = 4096, - /// /// GitHubActions build provider. /// diff --git a/src/Cake.Common/Build/BuildSystem.cs b/src/Cake.Common/Build/BuildSystem.cs index 145a94659d..2410db5f6a 100644 --- a/src/Cake.Common/Build/BuildSystem.cs +++ b/src/Cake.Common/Build/BuildSystem.cs @@ -15,7 +15,6 @@ using Cake.Common.Build.Jenkins; using Cake.Common.Build.MyGet; using Cake.Common.Build.TeamCity; -using Cake.Common.Build.TFBuild; using Cake.Common.Build.TravisCI; namespace Cake.Common.Build @@ -40,7 +39,6 @@ public sealed class BuildSystem /// The Bitbucket Pipelines provider. /// The Go.CD provider. /// The GitLab CI provider. - /// The TF Build provider. /// The GitHub Actions provider. /// The Azure Pipelines provider. public BuildSystem( @@ -55,7 +53,6 @@ public BuildSystem( IBitbucketPipelinesProvider bitbucketPipelinesProvider, IGoCDProvider goCDProvider, IGitLabCIProvider gitLabCIProvider, - ITFBuildProvider tfBuildProvider, IGitHubActionsProvider gitHubActionsProvider, IAzurePipelinesProvider azurePipelinesProvider) { @@ -103,10 +100,6 @@ public BuildSystem( { throw new ArgumentNullException(nameof(gitLabCIProvider)); } - if (tfBuildProvider == null) - { - throw new ArgumentNullException(nameof(tfBuildProvider)); - } if (gitHubActionsProvider == null) { throw new ArgumentNullException(nameof(gitHubActionsProvider)); @@ -127,9 +120,6 @@ public BuildSystem( BitbucketPipelines = bitbucketPipelinesProvider; GoCD = goCDProvider; GitLabCI = gitLabCIProvider; -#pragma warning disable CS0618 // Type or member is obsolete - TFBuild = tfBuildProvider; -#pragma warning restore CS0618 // Type or member is obsolete GitHubActions = gitHubActionsProvider; AzurePipelines = azurePipelinesProvider; @@ -145,8 +135,7 @@ public BuildSystem( | (GoCD.IsRunningOnGoCD ? BuildProvider.GoCD : BuildProvider.Local) | (GitLabCI.IsRunningOnGitLabCI ? BuildProvider.GitLabCI : BuildProvider.Local) | (GitHubActions.IsRunningOnGitHubActions ? BuildProvider.GitHubActions : BuildProvider.Local) - | (AzurePipelines.IsRunningOnAzurePipelines ? BuildProvider.AzurePipelines : BuildProvider.Local) - | (AzurePipelines.IsRunningOnAzurePipelinesHosted ? BuildProvider.AzurePipelinesHosted : BuildProvider.Local); + | (AzurePipelines.IsRunningOnAzurePipelines ? BuildProvider.AzurePipelines : BuildProvider.Local); IsLocalBuild = Provider == BuildProvider.Local; @@ -156,7 +145,7 @@ public BuildSystem( || ((Provider & BuildProvider.TravisCI) != 0 && TravisCI.Environment.PullRequest.IsPullRequest) || ((Provider & BuildProvider.BitbucketPipelines) != 0 && BitbucketPipelines.Environment.PullRequest.IsPullRequest) || ((Provider & BuildProvider.GitLabCI) != 0 && GitLabCI.Environment.PullRequest.IsPullRequest) - || ((Provider & (BuildProvider.AzurePipelines | BuildProvider.AzurePipelinesHosted)) != 0 && AzurePipelines.Environment.PullRequest.IsPullRequest) + || ((Provider & BuildProvider.AzurePipelines) != 0 && AzurePipelines.Environment.PullRequest.IsPullRequest) || ((Provider & BuildProvider.GitHubActions) != 0 && GitHubActions.Environment.PullRequest.IsPullRequest) || ((Provider & BuildProvider.Jenkins) != 0 && Jenkins.Environment.Change.IsPullRequest); } @@ -508,42 +497,6 @@ public BuildSystem( /// public bool IsRunningOnGitLabCI => GitLabCI.IsRunningOnGitLabCI; - /// - /// Gets a value indicating whether this instance is running on TFS. - /// - /// - /// - /// if (BuildSystem.IsRunningOnTFS) - /// { - /// // Get the build commit hash. - /// var commitHash = BuildSystem.TFBuild.Environment.Repository.SourceVersion; - /// } - /// - /// - /// - /// true if this instance is running on TFS; otherwise, false. - /// - [Obsolete("Please use BuildSystem.IsRunningOnAzurePipelines instead.")] - public bool IsRunningOnTFS => TFBuild.IsRunningOnTFS; - - /// - /// Gets a value indicating whether this instance is running on VSTS. - /// - /// - /// - /// if (BuildSystem.IsRunningOnVSTS) - /// { - /// // Get the build commit hash. - /// var commitHash = BuildSystem.TFBuild.Environment.Repository.SourceVersion; - /// } - /// - /// - /// - /// true if this instance is running on VSTS; otherwise, false. - /// - [Obsolete("Please use BuildSystem.IsRunningOnAzurePipelinesHosted instead.")] - public bool IsRunningOnVSTS => TFBuild.IsRunningOnVSTS; - /// /// Gets a value indicating whether this instance is running on Azure Pipelines. /// @@ -561,38 +514,6 @@ public BuildSystem( /// public bool IsRunningOnAzurePipelines => AzurePipelines.IsRunningOnAzurePipelines; - /// - /// Gets a value indicating whether this instance is running on hosted Azure Pipelines. - /// - /// - /// - /// if (BuildSystem.IsRunningOnAzurePipelinesHosted) - /// { - /// // Get the build commit hash. - /// var commitHash = BuildSystem.AzurePipelines.Environment.Repository.SourceVersion; - /// } - /// - /// - /// - /// true if this instance is running on hosted Azure Pipelines; otherwise, false. - /// - public bool IsRunningOnAzurePipelinesHosted => AzurePipelines.IsRunningOnAzurePipelinesHosted; - - /// - /// Gets the TF Build Provider. - /// - /// - /// - /// if (BuildSystem.IsRunningOnVSTS) - /// { - /// // Get the build definition name. - /// var definitionName = BuildSystem.TFBuild.Environment.BuildDefinition.Name; - /// } - /// - /// - [Obsolete("Please use BuildSystem.AzurePipelines instead.")] - public ITFBuildProvider TFBuild { get; } - /// /// Gets the Azure Pipelines Provider. /// diff --git a/src/Cake.Common/Build/BuildSystemAliases.cs b/src/Cake.Common/Build/BuildSystemAliases.cs index 4bfd966846..197c7fc76f 100644 --- a/src/Cake.Common/Build/BuildSystemAliases.cs +++ b/src/Cake.Common/Build/BuildSystemAliases.cs @@ -15,7 +15,6 @@ using Cake.Common.Build.Jenkins; using Cake.Common.Build.MyGet; using Cake.Common.Build.TeamCity; -using Cake.Common.Build.TFBuild; using Cake.Common.Build.TravisCI; using Cake.Core; using Cake.Core.Annotations; @@ -48,7 +47,7 @@ public static BuildSystem BuildSystem(this ICakeContext context) } var appVeyorProvider = new AppVeyorProvider(context.Environment, context.ProcessRunner, context.Log); - var teamCityProvider = new TeamCityProvider(context.Environment, new BuildSystemServiceMessageWriter()); + var teamCityProvider = new TeamCityProvider(context.Environment, context.FileSystem, new BuildSystemServiceMessageWriter()); var myGetProvider = new MyGetProvider(context.Environment, new BuildSystemServiceMessageWriter()); var bambooProvider = new BambooProvider(context.Environment); var continuaCIProvider = new ContinuaCIProvider(context.Environment, new BuildSystemServiceMessageWriter()); @@ -58,11 +57,10 @@ public static BuildSystem BuildSystem(this ICakeContext context) var bitbucketPipelinesProvider = new BitbucketPipelinesProvider(context.Environment); var goCDProvider = new GoCDProvider(context.Environment, context.Log); var gitLabCIProvider = new GitLabCIProvider(context.Environment); - var tfBuildProvider = new TFBuildProvider(context.Environment, new BuildSystemServiceMessageWriter()); - var gitHubActionsProvider = new GitHubActionsProvider(context.Environment); + var gitHubActionsProvider = new GitHubActionsProvider(context.Environment, context.FileSystem); var azurePipelinesProvider = new AzurePipelinesProvider(context.Environment, new BuildSystemServiceMessageWriter()); - return new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, tfBuildProvider, gitHubActionsProvider, azurePipelinesProvider); + return new BuildSystem(appVeyorProvider, teamCityProvider, myGetProvider, bambooProvider, continuaCIProvider, jenkinsProvider, bitriseProvider, travisCIProvider, bitbucketPipelinesProvider, goCDProvider, gitLabCIProvider, gitHubActionsProvider, azurePipelinesProvider); } /// @@ -338,32 +336,6 @@ public static IGitLabCIProvider GitLabCI(this ICakeContext context) return buildSystem.GitLabCI; } - /// - /// Gets a instance that can be used to - /// obtain information from the Team Foundation Build environment. - /// - /// - /// - /// var isTFSBuild = TFBuild.IsRunningOnTFS; - /// - /// - /// The context. - /// A instance. - [CakePropertyAlias(Cache = true)] - [CakeNamespaceImport("Cake.Common.Build.TFBuild")] - [CakeNamespaceImport("Cake.Common.Build.TFBuild.Data")] - [Obsolete("Use AzurePipelines instead.")] - public static ITFBuildProvider TFBuild(this ICakeContext context) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var buildSystem = context.BuildSystem(); - return buildSystem.TFBuild; - } - /// /// Gets a instance that can be used to /// obtain information from the GitHub Actions environment. diff --git a/src/Cake.Common/Build/ContinuaCI/ContinuaCIProvider.cs b/src/Cake.Common/Build/ContinuaCI/ContinuaCIProvider.cs index e762b34536..b4ba480c45 100644 --- a/src/Cake.Common/Build/ContinuaCI/ContinuaCIProvider.cs +++ b/src/Cake.Common/Build/ContinuaCI/ContinuaCIProvider.cs @@ -49,12 +49,7 @@ public ContinuaCIProvider(ICakeEnvironment environment, IBuildSystemServiceMessa Environment = new ContinuaCIEnvironmentInfo(environment); } - /// - /// Gets a value indicating whether the current build is running on Continua CI. - /// - /// - /// true if the current build is running on Continua CI; otherwise, false. - /// + /// public bool IsRunningOnContinuaCI { get @@ -64,19 +59,10 @@ public bool IsRunningOnContinuaCI } } - /// - /// Gets the Continua CI environment. - /// - /// - /// The Continua CI environment. - /// + /// public ContinuaCIEnvironmentInfo Environment { get; } - /// - /// Write a status message to the Continua CI build log. - /// - /// Message contents. - /// Build status. + /// public void WriteMessage(string message, ContinuaCIMessageType status) { var name = Enum.GetName(typeof(ContinuaCIMessageType), status); @@ -92,30 +78,19 @@ public void WriteMessage(string message, ContinuaCIMessageType status) } } - /// - /// Write the start of a message group to the Continua CI build log. - /// - /// Group name. + /// public void WriteStartGroup(string groupName) { WriteServiceMessage("startGroup ", "name", groupName); } - /// - /// Write the end of a message block to the Continua CI build log. - /// - /// Group name. + /// public void WriteEndBlock(string groupName) { WriteServiceMessage("endGroup", "name", groupName); } - /// - /// Set a Continua CI build variable. - /// - /// Name of the variable to set. - /// Value to assign to the variable. - /// Set to 'true' to prevent the build failing if the variable has not been defined for the configuration.. + /// public void SetVariable(string name, string value, bool skipIfNotDefined = true) { WriteServiceMessage("setParameter", new Dictionary @@ -126,19 +101,13 @@ public void SetVariable(string name, string value, bool skipIfNotDefined = true) }); } - /// - /// Set a Continua CI build version. - /// - /// The new build version. + /// public void SetBuildVersion(string version) { WriteServiceMessage("setBuildVersion", "value", version); } - /// - /// Set a Continua CI build status message, which is shown on the build details page when a build is running. - /// - /// The new build status text. + /// public void SetBuildStatus(string text) { WriteServiceMessage("setBuildStatus", "value", text); diff --git a/src/Cake.Common/Build/ContinuaCI/IContinuaCIProvider.cs b/src/Cake.Common/Build/ContinuaCI/IContinuaCIProvider.cs index 3f420c943c..5ea9aa98ee 100644 --- a/src/Cake.Common/Build/ContinuaCI/IContinuaCIProvider.cs +++ b/src/Cake.Common/Build/ContinuaCI/IContinuaCIProvider.cs @@ -35,7 +35,7 @@ public interface IContinuaCIProvider /// /// Name of the variable to set. /// Value to assign to the variable. - /// Set to 'true' to prevent the build failing if the variable has not been defined for the configuration.. + /// Set to 'true' to prevent the build failing if the variable has not been defined for the configuration. void SetVariable(string name, string value, bool skipIfNotDefined = true); /// diff --git a/src/Cake.Common/Build/GitHubActions/Commands/ArtifactResponse.cs b/src/Cake.Common/Build/GitHubActions/Commands/ArtifactResponse.cs new file mode 100644 index 0000000000..7fc9ddd6c7 --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Commands/ArtifactResponse.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json.Serialization; + +namespace Cake.Common.Build.GitHubActions.Commands +{ + internal sealed class ArtifactResponse + { + [JsonPropertyName("containerId")] + public long ContainerId { get; set; } + + [JsonPropertyName("size")] + public long Size { get; set; } + + [JsonPropertyName("signedContent")] + public string SignedContent { get; set; } + + [JsonPropertyName("fileContainerResourceUrl")] + public string FileContainerResourceUrl { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("url")] + public string Url { get; set; } + } +} diff --git a/src/Cake.Common/Build/GitHubActions/Commands/ContainerItem.cs b/src/Cake.Common/Build/GitHubActions/Commands/ContainerItem.cs new file mode 100644 index 0000000000..f9fd045659 --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Commands/ContainerItem.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json.Serialization; + +namespace Cake.Common.Build.GitHubActions.Commands +{ + internal sealed class ContainerItem + { + [JsonPropertyName("containerId")] + public long ContainerId { get; set; } + + [JsonPropertyName("size")] + public long Size { get; set; } + + [JsonPropertyName("fileContainerResourceUrl")] + public string FileContainerResourceUrl { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("url")] + public string Url { get; set; } + + [JsonPropertyName("expiresOn")] + public DateTimeOffset ExpiresOn { get; set; } + } +} diff --git a/src/Cake.Common/Build/GitHubActions/Commands/ContainerItemResource.cs b/src/Cake.Common/Build/GitHubActions/Commands/ContainerItemResource.cs new file mode 100644 index 0000000000..8065fc0a31 --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Commands/ContainerItemResource.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text.Json.Serialization; + +namespace Cake.Common.Build.GitHubActions.Commands +{ + internal class ContainerItemResource + { + [JsonPropertyName("containerId")] + public long ContainerId { get; set; } + + [JsonPropertyName("scopeIdentifier")] + public Guid ScopeIdentifier { get; set; } + + [JsonPropertyName("path")] + public string Path { get; set; } + + [JsonPropertyName("itemType")] + public string ItemType { get; set; } + + [JsonPropertyName("status")] + public string Status { get; set; } + + [JsonPropertyName("dateCreated")] + public DateTimeOffset DateCreated { get; set; } + + [JsonPropertyName("dateLastModified")] + public DateTimeOffset DateLastModified { get; set; } + + [JsonPropertyName("createdBy")] + public Guid CreatedBy { get; set; } + + [JsonPropertyName("lastModifiedBy")] + public Guid LastModifiedBy { get; set; } + + [JsonPropertyName("itemLocation")] + public string ItemLocation { get; set; } + + [JsonPropertyName("contentLocation")] + public string ContentLocation { get; set; } + + [JsonPropertyName("contentId")] + public string ContentId { get; set; } + + [JsonPropertyName("fileLength")] + public long? FileLength { get; set; } + + [JsonPropertyName("fileEncoding")] + public long? FileEncoding { get; set; } + + [JsonPropertyName("fileType")] + public long? FileType { get; set; } + + [JsonPropertyName("fileId")] + public long? FileId { get; set; } + } +} diff --git a/src/Cake.Common/Build/GitHubActions/Commands/CreateArtifactParameters.cs b/src/Cake.Common/Build/GitHubActions/Commands/CreateArtifactParameters.cs new file mode 100644 index 0000000000..9930c25bbe --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Commands/CreateArtifactParameters.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Cake.Common.Build.GitHubActions.Commands +{ + internal sealed class CreateArtifactParameters + { + public string Name { get; set; } + + public string Type { get; set; } + + public CreateArtifactParameters(string name) + { + Name = name; + Type = "actions_storage"; + } + } +} diff --git a/src/Cake.Common/Build/GitHubActions/Commands/GitHubActionsCommands.cs b/src/Cake.Common/Build/GitHubActions/Commands/GitHubActionsCommands.cs new file mode 100644 index 0000000000..8eba25d7d2 --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Commands/GitHubActionsCommands.cs @@ -0,0 +1,425 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Threading.Tasks; +using Cake.Common.Build.GitHubActions.Data; +using Cake.Core; +using Cake.Core.IO; + +namespace Cake.Common.Build.GitHubActions.Commands +{ + /// + /// Provides GitHub Actions commands for a current build. + /// + public sealed class GitHubActionsCommands + { + private const string ApiVersion = "6.0-preview"; + private const string AcceptHeader = "application/json; api-version=" + ApiVersion; + private const string ContentTypeHeader = "application/json"; + private const string AcceptGzip = "application/octet-stream; api-version=" + ApiVersion; + private const string AcceptEncodingGzip = "gzip"; + + private readonly ICakeEnvironment _environment; + private readonly IFileSystem _fileSystem; + private readonly GitHubActionsEnvironmentInfo _actionsEnvironment; + private readonly Func _createHttpClient; + + /// + /// Initializes a new instance of the class. + /// + /// The environment. + /// The actions environment. + /// The file system. + /// The http client factory. + public GitHubActionsCommands( + ICakeEnvironment environment, + IFileSystem fileSystem, + GitHubActionsEnvironmentInfo actionsEnvironment, + Func createHttpClient) + { + _environment = environment ?? throw new ArgumentNullException(nameof(environment)); + _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); + _actionsEnvironment = actionsEnvironment ?? throw new ArgumentNullException(nameof(actionsEnvironment)); + _createHttpClient = createHttpClient ?? throw new ArgumentNullException(nameof(createHttpClient)); + } + + /// + /// Prepends a directory to the system PATH variable and automatically makes it available to all subsequent actions in the current job. + /// + /// The directory path. + public void AddPath(DirectoryPath path) + { + if (path is null) + { + throw new ArgumentNullException(nameof(path)); + } + + if (_actionsEnvironment.Runtime.SystemPath == null) + { + throw new CakeException("GitHub Actions Runtime SystemPath missing."); + } + + var file = _fileSystem.GetFile(_actionsEnvironment.Runtime.SystemPath); + using var stream = file.Open(FileMode.Append, FileAccess.Write, FileShare.None); + using var writer = new StreamWriter(stream); + writer.WriteLine(path.MakeAbsolute(_environment).FullPath); + } + + /// + /// Creates or updates an environment variable for any steps running next in a job. + /// + /// The key. + /// The Value. + public void SetEnvironmentVariable(string key, string value) + { + if (string.IsNullOrEmpty(key)) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value is null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (_actionsEnvironment.Runtime.EnvPath == null) + { + throw new CakeException("GitHub Actions Runtime EnvPath missing."); + } + + var file = _fileSystem.GetFile(_actionsEnvironment.Runtime.EnvPath); + using var stream = file.Open(FileMode.Append, FileAccess.Write, FileShare.None); + using var writer = new StreamWriter(stream); + writer.Write(key); + writer.WriteLine("< + /// Upload local file into a file container folder, and create an artifact. + /// + /// Path to the local file. + /// The artifact name. + /// A representing the asynchronous operation. + public async Task UploadArtifact(FilePath path, string artifactName) + { + var file = _fileSystem.GetFile(ValidateArtifactParameters(path, artifactName)); + + if (!file.Exists) + { + throw new FileNotFoundException("Artifact file not found.", file.Path.FullPath); + } + + await CreateAndUploadArtifactFiles(artifactName, file.Path.GetDirectory(), file); + } + + /// + /// Upload local directory files into a file container folder, and create an artifact. + /// + /// Path to the local directory. + /// The artifact name. + /// A representing the asynchronous operation. + public async Task UploadArtifact(DirectoryPath path, string artifactName) + { + var directory = _fileSystem.GetDirectory(ValidateArtifactParameters(path, artifactName)); + + if (!directory.Exists) + { + throw new DirectoryNotFoundException(FormattableString.Invariant($"Artifact directory {directory.Path.FullPath} not found.")); + } + + var files = directory + .GetFiles("*", SearchScope.Recursive) + .ToArray(); + + await CreateAndUploadArtifactFiles(artifactName, directory.Path, files); + } + + /// + /// Download remote artifact container into local directory. + /// + /// The artifact name. + /// Path to the local directory. + /// A representing the asynchronous operation. + public async Task DownloadArtifact(string artifactName, DirectoryPath path) + { + var directory = _fileSystem.GetDirectory(ValidateArtifactParameters(path, artifactName)); + + if (!directory.Exists) + { + throw new DirectoryNotFoundException(FormattableString.Invariant($"Local directory {directory.Path.FullPath} not found.")); + } + + var client = GetRuntimeHttpClient(); + + var artifactResourceUrl = await GetArtifactResourceUrl(client, artifactName); + + var containerItemResources = await GetContainerItemResources( + client, + directory.Path, + artifactName, + artifactResourceUrl); + + await DownloadItemResources(client, containerItemResources); + } + + private async Task DownloadItemResources(HttpClient client, (FilePath FilePath, string ContentLocation, long FileLength)[] containerItemResourceContent) + { + foreach (var (filePath, contentLocation, fileLength) in containerItemResourceContent) + { + await DownloadItemResource(client, filePath, contentLocation, fileLength); + } + } + + private async Task DownloadItemResource( + HttpClient client, + FilePath filePath, + string contentLocation, + long fileLength) + { + var contentDirectory = _fileSystem.GetDirectory(filePath.GetDirectory()); + + if (!contentDirectory.Exists) + { + contentDirectory.Create(); + } + + var contentFile = _fileSystem.GetFile(filePath); + + using var contentFileStream = contentFile.OpenWrite(); + + if (fileLength == 0) + { + return; + } + + using var contentResponse = await client.SendAsync( + new HttpRequestMessage( + HttpMethod.Get, + contentLocation) + { + Headers = + { + Accept = { MediaTypeWithQualityHeaderValue.Parse(AcceptGzip) }, + AcceptEncoding = { StringWithQualityHeaderValue.Parse(AcceptEncodingGzip) } + } + }); + + contentResponse.EnsureSuccessStatusCode(); + + using var contentResponseStream = await contentResponse.Content.ReadAsStreamAsync(); + + await contentResponseStream.CopyToAsync(contentFileStream); + } + + private async Task<(FilePath LocalPath, string ContentLocation, long FileLength)[]> GetContainerItemResources( + HttpClient client, + DirectoryPath path, + string artifactName, + string artifactResourceUrl) + { + using var resourceResponse = await client.GetAsync(artifactResourceUrl); + + resourceResponse.EnsureSuccessStatusCode(); + + using var resourceResponseStream = await resourceResponse.Content.ReadAsStreamAsync(); + + var containerItemResource = await JsonSerializer.DeserializeAsync>(resourceResponseStream); + + int artifactNameLength = artifactName.Length; + int relativePathStart = artifactNameLength + 1; + var containerItemResourceContent = + containerItemResource + ?.Value + .Where(content => content?.Path is string path + && path.Length > relativePathStart + && path[artifactNameLength] is char separator + && (separator == '/' || separator == '\\') + && path.StartsWith(artifactName) + && content.ItemType?.ToLowerInvariant() == "file") + .Select(content => (path.CombineWithFilePath(content.Path[relativePathStart..]), + content.ContentLocation, + content.FileLength ?? 0)) + .ToArray(); + + if (containerItemResourceContent == null || containerItemResourceContent.Length == 0) + { + throw new Exception($"Artifact \"{artifactName}\" content not found."); + } + + return containerItemResourceContent; + } + + private async Task GetArtifactResourceUrl(HttpClient client, string artifactName) + { + var artifactUrl = GetArtifactUrl(artifactName); + + using var containerResponse = await client.GetAsync(artifactUrl); + + containerResponse.EnsureSuccessStatusCode(); + + using var containerResponseStream = await containerResponse.Content.ReadAsStreamAsync(); + + var containerItems = await JsonSerializer.DeserializeAsync>(containerResponseStream); + + var artifactsLookup = (containerItems?.Value ?? Array.Empty()) + .Where(item => !string.IsNullOrWhiteSpace(item.FileContainerResourceUrl) + && !string.IsNullOrWhiteSpace(item.Name)) + .ToLookup( + key => key.Name, + item => string.Concat(item.FileContainerResourceUrl, "?itemPath=", Uri.EscapeDataString(item.Name))); + + return artifactsLookup[artifactName].FirstOrDefault() + ?? throw new Exception($"Artifact \"{artifactName}\" not found."); + } + + private T ValidateArtifactParameters(T path, string artifactName) where T : IPath + { + if (path is null) + { + throw new ArgumentNullException(nameof(path)); + } + + if (string.IsNullOrWhiteSpace(artifactName)) + { + throw new ArgumentNullException(nameof(artifactName)); + } + + if (string.IsNullOrWhiteSpace(_actionsEnvironment.Runtime.Token)) + { + throw new CakeException("GitHub Actions Runtime Token missing."); + } + + if (string.IsNullOrWhiteSpace(_actionsEnvironment.Runtime.Url)) + { + throw new CakeException("GitHub Actions Runtime Url missing."); + } + + if (string.IsNullOrWhiteSpace(_actionsEnvironment.Workflow.RunId)) + { + throw new CakeException("GitHub Actions Workflow RunId missing."); + } + + return path.MakeAbsolute(_environment); + } + + private async Task CreateAndUploadArtifactFiles( + string artifactName, + DirectoryPath rootPath, + params IFile[] files) + { + var artifactUrl = GetArtifactUrl(artifactName); + + var client = GetRuntimeHttpClient(); + + var artifactResponse = await CreateArtifact(artifactName, client, artifactUrl); + + long totalFileSize = 0L; + foreach (var file in files) + { + using var artifactStream = file.OpenRead(); + await UploadFile(rootPath, artifactName, artifactResponse, client, artifactStream, file); + totalFileSize += file.Length; + } + + await FinalizeArtifact(client, artifactUrl, totalFileSize); + } + + private string GetArtifactUrl(string artifactName) + { + return string.Concat( + _actionsEnvironment.Runtime.Url, + "_apis/pipelines/workflows/", + _actionsEnvironment.Workflow.RunId, + "/artifacts?api-version=", + ApiVersion, + "&artifactName=", + Uri.EscapeDataString(artifactName)); + } + + private HttpClient GetRuntimeHttpClient([System.Runtime.CompilerServices.CallerMemberName] string memberName = null) + { + var client = _createHttpClient(memberName); + client.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(AcceptHeader)); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _actionsEnvironment.Runtime.Token); + return client; + } + + private static async Task FinalizeArtifact(HttpClient client, string artifactUrl, long totalSize) + { + var jsonData = JsonSerializer.SerializeToUtf8Bytes(new PatchArtifactSize(totalSize)); + + var patchResponse = await client.SendAsync( + new HttpRequestMessage( + new HttpMethod("PATCH"), + artifactUrl) + { + Content = new ByteArrayContent(jsonData) + { + Headers = { ContentType = MediaTypeHeaderValue.Parse(ContentTypeHeader) } + } + }); + + patchResponse.EnsureSuccessStatusCode(); + } + + private static async Task UploadFile(DirectoryPath rootPath, string artifactName, ArtifactResponse artifactResponse, HttpClient client, Stream artifactStream, IFile file) + { + var itemPath = string.Concat( + artifactName, + "/", + rootPath.GetRelativePath(file.Path).FullPath); + + var putFileUrl = string.Concat( + artifactResponse?.FileContainerResourceUrl ?? throw new ArgumentNullException("FileContainerResourceUrl"), + $"?itemPath={Uri.EscapeDataString(itemPath)}"); + + var putResponse = await client.PutAsync( + putFileUrl, + new StreamContent(artifactStream) + { + Headers = + { + ContentType = MediaTypeHeaderValue.Parse("application/octet-stream"), + ContentLength = file.Length, + ContentRange = new ContentRangeHeaderValue(0, file.Length - 1L, file.Length) + } + }); + + if (!putResponse.IsSuccessStatusCode) + { + throw new CakeException( + FormattableString.Invariant($"Put artifact file {itemPath} failed."), + new HttpRequestException( + FormattableString.Invariant($"Response status code does not indicate success: {putResponse.StatusCode:d} ({putResponse.ReasonPhrase})."))); + } + } + + private static async Task CreateArtifact(string artifactName, HttpClient client, string artifactUrl) + { + var jsonData = JsonSerializer.SerializeToUtf8Bytes(new CreateArtifactParameters(artifactName)); + var response = await client.PostAsync( + artifactUrl, + new ByteArrayContent(jsonData) + { + Headers = { ContentType = MediaTypeHeaderValue.Parse(ContentTypeHeader) } + }); + + response.EnsureSuccessStatusCode(); + + using var responseStream = await response.Content.ReadAsStreamAsync(); + var artifactResponse = await JsonSerializer.DeserializeAsync(responseStream) + ?? throw new CakeException("Failed to parse ArtifactResponse"); + + return artifactResponse; + } + } +} diff --git a/src/Cake.Common/Build/GitHubActions/Commands/PatchArtifactSize.cs b/src/Cake.Common/Build/GitHubActions/Commands/PatchArtifactSize.cs new file mode 100644 index 0000000000..f70e245251 --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Commands/PatchArtifactSize.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Cake.Common.Build.GitHubActions.Commands +{ + internal sealed class PatchArtifactSize + { + public long Size { get; set; } + + public PatchArtifactSize(long size) + { + Size = size; + } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Build/GitHubActions/Commands/Values.cs b/src/Cake.Common/Build/GitHubActions/Commands/Values.cs new file mode 100644 index 0000000000..73c44ad61f --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Commands/Values.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json.Serialization; + +namespace Cake.Common.Build.GitHubActions.Commands +{ + internal sealed class Values + { + [JsonPropertyName("count")] + public long Count { get; set; } + + [JsonPropertyName("value")] + public T[] Value { get; set; } + } +} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildTaskStatus.cs b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsArchitecture.cs similarity index 50% rename from src/Cake.Common/Build/TFBuild/Data/TFBuildTaskStatus.cs rename to src/Cake.Common/Build/GitHubActions/Data/GitHubActionsArchitecture.cs index 547e9e5122..11cce1248b 100644 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildTaskStatus.cs +++ b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsArchitecture.cs @@ -1,32 +1,37 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Cake.Common.Build.TFBuild.Data +namespace Cake.Common.Build.GitHubActions.Data { /// - /// Provides the status of a TF Build task record. + /// The GitHub Actions Architecture. /// - public enum TFBuildTaskStatus + public enum GitHubActionsArchitecture { /// - /// Unknown status. + /// Unknown. /// Unknown, /// - /// Initialized status. + /// X86. /// - Initialized, + X86, /// - /// In progress status. + /// X64. /// - InProgress, + X64, /// - /// Completed status. + /// ARM. /// - Completed + ARM, + + /// + /// ARM64. + /// + ARM64 } } diff --git a/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsEnvironmentInfo.cs b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsEnvironmentInfo.cs index e5c4114ca3..3c363cd254 100644 --- a/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsEnvironmentInfo.cs +++ b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsEnvironmentInfo.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Cake.Core; +using Cake.Core.IO; namespace Cake.Common.Build.GitHubActions.Data { @@ -21,6 +22,7 @@ public GitHubActionsEnvironmentInfo(ICakeEnvironment environment) Runner = new GitHubActionsRunnerInfo(environment); Workflow = new GitHubActionsWorkflowInfo(environment); PullRequest = new GitHubActionsPullRequestInfo(environment); + Runtime = new GitHubActionsRuntimeInfo(environment); } /// @@ -61,7 +63,7 @@ public GitHubActionsEnvironmentInfo(ICakeEnvironment environment) /// } /// /// - public string Home => GetEnvironmentString("HOME"); + public DirectoryPath Home => GetEnvironmentDirectoryPath("HOME"); /// /// Gets GitHub Actions runner information. @@ -201,5 +203,25 @@ public GitHubActionsEnvironmentInfo(ICakeEnvironment environment) /// /// public GitHubActionsPullRequestInfo PullRequest { get; } + + /// + /// Gets GitHub Actions runtime information. + /// + /// + /// The GitHub Actions runtime information. + /// + /// Via BuildSystem. + /// + /// + /// // TODO + /// + /// + /// Via GitHubActions. + /// + /// + /// // TODO + /// + /// + public GitHubActionsRuntimeInfo Runtime { get; } } } diff --git a/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRefType.cs b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRefType.cs new file mode 100644 index 0000000000..a87288777f --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRefType.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Cake.Common.Build.GitHubActions.Data +{ + /// + /// The GitHub Actions Ref Type. + /// + public enum GitHubActionsRefType + { + /// + /// Unknown. + /// + Unknown, + + /// + /// Branch. + /// + Branch, + + /// + /// Tag. + /// + Tag + } +} diff --git a/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRunnerInfo.cs b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRunnerInfo.cs index 1bb31db6dc..9361d59993 100644 --- a/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRunnerInfo.cs +++ b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRunnerInfo.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Cake.Core; +using Cake.Core.IO; namespace Cake.Common.Build.GitHubActions.Data { @@ -20,6 +21,14 @@ public GitHubActionsRunnerInfo(ICakeEnvironment environment) { } + /// + /// Gets the name of the runner executing the job. + /// + /// + /// The name of the runner executing the job. + /// + public string Name => GetEnvironmentString("RUNNER_NAME"); + /// /// Gets the operating system of the runner executing the job. /// @@ -36,7 +45,7 @@ public GitHubActionsRunnerInfo(ICakeEnvironment environment) /// The path of the temporary directory for the runner. /// This directory is guaranteed to be empty at the start of each job, even on self-hosted runners. /// - public string Temp => GetEnvironmentString("RUNNER_TEMP"); + public DirectoryPath Temp => GetEnvironmentDirectoryPath("RUNNER_TEMP"); /// /// Gets the path of the directory containing some of the pre-installed tools for GitHub-hosted runners. @@ -44,7 +53,7 @@ public GitHubActionsRunnerInfo(ICakeEnvironment environment) /// /// The path of the directory containing some of the pre-installed tools for GitHub-hosted runners. /// - public string ToolCache => GetEnvironmentString("RUNNER_TOOL_CACHE"); + public DirectoryPath ToolCache => GetEnvironmentDirectoryPath("RUNNER_TOOL_CACHE"); /// /// Gets the runner workspace directory path. @@ -52,6 +61,46 @@ public GitHubActionsRunnerInfo(ICakeEnvironment environment) /// /// The runner workspace directory path. /// - public string Workspace => GetEnvironmentString("RUNNER_WORKSPACE"); + public DirectoryPath Workspace => GetEnvironmentDirectoryPath("RUNNER_WORKSPACE"); + + /// + /// Gets the runner image OS on hosted agents. + /// + /// + /// The runner image OS on hosted agents. + /// + public string ImageOS => GetEnvironmentString("ImageOS"); + + /// + /// Gets the runner image version on hosted agents. + /// + /// + /// The runner image version on hosted agents. + /// + public string ImageVersion => GetEnvironmentString("ImageVersion"); + + /// + /// Gets the runner user name. + /// + /// + /// The runner user name. + /// + public string User => GetEnvironmentString("RUNNER_USER"); + + /// + /// Gets the runner architecture of the runner executing the job. + /// + /// + /// The runner architecture of the runner executing the job. Possible values are X86, X64, ARM, and ARM64. + /// + public GitHubActionsArchitecture Architecture => GetEnvironmentString("RUNNER_ARCH") + ?.ToUpperInvariant() switch + { + "X86" => GitHubActionsArchitecture.X86, + "X64" => GitHubActionsArchitecture.X64, + "ARM" => GitHubActionsArchitecture.ARM, + "ARM64" => GitHubActionsArchitecture.ARM64, + _ => GitHubActionsArchitecture.Unknown + }; } } diff --git a/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRuntimeInfo.cs b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRuntimeInfo.cs new file mode 100644 index 0000000000..a09f0393d3 --- /dev/null +++ b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsRuntimeInfo.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Core; +using Cake.Core.IO; + +namespace Cake.Common.Build.GitHubActions.Data +{ + /// + /// Provides GitHub Actions runtime information for the current build. + /// + public sealed class GitHubActionsRuntimeInfo : GitHubActionsInfo + { + /// + /// Initializes a new instance of the class. + /// + /// The environment. + public GitHubActionsRuntimeInfo(ICakeEnvironment environment) + : base(environment) + { + } + + /// + /// Gets a value indicating whether the GitHub Actions Runtime is available for the current build. + /// + /// + /// true if the GitHub Actions Runtime is available for the current build. + /// + public bool IsRuntimeAvailable + => !string.IsNullOrWhiteSpace(Token) && !string.IsNullOrWhiteSpace(Url); + + /// + /// Gets the current runtime API authorization token. + /// + /// + /// The current runtime API authorization token. + /// + public string Token => GetEnvironmentString("ACTIONS_RUNTIME_TOKEN"); + + /// + /// Gets the current runtime API endpoint url. + /// + /// + /// The current runtime API endpoint url. + /// + public string Url => GetEnvironmentString("ACTIONS_RUNTIME_URL"); + + /// + /// Gets the path to environment file to set an environment variable that the following steps in a job can use. + /// + /// + /// The path to environment file to set an environment variable that the following steps in a job can use. + /// + public FilePath EnvPath => GetEnvironmentFilePath("GITHUB_ENV"); + + /// + /// Gets the path to path file to add a path to system path that the following steps in a job can use. + /// + /// + /// The path to path file to add a path to system path that the following steps in a job can use. + /// + public FilePath SystemPath => GetEnvironmentFilePath("GITHUB_PATH"); + } +} \ No newline at end of file diff --git a/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsWorkflowInfo.cs b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsWorkflowInfo.cs index ecf88e7cb3..aa89390058 100644 --- a/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsWorkflowInfo.cs +++ b/src/Cake.Common/Build/GitHubActions/Data/GitHubActionsWorkflowInfo.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Cake.Core; +using Cake.Core.IO; namespace Cake.Common.Build.GitHubActions.Data { @@ -28,6 +29,14 @@ public GitHubActionsWorkflowInfo(ICakeEnvironment environment) /// public string Action => GetEnvironmentString("GITHUB_ACTION"); + /// + /// Gets the path where your action is located. You can use this path to access files located in the same repository as your action. This variable is only supported in composite run steps actions. + /// + /// + /// The path where your action is located. You can use this path to access files located in the same repository as your action. This variable is only supported in composite run steps actions. + /// + public DirectoryPath ActionPath => GetEnvironmentDirectoryPath("GITHUB_ACTION_PATH"); + /// /// Gets the name of the person or app that initiated the workflow. /// @@ -36,6 +45,14 @@ public GitHubActionsWorkflowInfo(ICakeEnvironment environment) /// public string Actor => GetEnvironmentString("GITHUB_ACTOR"); + /// + /// Gets the API URL. + /// + /// + /// The API URL. For example: https://api.github.com. + /// + public string ApiUrl => GetEnvironmentString("GITHUB_API_URL"); + /// /// Gets the branch of the base repository. /// @@ -58,7 +75,15 @@ public GitHubActionsWorkflowInfo(ICakeEnvironment environment) /// /// The path of the file with the complete webhook event payload. /// - public string EventPath => GetEnvironmentString("GITHUB_EVENT_PATH"); + public FilePath EventPath => GetEnvironmentFilePath("GITHUB_EVENT_PATH"); + + /// + /// Gets the GraphQL API URL. + /// + /// + /// The GraphQL API URL. For example: https://api.github.com/graphql. + /// + public string GraphQLUrl => GetEnvironmentString("GITHUB_GRAPHQL_URL"); /// /// Gets the branch of the head repository. @@ -116,6 +141,14 @@ public GitHubActionsWorkflowInfo(ICakeEnvironment environment) /// public int RunNumber => GetEnvironmentInteger("GITHUB_RUN_NUMBER"); + /// + /// Gets the URL of the GitHub server. + /// + /// + /// The URL of the GitHub server. For example: https://github.com. + /// + public string ServerUrl => GetEnvironmentString("GITHUB_SERVER_URL"); + /// /// Gets the commit SHA that triggered the workflow. /// @@ -138,6 +171,44 @@ public GitHubActionsWorkflowInfo(ICakeEnvironment environment) /// /// The GitHub workspace directory path. /// - public string Workspace => GetEnvironmentString("GITHUB_WORKSPACE"); + public DirectoryPath Workspace => GetEnvironmentDirectoryPath("GITHUB_WORKSPACE"); + + /// + /// Gets the number of attempts for current run. + /// + /// + /// The attempt number for current run. + /// + public int Attempt => GetEnvironmentInteger("GITHUB_RUN_ATTEMPT"); + + /// + /// Gets a value indicating whether if branch protections are configured for the ref that triggered the workflow run. + /// + /// + /// Value whether if branch protections are configured for the ref that triggered the workflow run. + /// + public bool RefProtected => GetEnvironmentBoolean("GITHUB_REF_PROTECTED"); + + /// + /// Gets the branch or tag name that triggered the workflow run. + /// + /// + /// The branch or tag name that triggered the workflow run. + /// + public string RefName => GetEnvironmentString("GITHUB_REF_NAME"); + + /// + /// Gets the type of ref that triggered the workflow run. + /// + /// + /// The type of ref that triggered the workflow run. Valid values are branch or tag. + /// + public GitHubActionsRefType RefType => GetEnvironmentString("GITHUB_REF_TYPE") + ?.ToLowerInvariant() switch + { + "branch" => GitHubActionsRefType.Branch, + "tag" => GitHubActionsRefType.Tag, + _ => GitHubActionsRefType.Unknown + }; } } diff --git a/src/Cake.Common/Build/GitHubActions/GitHubActionsInfo.cs b/src/Cake.Common/Build/GitHubActions/GitHubActionsInfo.cs index 5bb2fd1d08..1c0ce6f64a 100644 --- a/src/Cake.Common/Build/GitHubActions/GitHubActionsInfo.cs +++ b/src/Cake.Common/Build/GitHubActions/GitHubActionsInfo.cs @@ -4,6 +4,7 @@ using System; using Cake.Core; +using Cake.Core.IO; namespace Cake.Common.Build.GitHubActions { @@ -24,7 +25,7 @@ protected GitHubActionsInfo(ICakeEnvironment environment) } /// - /// Gets an environment variable as a . + /// Gets an environment variable as a . /// /// The environment variable name. /// The environment variable. @@ -33,6 +34,30 @@ protected string GetEnvironmentString(string variable) return _environment.GetEnvironmentVariable(variable) ?? string.Empty; } + /// + /// Gets an environment variable as a . + /// + /// The environment variable name. + /// The environment variable. + protected DirectoryPath GetEnvironmentDirectoryPath(string variable) + { + return _environment.GetEnvironmentVariable(variable) is string value + ? DirectoryPath.FromString(value) + : null; + } + + /// + /// Gets an environment variable as a . + /// + /// The environment variable name. + /// The environment variable. + protected FilePath GetEnvironmentFilePath(string variable) + { + return _environment.GetEnvironmentVariable(variable) is string value + ? FilePath.FromString(value) + : null; + } + /// /// Gets an environment variable as a . /// diff --git a/src/Cake.Common/Build/GitHubActions/GitHubActionsProvider.cs b/src/Cake.Common/Build/GitHubActions/GitHubActionsProvider.cs index aa951bb8aa..f8b600c8e3 100644 --- a/src/Cake.Common/Build/GitHubActions/GitHubActionsProvider.cs +++ b/src/Cake.Common/Build/GitHubActions/GitHubActionsProvider.cs @@ -3,8 +3,10 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Build.GitHubActions.Commands; using Cake.Common.Build.GitHubActions.Data; using Cake.Core; +using Cake.Core.IO; namespace Cake.Common.Build.GitHubActions { @@ -19,26 +21,21 @@ public class GitHubActionsProvider : IGitHubActionsProvider /// Initializes a new instance of the class. /// /// The environment. - public GitHubActionsProvider(ICakeEnvironment environment) + /// The file system. + public GitHubActionsProvider(ICakeEnvironment environment, IFileSystem fileSystem) { _environment = environment ?? throw new ArgumentNullException(nameof(environment)); Environment = new GitHubActionsEnvironmentInfo(environment); + Commands = new GitHubActionsCommands(environment, fileSystem, Environment, _ => new System.Net.Http.HttpClient()); } - /// - /// Gets a value indicating whether the current build is running on GitHub Actions. - /// - /// - /// true if the current build is running on GitHub Actions; otherwise, false. - /// + /// public bool IsRunningOnGitHubActions => _environment.GetEnvironmentVariable("GITHUB_ACTIONS")?.Equals("true", StringComparison.OrdinalIgnoreCase) ?? false; - /// - /// Gets the GitHub Actions environment. - /// - /// - /// The GitHub Actions environment. - /// + /// public GitHubActionsEnvironmentInfo Environment { get; } + + /// + public GitHubActionsCommands Commands { get; } } } diff --git a/src/Cake.Common/Build/GitHubActions/IGitHubActionsProvider.cs b/src/Cake.Common/Build/GitHubActions/IGitHubActionsProvider.cs index edb4c446fd..32ae3fb917 100644 --- a/src/Cake.Common/Build/GitHubActions/IGitHubActionsProvider.cs +++ b/src/Cake.Common/Build/GitHubActions/IGitHubActionsProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Build.GitHubActions.Commands; using Cake.Common.Build.GitHubActions.Data; namespace Cake.Common.Build.GitHubActions @@ -26,5 +27,13 @@ public interface IGitHubActionsProvider /// The GitHub Actions environment. /// GitHubActionsEnvironmentInfo Environment { get; } + + /// + /// Gets the GitHub Actions commands. + /// + /// + /// The GitHub Actions commands. + /// + public GitHubActionsCommands Commands { get; } } } diff --git a/src/Cake.Common/Build/GitLabCI/GitLabCIProvider.cs b/src/Cake.Common/Build/GitLabCI/GitLabCIProvider.cs index e61d2b6e53..3228dcc195 100644 --- a/src/Cake.Common/Build/GitLabCI/GitLabCIProvider.cs +++ b/src/Cake.Common/Build/GitLabCI/GitLabCIProvider.cs @@ -25,20 +25,10 @@ public GitLabCIProvider(ICakeEnvironment environment) Environment = new GitLabCIEnvironmentInfo(environment); } - /// - /// Gets a value indicating whether the current build is running on GitLab CI. - /// - /// - /// true if the current build is running on GitLab CI; otherwise, false. - /// + /// public bool IsRunningOnGitLabCI => _environment.GetEnvironmentVariable("CI_SERVER")?.Equals("yes", StringComparison.OrdinalIgnoreCase) ?? false; - /// - /// Gets the GitLab CI environment. - /// - /// - /// The GitLab CI environment. - /// + /// public GitLabCIEnvironmentInfo Environment { get; } } } diff --git a/src/Cake.Common/Build/GoCD/GoCDProvider.cs b/src/Cake.Common/Build/GoCD/GoCDProvider.cs index 63e5ecd0c9..d9de5da232 100644 --- a/src/Cake.Common/Build/GoCD/GoCDProvider.cs +++ b/src/Cake.Common/Build/GoCD/GoCDProvider.cs @@ -35,40 +35,19 @@ public GoCDProvider(ICakeEnvironment environment, ICakeLog log) Environment = new GoCDEnvironmentInfo(environment); } - /// - /// Gets a value indicating whether the current build is running on Go.CD. - /// - /// - /// true if the current build is running on Go.CD.; otherwise, false. - /// + /// public bool IsRunningOnGoCD => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("GO_SERVER_URL")); - /// - /// Gets the Go.CD environment. - /// - /// - /// The Go.CD environment. - /// + /// public GoCDEnvironmentInfo Environment { get; } - /// - /// Gets the Go.CD build history, including the repository modifications that caused the pipeline to start. - /// - /// The Go.CD username. - /// The Go.CD password. - /// The Go.CD build history. + /// public GoCDHistoryInfo GetHistory(string username, string password) { return GetHistory(username, password, Environment.GoCDUrl); } - /// - /// Gets the Go.CD build history, including the repository modifications that caused the pipeline to start. - /// - /// The Go.CD username. - /// The Go.CD password. - /// The Go.CD server URL. - /// The Go.CD build history. + /// public GoCDHistoryInfo GetHistory(string username, string password, string serverUrl) { if (username == null) diff --git a/src/Cake.Common/Build/IBuildSystemServiceMessageWriter.cs b/src/Cake.Common/Build/IBuildSystemServiceMessageWriter.cs index ebbd4c27f1..f0ebcfaad8 100644 --- a/src/Cake.Common/Build/IBuildSystemServiceMessageWriter.cs +++ b/src/Cake.Common/Build/IBuildSystemServiceMessageWriter.cs @@ -20,6 +20,7 @@ internal sealed class BuildSystemServiceMessageWriter : IBuildSystemServiceMessa public void Write(string format, params object[] args) { Console.Out.WriteLine(format, args); + Console.Out.Flush(); } } } diff --git a/src/Cake.Common/Build/Jenkins/JenkinsProvider.cs b/src/Cake.Common/Build/Jenkins/JenkinsProvider.cs index 2cdf918bf0..b59853e1c1 100644 --- a/src/Cake.Common/Build/Jenkins/JenkinsProvider.cs +++ b/src/Cake.Common/Build/Jenkins/JenkinsProvider.cs @@ -25,20 +25,10 @@ public JenkinsProvider(ICakeEnvironment environment) Environment = new JenkinsEnvironmentInfo(_environment); } - /// - /// Gets a value indicating whether this instance is running on jenkins. - /// - /// - /// true if this instance is running on jenkins; otherwise, false. - /// + /// public bool IsRunningOnJenkins => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("JENKINS_URL")); - /// - /// Gets the Jenkins environment. - /// - /// - /// The Jenkins environment. - /// + /// public JenkinsEnvironmentInfo Environment { get; } } } \ No newline at end of file diff --git a/src/Cake.Common/Build/MyGet/MyGetProvider.cs b/src/Cake.Common/Build/MyGet/MyGetProvider.cs index e3718dee7f..9610b7f92b 100644 --- a/src/Cake.Common/Build/MyGet/MyGetProvider.cs +++ b/src/Cake.Common/Build/MyGet/MyGetProvider.cs @@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; +using System.Text; using Cake.Core; namespace Cake.Common.Build.MyGet @@ -19,22 +20,25 @@ public sealed class MyGetProvider : IMyGetProvider private const string MessagePrefix = "##myget["; private const string MessagePostfix = "]"; - private static readonly Dictionary _sanitizationTokens; + private static readonly Dictionary _sanitizationTokens; + private static readonly char[] _specialCharacters; private readonly ICakeEnvironment _environment; private readonly IBuildSystemServiceMessageWriter _writer; static MyGetProvider() { - _sanitizationTokens = new Dictionary + _sanitizationTokens = new Dictionary { - { "|", "||" }, - { "\'", "|\'" }, - { "\n", "|n" }, - { "\r", "|r" }, - { "[", "|['" }, - { "]", "|]" } + { '|', "||" }, + { '\'', "|\'" }, + { '\n', "|n" }, + { '\r', "|r" }, + { '[', "|[" }, + { ']', "|]" } }; + + _specialCharacters = _sanitizationTokens.Keys.ToArray(); } /// @@ -48,12 +52,7 @@ public MyGetProvider(ICakeEnvironment environment, IBuildSystemServiceMessageWri _writer = writer ?? throw new ArgumentNullException(nameof(writer)); } - /// - /// Gets a value indicating whether the current build is running on MyGet. - /// - /// - /// true if the current build is running on MyGet; otherwise, false. - /// + /// public bool IsRunningOnMyGet { get @@ -63,20 +62,13 @@ public bool IsRunningOnMyGet } } - /// - /// Report a build problem to MyGet. - /// - /// Description of build problem. + /// public void BuildProblem(string description) { WriteServiceMessage("buildProblem", "description", description); } - /// - /// Allows setting an environment variable that can be used by a future process. - /// - /// Name of the parameter to set. - /// Value to assign to the parameter. + /// public void SetParameter(string name, string value) { WriteServiceMessage("setParameter", new Dictionary @@ -86,12 +78,7 @@ public void SetParameter(string name, string value) }); } - /// - /// Write a status message to the MyGet build log. - /// - /// Message contents. - /// Build status. - /// Error details if status is error. + /// public void WriteStatus(string message, MyGetBuildStatus status, string errorDetails = null) { var statusToWrite = string.Empty; @@ -126,10 +113,7 @@ public void WriteStatus(string message, MyGetBuildStatus status, string errorDet WriteServiceMessage("message", attrs); } - /// - /// Tells MyGet to change the current build number. - /// - /// The required build number. + /// public void SetBuildNumber(string buildNumber) { WriteServiceMessage("buildNumber", buildNumber); @@ -137,7 +121,7 @@ public void SetBuildNumber(string buildNumber) private void WriteServiceMessage(string messageName, string attributeValue) { - WriteServiceMessage(messageName, new Dictionary { { " ", attributeValue } }); + WriteServiceMessage(messageName, new Dictionary { { string.Empty, attributeValue } }); } private void WriteServiceMessage(string messageName, string attributeName, string attributeValue) @@ -153,11 +137,12 @@ private void WriteServiceMessage(string messageName, Dictionary values .Select(keypair => { - if (string.IsNullOrWhiteSpace(keypair.Key)) + var sanitizedValue = Sanitize(keypair.Value); + if (string.IsNullOrEmpty(keypair.Key)) { - return string.Format(CultureInfo.InvariantCulture, "'{0}'", Sanitize(keypair.Value)); + return string.Format(CultureInfo.InvariantCulture, "'{0}'", sanitizedValue); } - return string.Format(CultureInfo.InvariantCulture, "{0}='{1}'", keypair.Key, Sanitize(keypair.Value)); + return string.Format(CultureInfo.InvariantCulture, "{0}='{1}'", keypair.Key, sanitizedValue); }) .ToArray()); @@ -166,12 +151,33 @@ private void WriteServiceMessage(string messageName, Dictionary private static string Sanitize(string source) { - foreach (var charPair in _sanitizationTokens) + if (string.IsNullOrEmpty(source)) + { + return string.Empty; + } + + // When source does not contain special characters, then it is possible to skip building new string. + // This approach can possibly iterate through string 2 times, but special characters are exceptional. + if (source.IndexOfAny(_specialCharacters) < 0) + { + return source; + } + + var stringBuilder = new StringBuilder(source.Length * 2); + for (int index = 0; index < source.Length; index++) { - source = source.Replace(charPair.Key, charPair.Value); + char sourceChar = source[index]; + if (_sanitizationTokens.TryGetValue(sourceChar, out var replacement)) + { + stringBuilder.Append(replacement); + } + else + { + stringBuilder.Append(sourceChar); + } } - return source; + return stringBuilder.ToString(); } } } \ No newline at end of file diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildAgentInfo.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildAgentInfo.cs deleted file mode 100644 index 20a38eaa40..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildAgentInfo.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Core; -using Cake.Core.IO; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides TF Build agent info for the current build and build agent. - /// - public sealed class TFBuildAgentInfo : TFInfo - { - /// - /// Initializes a new instance of the class. - /// - /// The environment. - public TFBuildAgentInfo(ICakeEnvironment environment) - : base(environment) - { - } - - /// - /// Gets the local path on the agent where all folders for a given build definition are created. - /// - /// - /// The local path on the agent where all folders for a given build definition are created. - /// - /// c:\agent\_work\1. - public FilePath BuildDirectory => GetEnvironmentString("AGENT_BUILDDIRECTORY"); - - /// - /// Gets the directory the agent is installed into. This contains the agent software. - /// - /// If you are using a self-hosted agent, this directory is specified by you. - /// - /// The directory the agent is installed into. - /// - /// c:\agent\. - public FilePath HomeDirectory => GetEnvironmentString("AGENT_HOMEDIRECTORY"); - - /// - /// Gets the working directory for this agent. - /// - /// - /// The working directory for this agent. - /// - public FilePath WorkingDirectory => GetEnvironmentString("AGENT_WORKFOLDER"); - - /// - /// Gets the ID of the agent. - /// - /// - /// The ID of the agent. - /// - public int Id => GetEnvironmentInteger("AGENT_ID"); - - /// - /// Gets the display name of the running job. - /// - /// - /// The display name of the running job. - /// - public string JobName => GetEnvironmentString("AGENT_JOBNAME"); - - /// - /// Gets the status of the build. - /// - /// - /// The status of the build. - /// - public string JobStatus => GetEnvironmentString("AGENT_JOBSTATUS"); - - /// - /// Gets the name of the agent that is registered with the pool. - /// - /// If you are using a self-hosted agent, this is specified by you. - /// - /// The name of the agent that is registered with the pool. - /// - public string Name => GetEnvironmentString("AGENT_NAME"); - - /// - /// Gets the name of the machine on which the agent is installed. - /// - /// - /// The name of the machine on which the agent is installed. - /// - public string MachineName => GetEnvironmentString("AGENT_MACHINENAME"); - - /// - /// Gets the directory used by tasks such as Node Tool Installer and Use Python Version to switch between multiple versions of a tool. - /// - /// - /// These tasks will add tools from this directory to PATH so that subsequent build steps can use them. - /// - /// - /// The task directory. - /// - public FilePath ToolsDirectory => GetEnvironmentString("AGENT_TOOLSDIRECTORY"); - - /// - /// Gets a value indicating whether the current agent is a hosted agent. - /// - /// - /// true if the current agent is a hosted agent; otherwise, false. - /// - public bool IsHosted => Name != null && (Name.StartsWith("Hosted") || Name.StartsWith("Azure Pipelines")); - } -} \ No newline at end of file diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildArtifactType.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildArtifactType.cs deleted file mode 100644 index 692293c10a..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildArtifactType.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides the type of a TF Build artifact. - /// - public enum TFBuildArtifactType - { - /// - /// The container type. - /// - Container, - - /// - /// The file path type. - /// - FilePath, - - /// - /// The version control path type. - /// - VersionControl, - - /// - /// The Git reference type. - /// - GitRef, - - /// - /// The TFVC label type. - /// - TFVCLabel - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildDefinitionInfo.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildDefinitionInfo.cs deleted file mode 100644 index 9a8dcd300b..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildDefinitionInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Core; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides TF Build Definition information for the current build. - /// - public sealed class TFBuildDefinitionInfo : TFInfo - { - /// - /// Initializes a new instance of the class. - /// - /// The environment. - public TFBuildDefinitionInfo(ICakeEnvironment environment) - : base(environment) - { - } - - /// - /// Gets the build definition ID. - /// - /// - /// The build definition ID. - /// - public int Id => GetEnvironmentInteger("SYSTEM_DEFINITIONID"); - - /// - /// Gets the build definition name. - /// - /// - /// The build definition name. - /// - public string Name => GetEnvironmentString("BUILD_DEFINITIONNAME"); - - /// - /// Gets the build definition version. - /// - /// - /// The build definition version. - /// - public int Version => GetEnvironmentInteger("BUILD_DEFINITIONVERSION"); - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildEnvironmentInfo.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildEnvironmentInfo.cs deleted file mode 100644 index 30f39f8341..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildEnvironmentInfo.cs +++ /dev/null @@ -1,321 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Core; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides TF Build Environment information for the current build. - /// - public sealed class TFBuildEnvironmentInfo : TFInfo - { - /// - /// Initializes a new instance of the class. - /// - /// The environment. - public TFBuildEnvironmentInfo(ICakeEnvironment environment) - : base(environment) - { - Repository = new TFBuildRepositoryInfo(environment); - BuildDefinition = new TFBuildDefinitionInfo(environment); - Build = new TFBuildInfo(environment); - PullRequest = new TFBuildPullRequestInfo(environment); - Agent = new TFBuildAgentInfo(environment); - TeamProject = new TFBuildTeamProjectInfo(environment); - } - - /// - /// Gets TF Build repository information. - /// - /// - /// The TF Build repository information. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"Repository: - /// Branch: {0} - /// SourceVersion: {1} - /// Shelveset: {2}", - /// BuildSystem.TFBuild.Environment.Repository.Branch, - /// BuildSystem.TFBuild.Environment.Repository.SourceVersion, - /// BuildSystem.TFBuild.Environment.Repository.Shelveset - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - /// Via TFBuild. - /// - /// - /// if (TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"Repository: - /// Branch: {0} - /// SourceVersion: {1} - /// Shelveset: {2}", - /// TFBuild.Environment.Repository.Branch, - /// TFBuild.Environment.Repository.SourceVersion, - /// TFBuild.Environment.Repository.Shelveset - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - public TFBuildRepositoryInfo Repository { get; } - - /// - /// Gets TF Build Definition information. - /// - /// - /// The TF Build Definition. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"BuildDefinition: - /// Id: {0} - /// Name: {1} - /// Version: {2}", - /// BuildSystem.TFBuild.Environment.BuildDefinition.Id, - /// BuildSystem.TFBuild.Environment.BuildDefinition.Name, - /// BuildSystem.TFBuild.Environment.BuildDefinition.Version - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - /// Via TFBuild. - /// - /// - /// if (TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"BuildDefinition: - /// Id: {0} - /// Name: {1} - /// Version: {2}", - /// TFBuild.Environment.BuildDefinition.Id, - /// TFBuild.Environment.BuildDefinition.Name, - /// TFBuild.Environment.BuildDefinition.Version - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - public TFBuildDefinitionInfo BuildDefinition { get; } - - /// - /// Gets TF Build information. - /// - /// - /// The TF Build. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"Build: - /// Id: {0} - /// Number: {1} - /// QueuedBy: {2}", - /// BuildSystem.TFBuild.Environment.Build.Id, - /// BuildSystem.TFBuild.Environment.Build.Number, - /// BuildSystem.TFBuild.Environment.Build.QueuedBy - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - /// Via TFBuild. - /// - /// - /// if (TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"Build: - /// Id: {0} - /// Number: {1} - /// QueuedBy: {2}", - /// TFBuild.Environment.Build.Id, - /// TFBuild.Environment.Build.Number, - /// TFBuild.Environment.Build.QueuedBy - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - public TFBuildInfo Build { get; } - - /// - /// Gets TF Build pull request information. - /// - /// - /// The TF Build pull request information. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"PullRequest: - /// IsPullRequest: {0} - /// Id: {1} - /// Number: {2}", - /// BuildSystem.TFBuild.Environment.PullRequest.IsPullRequest, - /// BuildSystem.TFBuild.Environment.PullRequest.Id, - /// BuildSystem.TFBuild.Environment.PullRequest.Number - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - /// Via TFBuild. - /// - /// - /// if (TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"PullRequest: - /// IsPullRequest: {0} - /// Id: {1} - /// Number: {2}", - /// TFBuild.Environment.PullRequest.IsPullRequest, - /// TFBuild.Environment.PullRequest.Id, - /// TFBuild.Environment.PullRequest.Number - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - public TFBuildPullRequestInfo PullRequest { get; } - - /// - /// Gets TF Team Project information. - /// - /// - /// The TF Team Project. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"TeamProject: - /// Id: {0} - /// Name: {1}", - /// BuildSystem.TFBuild.Environment.TeamProject.Id, - /// BuildSystem.TFBuild.Environment.TeamProject.Name - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - /// Via TFBuild. - /// - /// - /// if (TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"TeamProject: - /// Id: {0} - /// Name: {1}", - /// TFBuild.Environment.TeamProject.Id, - /// TFBuild.Environment.TeamProject.Name - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - public TFBuildTeamProjectInfo TeamProject { get; } - - /// - /// Gets TF Build agent information. - /// - /// - /// The TF Build agent. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"Agent: - /// Id: {0} - /// Name: {1}", - /// BuildSystem.TFBuild.Environment.Agent.Id, - /// BuildSystem.TFBuild.Environment.Agent.Name - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - /// Via TFBuild. - /// - /// - /// if (TFBuild.IsRunningOnTFBuild) - /// { - /// Information( - /// @"Agent: - /// Id: {0} - /// Name: {1}", - /// TFBuild.Environment.Agent.Id, - /// TFBuild.Environment.Agent.Name - /// ); - /// } - /// else - /// { - /// Information("Not running on TFBuild"); - /// } - /// - /// - public TFBuildAgentInfo Agent { get; } - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildInfo.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildInfo.cs deleted file mode 100644 index e3815607f7..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildInfo.cs +++ /dev/null @@ -1,151 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Core; -using Cake.Core.IO; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides TF Build info for the current build. - /// - public sealed class TFBuildInfo : TFInfo - { - /// - /// Initializes a new instance of the class. - /// - /// The environment. - public TFBuildInfo(ICakeEnvironment environment) - : base(environment) - { - TriggeredBy = new TFBuildTriggeredBy(environment); - } - - /// - /// Gets the a special variable that carries the security token used by the running build. - /// - /// - /// The security token. - /// - public string AccessToken => GetEnvironmentString("SYSTEM_ACCESSTOKEN"); - - /// - /// Gets a value indicating whether more detailed logs to debug pipeline problems is enabled. - /// - /// - /// True if more detailed logs are enabled. - /// - public bool Debug => GetEnvironmentBoolean("SYSTEM_DEBUG"); - - /// - /// Gets the local path on the agent where any artifacts are copied to before being pushed to their destination. - /// - /// - /// The path of the staging directory. - /// - public FilePath ArtifactStagingDirectory => GetEnvironmentString("BUILD_ARTIFACTSTAGINGDIRECTORY"); - - /// - /// Gets the local path on the agent you can use as an output folder for compiled binaries. - /// - /// - /// The path to the binaries directory. - /// - public FilePath BinariesDirectory => GetEnvironmentString("BUILD_BINARIESDIRECTORY"); - - /// - /// Gets the ID of the record for the completed build. - /// - /// - /// The ID of the record for the completed build. - /// - public int Id => GetEnvironmentInteger("BUILD_BUILDID"); - - /// - /// Gets the name of the completed build. - /// - /// You can specify the build number format that generates this value in the build definition. - /// - /// The name of the completed build. - /// - public string Number => GetEnvironmentString("BUILD_BUILDNUMBER"); - - /// - /// Gets the URI for the build. - /// - /// vstfs:///Build/Build/1430. - /// - /// The URI for the build. - /// - public Uri Uri => new Uri(GetEnvironmentString("BUILD_BUILDURI")); - - /// - /// Gets the user who queued the build. - /// - /// - /// The user who queued the build. - /// - public string QueuedBy => GetEnvironmentString("BUILD_QUEUEDBY"); - - /// - /// Gets the event that caused the build to run. - /// - /// - /// The event name. - /// - public string Reason => GetEnvironmentString("BUILD_REASON"); - - /// - /// Gets the user the build was requested for. - /// - /// - /// The user the build was requested for. - /// - public string RequestedFor => GetEnvironmentString("BUILD_REQUESTEDFOR"); - - /// - /// Gets the email of the user the build was requested for. - /// - /// - /// The email of the user the build was requested for. - /// - public string RequestedForEmail => GetEnvironmentString("BUILD_REQUESTEDFOREMAIL"); - - /// - /// Gets the local path on the agent where your source code files are downloaded. - /// - /// - /// The source code directory. - /// - public FilePath SourcesDirectory => GetEnvironmentString("BUILD_SOURCESDIRECTORY"); - - /// - /// Gets the local path on the agent where any artifacts are copied to before being pushed to their destination. - /// - /// - /// The staging directory. - /// - public FilePath StagingDirectory => GetEnvironmentString("BUILD_STAGINGDIRECTORY"); - - /// - /// Gets local path on the agent where the test results are created. - /// - /// - /// The test result directory. - /// - public FilePath TestResultsDirectory => GetEnvironmentString("COMMON_TESTRESULTSDIRECTORY"); - - /// - /// Gets TF Build TriggeredBy information. - /// - /// - /// This is only populated if the build was triggered by another build. - /// - /// - /// The TF Build Trigger information. - /// - public TFBuildTriggeredBy TriggeredBy { get; } - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildMessageData.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildMessageData.cs deleted file mode 100644 index 3558857979..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildMessageData.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides optional data associated with a TF Build logging message. - /// - public sealed class TFBuildMessageData - { - /// - /// Gets or sets the source file path the message should originate from. - /// - /// - /// The path of the originating file. - /// - public string SourcePath { get; set; } - - /// - /// Gets or sets the line number the message relates to. - /// - /// - /// The line number. - /// - public int? LineNumber { get; set; } - - /// - /// Gets or sets the column number the message relates to. - /// - /// - /// The column number. - /// - public int? ColumnNumber { get; set; } - - /// - /// Gets or sets the error code of the warning or error message. - /// - /// - /// The error code of the warning or error. - /// - public int? ErrorCode { get; set; } - - internal Dictionary GetProperties() - { - var properties = new Dictionary(); - if (!string.IsNullOrWhiteSpace(SourcePath)) - { - properties.Add("sourcepath", SourcePath); - } - if (LineNumber.HasValue) - { - properties.Add("linenumber", LineNumber.ToString()); - } - if (ColumnNumber.HasValue) - { - properties.Add("columnnumber", ColumnNumber.ToString()); - } - if (ErrorCode.HasValue) - { - properties.Add("code", ErrorCode.ToString()); - } - return properties; - } - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildPublishCodeCoverageData.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildPublishCodeCoverageData.cs deleted file mode 100644 index 5bc484f97f..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildPublishCodeCoverageData.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Cake.Core; -using Cake.Core.IO; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Providers TF Build agent for publishing code coverage results. - /// - public class TFBuildPublishCodeCoverageData - { - /// - /// Gets or Sets the tool from which code coverage results are generated. - /// - public TFCodeCoverageToolType? CodeCoverageTool { get; set; } - - /// - /// Gets or Sets the path of the summary file containing code coverage statistics, such as line, method, and class coverage. - /// - public FilePath SummaryFileLocation { get; set; } - - /// - /// Gets or Sets the Path of the code coverage HTML report directory. The report directory is published for later viewing as an artifact of the build. - /// - public DirectoryPath ReportDirectory { get; set; } - - /// - /// Gets or Sets the file paths for any additional code coverage files to be published as artifacts of the build. - /// - public FilePath[] AdditionalCodeCoverageFiles { get; set; } - - internal Dictionary GetProperties(ICakeEnvironment environment, FilePath summaryFilePath = null) - { - if (environment == null) - { - throw new ArgumentNullException(nameof(environment)); - } - - var properties = new Dictionary(); - - if (CodeCoverageTool.HasValue) - { - properties.Add("codecoveragetool", CodeCoverageTool.Value.ToString()); - } - - if (summaryFilePath != null) - { - properties.Add("summaryfile", - summaryFilePath - .MakeAbsolute(environment) - .FullPath - .Replace(summaryFilePath.Separator, System.IO.Path.DirectorySeparatorChar)); - } - - if (SummaryFileLocation != null && summaryFilePath == null) - { - properties.Add("summaryfile", - SummaryFileLocation - .MakeAbsolute(environment) - .FullPath - .Replace(SummaryFileLocation.Separator, System.IO.Path.DirectorySeparatorChar)); - } - - if (ReportDirectory != null) - { - properties.Add("reportdirectory", - ReportDirectory - .MakeAbsolute(environment) - .FullPath - .Replace(ReportDirectory.Separator, System.IO.Path.DirectorySeparatorChar)); - } - - if (AdditionalCodeCoverageFiles != null && AdditionalCodeCoverageFiles.Any()) - { - properties.Add("additionalcodecoveragefiles", - string.Join(",", - AdditionalCodeCoverageFiles - .Select(filePath => - filePath - .MakeAbsolute(environment) - .FullPath - .Replace(filePath.Separator, System.IO.Path.DirectorySeparatorChar)))); - } - - return properties; - } - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildPublishTestResultsData.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildPublishTestResultsData.cs deleted file mode 100644 index 147789e798..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildPublishTestResultsData.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Cake.Core; -using Cake.Core.IO; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides TF Build agent info for publishing test results. - /// - public class TFBuildPublishTestResultsData - { - /// - /// Gets or Sets the type test runner the results are formatted in. - /// - public TFTestRunnerType? TestRunner { get; set; } - - /// - /// Gets or sets the list of Test Result files to publish. - /// - public ICollection TestResultsFiles { get; set; } = new List(); - - /// - /// Gets or Sets whether to merge all Test Result Files into one run. - /// - public bool? MergeTestResults { get; set; } - - /// - /// Gets or Sets the Platform for which the tests were run on. - /// - public string Platform { get; set; } - - /// - /// Gets or Sets the configuration for which the tests were run on. - /// - public string Configuration { get; set; } - - /// - /// Gets or Sets a name for the Test Run. - /// - public string TestRunTitle { get; set; } - - /// - /// Gets or Sets whether to opt in/out of publishing test run level attachments. - /// - public bool? PublishRunAttachments { get; set; } - - internal Dictionary GetProperties(ICakeEnvironment environment) - { - if (environment == null) - { - throw new ArgumentNullException(nameof(environment)); - } - - var properties = new Dictionary(); - - if (TestRunner.HasValue) - { - properties.Add("type", TestRunner.Value.ToString()); - } - if (MergeTestResults.HasValue) - { - properties.Add("mergeResults", MergeTestResults.ToString().ToLowerInvariant()); - } - if (!string.IsNullOrWhiteSpace(Platform)) - { - properties.Add("platform", Platform); - } - if (!string.IsNullOrWhiteSpace(Configuration)) - { - properties.Add("config", Configuration); - } - if (!string.IsNullOrWhiteSpace(TestRunTitle)) - { - properties.Add("runTitle", $"'{TestRunTitle}'"); - } - if (PublishRunAttachments.HasValue) - { - properties.Add("publishRunAttachments", PublishRunAttachments.ToString().ToLowerInvariant()); - } - if (TestResultsFiles != null && TestResultsFiles.Any()) - { - properties.Add("resultFiles", - string.Join(",", - TestResultsFiles.Select(filePath => - filePath - .MakeAbsolute(environment) - .FullPath - .Replace(filePath.Separator, System.IO.Path.DirectorySeparatorChar)))); - } - - return properties; - } - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildPullRequestInfo.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildPullRequestInfo.cs deleted file mode 100644 index 1a07680e25..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildPullRequestInfo.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Core; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides TF Build pull request information for the current build. - /// - public sealed class TFBuildPullRequestInfo : TFInfo - { - /// - /// Initializes a new instance of the class. - /// - /// The environment. - public TFBuildPullRequestInfo(ICakeEnvironment environment) - : base(environment) - { - } - - /// - /// Gets a value indicating whether the pull request is from a fork of the repository. - /// - public bool IsFork => GetEnvironmentBoolean("SYSTEM_PULLREQUEST_ISFORK"); - - /// - /// Gets a value indicating whether the current build was started by a pull request. - /// - /// - /// true if the current build was started by a pull request; otherwise, false. - /// - public bool IsPullRequest => Id > 0; - - /// - /// Gets the ID of the pull request that caused this build. - /// This value is set only if the build ran because of a Git PR affected by a branch policy. - /// - /// - /// The ID of the pull request that caused this build. - /// - public int Id => GetEnvironmentInteger("SYSTEM_PULLREQUEST_PULLREQUESTID"); - - /// - /// Gets the number of the pull request that caused this build. - /// This value is set for pull requests from GitHub which have a different pull request ID and pull request number. - /// - /// - /// The number of the pull request that caused this build. - /// - public int Number => GetEnvironmentInteger("SYSTEM_PULLREQUEST_PULLREQUESTNUMBER"); - - /// - /// Gets the branch that is being reviewed in a pull request. - /// - /// - /// This property is populated only if the build ran because of a Git PR affected by a branch policy. - /// - public string SourceBranch => GetEnvironmentString("SYSTEM_PULLREQUEST_SOURCEBRANCH"); - - /// - /// Gets the URL to the repo that contains the pull requests. - /// - /// - /// This property is populated only if the build ran because of a Git PR affected by a branch policy. It is not initialized for GitHub PRs. - /// - public Uri SourceRepositoryUri => GetEnvironmentUri("SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI"); - - /// - /// Gets the branch that is the target of a pull request. - /// - /// - /// This property is populated only if the build ran because of a Git PR affected by a branch policy. - /// - public string TargetBranch => GetEnvironmentString("SYSTEM_PULLREQUEST_TARGETBRANCH"); - } -} \ No newline at end of file diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildRecordData.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildRecordData.cs deleted file mode 100644 index 44df771882..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildRecordData.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides optional data associated with a TF Build timeline record. - /// - public sealed class TFBuildRecordData - { - /// - /// Gets or sets the parent record of a new or existing timeline record. - /// - /// - /// The ID of the parent record. - /// - public Guid ParentRecord { get; set; } - - /// - /// Gets or sets the start time of this record. - /// - /// - /// The start time of this record. - /// - public DateTime? StartTime { get; set; } - - /// - /// Gets or sets the finish time of this record. - /// - /// - /// The finish time of this record. - /// - public DateTime? FinishTime { get; set; } - - /// - /// Gets or sets the current progress of this record. - /// - /// - /// The current progress of this record. - /// - public int? Progress { get; set; } - - /// - /// Gets or sets the current status of this record. - /// - /// - /// The current status of this record. - /// - public TFBuildTaskStatus? Status { get; set; } - - /// - /// Gets or sets the result of this record. - /// - /// - /// The result of this record. - /// - public TFBuildTaskResult? Result { get; set; } - - internal Dictionary GetProperties() - { - var properties = new Dictionary(); - if (ParentRecord != default(Guid)) - { - properties.Add("parentid", ParentRecord.ToString()); - } - if (StartTime.HasValue) - { - properties.Add("starttime", StartTime.ToString()); - } - if (FinishTime.HasValue) - { - properties.Add("finishtime", FinishTime.ToString()); - } - if (Progress.HasValue) - { - properties.Add("progress", Progress.ToString()); - } - if (Status.HasValue) - { - properties.Add("state", Status.ToString()); - } - if (Result.HasValue) - { - properties.Add("result", Result.ToString()); - } - return properties; - } - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildRepositoryInfo.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildRepositoryInfo.cs deleted file mode 100644 index fcdb88291a..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildRepositoryInfo.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Core; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides TF Build Repository information for the current build. - /// - public sealed class TFBuildRepositoryInfo : TFInfo - { - /// - /// Initializes a new instance of the class. - /// - /// The environment. - public TFBuildRepositoryInfo(ICakeEnvironment environment) - : base(environment) - { - } - - /// - /// Gets the branch the build was queued for. - /// - /// - /// The full SCM branch. - /// - public string SourceBranch => GetEnvironmentString("BUILD_SOURCEBRANCH"); - - /// - /// Gets name of the branch the build was queued for. - /// - /// - /// The SCM branch name. - /// - public string SourceBranchName => GetEnvironmentString("BUILD_SOURCEBRANCHNAME"); - - /// - /// Gets name of the branch the build was queued for. - /// - /// - /// The SCM branch name. - /// - [Obsolete("Please use TFBuildRepositoryInfo.SourceBranchName instead")] - public string Branch => SourceBranchName; - - /// - /// Gets the latest version control change that is included in this build. - /// - /// Note: for Git this is the commit ID. For TFVC this is the changeset. - /// - /// The SCM source version. - /// - public string SourceVersion => GetEnvironmentString("BUILD_SOURCEVERSION"); - - /// - /// Gets the comment of the commit or changeset. - /// - /// Note: This variable is available in TFS 2015.4. - /// - /// The comment. - /// - public string SourceVersionMessage => GetEnvironmentString("BUILD_SOURCEVERSIONMESSAGE"); - - /// - /// Gets the name of the shelveset you are building, if you are running a gated build or a shelveset build. - /// - /// Defined only if your repository is Team Foundation Version Control. - /// - /// The shelveset name. - /// - public string Shelveset => GetEnvironmentString("BUILD_SOURCETFVCSHELVESET"); - - /// - /// Gets the name of the repository. - /// - /// - /// The name of the repository. - /// - public string RepoName => GetEnvironmentString("BUILD_REPOSITORY_NAME"); - - /// - /// Gets the type of the current repository. - /// - /// - /// The type of the current repository. - /// - public TFRepositoryType? Provider => GetRepositoryType("BUILD_REPOSITORY_PROVIDER"); - - /// - /// Gets the value you've selected for Checkout submodules on the repository tab. - /// - /// - /// The checkout submodule value. - /// - public string GitSubmoduleCheckout => GetEnvironmentString("BUILD_REPOSITORY_GIT_SUBMODULECHECKOUT"); - } -} \ No newline at end of file diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildTeamProjectInfo.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildTeamProjectInfo.cs deleted file mode 100644 index a4a983c576..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildTeamProjectInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Core; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides Team Foundation Team Project information for the current build. - /// - public sealed class TFBuildTeamProjectInfo : TFInfo - { - /// - /// Initializes a new instance of the class. - /// - /// The environment. - public TFBuildTeamProjectInfo(ICakeEnvironment environment) : base(environment) - { - } - - /// - /// Gets the name of the team project that contains this build. - /// - /// - /// The name of the team project that contains this build. - /// - public string Name => GetEnvironmentString("SYSTEM_TEAMPROJECT"); - - /// - /// Gets the ID of the team project that contains this build. - /// - /// - /// The ID of the team project that contains this build. - /// - public string Id => GetEnvironmentString("SYSTEM_TEAMPROJECTID"); - - /// - /// Gets the URI of the team foundation collection. - /// - /// - /// The URI of the team foundation collection. - /// - public Uri CollectionUri => GetEnvironmentUri("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"); - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildTriggeredBy.cs b/src/Cake.Common/Build/TFBuild/Data/TFBuildTriggeredBy.cs deleted file mode 100644 index 1eb15ee5e1..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildTriggeredBy.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Cake.Core; - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides TF Build Trigger information for the current build. - /// - /// - /// Only populated if the build was triggered by another build. - /// - public class TFBuildTriggeredBy : TFInfo - { - /// - /// Initializes a new instance of the class. - /// - /// The environment. - public TFBuildTriggeredBy(ICakeEnvironment environment) : base(environment) - { - } - - /// - /// Gets the BuildID of the triggering build. - /// - public int BuildId => GetEnvironmentInteger("BUILD_TRIGGEREDBY_BUILDID"); - - /// - /// Gets the DefinitionID of the triggering build. - /// - public int DefinitionId => GetEnvironmentInteger("BUILD_TRIGGEREDBY_DEFINITIONID"); - - /// - /// Gets the name of the triggering build pipeline. - /// - public string DefinitionName => GetEnvironmentString("BUILD_TRIGGEREDBY_DEFINITIONNAME"); - - /// - /// Gets the number of the triggering build. - /// - public string BuildNumber => GetEnvironmentString("BUILD_TRIGGEREDBY_BUILDNUMBER"); - - /// - /// Gets the ID of the project that contains the triggering build. - /// - public string ProjectId => GetEnvironmentString("BUILD_TRIGGEREDBY_PROJECTID"); - } -} \ No newline at end of file diff --git a/src/Cake.Common/Build/TFBuild/Data/TFRepositoryType.cs b/src/Cake.Common/Build/TFBuild/Data/TFRepositoryType.cs deleted file mode 100644 index 9f486a1ac7..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFRepositoryType.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Provides the known values for the TF Build Repository types. - /// - public enum TFRepositoryType - { - /// - /// TFS Git repository. - /// - TfsGit, - - /// - /// Team Foundation Version Control repository. - /// - TfsVersionControl, - - /// - /// Git repository hosted on an external server. - /// - Git, - - /// - /// GitHub repository. - /// - GitHub, - - /// - /// Subversion repository. - /// - Svn - } -} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFTestRunnerType.cs b/src/Cake.Common/Build/TFBuild/Data/TFTestRunnerType.cs deleted file mode 100644 index bc559ac729..0000000000 --- a/src/Cake.Common/Build/TFBuild/Data/TFTestRunnerType.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Cake.Common.Build.TFBuild.Data -{ - /// - /// Providers known values for the TF Test Runner types. - /// - public enum TFTestRunnerType - { - /// - /// JUnit Test Result Format - /// - JUnit, - - /// - /// NUnit (v2) Test Result Format - /// - NUnit, - - /// - /// Visual Studio (MSTest) Test Result Format - /// - VSTest, - - /// - /// XUnit Test Result Format - /// - XUnit - } -} diff --git a/src/Cake.Common/Build/TFBuild/ITFBuildCommands.cs b/src/Cake.Common/Build/TFBuild/ITFBuildCommands.cs deleted file mode 100644 index 099cd5b3d5..0000000000 --- a/src/Cake.Common/Build/TFBuild/ITFBuildCommands.cs +++ /dev/null @@ -1,215 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Common.Build.TFBuild.Data; -using Cake.Core.IO; - -namespace Cake.Common.Build.TFBuild -{ - /// - /// Represents a TF Build command provider. - /// - public interface ITFBuildCommands - { - /// - /// Log a warning issue to timeline record of current task. - /// - /// The warning message. - void WriteWarning(string message); - - /// - /// Log a warning issue with detailed data to timeline record of current task. - /// - /// The warning message. - /// The message data. - void WriteWarning(string message, TFBuildMessageData data); - - /// - /// Log an error to timeline record of current task. - /// - /// The error message. - void WriteError(string message); - - /// - /// Log an error with detailed data to timeline record of current task. - /// - /// The error message. - /// The message data. - void WriteError(string message, TFBuildMessageData data); - - /// - /// Set progress and current operation for current task. - /// - /// Current progress as percentage. - /// The current operation. - void SetProgress(int progress, string currentOperation); - - /// - /// Finish timeline record for current task and set task result to succeeded. - /// - void CompleteCurrentTask(); - - /// - /// Finish timeline record for current task and set task result. - /// - /// The task result status. - void CompleteCurrentTask(TFBuildTaskResult result); - - /// - /// Create detail timeline record. - /// - /// Name of the new timeline record. - /// Type of the new timeline record. - /// Order of the timeline record. - /// The timeline record ID. - Guid CreateNewRecord(string name, string type, int order); - - /// - /// Create detail timeline record. - /// - /// Name of the new timeline record. - /// Type of the new timeline record. - /// Order of the timeline record. - /// Additional data for the new timeline record. - /// The timeline record ID. - Guid CreateNewRecord(string name, string type, int order, TFBuildRecordData data); - - /// - /// Update an existing detail timeline record. - /// - /// The ID of the existing timeline record. - /// Additional data for the timeline record. - void UpdateRecord(Guid id, TFBuildRecordData data); - - /// - /// Sets a variable in the variable service of the task context. - /// - /// - /// The variable is exposed to following tasks as an environment variable. - /// - /// The variable name. - /// The variable value. - void SetVariable(string name, string value); - - /// - /// Sets a secret variable in the variable service of the task context. - /// - /// - /// The variable is not exposed to following tasks as an environment variable, and must be passed as inputs. - /// - /// The variable name. - /// The variable value. - void SetSecretVariable(string name, string value); - - /// - /// Upload and attach summary markdown to current timeline record. - /// - /// - /// This summary is added to the build/release summary and is not available for download with logs. - /// - /// Path to the summary markdown file. - void UploadTaskSummary(FilePath markdownPath); - - /// - /// Upload file as additional log information to the current timeline record. - /// - /// - /// - /// The file shall be available for download along with task logs. - /// - /// - /// Requires agent version 1.101. - /// - /// - /// Path to the additional log file. - void UploadTaskLogFile(FilePath logFile); - - /// - /// Create an artifact link, such as a file or folder path or a version control path. - /// - /// The artifact name.. - /// The artifact type. - /// The link path or value. - void LinkArtifact(string name, TFBuildArtifactType type, string location); - - /// - /// Upload local file into a file container folder. - /// - /// Folder that the file will upload to. - /// Path to the local file. - void UploadArtifact(string folderName, FilePath file); - - /// - /// Upload local file into a file container folder, and create an artifact. - /// - /// Folder that the file will upload to. - /// Path to the local file. - /// The artifact name. - void UploadArtifact(string folderName, FilePath file, string artifactName); - - /// - /// Upload local directory as a container folder, and create an artifact. - /// - /// Path to the local directory. - void UploadArtifactDirectory(DirectoryPath directory); - - /// - /// Upload local directory as a container folder, and create an artifact with the specified name. - /// - /// Path to the local directory. - /// The artifact name. - void UploadArtifactDirectory(DirectoryPath directory, string artifactName); - - /// - /// Upload additional log to build container's logs/tool folder. - /// - /// The log file. - void UploadBuildLogFile(FilePath logFile); - - /// - /// Update build number for current build. - /// - /// - /// Requires agent version 1.88. - /// - /// The build number. - void UpdateBuildNumber(string buildNumber); - - /// - /// Add a tag for current build. - /// - /// - /// Requires agent version 1.95. - /// - /// The tag. - void AddBuildTag(string tag); - - /// - /// Publishes and uploads tests results. - /// - /// The publish test results data. - void PublishTestResults(TFBuildPublishTestResultsData data); - - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage data. - void PublishCodeCoverage(TFBuildPublishCodeCoverageData data); - - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage summary file path. - /// The code coverage data. - void PublishCodeCoverage(FilePath summaryFilePath, TFBuildPublishCodeCoverageData data); - - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage summary file path. - /// The configuration action for the code coverage data. - void PublishCodeCoverage(FilePath summaryFilePath, Action action); - } -} diff --git a/src/Cake.Common/Build/TFBuild/ITFBuildProvider.cs b/src/Cake.Common/Build/TFBuild/ITFBuildProvider.cs deleted file mode 100644 index b867d93d44..0000000000 --- a/src/Cake.Common/Build/TFBuild/ITFBuildProvider.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Common.Build.TFBuild.Data; - -namespace Cake.Common.Build.TFBuild -{ - /// - /// Represents a TF Build provider. - /// - public interface ITFBuildProvider - { - /// - /// Gets a value indicating whether the current build is running on TFS. - /// - /// - /// true if the current build is running on TFS; otherwise, false. - /// - [Obsolete("Please use ITFBuildProvider.IsRunningOnAzurePipelines instead.")] - bool IsRunningOnTFS { get; } - - /// - /// Gets a value indicating whether the current build is running on VSTS. - /// - /// - /// true if the current build is running on VSTS; otherwise, false. - /// - [Obsolete("Please use ITFBuildProvider.IsRunningOnAzurePipelinesHosted instead.")] - bool IsRunningOnVSTS { get; } - - /// - /// Gets a value indicating whether the current build is running on Azure Pipelines. - /// - /// - /// true if the current build is running on Azure Pipelines; otherwise, false. - /// - bool IsRunningOnAzurePipelines { get; } - - /// - /// Gets a value indicating whether the current build is running on hosted Azure Pipelines. - /// - /// - /// true if the current build is running on hosted Azure Pipelines; otherwise, false. - /// - bool IsRunningOnAzurePipelinesHosted { get; } - - /// - /// Gets the TF Build environment. - /// - /// - /// The TF Build environment. - /// - TFBuildEnvironmentInfo Environment { get; } - - /// - /// Gets the TF Build Commands provider. - /// - /// - /// The TF Build commands provider. - /// - ITFBuildCommands Commands { get; } - } -} diff --git a/src/Cake.Common/Build/TFBuild/TFBuildCommands.cs b/src/Cake.Common/Build/TFBuild/TFBuildCommands.cs deleted file mode 100644 index 0661733263..0000000000 --- a/src/Cake.Common/Build/TFBuild/TFBuildCommands.cs +++ /dev/null @@ -1,408 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Cake.Common.Build.TFBuild.Data; -using Cake.Core; -using Cake.Core.Diagnostics; -using Cake.Core.IO; - -namespace Cake.Common.Build.TFBuild -{ - /// - /// Responsible for issuing TF Build agent commands (see ). - /// - public sealed class TFBuildCommands : ITFBuildCommands - { - private const string MessagePrefix = "##vso["; - private const string MessagePostfix = "]"; - - private readonly ICakeEnvironment _environment; - private readonly IBuildSystemServiceMessageWriter _writer; - - /// - /// Initializes a new instance of the class. - /// - /// The environment. - /// The build system service message writer. - public TFBuildCommands(ICakeEnvironment environment, IBuildSystemServiceMessageWriter writer) - { - _environment = environment ?? throw new ArgumentNullException(nameof(environment)); - _writer = writer ?? throw new ArgumentNullException(nameof(writer)); - } - - /// - /// Log a warning issue to timeline record of current task. - /// - /// The warning message. - public void WriteWarning(string message) - { - WriteLoggingCommand("task.logissue", new Dictionary - { - ["type"] = "warning" - }, message); - } - - /// - /// Log a warning issue with detailed data to timeline record of current task. - /// - /// The warning message. - /// The message data. - public void WriteWarning(string message, TFBuildMessageData data) - { - var properties = data.GetProperties(); - properties.Add("type", "warning"); - WriteLoggingCommand("task.logissue", properties, message); - } - - /// - /// Log an error to timeline record of current task. - /// - /// The error message. - public void WriteError(string message) - { - WriteLoggingCommand("task.logissue", new Dictionary - { - ["type"] = "error" - }, message); - } - - /// - /// Log an error with detailed data to timeline record of current task. - /// - /// The error message. - /// The message data. - public void WriteError(string message, TFBuildMessageData data) - { - var properties = data.GetProperties(); - properties.Add("type", "error"); - WriteLoggingCommand("task.logissue", properties, message); - } - - /// - /// Set progress and current operation for current task. - /// - /// Current progress as percentage. - /// The current operation. - public void SetProgress(int progress, string currentOperation) - { - WriteLoggingCommand("task.setprogress", new Dictionary - { - ["value"] = progress.ToString() - }, currentOperation); - } - - /// - /// Finish timeline record for current task and set task result to succeeded. - /// - public void CompleteCurrentTask() - { - WriteLoggingCommand("task.complete", "DONE"); - } - - /// - /// Finish timeline record for current task and set task result. - /// - /// The task result status. - public void CompleteCurrentTask(TFBuildTaskResult result) - { - WriteLoggingCommand("task.complete", new Dictionary - { - ["result"] = result.ToString() - }, "DONE"); - } - - /// - /// Create detail timeline record. - /// - /// Name of the new timeline record. - /// Type of the new timeline record. - /// Order of the timeline record. - /// The timeline record ID. - public Guid CreateNewRecord(string name, string type, int order) - { - var guid = Guid.NewGuid(); - WriteLoggingCommand("task.logdetail", new Dictionary - { - ["id"] = guid.ToString(), - ["name"] = name, - ["type"] = type, - ["order"] = order.ToString() - }, "create new timeline record"); - return guid; - } - - /// - /// Create detail timeline record. - /// - /// Name of the new timeline record. - /// Type of the new timeline record. - /// Order of the timeline record. - /// Additional data for the new timeline record. - /// The timeline record ID. - public Guid CreateNewRecord(string name, string type, int order, TFBuildRecordData data) - { - var guid = Guid.NewGuid(); - var properties = data.GetProperties(); - properties.Add("id", guid.ToString()); - properties.Add("name", name); - properties.Add("type", type); - properties.Add("order", order.ToString()); - WriteLoggingCommand("task.logdetail", properties, "create new timeline record"); - return guid; - } - - /// - /// Update an existing detail timeline record. - /// - /// The ID of the existing timeline record. - /// Additional data for the timeline record. - public void UpdateRecord(Guid id, TFBuildRecordData data) - { - var properties = data.GetProperties(); - properties.Add("id", id.ToString()); - WriteLoggingCommand("task.logdetail", properties, "update"); - } - - /// - /// Sets a variable in the variable service of the task context. - /// - /// - /// The variable is exposed to following tasks as an environment variable. - /// - /// The variable name. - /// The variable value. - public void SetVariable(string name, string value) - { - WriteLoggingCommand("task.setvariable", new Dictionary - { - ["variable"] = name - }, value); - } - - /// - /// Sets a secret variable in the variable service of the task context. - /// - /// - /// The variable is not exposed to following tasks as an environment variable, and must be passed as inputs. - /// - /// The variable name. - /// The variable value. - public void SetSecretVariable(string name, string value) - { - WriteLoggingCommand("task.setvariable", new Dictionary - { - ["variable"] = name, - ["issecret"] = "true" - }, value); - } - - /// - /// Upload and attach summary markdown to current timeline record. - /// - /// - /// This summary is added to the build/release summary and is not available for download with logs. - /// - /// Path to the summary markdown file. - public void UploadTaskSummary(FilePath markdownPath) - { - WriteLoggingCommand("task.uploadsummary", markdownPath.MakeAbsolute(_environment).FullPath); - } - - /// - /// Upload file as additional log information to the current timeline record. - /// - /// - /// - /// The file shall be available for download along with task logs. - /// - /// - /// Requires agent version 1.101. - /// - /// - /// Path to the additional log file. - public void UploadTaskLogFile(FilePath logFile) - { - WriteLoggingCommand("task.uploadfile", logFile.MakeAbsolute(_environment).FullPath); - } - - /// - /// Create an artifact link, such as a file or folder path or a version control path. - /// - /// The artifact name.. - /// The artifact type. - /// The link path or value. - public void LinkArtifact(string name, TFBuildArtifactType type, string location) - { - WriteLoggingCommand("artifact.associate", new Dictionary - { - ["artifactname"] = name, - ["type"] = type.ToString() - }, location); - } - - /// - /// Upload local file into a file container folder. - /// - /// Folder that the file will upload to. - /// Path to the local file. - public void UploadArtifact(string folderName, FilePath file) - { - WriteLoggingCommand("artifact.upload", new Dictionary - { - ["containerfolder"] = folderName - }, file.MakeAbsolute(_environment).FullPath); - } - - /// - /// Upload local file into a file container folder, and create an artifact. - /// - /// Folder that the file will upload to. - /// Path to the local file. - /// The artifact name. - public void UploadArtifact(string folderName, FilePath file, string artifactName) - { - WriteLoggingCommand("artifact.upload", new Dictionary - { - ["containerfolder"] = folderName, - ["artifactname"] = artifactName - }, file.MakeAbsolute(_environment).FullPath); - } - - /// - public void UploadArtifactDirectory(DirectoryPath directory) - { - if (directory == null) - { - throw new ArgumentNullException(nameof(directory)); - } - - UploadArtifactDirectory(directory, directory.GetDirectoryName()); - } - - /// - public void UploadArtifactDirectory(DirectoryPath directory, string artifactName) - { - if (directory == null) - { - throw new ArgumentNullException(nameof(directory)); - } - - if (artifactName == null) - { - throw new ArgumentNullException(nameof(artifactName)); - } - - WriteLoggingCommand("artifact.upload", new Dictionary - { - ["containerfolder"] = artifactName, - ["artifactname"] = artifactName - }, directory.MakeAbsolute(_environment).FullPath); - } - - /// - /// Upload additional log to build container's logs/tool folder. - /// - /// The log file. - public void UploadBuildLogFile(FilePath logFile) - { - WriteLoggingCommand("build.uploadlog", logFile.MakeAbsolute(_environment).FullPath); - } - - /// - /// Update build number for current build. - /// - /// - /// Requires agent version 1.88. - /// - /// The build number. - public void UpdateBuildNumber(string buildNumber) - { - WriteLoggingCommand("build.updatebuildnumber", buildNumber); - } - - /// - /// Add a tag for current build. - /// - /// - /// Requires agent version 1.95. - /// - /// The tag. - public void AddBuildTag(string tag) - { - WriteLoggingCommand("build.addbuildtag", tag); - } - - /// - /// Publishes and uploads tests results. - /// - /// The publish test results data. - public void PublishTestResults(TFBuildPublishTestResultsData data) - { - var properties = data.GetProperties(_environment); - WriteLoggingCommand("results.publish", properties, string.Empty); - } - - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage data. - public void PublishCodeCoverage(TFBuildPublishCodeCoverageData data) - { - var properties = data.GetProperties(_environment); - WriteLoggingCommand("codecoverage.publish", properties, string.Empty); - } - - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage summary file path. - /// The code coverage data. - public void PublishCodeCoverage(FilePath summaryFilePath, TFBuildPublishCodeCoverageData data) - { - if (summaryFilePath == null) - { - throw new ArgumentNullException(nameof(summaryFilePath)); - } - - var properties = data.GetProperties(_environment, summaryFilePath); - WriteLoggingCommand("codecoverage.publish", properties, string.Empty); - } - - /// - /// Publishes and uploads code coverage results. - /// - /// The code coverage summary file path. - /// The configuration action for the code coverage data. - public void PublishCodeCoverage(FilePath summaryFilePath, Action action) - { - if (action == null) - { - throw new ArgumentNullException(nameof(action)); - } - - var data = new TFBuildPublishCodeCoverageData(); - action(data); - - PublishCodeCoverage(summaryFilePath, data); - } - - private void WriteLoggingCommand(string actionName, string value) - { - WriteLoggingCommand(actionName, new Dictionary(), value); - } - - private void WriteLoggingCommand(string actionName, Dictionary properties, string value) - { - var props = string.Join(string.Empty, properties.Select(pair => - { - return string.Format(CultureInfo.InvariantCulture, "{0}={1};", pair.Key, pair.Value); - })); - _writer.Write("{0}{1} {2}{3}{4}", MessagePrefix, actionName, props, MessagePostfix, value); - } - } -} diff --git a/src/Cake.Common/Build/TFBuild/TFBuildProvider.cs b/src/Cake.Common/Build/TFBuild/TFBuildProvider.cs deleted file mode 100644 index 727fc24d66..0000000000 --- a/src/Cake.Common/Build/TFBuild/TFBuildProvider.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Common.Build.TFBuild.Data; -using Cake.Core; - -namespace Cake.Common.Build.TFBuild -{ - /// - /// Responsible for communicating with Team Foundation Build (VSTS or TFS). - /// - public sealed class TFBuildProvider : ITFBuildProvider - { - private readonly ICakeEnvironment _environment; - - /// - /// Initializes a new instance of the class. - /// - /// The environment. - /// The build system service message writer. - public TFBuildProvider(ICakeEnvironment environment, IBuildSystemServiceMessageWriter writer) - { - _environment = environment ?? throw new ArgumentNullException(nameof(environment)); - Environment = new TFBuildEnvironmentInfo(environment); - Commands = new TFBuildCommands(environment, writer); - } - - /// - /// Gets a value indicating whether the current build is running on TFS. - /// - /// - /// true if the current build is running on TFS; otherwise, false. - /// - [Obsolete("Please use TFBuildProvider.IsRunningOnAzurePipelines instead.")] - public bool IsRunningOnTFS => IsRunningOnAzurePipelines; - - /// - /// Gets a value indicating whether the current build is running on VSTS. - /// - /// - /// true if the current build is running on VSTS; otherwise, false. - /// - [Obsolete("Please use TFBuildProvider.IsRunningOnAzurePipelinesHosted instead.")] - public bool IsRunningOnVSTS => IsRunningOnAzurePipelinesHosted; - - /// - /// Gets a value indicating whether the current build is running on Azure Pipelines. - /// - /// - /// true if the current build is running on Azure Pipelines; otherwise, false. - /// - public bool IsRunningOnAzurePipelines - => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("TF_BUILD")) && !IsHostedAgent; - - /// - /// Gets a value indicating whether the current build is running on hosted Azure Pipelines. - /// - /// - /// true if the current build is running on hosted Azure Pipelines; otherwise, false. - /// - public bool IsRunningOnAzurePipelinesHosted - => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("TF_BUILD")) && IsHostedAgent; - - /// - /// Gets the TF Build environment. - /// - /// - /// The TF Build environment. - /// - public TFBuildEnvironmentInfo Environment { get; } - - /// - /// Gets the TF Build Commands provider. - /// - /// - /// The TF Build commands provider. - /// - public ITFBuildCommands Commands { get; } - - /// - /// Gets a value indicating whether the current build is running on a hosted build agent. - /// - /// - /// true if the current build is running on a hosted agent; otherwise, false. - /// - private bool IsHostedAgent => Environment.Agent.IsHosted; - } -} diff --git a/src/Cake.Common/Build/TFBuild/TFInfo.cs b/src/Cake.Common/Build/TFBuild/TFInfo.cs deleted file mode 100644 index 36732c17a5..0000000000 --- a/src/Cake.Common/Build/TFBuild/TFInfo.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Common.Build.TFBuild.Data; -using Cake.Core; - -namespace Cake.Common.Build.TFBuild -{ - /// - /// Base class used to provide information about the TF Build environment. - /// - public abstract class TFInfo - { - private readonly ICakeEnvironment _environment; - - /// - /// Initializes a new instance of the class. - /// - /// The environment. - protected TFInfo(ICakeEnvironment environment) - { - _environment = environment; - } - - /// - /// Gets an environment variable as a . - /// - /// The environment variable name. - /// The environment variable. - protected string GetEnvironmentString(string variable) - { - return _environment.GetEnvironmentVariable(variable) ?? string.Empty; - } - - /// - /// Gets an environment variable as a . - /// - /// The environment variable name. - /// The environment variable. - protected int GetEnvironmentInteger(string variable) - { - var value = GetEnvironmentString(variable); - if (!string.IsNullOrWhiteSpace(value)) - { - int result; - if (int.TryParse(value, out result)) - { - return result; - } - } - return 0; - } - - /// - /// Gets an environment variable as a . - /// - /// The environment variable name. - /// The environment variable. - protected bool GetEnvironmentBoolean(string variable) - { - var value = GetEnvironmentString(variable); - if (!string.IsNullOrWhiteSpace(value)) - { - return value.Equals("true", StringComparison.OrdinalIgnoreCase); - } - return false; - } - - /// - /// Gets an environment variable as a . - /// - /// The environment variable name. - /// The environment variable. - protected Uri GetEnvironmentUri(string variable) - { - var value = GetEnvironmentString(variable); - Uri uri; - if (Uri.TryCreate(value, UriKind.Absolute, out uri)) - { - return uri; - } - return null; - } - - /// - /// Gets the current repository type as a from an environment variable. - /// - /// The environment variable name. - /// The current repository type. - protected TFRepositoryType? GetRepositoryType(string variable) - { - var value = GetEnvironmentString(variable); - TFRepositoryType type; - if (Enum.TryParse(value, true, out type)) - { - return type; - } - return null; - } - } -} diff --git a/src/Cake.Common/Build/TeamCity/Data/TeamCityBuildInfo.cs b/src/Cake.Common/Build/TeamCity/Data/TeamCityBuildInfo.cs index ce474497c8..5a75b78da3 100644 --- a/src/Cake.Common/Build/TeamCity/Data/TeamCityBuildInfo.cs +++ b/src/Cake.Common/Build/TeamCity/Data/TeamCityBuildInfo.cs @@ -2,7 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Xml.Linq; +using System.Xml.XPath; using Cake.Core; +using Cake.Core.IO; namespace Cake.Common.Build.TeamCity.Data { @@ -11,6 +18,8 @@ namespace Cake.Common.Build.TeamCity.Data /// public class TeamCityBuildInfo : TeamCityInfo { + private DateTimeOffset? _startDateTime; + /// /// Gets the build configuration name. /// @@ -27,13 +36,126 @@ public class TeamCityBuildInfo : TeamCityInfo /// public string Number => GetEnvironmentString("BUILD_NUMBER"); + /// + /// Gets the build start date and time. + /// + /// + /// The build start date and time if available, or . + /// + /// + /// The build start date and time are obtained from reading two environment variables + /// BUILD_START_DATE (yyyyMMdd) and BUILD_START_TIME (HHmmss) are automatically set by JetBrain's + /// Groovy plug plugin. + /// + public DateTimeOffset? StartDateTime + { + get + { + if (_startDateTime.HasValue) + { + return _startDateTime; + } + + var startDate = GetEnvironmentString("BUILD_START_DATE"); // yyyyMMdd + var startTime = GetEnvironmentString("BUILD_START_TIME"); // HHmmss + + if (DateTimeOffset.TryParseExact($"{startDate}{startTime}", "yyyyMMddHHmmss", CultureInfo.InvariantCulture, + DateTimeStyles.AssumeLocal, out var startDateTime)) + { + _startDateTime = startDateTime; + } + + return _startDateTime; + } + } + + /// + /// Gets the branch display name. + /// + /// + /// The branch display name. + /// + public string BranchName => ConfigProperties.ContainsKey("teamcity.build.branch") ? ConfigProperties["teamcity.build.branch"] : string.Empty; + + /// + /// Gets the vcs branch name. + /// + /// + /// The vcs branch name. + /// + public string VcsBranchName + { + get + { + var rootBranchKey = ConfigProperties.Keys.FirstOrDefault(k => k.StartsWith("teamcity.build.vcs.branch.")); + return !string.IsNullOrWhiteSpace(rootBranchKey) ? ConfigProperties[rootBranchKey] : string.Empty; + } + } + + /// + /// Gets the TeamCity build properties. + /// + /// + /// The TeamCity build properties as a key/value dictionary. + /// + public Dictionary BuildProperties => _buildProperties.Value; + + /// + /// Gets the TeamCity config properties. + /// + /// + /// The TeamCity config properties as a key/value dictionary. + /// + public Dictionary ConfigProperties => _configProperties.Value; + + /// + /// Gets the TeamCity runner properties. + /// + /// + /// The TeamCity runner properties as a key/value dictionary. + /// + public Dictionary RunnerProperties => _runnerProperties.Value; + + private readonly Lazy> _buildProperties; + private readonly Lazy> _configProperties; + private readonly Lazy> _runnerProperties; + + private Dictionary ReadAndParseFile(IFileSystem fileSystem, string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) + { + return new Dictionary(); + } + + var configurationPropertiesXmlFile = fileSystem.GetFile($"{fileName}.xml"); + if (!configurationPropertiesXmlFile.Exists) + { + return new Dictionary(); + } + + var configurationPropertiesXml = XDocument.Load(configurationPropertiesXmlFile.OpenRead()); + + return configurationPropertiesXml.XPathSelectElements("//entry") + .Where(entry => entry.Attribute("key") != null) + .ToDictionary(entry => entry.Attribute("key").Value, entry => entry.Value); + } + + private string BuildValueIfExists(string key) + { + return BuildProperties.ContainsKey(key) ? BuildProperties[key] : string.Empty; + } + /// /// Initializes a new instance of the class. /// /// The environment. - public TeamCityBuildInfo(ICakeEnvironment environment) + /// The file system. + public TeamCityBuildInfo(ICakeEnvironment environment, IFileSystem fileSystem) : base(environment) { + _buildProperties = new Lazy>(() => ReadAndParseFile(fileSystem, GetEnvironmentString("TEAMCITY_BUILD_PROPERTIES_FILE"))); + _configProperties = new Lazy>(() => ReadAndParseFile(fileSystem, BuildValueIfExists("teamcity.configuration.properties.file"))); + _runnerProperties = new Lazy>(() => ReadAndParseFile(fileSystem, BuildValueIfExists("teamcity.runner.properties.file"))); } } -} \ No newline at end of file +} diff --git a/src/Cake.Common/Build/TeamCity/Data/TeamCityEnvironmentInfo.cs b/src/Cake.Common/Build/TeamCity/Data/TeamCityEnvironmentInfo.cs index 730581df6b..a5159a0011 100644 --- a/src/Cake.Common/Build/TeamCity/Data/TeamCityEnvironmentInfo.cs +++ b/src/Cake.Common/Build/TeamCity/Data/TeamCityEnvironmentInfo.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Cake.Core; +using Cake.Core.IO; namespace Cake.Common.Build.TeamCity.Data { @@ -149,12 +150,13 @@ public class TeamCityEnvironmentInfo : TeamCityInfo /// Initializes a new instance of the class. /// /// The environment. - public TeamCityEnvironmentInfo(ICakeEnvironment environment) + /// The file system. + public TeamCityEnvironmentInfo(ICakeEnvironment environment, IFileSystem fileSystem) : base(environment) { Project = new TeamCityProjectInfo(environment); - Build = new TeamCityBuildInfo(environment); - PullRequest = new TeamCityPullRequestInfo(environment); + Build = new TeamCityBuildInfo(environment, fileSystem); + PullRequest = new TeamCityPullRequestInfo(environment, Build); } } } \ No newline at end of file diff --git a/src/Cake.Common/Build/TeamCity/Data/TeamCityPullRequestInfo.cs b/src/Cake.Common/Build/TeamCity/Data/TeamCityPullRequestInfo.cs index 9919303e81..487116e007 100644 --- a/src/Cake.Common/Build/TeamCity/Data/TeamCityPullRequestInfo.cs +++ b/src/Cake.Common/Build/TeamCity/Data/TeamCityPullRequestInfo.cs @@ -11,8 +11,12 @@ namespace Cake.Common.Build.TeamCity.Data /// public class TeamCityPullRequestInfo : TeamCityInfo { - private static bool InferIsPullRequest(string gitReferenceName) + private readonly TeamCityBuildInfo _buildInfo; + + private bool InferIsPullRequest() { + var gitReferenceName = GetBranchRef(); + if (string.IsNullOrEmpty(gitReferenceName)) { return false; @@ -37,8 +41,10 @@ private static bool InferIsPullRequest(string gitReferenceName) return false; } - private static int? GetPullRequestNumber(string gitReferenceName) + private int? GetPullRequestNumber() { + var gitReferenceName = GetBranchRef(); + if (string.IsNullOrEmpty(gitReferenceName)) { return null; @@ -54,6 +60,18 @@ private static bool InferIsPullRequest(string gitReferenceName) return null; } + private string GetBranchRef() + { + var gitBranch = GetEnvironmentString("Git_Branch"); + + if (string.IsNullOrWhiteSpace(gitBranch)) + { + gitBranch = _buildInfo.VcsBranchName; + } + + return gitBranch; + } + /// /// Gets a value indicating whether the current build was started by a pull request. /// @@ -63,7 +81,7 @@ private static bool InferIsPullRequest(string gitReferenceName) /// /// env.Git_Branch is a required parameter in TeamCity for this to work. /// - public bool IsPullRequest => InferIsPullRequest(GetEnvironmentString("Git_Branch")); + public bool IsPullRequest => InferIsPullRequest(); /// /// Gets the pull request number. @@ -74,15 +92,17 @@ private static bool InferIsPullRequest(string gitReferenceName) /// /// env.Git_Branch is a required parameter in TeamCity for this to work. /// - public int? Number => IsPullRequest ? GetPullRequestNumber(GetEnvironmentString("Git_Branch")) : null; + public int? Number => IsPullRequest ? GetPullRequestNumber() : null; /// /// Initializes a new instance of the class. /// /// The environment. - public TeamCityPullRequestInfo(ICakeEnvironment environment) + /// The TeamCity build info. + public TeamCityPullRequestInfo(ICakeEnvironment environment, TeamCityBuildInfo buildInfo) : base(environment) { + _buildInfo = buildInfo; } } } \ No newline at end of file diff --git a/src/Cake.Common/Build/TeamCity/ITeamCityProvider.cs b/src/Cake.Common/Build/TeamCity/ITeamCityProvider.cs index bff2234286..ca5c085384 100644 --- a/src/Cake.Common/Build/TeamCity/ITeamCityProvider.cs +++ b/src/Cake.Common/Build/TeamCity/ITeamCityProvider.cs @@ -73,9 +73,9 @@ public interface ITeamCityProvider /// /// Report a build problem to TeamCity. /// - /// Description of build problem. - /// Build identity. - void BuildProblem(string description, string identity); + /// A human-readable plain text describing the build problem. By default, the description appears in the build status text and in the list of build's problems. The text is limited to 4000 symbols, and will be truncated if the limit is exceeded. + /// A unique problem ID (optional). Different problems must have different identity, same problems - same identity, which should not change throughout builds if the same problem, for example, the same compilation error occurs. It must be a valid Java ID up to 60 characters. If omitted, the identity is calculated based on the description text. + void BuildProblem(string description, string identity = null); /// /// Tell TeamCity to import data of a given type. diff --git a/src/Cake.Common/Build/TeamCity/TeamCityProvider.cs b/src/Cake.Common/Build/TeamCity/TeamCityProvider.cs index 047512a069..b9249fc881 100644 --- a/src/Cake.Common/Build/TeamCity/TeamCityProvider.cs +++ b/src/Cake.Common/Build/TeamCity/TeamCityProvider.cs @@ -24,64 +24,13 @@ public sealed class TeamCityProvider : ITeamCityProvider private static readonly Dictionary _sanitizationTokens; private readonly ICakeEnvironment _environment; + private readonly IFileSystem _fileSystem; private readonly IBuildSystemServiceMessageWriter _writer; - /// - /// Gets a value indicating whether the current build is running on TeamCity. - /// - /// - /// true if the current build is running on TeamCity; otherwise, false. - /// + /// public bool IsRunningOnTeamCity => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("TEAMCITY_VERSION")); - /// - /// Gets the TeamCity environment. - /// - /// - /// The TeamCity environment. - /// - /// Via BuildSystem. - /// - /// - /// if (BuildSystem.TeamCity.IsRunningOnTeamCity) - /// { - /// Information( - /// @"Environment: - /// PullRequest: {0} - /// Build Configuration Name: {1} - /// TeamCity Project Name: {2}", - /// BuildSystem.TeamCity.Environment.PullRequest.IsPullRequest, - /// BuildSystem.TeamCity.Environment.Build.BuildConfName, - /// BuildSystem.TeamCity.Environment.Project.Name - /// ); - /// } - /// else - /// { - /// Information("Not running on TeamCity"); - /// } - /// - /// - /// Via TeamCity. - /// - /// - /// if (TeamCity.IsRunningOnTeamCity) - /// { - /// Information( - /// @"Environment: - /// PullRequest: {0} - /// Build Configuration Name: {1} - /// TeamCity Project Name: {2}", - /// BuildSystem.TeamCity.Environment.PullRequest.IsPullRequest, - /// BuildSystem.TeamCity.Environment.Build.BuildConfName, - /// BuildSystem.TeamCity.Environment.Project.Name - /// ); - /// } - /// else - /// { - /// Information("Not running on TeamCity"); - /// } - /// - /// + /// public TeamCityEnvironmentInfo Environment { get; } static TeamCityProvider() @@ -101,84 +50,60 @@ static TeamCityProvider() /// Initializes a new instance of the class. /// /// The cake environment. + /// The cake file system. /// The build system service message writer. - public TeamCityProvider(ICakeEnvironment environment, IBuildSystemServiceMessageWriter writer) + public TeamCityProvider(ICakeEnvironment environment, IFileSystem fileSystem, IBuildSystemServiceMessageWriter writer) { _environment = environment ?? throw new ArgumentNullException(nameof(environment)); + _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _writer = writer ?? throw new ArgumentNullException(nameof(writer)); - Environment = new TeamCityEnvironmentInfo(environment); + Environment = new TeamCityEnvironmentInfo(environment, fileSystem); } - /// - /// Write a progress message to the TeamCity build log. - /// - /// Build log message. + /// public void WriteProgressMessage(string message) { WriteServiceMessage("progressMessage", message); } - /// - /// Write a progressStart message to the TeamCity build log. - /// - /// Build log message. + /// public void WriteStartProgress(string message) { WriteServiceMessage("progressStart", message); } - /// - /// Write a progressFinish message to the TeamCity build log. - /// - /// Build log message. + /// public void WriteEndProgress(string message) { WriteServiceMessage("progressFinish", message); } - /// - /// Write the start of a message block to the TeamCity build log. - /// - /// Block name. + /// public void WriteStartBlock(string blockName) { WriteServiceMessage("blockOpened", "name", blockName); } - /// - /// Write the end of a message block to the TeamCity build log. - /// - /// Block name. + /// public void WriteEndBlock(string blockName) { WriteServiceMessage("blockClosed", "name", blockName); } - /// - /// Write the start of a build block to the TeamCity build log. - /// - /// Build compiler name. + /// public void WriteStartBuildBlock(string compilerName) { WriteServiceMessage("compilationStarted", "compiler", compilerName); } - /// - /// Write the end of a build block to the TeamCity build log. - /// - /// Build compiler name. + /// public void WriteEndBuildBlock(string compilerName) { WriteServiceMessage("compilationFinished", "compiler", compilerName); } - /// - /// Write a status message to the TeamCity build log. - /// - /// Message contents. - /// Build status. - /// Error details if status is error. + /// public void WriteStatus(string message, string status = "NORMAL", string errorDetails = null) { var attrs = new Dictionary @@ -195,11 +120,7 @@ public void WriteStatus(string message, string status = "NORMAL", string errorDe WriteServiceMessage("message", attrs); } - /// - /// Tell TeamCity to import data of a given type. - /// - /// Date type. - /// Data file path. + /// public void ImportData(string type, FilePath path) { if (type == null) @@ -218,11 +139,7 @@ public void ImportData(string type, FilePath path) }); } - /// - /// Tell TeamCity to import coverage from dotCover snapshot file. - /// - /// Snapshot file path. - /// The full path to the dotCover home folder to override the bundled dotCover. + /// public void ImportDotCoverCoverage(FilePath snapshotFile, DirectoryPath dotCoverHome = null) { if (snapshotFile == null) @@ -247,12 +164,8 @@ public void ImportDotCoverCoverage(FilePath snapshotFile, DirectoryPath dotCover }); } - /// - /// Report a build problem to TeamCity. - /// - /// Description of build problem. - /// Build identity. - public void BuildProblem(string description, string identity) + /// + public void BuildProblem(string description, string identity = null) { var tokens = new Dictionary { { "description", description } }; if (!string.IsNullOrEmpty(identity)) @@ -263,29 +176,19 @@ public void BuildProblem(string description, string identity) WriteServiceMessage("buildProblem", tokens); } - /// - /// Tells TeamCity to publish artifacts in the given directory. - /// - /// Path to artifacts. + /// public void PublishArtifacts(string path) { WriteServiceMessage("publishArtifacts", " ", path); } - /// - /// Tells TeamCity to change the current build number. - /// - /// The required build number. + /// public void SetBuildNumber(string buildNumber) { WriteServiceMessage("buildNumber", buildNumber); } - /// - /// Tells TeamCity to set a named parameter with a given value. - /// - /// The name of the parameter to set. - /// The value to set for the named parameter. + /// public void SetParameter(string parameterName, string parameterValue) { WriteServiceMessage("setParameter", new Dictionary diff --git a/src/Cake.Common/Build/TravisCI/Data/TravisCIJobInfo.cs b/src/Cake.Common/Build/TravisCI/Data/TravisCIJobInfo.cs index d66ec4146d..6ba440c9b7 100644 --- a/src/Cake.Common/Build/TravisCI/Data/TravisCIJobInfo.cs +++ b/src/Cake.Common/Build/TravisCI/Data/TravisCIJobInfo.cs @@ -12,7 +12,7 @@ namespace Cake.Common.Build.TravisCI.Data public sealed class TravisCIJobInfo : TravisCIInfo { /// - /// Gets the job identifier for the current job.. + /// Gets the job identifier for the current job. /// /// /// The job identifier. diff --git a/src/Cake.Common/Build/TravisCI/TravisCIProvider.cs b/src/Cake.Common/Build/TravisCI/TravisCIProvider.cs index 03e8e96d40..b0691d5553 100644 --- a/src/Cake.Common/Build/TravisCI/TravisCIProvider.cs +++ b/src/Cake.Common/Build/TravisCI/TravisCIProvider.cs @@ -50,35 +50,19 @@ public TravisCIProvider(ICakeEnvironment environment, IBuildSystemServiceMessage Environment = new TravisCIEnvironmentInfo(environment); } - /// - /// Gets a value indicating whether this instance is running on Travis CI. - /// - /// - /// true if this instance is running on Travis CI; otherwise, false. - /// + /// public bool IsRunningOnTravisCI => !string.IsNullOrWhiteSpace(_environment.GetEnvironmentVariable("TRAVIS")); - /// - /// Gets the Travis CI environment. - /// - /// - /// The environment. - /// + /// public TravisCIEnvironmentInfo Environment { get; } - /// - /// Write the start of a message fold to the Travis CI build log. - /// - /// Name of the group. + /// public void WriteStartFold(string name) { WriteServiceMessage("fold", "start", name); } - /// - /// Write the start of a message fold to the Travis CI build log. - /// - /// Name of the group. + /// public void WriteEndFold(string name) { WriteServiceMessage("fold", "end", name); diff --git a/src/Cake.Common/Cake.Common.csproj b/src/Cake.Common/Cake.Common.csproj index ec080f992e..b83e2afa8c 100644 --- a/src/Cake.Common/Cake.Common.csproj +++ b/src/Cake.Common/Cake.Common.csproj @@ -1,7 +1,6 @@  Cake.Common - net46;netstandard2.0 Library AnyCpu true @@ -16,15 +15,4 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/Cake.Common/EnviromentAliases.cs b/src/Cake.Common/EnviromentAliases.cs index a7fb468008..a6992c07bc 100644 --- a/src/Cake.Common/EnviromentAliases.cs +++ b/src/Cake.Common/EnviromentAliases.cs @@ -157,7 +157,11 @@ public static bool HasEnvironmentVariable(this ICakeContext context, string vari [CakeAliasCategory("Platform")] public static bool IsRunningOnWindows(this ICakeContext context) { - return !IsRunningOnUnix(context); + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + return context.Environment.Platform.IsWindows(); } /// @@ -186,10 +190,62 @@ public static bool IsRunningOnUnix(this ICakeContext context) return context.Environment.Platform.IsUnix(); } + /// + /// Determines whether the build script running on a macOS based system. + /// + /// + /// + /// if (IsRunningOnMacOs()) + /// { + /// Information("macOS!"); + /// } + /// + /// + /// The context. + /// + /// true if the build script running on a macOS based system; otherwise false. + /// + [CakeMethodAlias] + [CakeAliasCategory("Platform")] + public static bool IsRunningOnMacOs(this ICakeContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + return context.Environment.Platform.IsOSX(); + } + + /// + /// Determines whether the build script running on a Linux based system. + /// + /// + /// + /// if (IsRunningOnLinux()) + /// { + /// Information("Linux!"); + /// } + /// + /// + /// The context. + /// + /// true if the build script running on a Linux based system; otherwise false. + /// + [CakeMethodAlias] + [CakeAliasCategory("Platform")] + public static bool IsRunningOnLinux(this ICakeContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + return context.Environment.Platform.IsLinux(); + } + private static T Convert(string value) { var converter = TypeDescriptor.GetConverter(typeof(T)); return (T)converter.ConvertFromInvariantString(value); } } -} \ No newline at end of file +} diff --git a/src/Cake.Common/IO/DirectoryAliases.cs b/src/Cake.Common/IO/DirectoryAliases.cs index 49f4a2b292..b45fae03a3 100644 --- a/src/Cake.Common/IO/DirectoryAliases.cs +++ b/src/Cake.Common/IO/DirectoryAliases.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Cake.Common.IO; using Cake.Common.IO.Paths; using Cake.Core; using Cake.Core.Annotations; @@ -50,34 +51,6 @@ public static ConvertableDirectoryPath Directory(this ICakeContext context, stri return new ConvertableDirectoryPath(new DirectoryPath(path)); } - /// - /// Deletes the specified directories. - /// - /// - /// - /// var directoriesToDelete = new DirectoryPath[]{ - /// Directory("be"), - /// Directory("gone") - /// }; - /// DeleteDirectories(directoriesToDelete, recursive:true); - /// - /// - /// The context. - /// The directory paths. - /// Will perform a recursive delete if set to true. - [Obsolete("Use the overload that accepts DeleteDirectorySettings instead.")] - [CakeMethodAlias] - [CakeAliasCategory("Delete")] - public static void DeleteDirectories(this ICakeContext context, IEnumerable directories, bool recursive = false) - { - if (directories == null) - { - throw new ArgumentNullException(nameof(directories)); - } - - DeleteDirectories(context, directories, new DeleteDirectorySettings { Recursive = recursive }); - } - /// /// Deletes the specified directories. /// @@ -111,29 +84,6 @@ public static void DeleteDirectories(this ICakeContext context, IEnumerable - /// Deletes the specified directories. - /// - /// - /// - /// var directoriesToDelete = new []{ - /// "be", - /// "gone" - /// }; - /// DeleteDirectories(directoriesToDelete, recursive:true); - /// - /// - /// The context. - /// The directory paths. - /// Will perform a recursive delete if set to true. - [Obsolete("Use the overload that accepts DeleteDirectorySettings instead.")] - [CakeMethodAlias] - [CakeAliasCategory("Delete")] - public static void DeleteDirectories(this ICakeContext context, IEnumerable directories, bool recursive = false) - { - DeleteDirectories(context, directories, new DeleteDirectorySettings { Recursive = recursive }); - } - /// /// Deletes the specified directories. /// @@ -168,25 +118,6 @@ public static void DeleteDirectories(this ICakeContext context, IEnumerable - /// Deletes the specified directory. - /// - /// - /// - /// DeleteDirectory("./be/gone", recursive:true); - /// - /// - /// The context. - /// The directory path. - /// Will perform a recursive delete if set to true. - [Obsolete("Use the overload that accepts DeleteDirectorySettings instead.")] - [CakeMethodAlias] - [CakeAliasCategory("Delete")] - public static void DeleteDirectory(this ICakeContext context, DirectoryPath path, bool recursive = false) - { - DeleteDirectory(context, path, new DeleteDirectorySettings { Recursive = recursive }); - } - /// /// Deletes the specified directory. /// @@ -221,7 +152,7 @@ public static void DeleteDirectory(this ICakeContext context, DirectoryPath path /// The pattern to match. [CakeMethodAlias] [CakeAliasCategory("Clean")] - public static void CleanDirectories(this ICakeContext context, string pattern) + public static void CleanDirectories(this ICakeContext context, GlobPattern pattern) { var directories = context.GetDirectories(pattern); if (directories.Count == 0) @@ -250,7 +181,7 @@ public static void CleanDirectories(this ICakeContext context, string pattern) /// The predicate used to filter directories based on file system information. [CakeMethodAlias] [CakeAliasCategory("Clean")] - public static void CleanDirectories(this ICakeContext context, string pattern, Func predicate) + public static void CleanDirectories(this ICakeContext context, GlobPattern pattern, Func predicate) { var directories = context.GetDirectories(pattern, new GlobberSettings { Predicate = predicate }); if (directories.Count == 0) @@ -389,6 +320,68 @@ public static void EnsureDirectoryExists(this ICakeContext context, DirectoryPat } } + /// + /// Deletes the specified directory and its contents if it exists. + /// + /// + /// + /// EnsureDirectoryDoesNotExist("./be/gone"); + /// + /// + /// The context. + /// The directory path. + [CakeMethodAlias] + [CakeAliasCategory("DoesNotExist")] + public static void EnsureDirectoryDoesNotExist(this ICakeContext context, DirectoryPath path) + { + context.EnsureDirectoryDoesNotExist(path, new DeleteDirectorySettings { Recursive = true, Force = true }); + } + + /// + /// Deletes the specified directory if it exists. + /// + /// + /// + /// EnsureDirectoryDoesNotExist("./be/gone", new DeleteDirectorySettings { + /// Recursive = true, + /// Force = true + /// }); + /// + /// + /// The context. + /// The directory path. + /// The delete settings. + [CakeMethodAlias] + [CakeAliasCategory("DoesNotExist")] + public static void EnsureDirectoryDoesNotExist(this ICakeContext context, DirectoryPath path, DeleteDirectorySettings settings) + { + if (context.DirectoryExists(path)) + { + context.DeleteDirectory(path, settings); + } + } + + /// + /// Deletes the specified directory if it exists. + /// + /// + /// + /// EnsureDirectoryDoesNotExist("./be/gone", new EnsureDirectoryDoesNotExistSettings { + /// Recursive = true, + /// Force = true + /// }); + /// + /// + /// The context. + /// The directory path. + /// The delete settings. + [CakeMethodAlias] + [CakeAliasCategory("DoesNotExist")] + public static void EnsureDirectoryDoesNotExist(this ICakeContext context, DirectoryPath path, EnsureDirectoryDoesNotExistSettings settings) + { + context.EnsureDirectoryDoesNotExist(path, settings as DeleteDirectorySettings); + } + /// /// Copies the contents of a directory, including subdirectories to the specified location. /// @@ -520,6 +513,68 @@ public static DirectoryPath MakeAbsolute(this ICakeContext context, DirectoryPat return path.MakeAbsolute(context.Environment); } + /// + /// Makes the directory path relative (if absolute) to a specified root directory. If no root directory is defined + /// the current working directory is used as default root. + /// + /// + /// + /// var path = MakeRelative(Directory("C:\Cake\Tests\Integration")); + /// + /// + /// The context. + /// The path. + /// The root path. + /// A relative directory path. + [CakeMethodAlias] + [CakeAliasCategory("Path")] + public static DirectoryPath MakeRelative(this ICakeContext context, DirectoryPath path, DirectoryPath rootPath = null) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + var root = rootPath ?? context.Environment.WorkingDirectory; + return root.GetRelativePath(path); + } + + /// + /// Makes the file path relative (if absolute) to a specified root directory. If no root directory is defined + /// the current working directory is used as default root. + /// + /// + /// + /// var path = MakeRelative(Directory("C:\Cake\Tests\Integration\file.cake")); + /// + /// + /// The context. + /// The path. + /// The root path. + /// A relative file path. + [CakeMethodAlias] + [CakeAliasCategory("Path")] + public static FilePath MakeRelative(this ICakeContext context, FilePath path, DirectoryPath rootPath = null) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + var root = rootPath ?? context.Environment.WorkingDirectory; + return root.GetRelativePath(path); + } + /// /// Moves an existing directory to a new location, providing the option to specify a new directory name. /// diff --git a/src/Cake.Common/IO/EnsureDirectoryDoesNotExistSettings.cs b/src/Cake.Common/IO/EnsureDirectoryDoesNotExistSettings.cs new file mode 100644 index 0000000000..27e174d158 --- /dev/null +++ b/src/Cake.Common/IO/EnsureDirectoryDoesNotExistSettings.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Cake.Common.IO +{ + /// + /// Contains settings used by EnsureDirectoryDoesNotExistSettings. + /// + public class EnsureDirectoryDoesNotExistSettings : DeleteDirectorySettings + { + } +} diff --git a/src/Cake.Common/IO/FileAliases.cs b/src/Cake.Common/IO/FileAliases.cs index 7ca10ee925..eac90d6ca5 100644 --- a/src/Cake.Common/IO/FileAliases.cs +++ b/src/Cake.Common/IO/FileAliases.cs @@ -100,7 +100,7 @@ public static void CopyFile(this ICakeContext context, FilePath filePath, FilePa /// [CakeMethodAlias] [CakeAliasCategory("Copy")] - public static void CopyFiles(this ICakeContext context, string pattern, DirectoryPath targetDirectoryPath) + public static void CopyFiles(this ICakeContext context, GlobPattern pattern, DirectoryPath targetDirectoryPath) { FileCopier.CopyFiles(context, pattern, targetDirectoryPath, false); } @@ -166,7 +166,7 @@ public static void CopyFiles(this ICakeContext context, IEnumerable file /// [CakeMethodAlias] [CakeAliasCategory("Copy")] - public static void CopyFiles(this ICakeContext context, string pattern, DirectoryPath targetDirectoryPath, bool preserveFolderStructure) + public static void CopyFiles(this ICakeContext context, GlobPattern pattern, DirectoryPath targetDirectoryPath, bool preserveFolderStructure) { FileCopier.CopyFiles(context, pattern, targetDirectoryPath, preserveFolderStructure); } @@ -251,7 +251,7 @@ public static void MoveFileToDirectory(this ICakeContext context, FilePath fileP /// [CakeMethodAlias] [CakeAliasCategory("Move")] - public static void MoveFiles(this ICakeContext context, string pattern, DirectoryPath targetDirectoryPath) + public static void MoveFiles(this ICakeContext context, GlobPattern pattern, DirectoryPath targetDirectoryPath) { FileMover.MoveFiles(context, pattern, targetDirectoryPath); } @@ -305,7 +305,7 @@ public static void MoveFile(this ICakeContext context, FilePath filePath, FilePa /// [CakeMethodAlias] [CakeAliasCategory("Delete")] - public static void DeleteFiles(this ICakeContext context, string pattern) + public static void DeleteFiles(this ICakeContext context, GlobPattern pattern) { FileDeleter.DeleteFiles(context, pattern); } diff --git a/src/Cake.Common/IO/FileCopier.cs b/src/Cake.Common/IO/FileCopier.cs index bb59bcfb48..d633bcc3cb 100644 --- a/src/Cake.Common/IO/FileCopier.cs +++ b/src/Cake.Common/IO/FileCopier.cs @@ -60,7 +60,7 @@ public static void CopyFile(ICakeContext context, FilePath filePath, FilePath ta CopyFileCore(context, filePath, targetFilePath, null); } - public static void CopyFiles(ICakeContext context, string pattern, DirectoryPath targetDirectoryPath, bool preserverFolderStructure) + public static void CopyFiles(ICakeContext context, GlobPattern pattern, DirectoryPath targetDirectoryPath, bool preserverFolderStructure) { if (context == null) { @@ -85,19 +85,22 @@ public static void CopyFiles(ICakeContext context, IEnumerable filePat { if (context == null) { - throw new ArgumentNullException("context"); + throw new ArgumentNullException(nameof(context)); } if (filePaths == null) { - throw new ArgumentNullException("filePaths"); + throw new ArgumentNullException(nameof(filePaths)); } if (targetDirectoryPath == null) { - throw new ArgumentNullException("targetDirectoryPath"); + throw new ArgumentNullException(nameof(targetDirectoryPath)); } + // Make all path absolute var absoluteTargetDirectoryPath = targetDirectoryPath.MakeAbsolute(context.Environment); + var absoluteFilePaths = filePaths.Select(x => x.MakeAbsolute(context.Environment)).ToList(); + // Make sure the target directory exist. if (!context.FileSystem.Exist(absoluteTargetDirectoryPath)) { @@ -109,18 +112,18 @@ public static void CopyFiles(ICakeContext context, IEnumerable filePat if (preserverFolderStructure) { var commonPath = string.Empty; - var separatedPath = filePaths - .First(str => str.ToString().Length == filePaths.Max(st2 => st2.ToString().Length)).ToString() - .Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries) + var separatedPath = absoluteFilePaths + .First(str => str.ToString().Length == absoluteFilePaths.Max(st2 => st2.ToString().Length)).ToString() + .Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries) .ToList(); foreach (string pathSegment in separatedPath) { - if (commonPath.Length == 0 && filePaths.All(str => str.ToString().StartsWith(pathSegment))) + if (commonPath.Length == 0 && absoluteFilePaths.All(str => str.ToString().StartsWith(pathSegment))) { commonPath = pathSegment; } - else if (filePaths.All(str => str.ToString().StartsWith(commonPath + "/" + pathSegment))) + else if (absoluteFilePaths.All(str => str.ToString().StartsWith(commonPath + "/" + pathSegment))) { commonPath += "/" + pathSegment; } @@ -130,16 +133,39 @@ public static void CopyFiles(ICakeContext context, IEnumerable filePat } } + if (absoluteFilePaths.Count == 1 && absoluteFilePaths.First().FullPath.Contains(context.Environment.WorkingDirectory.FullPath)) + { + var relativePath = absoluteFilePaths.First().FullPath.Remove(0, context.Environment.WorkingDirectory.FullPath.Length + 1); + var relativePathParts = relativePath.Split('/').ToList(); + + if (relativePathParts.Count > 2) + { + relativePathParts.RemoveAt(0); + var workdirRelativeStructurePath = string.Join("/", relativePathParts.ToArray()); + + var index = commonPath.IndexOf(workdirRelativeStructurePath, StringComparison.Ordinal); + commonPath = index < 0 + ? commonPath + : commonPath.Remove(index, workdirRelativeStructurePath.Length); + } + } + // Iterate all files and copy them. - foreach (var filePath in filePaths) + foreach (var filePath in absoluteFilePaths) { CopyFileCore(context, filePath, absoluteTargetDirectoryPath.GetFilePath(filePath), context.DirectoryExists(commonPath) ? commonPath : null); } } else { + // #1663: For empty enumerations, just return. + if (!absoluteFilePaths.Any()) + { + return; + } + // Iterate all files and copy them. - foreach (var filePath in filePaths) + foreach (var filePath in absoluteFilePaths) { CopyFileCore(context, filePath, absoluteTargetDirectoryPath.GetFilePath(filePath), null); } diff --git a/src/Cake.Common/IO/FileDeleter.cs b/src/Cake.Common/IO/FileDeleter.cs index 252e3f80b4..b1b884a3b0 100644 --- a/src/Cake.Common/IO/FileDeleter.cs +++ b/src/Cake.Common/IO/FileDeleter.cs @@ -14,7 +14,7 @@ namespace Cake.Common.IO { internal static class FileDeleter { - public static void DeleteFiles(ICakeContext context, string pattern) + public static void DeleteFiles(ICakeContext context, GlobPattern pattern) { if (context == null) { diff --git a/src/Cake.Common/IO/FileMover.cs b/src/Cake.Common/IO/FileMover.cs index 1e7dde1cf0..b41c48e687 100644 --- a/src/Cake.Common/IO/FileMover.cs +++ b/src/Cake.Common/IO/FileMover.cs @@ -31,7 +31,7 @@ public static void MoveFileToDirectory(ICakeContext context, FilePath filePath, MoveFile(context, filePath, targetDirectoryPath.GetFilePath(filePath)); } - public static void MoveFiles(ICakeContext context, string pattern, DirectoryPath targetDirectoryPath) + public static void MoveFiles(ICakeContext context, GlobPattern pattern, DirectoryPath targetDirectoryPath) { if (context == null) { diff --git a/src/Cake.Common/IO/GlobbingAliases.cs b/src/Cake.Common/IO/GlobbingAliases.cs index ff52cfd3b6..bcd1fa292d 100644 --- a/src/Cake.Common/IO/GlobbingAliases.cs +++ b/src/Cake.Common/IO/GlobbingAliases.cs @@ -33,7 +33,7 @@ public static class GlobbingAliases /// A . [CakeMethodAlias] [CakeAliasCategory("Files")] - public static FilePathCollection GetFiles(this ICakeContext context, string pattern) + public static FilePathCollection GetFiles(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -43,39 +43,6 @@ public static FilePathCollection GetFiles(this ICakeContext context, string patt return new FilePathCollection(context.Globber.Match(pattern).OfType()); } - /// - /// Gets all files matching the specified pattern. - /// - /// - /// - /// Func<IFileSystemInfo, bool> exclude_node_modules = - /// fileSystemInfo => !fileSystemInfo.Path.FullPath.EndsWith( - /// "node_modules", StringComparison.OrdinalIgnoreCase); - /// - /// var files = GetFiles("./**/Cake.*.dll", exclude_node_modules); - /// foreach(var file in files) - /// { - /// Information("File: {0}", file); - /// } - /// - /// - /// The context. - /// The glob pattern to match. - /// The predicate used to filter directories based on file system information. - /// A . - [CakeMethodAlias] - [CakeAliasCategory("Files")] - [Obsolete("Please use the GetFiles overload that accept globber settings instead.", false)] - public static FilePathCollection GetFiles(this ICakeContext context, string pattern, Func predicate) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - return new FilePathCollection(context.Globber.Match(pattern, predicate).OfType()); - } - /// /// Gets all files matching the specified pattern. /// @@ -94,11 +61,11 @@ public static FilePathCollection GetFiles(this ICakeContext context, string patt /// /// The context. /// The glob pattern to match. - /// The globber settings.. + /// The globber settings. /// A . [CakeMethodAlias] [CakeAliasCategory("Files")] - public static FilePathCollection GetFiles(this ICakeContext context, string pattern, GlobberSettings settings) + public static FilePathCollection GetFiles(this ICakeContext context, GlobPattern pattern, GlobberSettings settings) { if (context == null) { @@ -125,7 +92,7 @@ public static FilePathCollection GetFiles(this ICakeContext context, string patt /// A . [CakeMethodAlias] [CakeAliasCategory("Directories")] - public static DirectoryPathCollection GetDirectories(this ICakeContext context, string pattern) + public static DirectoryPathCollection GetDirectories(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -135,39 +102,6 @@ public static DirectoryPathCollection GetDirectories(this ICakeContext context, return new DirectoryPathCollection(context.Globber.Match(pattern).OfType()); } - /// - /// Gets all directories matching the specified pattern. - /// - /// - /// - /// Func<IFileSystemInfo, bool> exclude_node_modules = - /// fileSystemInfo => !fileSystemInfo.Path.FullPath.EndsWith( - /// "node_modules", StringComparison.OrdinalIgnoreCase); - /// - /// var directories = GetDirectories("./src/**/obj/*", exclude_node_modules); - /// foreach(var directory in directories) - /// { - /// Information("Directory: {0}", directory); - /// } - /// - /// - /// The context. - /// The glob pattern to match. - /// The predicate used to filter directories based on file system information. - /// A . - [CakeMethodAlias] - [CakeAliasCategory("Directories")] - [Obsolete("Please use the GetDirectories overload that accept globber settings instead.", false)] - public static DirectoryPathCollection GetDirectories(this ICakeContext context, string pattern, Func predicate) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - return new DirectoryPathCollection(context.Globber.Match(pattern, predicate).OfType()); - } - /// /// Gets all directories matching the specified pattern. /// @@ -190,7 +124,7 @@ public static DirectoryPathCollection GetDirectories(this ICakeContext context, /// A . [CakeMethodAlias] [CakeAliasCategory("Directories")] - public static DirectoryPathCollection GetDirectories(this ICakeContext context, string pattern, GlobberSettings settings) + public static DirectoryPathCollection GetDirectories(this ICakeContext context, GlobPattern pattern, GlobberSettings settings) { if (context == null) { @@ -206,7 +140,7 @@ public static DirectoryPathCollection GetDirectories(this ICakeContext context, /// /// /// var paths = GetPaths("./src/**/obj/*"); - /// foreach(var paths in paths) + /// foreach(var path in paths) /// { /// Information("Path: {0}", path); /// } @@ -217,7 +151,7 @@ public static DirectoryPathCollection GetDirectories(this ICakeContext context, /// A . [CakeMethodAlias] [CakeAliasCategory("Paths")] - public static PathCollection GetPaths(this ICakeContext context, string pattern) + public static PathCollection GetPaths(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -237,7 +171,7 @@ public static PathCollection GetPaths(this ICakeContext context, string pattern) /// "node_modules", StringComparison.OrdinalIgnoreCase); /// /// var paths = GetPaths("./src/**/obj/*", new GlobberSettings { Predicate = exclude_node_modules }); - /// foreach(var paths in paths) + /// foreach(var path in paths) /// { /// Information("Path: {0}", path); /// } @@ -249,7 +183,7 @@ public static PathCollection GetPaths(this ICakeContext context, string pattern) /// A . [CakeMethodAlias] [CakeAliasCategory("Paths")] - public static PathCollection GetPaths(this ICakeContext context, string pattern, GlobberSettings settings) + public static PathCollection GetPaths(this ICakeContext context, GlobPattern pattern, GlobberSettings settings) { if (context == null) { @@ -259,4 +193,4 @@ public static PathCollection GetPaths(this ICakeContext context, string pattern, return new PathCollection(context.Globber.Match(pattern, settings)); } } -} \ No newline at end of file +} diff --git a/src/Cake.Common/IO/Paths/ConvertableDirectoryPath.cs b/src/Cake.Common/IO/Paths/ConvertableDirectoryPath.cs index 4541a1c3b1..7a0c15b1d4 100644 --- a/src/Cake.Common/IO/Paths/ConvertableDirectoryPath.cs +++ b/src/Cake.Common/IO/Paths/ConvertableDirectoryPath.cs @@ -66,6 +66,28 @@ internal ConvertableDirectoryPath(DirectoryPath path) return new ConvertableDirectoryPath(left.Path.Combine(right.Path)); } + /// + /// Operator that combines A instance + /// with a instance. + /// + /// The left directory path operand. + /// The right directory path operand. + /// A new directory path representing a combination of the two provided paths. + public static ConvertableDirectoryPath operator +(DirectoryPath left, ConvertableDirectoryPath right) + { + if (left is null) + { + throw new ArgumentNullException(nameof(left)); + } + + if (right is null) + { + throw new ArgumentNullException(nameof(right)); + } + + return new ConvertableDirectoryPath(left.Combine(right)); + } + /// /// Operator that combines A instance /// with a instance. diff --git a/src/Cake.Common/Modules/CommonModule.cs b/src/Cake.Common/Modules/CommonModule.cs index edcc808bf4..aa385828ff 100644 --- a/src/Cake.Common/Modules/CommonModule.cs +++ b/src/Cake.Common/Modules/CommonModule.cs @@ -12,10 +12,7 @@ namespace Cake.Common.Modules /// public sealed class CommonModule : ICakeModule { - /// - /// Performs custom registrations in the provided registrar. - /// - /// The container registrar. + /// public void Register(ICakeContainerRegistrar registrar) { } diff --git a/src/Cake.Common/Polyfill/XmlTransformationHelper.cs b/src/Cake.Common/Polyfill/XmlTransformationHelper.cs index f86654f431..a5cdd787bf 100644 --- a/src/Cake.Common/Polyfill/XmlTransformationHelper.cs +++ b/src/Cake.Common/Polyfill/XmlTransformationHelper.cs @@ -9,11 +9,11 @@ namespace Cake.Common.Polyfill { internal static class XmlTransformationHelper { - public static void Transform(XmlReader xsl, XmlReader xml, XmlWriter result) + public static void Transform(XmlReader xsl, XsltArgumentList arguments, XmlReader xml, XmlWriter result) { var xslTransform = new XslCompiledTransform(); xslTransform.Load(xsl); - xslTransform.Transform(xml, result); + xslTransform.Transform(xml, arguments, result); } } } diff --git a/src/Cake.Common/ReleaseNotes.cs b/src/Cake.Common/ReleaseNotes.cs index adef27c75e..b02fefc893 100644 --- a/src/Cake.Common/ReleaseNotes.cs +++ b/src/Cake.Common/ReleaseNotes.cs @@ -15,6 +15,12 @@ public sealed class ReleaseNotes { private readonly List _notes; + /// + /// Gets the version. + /// + /// The version. + public SemVersion SemVersion { get; } + /// /// Gets the version. /// @@ -33,6 +39,21 @@ public sealed class ReleaseNotes /// The raw text of the Version line. public string RawVersionLine { get; } + /// + /// Initializes a new instance of the class. + /// + /// The semantic version. + /// The notes. + /// The raw text of the version line. + public ReleaseNotes(SemVersion semVersion, IEnumerable notes, string rawVersionLine) + : this( + semVersion?.AssemblyVersion ?? throw new ArgumentNullException(nameof(semVersion)), + semVersion, + notes, + rawVersionLine) + { + } + /// /// Initializes a new instance of the class. /// @@ -40,12 +61,18 @@ public sealed class ReleaseNotes /// The notes. /// The raw text of the version line. public ReleaseNotes(Version version, IEnumerable notes, string rawVersionLine) + : this( + version ?? throw new ArgumentNullException(nameof(version)), + new SemVersion(version.Major, version.Minor, version.Build), + notes, + rawVersionLine) + { + } + + private ReleaseNotes(Version version, SemVersion semVersion, IEnumerable notes, string rawVersionLine) { - if (version == null) - { - throw new ArgumentNullException(nameof(version)); - } - Version = version; + Version = version ?? throw new ArgumentNullException(nameof(version)); + SemVersion = semVersion ?? throw new ArgumentNullException(nameof(semVersion)); RawVersionLine = rawVersionLine; _notes = new List(notes ?? Enumerable.Empty()); } diff --git a/src/Cake.Common/ReleaseNotesAliases.cs b/src/Cake.Common/ReleaseNotesAliases.cs index ab7ca2a140..f98e84fd0e 100644 --- a/src/Cake.Common/ReleaseNotesAliases.cs +++ b/src/Cake.Common/ReleaseNotesAliases.cs @@ -17,6 +17,7 @@ namespace Cake.Common /// Contains functionality related to release notes. /// [CakeAliasCategory("Release Notes")] + public static class ReleaseNotesAliases { private static readonly ReleaseNotesParser _parser; diff --git a/src/Cake.Common/ReleaseNotesParser.cs b/src/Cake.Common/ReleaseNotesParser.cs index 70970e1358..44f0c84ef5 100644 --- a/src/Cake.Common/ReleaseNotesParser.cs +++ b/src/Cake.Common/ReleaseNotesParser.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - using System; using System.Collections.Generic; using System.Linq; @@ -22,7 +21,7 @@ public sealed class ReleaseNotesParser /// public ReleaseNotesParser() { - _versionRegex = new Regex(@"([0-9]+\.)+[0-9]+"); + _versionRegex = new Regex(@"(?\d+(\s*\.\s*\d+){0,3})(?-[a-z][0-9a-z-]*)?"); } /// @@ -68,15 +67,14 @@ private IReadOnlyList ParseComplexFormat(string[] lines) break; } - // Parse header. - var versionResult = _versionRegex.Match(lines[lineIndex]); - if (!versionResult.Success) + // Create release notes. + var semVer = SemVersion.Zero; + var version = SemVersion.TryParse(lines[lineIndex], out semVer); + if (!version) { throw new CakeException("Could not parse version from release notes header."); } - // Create release notes. - var version = Version.Parse(versionResult.Value); var rawVersionLine = lines[lineIndex]; // Increase the line index. @@ -106,10 +104,10 @@ private IReadOnlyList ParseComplexFormat(string[] lines) lineIndex++; } - result.Add(new ReleaseNotes(version, notes, rawVersionLine)); + result.Add(new ReleaseNotes(semVer, notes, rawVersionLine)); } - return result.OrderByDescending(x => x.Version).ToArray(); + return result.OrderByDescending(x => x.SemVersion).ToArray(); } private IReadOnlyList ParseSimpleFormat(string[] lines) @@ -133,24 +131,22 @@ private IReadOnlyList ParseSimpleFormat(string[] lines) } // Parse header. - var versionResult = _versionRegex.Match(line); - if (!versionResult.Success) + var semVer = SemVersion.Zero; + var version = SemVersion.TryParse(lines[lineIndex], out semVer); + if (!version) { throw new CakeException("Could not parse version from release notes header."); } - - var version = Version.Parse(versionResult.Value); - // Parse the description. - line = line.Substring(versionResult.Length).Trim('-', ' '); + line = line.Substring(semVer.ToString().Length).Trim('-', ' '); // Add the release notes to the result. - result.Add(new ReleaseNotes(version, new[] { line }, line)); + result.Add(new ReleaseNotes(semVer, new[] { line }, line)); lineIndex++; } - return result.OrderByDescending(x => x.Version).ToArray(); + return result.OrderByDescending(x => x.SemVersion).ToArray(); } } } \ No newline at end of file diff --git a/src/Cake.Common/Security/DirectoryHash.cs b/src/Cake.Common/Security/DirectoryHash.cs new file mode 100644 index 0000000000..ec50b38e37 --- /dev/null +++ b/src/Cake.Common/Security/DirectoryHash.cs @@ -0,0 +1,90 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using Cake.Core.IO; + +namespace Cake.Common.Security +{ + /// + /// Represents a calculated directory hash. + /// + public sealed class DirectoryHash + { + private readonly byte[] _hash; + + /// + /// Initializes a new instance of the class. + /// + /// The directory path. + /// The computed hash. + /// The algorithm used. + /// List of all computed . + public DirectoryHash( + DirectoryPath directoryPath, + byte[] hash, + HashAlgorithm hashAlgorithm, + IEnumerable fileHashList) + { + if (directoryPath == null) + { + throw new ArgumentNullException(nameof(directoryPath)); + } + + if (hash == null) + { + throw new ArgumentNullException(nameof(hash)); + } + + if (fileHashList == null) + { + throw new ArgumentNullException(nameof(fileHashList)); + } + + Path = directoryPath; + _hash = (byte[])hash.Clone(); + Algorithm = hashAlgorithm; + FileHashList.AddRange(fileHashList); + } + + /// + /// Gets the algorithm used for the hash computation. + /// + public HashAlgorithm Algorithm { get; } + + /// + /// Gets the for the directory. + /// + public DirectoryPath Path { get; } + + /// + /// Gets the list of for all files of the directory. + /// + public List FileHashList { get; } = new List(); + + /// + /// Gets the raw computed hash. + /// + public byte[] ComputedHash => (byte[])_hash.Clone(); + + /// + /// Convert the directory hash to a hexadecimal string. + /// + /// A hexadecimal string representing the computed hash. + public string ToHex() + { + // Each byte becomes two characters. Prepare the StringBuilder accordingly. + var builder = new StringBuilder(_hash.Length * 2); + + foreach (var b in _hash) + { + builder.AppendFormat("{0:x2}", b); + } + + return builder.ToString(); + } + } +} diff --git a/src/Cake.Common/Security/DirectoryHashCalculator.cs b/src/Cake.Common/Security/DirectoryHashCalculator.cs new file mode 100644 index 0000000000..c226c08be6 --- /dev/null +++ b/src/Cake.Common/Security/DirectoryHashCalculator.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using Cake.Common.IO; +using Cake.Core; +using Cake.Core.IO; + +namespace Cake.Common.Security +{ + /// + /// Class for calculating a hash for a directory. + /// + public class DirectoryHashCalculator + { + private readonly ICakeContext _context; + private readonly IHashAlgorithmBuilder _hashAlgorithmBuilder; + private readonly FileHashCalculator _fileHashCalculator; + + /// + /// Initializes a new instance of the class. + /// + /// The cake context. + /// The hash algorithm builder. + public DirectoryHashCalculator(ICakeContext context, IHashAlgorithmBuilder hashAlgorithmBuilder) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (hashAlgorithmBuilder == null) + { + throw new ArgumentNullException(nameof(hashAlgorithmBuilder)); + } + + _context = context; + _hashAlgorithmBuilder = hashAlgorithmBuilder; + _fileHashCalculator = new FileHashCalculator(_context.FileSystem, _hashAlgorithmBuilder); + } + + /// + /// Calculates the hash for a given directory. + /// + /// The directory path. + /// The glob pattern to match. + /// The hash algorithm to use. + /// A instance representing the calculated hash. + /// + /// + /// Information( + /// "Cake It calculates the hashes from all cs files in all subdirectories using a MD5 hash: {0}", + /// CalculateDirectoryHash("C:\directoryToHash", "./**/*.cs", HashAlgorithm.MD5).ToHex()); + /// + /// + public DirectoryHash Calculate( + DirectoryPath directoryPath, + IEnumerable pattern, + HashAlgorithm hashAlgorithm) + { + if (directoryPath == null) + { + throw new ArgumentNullException(nameof(directoryPath)); + } + + if (pattern == null) + { + throw new ArgumentNullException(nameof(pattern)); + } + + using (var incrementalDirectoryHash = _hashAlgorithmBuilder.CreateHashAlgorithm(hashAlgorithm)) + { + var fileHashList = new List(); + var files = GetDirectoryFiles(directoryPath, pattern).OrderBy(file => file.FullPath); + if (files.Any()) + { + var lastFile = files.LastOrDefault(); + foreach (var file in GetDirectoryFiles(directoryPath, pattern)) + { + var fileContentAndNameHash = CalculateFileContentAndNameHash(file, directoryPath, hashAlgorithm); + fileHashList.Add(fileContentAndNameHash); + if (file == lastFile) + { + incrementalDirectoryHash.TransformFinalBlock( + fileContentAndNameHash.ComputedHash, 0, + fileContentAndNameHash.ComputedHash.Length); + } + else + { + incrementalDirectoryHash.TransformBlock( + fileContentAndNameHash.ComputedHash, 0, + fileContentAndNameHash.ComputedHash.Length, + fileContentAndNameHash.ComputedHash, 0); + } + } + + var directoryHash = incrementalDirectoryHash.Hash; + return new DirectoryHash(directoryPath, directoryHash, hashAlgorithm, fileHashList); + } + + // No files found. + return null; + } + } + + /// + /// Calculates the hash for a given directory. + /// + /// The directory path. + /// The glob pattern to match. + /// The hash algorithm to use. + /// A instance representing the calculated hash. + /// + /// + /// Information( + /// "Cake It calculates the hashes from all cs files in all subdirectories using a MD5 hash: {0}", + /// CalculateDirectoryHash("C:\directoryToHash", "./**/*.cs", HashAlgorithm.MD5).ToHex()); + /// + /// + public DirectoryHash Calculate( + DirectoryPath directoryPath, + IEnumerable pattern, + HashAlgorithm hashAlgorithm) + { + if (directoryPath == null) + { + throw new ArgumentNullException(nameof(directoryPath)); + } + + if (pattern == null) + { + throw new ArgumentNullException(nameof(pattern)); + } + + return Calculate( + directoryPath, + pattern.Select(GlobPattern.FromString), + hashAlgorithm); + } + + private FilePathCollection GetDirectoryFiles( + DirectoryPath directoryPath, + IEnumerable pattern) + { + var directory = new Directory(directoryPath); + + if (!directory.Exists) + { + const string format = "Directory '{0}' does not exist."; + var message = string.Format(CultureInfo.InvariantCulture, format, directoryPath.FullPath); + throw new CakeException(message); + } + + var filePathCollection = new FilePathCollection(); + var fullGlobs = pattern.Select(x => directoryPath + x.Pattern).ToArray(); + + foreach (var glob in fullGlobs) + { + foreach (var file in _context.GetFiles(glob)) + { + filePathCollection.Add(file); + } + } + + return filePathCollection; + } + + private FileHash CalculateFileContentAndNameHash( + FilePath filePath, + DirectoryPath directoryPath, + HashAlgorithm hashAlgorithm) + { + if (filePath == null) + { + throw new ArgumentNullException(nameof(filePath)); + } + + if (directoryPath == null) + { + throw new ArgumentNullException(nameof(directoryPath)); + } + + using (var incrementalFileHash = _hashAlgorithmBuilder.CreateHashAlgorithm(hashAlgorithm)) + { + // Calculate file content hash + var fileContentHash = _fileHashCalculator.Calculate(filePath, hashAlgorithm); + + // Combine file content hash + incrementalFileHash.TransformBlock( + fileContentHash.ComputedHash, 0, + fileContentHash.ComputedHash.Length, + fileContentHash.ComputedHash, 0); + + // combine filename hash + var relativeFilePath = filePath.GetRelativePath(directoryPath); + var fileFullNameArray = Encoding.ASCII.GetBytes(filePath.GetFilename().FullPath); + using (var hashAlgorithmInstance = _hashAlgorithmBuilder.CreateHashAlgorithm(hashAlgorithm)) + { + var filenameHash = hashAlgorithmInstance.ComputeHash(fileFullNameArray); + incrementalFileHash.TransformFinalBlock( + filenameHash, 0, + filenameHash.Length); + } + var fileContentAndNameHash = incrementalFileHash.Hash; + + return new FileHash(filePath, fileContentAndNameHash, hashAlgorithm); + } + } + } +} diff --git a/src/Cake.Common/Security/FileHashCalculator.cs b/src/Cake.Common/Security/FileHashCalculator.cs index 12814c6829..b1eacc67fe 100644 --- a/src/Cake.Common/Security/FileHashCalculator.cs +++ b/src/Cake.Common/Security/FileHashCalculator.cs @@ -16,19 +16,36 @@ namespace Cake.Common.Security public sealed class FileHashCalculator { private readonly IFileSystem _fileSystem; + private readonly IHashAlgorithmBuilder _hashAlgorithmBuilder; /// /// Initializes a new instance of the class. /// /// The file system. public FileHashCalculator(IFileSystem fileSystem) + : this(fileSystem, new HashAlgorithmBuilder()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The file system. + /// The hash algorithm builder. + public FileHashCalculator(IFileSystem fileSystem, IHashAlgorithmBuilder hashAlgorithmBuilder) { if (fileSystem == null) { throw new ArgumentNullException(nameof(fileSystem)); } + if (hashAlgorithmBuilder == null) + { + throw new ArgumentNullException(nameof(hashAlgorithmBuilder)); + } + _fileSystem = fileSystem; + _hashAlgorithmBuilder = hashAlgorithmBuilder; } /// @@ -53,29 +70,12 @@ public FileHash Calculate(FilePath filePath, HashAlgorithm hashAlgorithm) throw new CakeException(message); } - using (var hashAlgo = GetHashAlgorithm(hashAlgorithm)) + using (var hashAlgo = _hashAlgorithmBuilder.CreateHashAlgorithm(hashAlgorithm)) using (var readStream = file.OpenRead()) { var hash = hashAlgo.ComputeHash(readStream); return new FileHash(filePath, hash, hashAlgorithm); } } - - private System.Security.Cryptography.HashAlgorithm GetHashAlgorithm(HashAlgorithm hashAlgorithm) - { - switch (hashAlgorithm) - { - case HashAlgorithm.MD5: - return MD5.Create(); - - case HashAlgorithm.SHA256: - return SHA256.Create(); - - case HashAlgorithm.SHA512: - return SHA512.Create(); - } - - throw new NotSupportedException(hashAlgorithm.ToString()); - } } } \ No newline at end of file diff --git a/src/Cake.Common/Security/HashAlgorithmBuilder.cs b/src/Cake.Common/Security/HashAlgorithmBuilder.cs new file mode 100644 index 0000000000..d74ea129db --- /dev/null +++ b/src/Cake.Common/Security/HashAlgorithmBuilder.cs @@ -0,0 +1,27 @@ +using System; +using System.Security.Cryptography; + +namespace Cake.Common.Security +{ + /// + public sealed class HashAlgorithmBuilder : IHashAlgorithmBuilder + { + /// + public System.Security.Cryptography.HashAlgorithm CreateHashAlgorithm(HashAlgorithm hashAlgorithm) + { + switch (hashAlgorithm) + { + case HashAlgorithm.MD5: + return MD5.Create(); + + case HashAlgorithm.SHA256: + return SHA256.Create(); + + case HashAlgorithm.SHA512: + return SHA512.Create(); + } + + throw new NotSupportedException(hashAlgorithm.ToString()); + } + } +} diff --git a/src/Cake.Common/Security/IHashAlgorithmBuilder.cs b/src/Cake.Common/Security/IHashAlgorithmBuilder.cs new file mode 100644 index 0000000000..6000e07a02 --- /dev/null +++ b/src/Cake.Common/Security/IHashAlgorithmBuilder.cs @@ -0,0 +1,17 @@ +namespace Cake.Common.Security +{ + /// + /// Creates a instance by + /// . + /// + public interface IHashAlgorithmBuilder + { + /// + /// Return a instance of by + /// enum value. + /// + /// Algorithm enum value. + /// A instance. + System.Security.Cryptography.HashAlgorithm CreateHashAlgorithm(HashAlgorithm hashAlgorithm); + } +} \ No newline at end of file diff --git a/src/Cake.Common/Security/SecurityAliases.cs b/src/Cake.Common/Security/SecurityAliases.cs index 9a46db948a..33611b7efe 100644 --- a/src/Cake.Common/Security/SecurityAliases.cs +++ b/src/Cake.Common/Security/SecurityAliases.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using Cake.Core; using Cake.Core.Annotations; using Cake.Core.IO; @@ -57,8 +58,106 @@ public static FileHash CalculateFileHash(this ICakeContext context, FilePath fil throw new ArgumentNullException(nameof(context)); } - var fileHashCalculator = new FileHashCalculator(context.FileSystem); + var fileHashCalculator = new FileHashCalculator(context.FileSystem, new HashAlgorithmBuilder()); return fileHashCalculator.Calculate(filePath, hashAlgorithm); } + + /// + /// Calculates the hash for a given directory using the default (SHA256) algorithm. + /// + /// The context. + /// The file path. + /// The glob pattern to match. + /// A instance representing the calculated hash. + /// + /// + /// Information( + /// "Cake It calculates the hashes from all cs files in all subdirectories using a SHA256 hash: {0}", + /// CalculateDirectoryHash("C:\directoryToHash", "./**/*.cs").ToHex()); + /// + /// + [CakeMethodAlias] + public static DirectoryHash CalculateDirectoryHash(this ICakeContext context, + IEnumerable globs, DirectoryPath directoryPath) + { + return CalculateDirectoryHash(context, directoryPath, globs, HashAlgorithm.SHA256); + } + + /// + /// Calculates the hash for a given directory. + /// + /// The context. + /// The file path. + /// The glob pattern to match. + /// The hash algorithm to use. + /// A instance representing the calculated hash. + /// + /// + /// Information( + /// "Cake It calculates the hashes from all cs files in all subdirectories using a MD5 hash: {0}", + /// CalculateDirectoryHash("C:\directoryToHash", "./**/*.cs", HashAlgorithm.MD5).ToHex()); + /// + /// + [CakeMethodAlias] + public static DirectoryHash CalculateDirectoryHash(this ICakeContext context, + DirectoryPath directoryPath, IEnumerable globs, HashAlgorithm hashAlgorithm) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var directoryHashCalculator = new DirectoryHashCalculator(context, new HashAlgorithmBuilder()); + return directoryHashCalculator.Calculate(directoryPath, globs, hashAlgorithm); + } + + /// + /// Calculates the hash for a given directory using the default (SHA256) algorithm. + /// + /// The context. + /// The file path. + /// The glob pattern to match. + /// A instance representing the calculated hash. + /// + /// + /// Information( + /// "Cake It calculates the hashes from all cs files in all subdirectories using a SHA256 hash: {0}", + /// CalculateDirectoryHash("C:\directoryToHash", "./**/*.cs").ToHex()); + /// + /// + [CakeMethodAlias] + public static DirectoryHash CalculateDirectoryHash(this ICakeContext context, + IEnumerable globs, DirectoryPath directoryPath) + { + return CalculateDirectoryHash(context, directoryPath, globs, HashAlgorithm.SHA256); + } + + /// + /// Calculates the hash for a given directory. + /// + /// The context. + /// The file path. + /// The glob pattern to match. + /// The hash algorithm to use. + /// A instance representing the calculated hash. + /// + /// + /// Information( + /// "Cake It calculates the hashes from all cs files in all subdirectories using a MD5 hash: {0}", + /// CalculateDirectoryHash("C:\directoryToHash", "./**/*.cs", HashAlgorithm.MD5).ToHex()); + /// + /// + [CakeMethodAlias] + public static DirectoryHash CalculateDirectoryHash(this ICakeContext context, + DirectoryPath directoryPath, IEnumerable globs, HashAlgorithm hashAlgorithm) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var directoryHashCalculator = new DirectoryHashCalculator(context, new HashAlgorithmBuilder()); + return directoryHashCalculator.Calculate(directoryPath, globs, hashAlgorithm); + } } } \ No newline at end of file diff --git a/src/Cake.Common/SemanticVersion.cs b/src/Cake.Common/SemanticVersion.cs new file mode 100644 index 0000000000..3d67dd35ad --- /dev/null +++ b/src/Cake.Common/SemanticVersion.cs @@ -0,0 +1,375 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using System.Text; +using System.Text.RegularExpressions; + +namespace Cake.Common +{ + /// + /// Class for representing semantic versions. + /// + public class SemVersion : IComparable, IComparable, IEquatable + { + /// + /// Gets the default version of a SemanticVersion. + /// + public static SemVersion Zero { get; } = new SemVersion(0, 0, 0, null, null, "0.0.0"); + + /// + /// Regex property for parsing a semantic version number. + /// + public static readonly Regex SemVerRegex = + new Regex( + @"(?0|(?:[1-9]\d*))(?:\.(?0|(?:[1-9]\d*))(?:\.(?0|(?:[1-9]\d*)))?(?:\-(?[0-9A-Z\.-]+))?(?:\+(?[0-9A-Z\.-]+))?)?", + RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase); + + /// + /// Gets the major number of the version. + /// + public int Major { get; } + + /// + /// Gets the minor number of the version. + /// + public int Minor { get; } + + /// + /// Gets the patch number of the version. + /// + public int Patch { get; } + + /// + /// Gets the prerelease of the version. + /// + public string PreRelease { get; } + + /// + /// Gets the meta of the version. + /// + public string Meta { get; } + + /// + /// Gets a value indicating whether semantic version is a prerelease or not. + /// + public bool IsPreRelease { get; } + + /// + /// Gets a value indicating whether semantic version has meta or not. + /// + public bool HasMeta { get; } + + /// + /// Gets the VersionString of the semantic version. + /// + public string VersionString { get; } + + /// + /// Gets the AssemblyVersion of the semantic version. + /// + public Version AssemblyVersion { get; } + + /// + /// Initializes a new instance of the class. + /// + /// Major number. + /// Minor number. + /// Patch number. + /// Prerelease string. + /// Meta string. + public SemVersion(int major, int minor, int patch, string preRelease = null, string meta = null) : this(major, minor, patch, preRelease, meta, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Major number. + /// Minor number. + /// Patch number. + /// Prerelease string. + /// Meta string. + /// The complete version number. + public SemVersion(int major, int minor, int patch, string preRelease, string meta, string versionString) + { + Major = major; + Minor = minor; + Patch = patch; + AssemblyVersion = new Version(major, minor, patch); + IsPreRelease = !string.IsNullOrEmpty(preRelease); + HasMeta = !string.IsNullOrEmpty(meta); + PreRelease = IsPreRelease ? preRelease : null; + Meta = HasMeta ? meta : null; + + if (!string.IsNullOrEmpty(versionString)) + { + VersionString = versionString; + } + else + { + var sb = new StringBuilder(); + sb.AppendFormat(CultureInfo.InvariantCulture, "{0}.{1}.{2}", Major, Minor, Patch); + + if (IsPreRelease) + { + sb.AppendFormat(CultureInfo.InvariantCulture, "-{0}", PreRelease); + } + + if (HasMeta) + { + sb.AppendFormat(CultureInfo.InvariantCulture, "+{0}", Meta); + } + + VersionString = sb.ToString(); + } + } + + /// + /// Method which tries to parse a semantic version string. + /// + /// the version that should be parsed. + /// the out parameter the parsed version should be stored in. + /// Returns a boolean indicating if the parse was successful. + public static bool TryParse(string version, + out SemVersion semVersion) + { + semVersion = Zero; + + if (string.IsNullOrEmpty(version)) + { + return false; + } + + var match = SemVerRegex.Match(version); + if (!match.Success) + { + return false; + } + + if (!int.TryParse( + match.Groups["Major"].Value, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out var major) || + !int.TryParse( + match.Groups["Minor"].Value, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out var minor) || + !int.TryParse( + match.Groups["Patch"].Value, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out var patch)) + { + return false; + } + + semVersion = new SemVersion( + major, + minor, + patch, + match.Groups["PreRelease"]?.Value, + match.Groups["Meta"]?.Value, + version); + + return true; + } + + /// + /// Checks if two SemVersion objects are equal. + /// + /// the other SemVersion want to test equality to. + /// A boolean indicating whether the objecst we're equal or not. + public bool Equals(SemVersion other) + { + return other is object + && Major == other.Major + && Minor == other.Minor + && Patch == other.Patch + && string.Equals(PreRelease, other.PreRelease, StringComparison.OrdinalIgnoreCase) + && string.Equals(Meta, other.Meta, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Compares to SemVersion objects to and another. + /// + /// The SemVersion object we compare with. + /// Return 0 if the objects are identical, 1 if the version is newer and -1 if the version is older. + public int CompareTo(SemVersion other) + { + if (other is null) + { + return 1; + } + + if (Equals(other)) + { + return 0; + } + + if (Major > other.Major) + { + return 1; + } + + if (Major < other.Major) + { + return -1; + } + + if (Minor > other.Minor) + { + return 1; + } + + if (Minor < other.Minor) + { + return -1; + } + + if (Patch > other.Patch) + { + return 1; + } + + if (Patch < other.Patch) + { + return -1; + } + + if (IsPreRelease != other.IsPreRelease) + { + return other.IsPreRelease ? 1 : -1; + } + + switch (StringComparer.InvariantCultureIgnoreCase.Compare(PreRelease, other.PreRelease)) + { + case 1: + return 1; + + case -1: + return -1; + + default: + { + return (string.IsNullOrEmpty(Meta) != string.IsNullOrEmpty(other.Meta)) + ? string.IsNullOrEmpty(Meta) ? 1 : -1 + : StringComparer.InvariantCultureIgnoreCase.Compare(Meta, other.Meta); + } + } + } + + /// + /// Compares to SemVersion objects to and another. + /// + /// The object we compare with. + /// Return 0 if the objects are identical, 1 if the version is newer and -1 if the version is older. + public int CompareTo(object obj) + { + return (obj is SemVersion semVersion) + ? CompareTo(semVersion) + : -1; + } + + /// + /// Equals-method for the SemVersion class. + /// + /// the other SemVersion want to test equality to. + /// A boolean indicating whether the objecst we're equal or not. + public override bool Equals(object obj) + { + return (obj is SemVersion semVersion) + && Equals(semVersion); + } + + /// + /// Method for getting the hashcode of the SemVersion object. + /// + /// The hashcode of the SemVersion object. + public override int GetHashCode() + { + unchecked + { + var hashCode = Major; + hashCode = (hashCode * 397) ^ Minor; + hashCode = (hashCode * 397) ^ Patch; + hashCode = (hashCode * 397) ^ (PreRelease != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(PreRelease) : 0); + hashCode = (hashCode * 397) ^ (Meta != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(Meta) : 0); + return hashCode; + } + } + + /// + /// Returns the string representation of an SemVersion object. + /// + /// The string representation of the object. + public override string ToString() + { + int[] verParts = { Major, Minor, Patch }; + string ver = string.Join(".", verParts); + return $"{ver}{(IsPreRelease ? "-" : string.Empty)}{PreRelease}{Meta}"; + } + + /// + /// The greater than-operator for the SemVersion class. + /// + /// first SemVersion. + /// second. SemVersion. + /// A value indicating if the operand1 was greater than operand2. + public static bool operator >(SemVersion operand1, SemVersion operand2) + => operand1 is { } && operand1.CompareTo(operand2) == 1; + + /// + /// The less than-operator for the SemVersion class. + /// + /// first SemVersion. + /// second. SemVersion. + /// A value indicating if the operand1 was less than operand2. + public static bool operator <(SemVersion operand1, SemVersion operand2) + => operand1 is { } + ? operand1.CompareTo(operand2) == -1 + : operand2 is { }; + + /// + /// The greater than or equal to-operator for the SemVersion class. + /// + /// first SemVersion. + /// second. SemVersion. + /// A value indicating if the operand1 was greater than or equal to operand2. + public static bool operator >=(SemVersion operand1, SemVersion operand2) + => operand1 is { } + ? operand1.CompareTo(operand2) >= 0 + : operand2 is null; + + /// + /// The lesser than or equal to-operator for the SemVersion class. + /// + /// first SemVersion. + /// second. SemVersion. + /// A value indicating if the operand1 was lesser than or equal to operand2. + public static bool operator <=(SemVersion operand1, SemVersion operand2) + => operand1 is null || operand1.CompareTo(operand2) <= 0; + + /// + /// The equal to-operator for the SemVersion class. + /// + /// first SemVersion. + /// second. SemVersion. + /// A value indicating if the operand1 was equal to operand2. + public static bool operator ==(SemVersion operand1, SemVersion operand2) + => operand1?.Equals(operand2) ?? operand2 is null; + + /// + /// The not equal to-operator for the SemVersion class. + /// + /// first SemVersion. + /// second. SemVersion. + /// A value indicating if the operand1 was not equal to operand2. + public static bool operator !=(SemVersion operand1, SemVersion operand2) + => !(operand1?.Equals(operand2) ?? operand2 is null); + } +} diff --git a/src/Cake.Common/Solution/Project/ProjectParser.cs b/src/Cake.Common/Solution/Project/ProjectParser.cs index c7749005f6..5b68fbe83e 100644 --- a/src/Cake.Common/Solution/Project/ProjectParser.cs +++ b/src/Cake.Common/Solution/Project/ProjectParser.cs @@ -183,6 +183,7 @@ from include in element.Attributes("Include") let nameElement = element.Element(ProjectXElement.Name) let projectElement = element.Element(ProjectXElement.Project) let packageElement = element.Element(ProjectXElement.Package) + let privateElement = element.Element(ProjectXElement.Private) select new ProjectReference { FilePath = filePath, @@ -190,7 +191,8 @@ from include in element.Attributes("Include") Name = nameElement?.Value, Project = projectElement?.Value, Package = string.IsNullOrEmpty(packageElement?.Value) - ? null : rootPath.CombineWithFilePath(packageElement.Value) + ? null : rootPath.CombineWithFilePath(packageElement.Value), + Private = privateElement == null ? (bool?)null : bool.Parse(privateElement.Value), }).ToArray(); return new ProjectParserResult( diff --git a/src/Cake.Common/Solution/Project/ProjectReference.cs b/src/Cake.Common/Solution/Project/ProjectReference.cs index ac29987b42..3022a28044 100644 --- a/src/Cake.Common/Solution/Project/ProjectReference.cs +++ b/src/Cake.Common/Solution/Project/ProjectReference.cs @@ -54,5 +54,13 @@ public sealed class ProjectReference /// The path of the project file that is being referenced. /// public FilePath Package { get; set; } + + /// + /// Gets or sets whether the reference should be copied to the output folder. + /// + /// + /// Whether the reference should be copied to the output folder. + /// + public bool? Private { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreator.cs b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreator.cs index 55e53542ef..72937fc161 100644 --- a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreator.cs +++ b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoCreator.cs @@ -61,8 +61,20 @@ public AssemblyInfoCreator(IFileSystem fileSystem, ICakeEnvironment environment, /// /// The output path. /// The settings. + /// The attribute format. + /// The attribute with value format. + /// The attribute with key value format. + /// The VB attribute format. + /// The VB attribute with value format. + /// The VB attribute with key value format. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] - public void Create(FilePath outputPath, AssemblyInfoSettings settings) + public void Create(FilePath outputPath, AssemblyInfoSettings settings, + string attributeFormat = CSharpAttributeFormat, + string attributeWithValueFormat = CSharpAttributeWithValueFormat, + string attributeWithKeyValueFormat = CSharpAttributeWithKeyValueFormat, + string vbAttributeFormat = VBAttributeFormat, + string vbAttributeWithValueFormat = VBAttributeWithValueFormat, + string vbAttributeWithKeyValueFormat = VBAttributeWithKeyValueFormat) { if (outputPath == null) { @@ -74,9 +86,6 @@ public void Create(FilePath outputPath, AssemblyInfoSettings settings) } string comment = CSharpComment; string usingFormat = CSharpUsingFormat; - string attributeFormat = CSharpAttributeFormat; - string attributeWithValueFormat = CSharpAttributeWithValueFormat; - string attributeWithKeyValueFormat = CSharpAttributeWithKeyValueFormat; var isVisualBasicAssemblyInfoFile = false; @@ -85,9 +94,9 @@ public void Create(FilePath outputPath, AssemblyInfoSettings settings) isVisualBasicAssemblyInfoFile = true; comment = VBComment; usingFormat = VBUsingFormat; - attributeFormat = VBAttributeFormat; - attributeWithValueFormat = VBAttributeWithValueFormat; - attributeWithKeyValueFormat = VBAttributeWithKeyValueFormat; + attributeFormat = vbAttributeFormat; + attributeWithValueFormat = vbAttributeWithValueFormat; + attributeWithKeyValueFormat = vbAttributeWithKeyValueFormat; } var data = new AssemblyInfoCreatorData(settings, isVisualBasicAssemblyInfoFile); diff --git a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoParser.cs b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoParser.cs index 43e5b17c07..3f70abad53 100644 --- a/src/Cake.Common/Solution/Project/Properties/AssemblyInfoParser.cs +++ b/src/Cake.Common/Solution/Project/Properties/AssemblyInfoParser.cs @@ -19,9 +19,9 @@ namespace Cake.Common.Solution.Project.Properties public sealed class AssemblyInfoParser { private const string CSharpNonQuotedPattern = @"^\s*\[assembly: (?:System\.Reflection\.)?{0}(?:Attribute)? ?\((?.*)\)"; - private const string CSharpQuotedPattern = @"^\s*\[assembly: (?:System\.Reflection\.)?{0}(?:Attribute)? ?\(""(?.*)""\)"; + private const string CSharpQuotedPattern = @"^\s*\[assembly: (?:System\.Reflection\.)?{0}(?:Attribute)? ?\(\s*""(?.*)""\s*\)"; private const string VBNonQuotedPattern = @"^\s*\.*)\)"; - private const string VBQuotedPattern = @"^\s*\.*)""\)"; + private const string VBQuotedPattern = @"^\s*\.*)""\s*\)"; private const string DefaultVersion = "1.0.0.0"; private readonly IFileSystem _fileSystem; @@ -122,4 +122,4 @@ private static IEnumerable ParseMultiple(string pattern, string attribut } } } -} \ No newline at end of file +} diff --git a/src/Cake.Common/Solution/Project/XmlDoc/XmlDocAliases.cs b/src/Cake.Common/Solution/Project/XmlDoc/XmlDocAliases.cs index e81cdf62bb..2d6c988bb2 100644 --- a/src/Cake.Common/Solution/Project/XmlDoc/XmlDocAliases.cs +++ b/src/Cake.Common/Solution/Project/XmlDoc/XmlDocAliases.cs @@ -72,14 +72,14 @@ public static IEnumerable ParseXmlDocExampleCode(this ICakeCo /// /// [CakeMethodAlias] - public static IEnumerable ParseXmlDocFilesExampleCode(this ICakeContext context, string pattern) + public static IEnumerable ParseXmlDocFilesExampleCode(this ICakeContext context, GlobPattern pattern) { if (context == null) { throw new ArgumentNullException(nameof(context)); } - if (string.IsNullOrWhiteSpace(pattern)) + if (string.IsNullOrWhiteSpace(pattern?.Pattern)) { throw new ArgumentNullException(nameof(pattern)); } diff --git a/src/Cake.Common/Solution/Project/XmlDoc/XmlDocExampleCodeParser.cs b/src/Cake.Common/Solution/Project/XmlDoc/XmlDocExampleCodeParser.cs index b8e1d9eb36..f162b2e5f8 100644 --- a/src/Cake.Common/Solution/Project/XmlDoc/XmlDocExampleCodeParser.cs +++ b/src/Cake.Common/Solution/Project/XmlDoc/XmlDocExampleCodeParser.cs @@ -90,9 +90,9 @@ from code in example.Elements("code") /// /// The globber file pattern. /// Parsed Example Code. - public IEnumerable ParseFiles(string pattern) + public IEnumerable ParseFiles(GlobPattern pattern) { - if (string.IsNullOrWhiteSpace(pattern)) + if (string.IsNullOrWhiteSpace(pattern?.Pattern)) { throw new ArgumentNullException(nameof(pattern), "Invalid pattern supplied."); } diff --git a/src/Cake.Common/Solution/SolutionParser.cs b/src/Cake.Common/Solution/SolutionParser.cs index 2ee2253e8d..0875357af1 100644 --- a/src/Cake.Common/Solution/SolutionParser.cs +++ b/src/Cake.Common/Solution/SolutionParser.cs @@ -73,6 +73,12 @@ public SolutionParserResult Parse(FilePath solutionPath) foreach (var line in file.ReadLines(Encoding.UTF8)) { var trimmed = line.Trim(); + + if (trimmed == string.Empty) + { + continue; + } + if (line.StartsWith("Project(\"{")) { var project = ParseSolutionProjectLine(file, line); @@ -151,10 +157,17 @@ private static SolutionProject ParseSolutionProjectLine(IFile file, string line) } result[position].Append(c); } + + var projectPath = new FilePath(pathBuilder.ToString()); + + var projectFullPath = projectPath.IsRelative ? + file.Path.GetDirectory().CombineWithFilePath(projectPath) : + projectPath; + return new SolutionProject( idBuilder.ToString(), nameBuilder.ToString(), - file.Path.GetDirectory().CombineWithFilePath(pathBuilder.ToString()), + projectFullPath, projectTypeBuilder.ToString()); } diff --git a/src/Cake.Common/Tools/Cake/CakeRunner.cs b/src/Cake.Common/Tools/Cake/CakeRunner.cs index dd7c2dc657..25f8192ff8 100644 --- a/src/Cake.Common/Tools/Cake/CakeRunner.cs +++ b/src/Cake.Common/Tools/Cake/CakeRunner.cs @@ -37,11 +37,7 @@ static CakeRunner() var executingAssemblyToolPath = ((FilePath)entryAssembly.Location).GetDirectory(); _executingAssemblyToolPaths = new[] { -#if NETCORE executingAssemblyToolPath.CombineWithFilePath("Cake.dll") -#else - executingAssemblyToolPath.CombineWithFilePath("Cake.exe") -#endif }; } @@ -144,17 +140,20 @@ private ProcessArgumentBuilder GetArguments(FilePath scriptPath, CakeSettings se if (settings.Verbosity.HasValue) { - builder.Append(string.Concat("-verbosity=", settings.Verbosity.Value.ToString())); + builder.Append(string.Concat("--verbosity=", settings.Verbosity.Value.ToString())); } if (settings.Arguments != null) { foreach (var argument in settings.Arguments) { + var key = argument.Key.Length == 1 + ? $"-{argument.Key}" : $"--{argument.Key}"; + builder.Append(string.Format( CultureInfo.InvariantCulture, - "-{0}={1}", - argument.Key, + "{0}={1}", + key, (argument.Value ?? string.Empty).Quote())); } } @@ -178,17 +177,10 @@ protected override IEnumerable GetToolExecutableNames() { return new[] { -#if NETCORE "Cake.dll", "cake", "Cake", "Cake.exe" -#else - "Cake.exe", - "cake", - "Cake", - "Cake.dll" -#endif }; } diff --git a/src/Cake.Common/Tools/Chocolatey/ChocolateyAliases.cs b/src/Cake.Common/Tools/Chocolatey/ChocolateyAliases.cs index 6c0579ce53..ca9bad1bd9 100644 --- a/src/Cake.Common/Tools/Chocolatey/ChocolateyAliases.cs +++ b/src/Cake.Common/Tools/Chocolatey/ChocolateyAliases.cs @@ -7,6 +7,7 @@ using Cake.Common.Tools.Chocolatey.ApiKey; using Cake.Common.Tools.Chocolatey.Config; using Cake.Common.Tools.Chocolatey.Download; +using Cake.Common.Tools.Chocolatey.Export; using Cake.Common.Tools.Chocolatey.Features; using Cake.Common.Tools.Chocolatey.Install; using Cake.Common.Tools.Chocolatey.New; @@ -1205,5 +1206,52 @@ public static void ChocolateyDownload(this ICakeContext context, string packageI var runner = new ChocolateyDownloader(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools, resolver); runner.Download(packageId, settings); } + + /// + /// Exports the currently installed Chocolatey packages to a packages.config file in the current working directory. + /// + /// The context. + /// + /// + /// ChocolateyExport(); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Export")] + [CakeNamespaceImport("Cake.Common.Tools.Chocolatey.Export")] + public static void ChocolateyExport(this ICakeContext context) + { + var settings = new ChocolateyExportSettings(); + ChocolateyExport(context, settings); + } + + /// + /// Exports the currently installed Chocolatey packages using the specified settings. + /// + /// The context. + /// The settings. + /// + /// Exported information should contain the package version numbers: + /// + /// ChocolateyExport( + /// new ChocolateyExportSettings { + /// IncludeVersionNumbers = true + /// }); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Export")] + [CakeNamespaceImport("Cake.Common.Tools.Chocolatey.Export")] + public static void ChocolateyExport(this ICakeContext context, ChocolateyExportSettings settings) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var resolver = new ChocolateyToolResolver(context.FileSystem, context.Environment); + var runner = new ChocolateyExporter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools, resolver); + runner.Export(settings); + } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/Chocolatey/ChocolateyToolResolver.cs b/src/Cake.Common/Tools/Chocolatey/ChocolateyToolResolver.cs index 46a038f61e..ad5e40a358 100644 --- a/src/Cake.Common/Tools/Chocolatey/ChocolateyToolResolver.cs +++ b/src/Cake.Common/Tools/Chocolatey/ChocolateyToolResolver.cs @@ -38,10 +38,7 @@ public ChocolateyToolResolver(IFileSystem fileSystem, ICakeEnvironment environme } } - /// - /// Resolves the path to choco.exe. - /// - /// The path to choco.exe. + /// public FilePath ResolvePath() { // Check if path already resolved diff --git a/src/Cake.Common/Tools/Chocolatey/Export/ChocolateyExporter.cs b/src/Cake.Common/Tools/Chocolatey/Export/ChocolateyExporter.cs new file mode 100644 index 0000000000..900f9e5f5e --- /dev/null +++ b/src/Cake.Common/Tools/Chocolatey/Export/ChocolateyExporter.cs @@ -0,0 +1,124 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using Cake.Core; +using Cake.Core.IO; +using Cake.Core.Tooling; + +namespace Cake.Common.Tools.Chocolatey.Export +{ + /// + /// The Chocolatey package exporter used to export Chocolatey packages. + /// + public sealed class ChocolateyExporter : ChocolateyTool + { + /// + /// Initializes a new instance of the class. + /// + /// The file system. + /// The environment. + /// The process runner. + /// The tool locator. + /// The Chocolatey tool resolver. + public ChocolateyExporter( + IFileSystem fileSystem, + ICakeEnvironment environment, + IProcessRunner processRunner, + IToolLocator tools, + IChocolateyToolResolver resolver) : base(fileSystem, environment, processRunner, tools, resolver) + { + } + + /// + /// Exports the currently installed Chocolatey packages using the specified settings. + /// + /// The settings. + public void Export(ChocolateyExportSettings settings) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + Run(settings, GetArguments(settings)); + } + + private ProcessArgumentBuilder GetArguments(ChocolateyExportSettings settings) + { + var builder = new ProcessArgumentBuilder(); + + builder.Append("export"); + + // Debug + if (settings.Debug) + { + builder.Append("-d"); + } + + // Verbose + if (settings.Verbose) + { + builder.Append("-v"); + } + + // Always say yes, so as to not show interactive prompt + builder.Append("-y"); + + // Force + if (settings.Force) + { + builder.Append("-f"); + } + + // Noop + if (settings.Noop) + { + builder.Append("--noop"); + } + + // Limit Output + if (settings.LimitOutput) + { + builder.Append("-r"); + } + + // Execution Timeout + if (settings.ExecutionTimeout != 0) + { + builder.Append("--execution-timeout"); + builder.AppendQuoted(settings.ExecutionTimeout.ToString(CultureInfo.InvariantCulture)); + } + + // Cache Location + if (!string.IsNullOrWhiteSpace(settings.CacheLocation)) + { + builder.Append("-c"); + builder.AppendQuoted(settings.CacheLocation); + } + + // Allow Unofficial + if (settings.AllowUnofficial) + { + builder.Append("--allowunofficial"); + } + + // Output File Path + if (settings.OutputFilePath != null) + { + builder.Append("--output-file-path"); + builder.AppendQuoted(settings.OutputFilePath.FullPath); + } + + // Include Version Numbers + if (settings.IncludeVersionNumbers) + { + builder.Append("--include-version-numbers"); + } + + return builder; + } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/Chocolatey/Export/ChocolateyExporterSettings.cs b/src/Cake.Common/Tools/Chocolatey/Export/ChocolateyExporterSettings.cs new file mode 100644 index 0000000000..f90c0a9402 --- /dev/null +++ b/src/Cake.Common/Tools/Chocolatey/Export/ChocolateyExporterSettings.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Core.IO; +using Cake.Core.Tooling; + +namespace Cake.Common.Tools.Chocolatey.Export +{ + /// + /// Contains settings used by . + /// + public sealed class ChocolateyExportSettings : ToolSettings + { + /// + /// Gets or sets a value indicating whether to run in debug mode. + /// + /// The debug flag. + public bool Debug { get; set; } + + /// + /// Gets or sets a value indicating whether to run in verbose mode. + /// + /// The verbose flag. + public bool Verbose { get; set; } + + /// + /// Gets or sets a value indicating whether to run in forced mode. + /// + /// The force flag. + public bool Force { get; set; } + + /// + /// Gets or sets a value indicating whether to run in noop mode. + /// + /// The noop flag. + public bool Noop { get; set; } + + /// + /// Gets or sets a value indicating whether to run in limited output mode. + /// + /// The limit output flag. + public bool LimitOutput { get; set; } + + /// + /// Gets or sets the execution timeout value. + /// + /// The execution timeout. + /// Default is 2700 seconds. + public int ExecutionTimeout { get; set; } + + /// + /// Gets or sets the location of the download cache. + /// + /// The download cache location. + public string CacheLocation { get; set; } + + /// + /// Gets or sets a value indicating whether to run in allow unofficial mode. + /// + /// The allow unofficial flag. + public bool AllowUnofficial { get; set; } + + /// + /// Gets or sets the path to the file that will be generated. + /// + /// The path to the file that is generated. + public FilePath OutputFilePath { get; set; } + + /// + /// Gets or sets a value indicating whether to include version numbers for installed packages. + /// + /// The include version numbers flag. + public bool IncludeVersionNumbers { get; set; } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotCover/DotCoverContext.cs b/src/Cake.Common/Tools/DotCover/DotCoverContext.cs index e923554fcb..60552cfc1d 100644 --- a/src/Cake.Common/Tools/DotCover/DotCoverContext.cs +++ b/src/Cake.Common/Tools/DotCover/DotCoverContext.cs @@ -10,38 +10,20 @@ namespace Cake.Common.Tools.DotCover { - internal sealed class DotCoverContext : ICakeContext + internal sealed class DotCoverContext : CakeContextAdapter { - private readonly ICakeContext _context; private readonly DotCoverProcessRunner _runner; - public IFileSystem FileSystem => _context.FileSystem; + public override ICakeLog Log { get; } - public ICakeEnvironment Environment => _context.Environment; - - public IGlobber Globber => _context.Globber; - - public ICakeLog Log { get; } - - public ICakeArguments Arguments => _context.Arguments; - - public IProcessRunner ProcessRunner => _runner; - - public IRegistry Registry => _context.Registry; - - public IToolLocator Tools => _context.Tools; - - public ICakeDataResolver Data => _context.Data; + public override IProcessRunner ProcessRunner => _runner; public FilePath FilePath => _runner.FilePath; public ProcessSettings Settings => _runner.ProcessSettings; - public ICakeConfiguration Configuration => _context.Configuration; - - public DotCoverContext(ICakeContext context) + public DotCoverContext(ICakeContext context) : base(context) { - _context = context; Log = new NullLog(); _runner = new DotCoverProcessRunner(); } diff --git a/src/Cake.Common/Tools/DotNet/Build/DotNetBuildSettings.cs b/src/Cake.Common/Tools/DotNet/Build/DotNetBuildSettings.cs new file mode 100644 index 0000000000..756dcfbbc5 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Build/DotNetBuildSettings.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Cake.Common.Tools.DotNet.MSBuild; +using Cake.Common.Tools.DotNetCore.Build; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.Build +{ + /// + /// Contains settings used by . + /// + public class DotNetBuildSettings : DotNetSettings + { + /// + /// Gets or sets the output directory. + /// + public DirectoryPath OutputDirectory { get; set; } + + /// + /// Gets or sets the target runtime. + /// + public string Runtime { get; set; } + + /// + /// Gets or sets the configuration under which to build. + /// + public string Configuration { get; set; } + + /// + /// Gets or sets the specific framework to compile. + /// + public string Framework { get; set; } + + /// + /// Gets or sets the value that defines what `*` should be replaced with in version field in project.json. + /// + public string VersionSuffix { get; set; } + + /// + /// Gets or sets a value indicating whether to mark the build as unsafe for incrementality. + /// This turns off incremental compilation and forces a clean rebuild of the project dependency graph. + /// + public bool NoIncremental { get; set; } + + /// + /// Gets or sets a value indicating whether to ignore project to project references and only build the root project. + /// + public bool NoDependencies { get; set; } + + /// + /// Gets or sets a value indicating whether to not do implicit NuGet package restore. + /// This makes build faster, but requires restore to be done before build is executed. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public bool NoRestore { get; set; } + + /// + /// Gets or sets a value indicating whether to display the startup banner or the copyright message. + /// + /// + /// Available since .NET Core 3.0 SDK. + /// + public bool NoLogo { get; set; } + + /// + /// Gets or sets the specified NuGet package sources to use during the build. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public ICollection Sources { get; set; } = new List(); + + /// + /// Gets or sets additional arguments to be passed to MSBuild. + /// + public DotNetMSBuildSettings MSBuildSettings { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/BuildServer/DotNetBuildServerSettings.cs b/src/Cake.Common/Tools/DotNet/BuildServer/DotNetBuildServerSettings.cs new file mode 100644 index 0000000000..8e70a96f0a --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/BuildServer/DotNetBuildServerSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.BuildServer; + +namespace Cake.Common.Tools.DotNet.BuildServer +{ + /// + /// Contains settings used by . + /// + public abstract class DotNetBuildServerSettings : DotNetSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/BuildServer/DotNetBuildServerShutdownSettings.cs b/src/Cake.Common/Tools/DotNet/BuildServer/DotNetBuildServerShutdownSettings.cs new file mode 100644 index 0000000000..3ab1053d9e --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/BuildServer/DotNetBuildServerShutdownSettings.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.BuildServer; + +namespace Cake.Common.Tools.DotNet.BuildServer +{ + /// + /// Contains settings used by . + /// + public class DotNetBuildServerShutdownSettings : DotNetBuildServerSettings + { + /// + /// Gets or sets if to shuts down the MSBuild build server. + /// + public bool? MSBuild { get; set; } + + /// + /// Gets or sets if to shuts down the the Razor build server. + /// + public bool? Razor { get; set; } + + /// + /// Gets or sets if to shuts down the VB/C# compiler build server. + /// + public bool? VBCSCompiler { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/Clean/DotNetCleanSettings.cs b/src/Cake.Common/Tools/DotNet/Clean/DotNetCleanSettings.cs new file mode 100644 index 0000000000..4c07f94bd6 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Clean/DotNetCleanSettings.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNet.MSBuild; +using Cake.Common.Tools.DotNetCore.Clean; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.Clean +{ + /// + /// Contains settings used by . + /// + public class DotNetCleanSettings : DotNetSettings + { + /// + /// Gets or sets the output directory. + /// + public DirectoryPath OutputDirectory { get; set; } + + /// + /// Gets or sets the configuration under which to build. + /// + public string Configuration { get; set; } + + /// + /// Gets or sets the specific framework to compile. + /// + public string Framework { get; set; } + + /// + /// Gets or sets the target runtime. + /// + public string Runtime { get; set; } + + /// + /// Gets or sets a value indicating whether to display the startup banner or the copyright message. + /// + /// + /// Available since .NET Core 3.0 SDK. + /// + public bool NoLogo { get; set; } + + /// + /// Gets or sets additional arguments to be passed to MSBuild. + /// + public DotNetMSBuildSettings MSBuildSettings { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/DotNetAliases.cs b/src/Cake.Common/Tools/DotNet/DotNetAliases.cs new file mode 100644 index 0000000000..311f0b6a67 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/DotNetAliases.cs @@ -0,0 +1,1849 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using Cake.Common.IO; +using Cake.Common.Tools.DotNet.Build; +using Cake.Common.Tools.DotNet.BuildServer; +using Cake.Common.Tools.DotNet.Clean; +using Cake.Common.Tools.DotNet.Execute; +using Cake.Common.Tools.DotNet.Format; +using Cake.Common.Tools.DotNet.MSBuild; +using Cake.Common.Tools.DotNet.NuGet.Delete; +using Cake.Common.Tools.DotNet.NuGet.Push; +using Cake.Common.Tools.DotNet.NuGet.Source; +using Cake.Common.Tools.DotNet.Pack; +using Cake.Common.Tools.DotNet.Publish; +using Cake.Common.Tools.DotNet.Restore; +using Cake.Common.Tools.DotNet.Run; +using Cake.Common.Tools.DotNet.SDKCheck; +using Cake.Common.Tools.DotNet.Test; +using Cake.Common.Tools.DotNet.Tool; +using Cake.Common.Tools.DotNet.VSTest; +using Cake.Common.Tools.DotNetCore.Build; +using Cake.Common.Tools.DotNetCore.BuildServer; +using Cake.Common.Tools.DotNetCore.Clean; +using Cake.Common.Tools.DotNetCore.Execute; +using Cake.Common.Tools.DotNetCore.MSBuild; +using Cake.Common.Tools.DotNetCore.NuGet.Delete; +using Cake.Common.Tools.DotNetCore.NuGet.Push; +using Cake.Common.Tools.DotNetCore.NuGet.Source; +using Cake.Common.Tools.DotNetCore.Pack; +using Cake.Common.Tools.DotNetCore.Publish; +using Cake.Common.Tools.DotNetCore.Restore; +using Cake.Common.Tools.DotNetCore.Run; +using Cake.Common.Tools.DotNetCore.Test; +using Cake.Common.Tools.DotNetCore.Tool; +using Cake.Common.Tools.DotNetCore.VSTest; +using Cake.Core; +using Cake.Core.Annotations; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet +{ + /// + /// Contains functionality related to .NET CLI. + /// + /// In order to use the commands for this alias, the .NET CLI tools will need to be installed on the machine where + /// the Cake script is being executed. See this page for information + /// on how to install. + /// + /// + [CakeAliasCategory("DotNet")] + public static class DotNetAliases + { + /// + /// Execute an assembly. + /// + /// The context. + /// The assembly path. + /// + /// + /// DotNetExecute("./bin/Debug/app.dll"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Execute")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Execute")] + public static void DotNetExecute(this ICakeContext context, FilePath assemblyPath) + { + context.DotNetExecute(assemblyPath, null); + } + + /// + /// Execute an assembly with arguments in the specific path. + /// + /// The context. + /// The assembly path. + /// The arguments. + /// + /// + /// DotNetExecute("./bin/Debug/app.dll", "--arg"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Execute")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Execute")] + public static void DotNetExecute(this ICakeContext context, FilePath assemblyPath, ProcessArgumentBuilder arguments) + { + context.DotNetExecute(assemblyPath, arguments, null); + } + + /// + /// Execute an assembly with arguments in the specific path with settings. + /// + /// The context. + /// The assembly path. + /// The arguments. + /// The settings. + /// + /// + /// var settings = new DotNetExecuteSettings + /// { + /// FrameworkVersion = "1.0.3" + /// }; + /// + /// DotNetExecute("./bin/Debug/app.dll", "--arg", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Execute")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Execute")] + public static void DotNetExecute(this ICakeContext context, FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetExecuteSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (assemblyPath is null) + { + throw new ArgumentNullException(nameof(assemblyPath)); + } + + if (settings is null) + { + settings = new DotNetExecuteSettings(); + } + + var executor = new DotNetCoreExecutor(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + executor.Execute(assemblyPath, arguments, settings); + } + + /// + /// Restore all NuGet Packages. + /// + /// The context. + /// + /// + /// DotNetRestore(); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Restore")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Restore")] + public static void DotNetRestore(this ICakeContext context) + { + context.DotNetRestore(null, null); + } + + /// + /// Restore all NuGet Packages in the specified path. + /// + /// The context. + /// Path to the project file to restore. + /// + /// + /// DotNetRestore("./src/MyProject/MyProject.csproj"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Restore")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Restore")] + public static void DotNetRestore(this ICakeContext context, string root) + { + context.DotNetRestore(root, null); + } + + /// + /// Restore all NuGet Packages with the settings. + /// + /// The context. + /// The settings. + /// + /// + /// var settings = new DotNetRestoreSettings + /// { + /// Sources = new[] {"https://www.example.com/nugetfeed", "https://www.example.com/nugetfeed2"}, + /// FallbackSources = new[] {"https://www.example.com/fallbacknugetfeed"}, + /// PackagesDirectory = "./packages", + /// Verbosity = Information, + /// DisableParallel = true, + /// InferRuntimes = new[] {"runtime1", "runtime2"} + /// }; + /// + /// DotNetRestore(settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Restore")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Restore")] + public static void DotNetRestore(this ICakeContext context, DotNetRestoreSettings settings) + { + context.DotNetRestore(null, settings); + } + + /// + /// Restore all NuGet Packages in the specified path with settings. + /// + /// The context. + /// Path to the project file to restore. + /// The settings. + /// + /// + /// var settings = new DotNetRestoreSettings + /// { + /// Sources = new[] {"https://www.example.com/nugetfeed", "https://www.example.com/nugetfeed2"}, + /// FallbackSources = new[] {"https://www.example.com/fallbacknugetfeed"}, + /// PackagesDirectory = "./packages", + /// Verbosity = Information, + /// DisableParallel = true, + /// InferRuntimes = new[] {"runtime1", "runtime2"} + /// }; + /// + /// DotNetRestore("./src/MyProject/MyProject.csproj", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Restore")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Restore")] + public static void DotNetRestore(this ICakeContext context, string root, DotNetRestoreSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetRestoreSettings(); + } + + var restorer = new DotNetCoreRestorer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools, context.Log); + restorer.Restore(root, settings); + } + + /// + /// Build all projects. + /// + /// The context. + /// The projects path. + /// + /// + /// DotNetBuild("./src/*"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Build")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Build")] + public static void DotNetBuild(this ICakeContext context, string project) + { + context.DotNetBuild(project, null); + } + + /// + /// Build all projects. + /// + /// The context. + /// The projects path. + /// The settings. + /// + /// + /// var settings = new DotNetBuildSettings + /// { + /// Framework = "netcoreapp2.0", + /// Configuration = "Debug", + /// OutputDirectory = "./artifacts/" + /// }; + /// + /// DotNetBuild("./src/*", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Build")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Build")] + public static void DotNetBuild(this ICakeContext context, string project, DotNetBuildSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetBuildSettings(); + } + + var builder = new DotNetCoreBuilder(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + builder.Build(project, settings); + } + + /// + /// Publish all projects. + /// + /// The context. + /// The projects path. + /// + /// + /// DotNetPublish("./src/*"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Publish")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Publish")] + public static void DotNetPublish(this ICakeContext context, string project) + { + context.DotNetPublish(project, null); + } + + /// + /// Publish all projects. + /// + /// The context. + /// The projects path. + /// The settings. + /// + /// + /// var settings = new DotNetPublishSettings + /// { + /// Framework = "netcoreapp2.0", + /// Configuration = "Release", + /// OutputDirectory = "./artifacts/" + /// }; + /// + /// DotNetPublish("./src/*", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Publish")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Publish")] + public static void DotNetPublish(this ICakeContext context, string project, DotNetPublishSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetPublishSettings(); + } + + var publisher = new DotNetCorePublisher(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + publisher.Publish(project, settings); + } + + /// + /// Test project. + /// + /// The context. + /// + /// + /// DotNetTest(); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Test")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Test")] + public static void DotNetTest(this ICakeContext context) + { + context.DotNetTest(null, null, null); + } + + /// + /// Test project with path. + /// + /// The context. + /// The project path. + /// + /// Specify the path to the .csproj file in the test project. + /// + /// DotNetTest("./test/Project.Tests/Project.Tests.csproj"); + /// + /// You could also specify a task that runs multiple test projects. + /// Cake task: + /// + /// Task("Test") + /// .Does(() => + /// { + /// var projectFiles = GetFiles("./test/**/*.csproj"); + /// foreach(var file in projectFiles) + /// { + /// DotNetTest(file.FullPath); + /// } + /// }); + /// + /// If your test project is using project.json, the project parameter should just be the directory path. + /// + /// DotNetTest("./test/Project.Tests/"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Test")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Test")] + public static void DotNetTest(this ICakeContext context, string project) + { + context.DotNetTest(project, null, null); + } + + /// + /// Test project with settings. + /// + /// The context. + /// The project path. + /// The settings. + /// + /// + /// var settings = new DotNetTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// DotNetTest("./test/Project.Tests/Project.Tests.csproj", settings); + /// + /// You could also specify a task that runs multiple test projects. + /// Cake task: + /// + /// Task("Test") + /// .Does(() => + /// { + /// var settings = new DotNetTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// var projectFiles = GetFiles("./test/**/*.csproj"); + /// foreach(var file in projectFiles) + /// { + /// DotNetTest(file.FullPath, settings); + /// } + /// }); + /// + /// If your test project is using project.json, the project parameter should just be the directory path. + /// + /// var settings = new DotNetTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// DotNetTest("./test/Project.Tests/", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Test")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Test")] + public static void DotNetTest(this ICakeContext context, string project, DotNetTestSettings settings) + { + context.DotNetTest(project, null, settings); + } + + /// + /// Test project with settings. + /// + /// The context. + /// The project path. + /// The arguments. + /// The settings. + /// + /// + /// var settings = new DotNetTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// DotNetTest("./test/Project.Tests/Project.Tests.csproj", settings); + /// + /// You could also specify a task that runs multiple test projects. + /// Cake task: + /// + /// Task("Test") + /// .Does(() => + /// { + /// var settings = new DotNetTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// var projectFiles = GetFiles("./test/**/*.csproj"); + /// foreach(var file in projectFiles) + /// { + /// DotNetTest(file.FullPath, "MSTest.MapInconclusiveToFailed=true", settings); + /// } + /// }); + /// + /// If your test project is using project.json, the project parameter should just be the directory path. + /// + /// var settings = new DotNetTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// DotNetTest("./test/Project.Tests/", "MSTest.MapInconclusiveToFailed=true", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Test")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Test")] + public static void DotNetTest(this ICakeContext context, string project, ProcessArgumentBuilder arguments, DotNetTestSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetTestSettings(); + } + + var tester = new DotNetCoreTester(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + tester.Test(project, arguments, settings); + } + + /// + /// Cleans a project's output. + /// + /// The context. + /// The project's path. + /// + /// + /// DotNetClean("./src/project"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Clean")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Clean")] + public static void DotNetClean(this ICakeContext context, string project) + { + context.DotNetClean(project, null); + } + + /// + /// Cleans a project's output. + /// + /// The context. + /// The projects path. + /// The settings. + /// + /// + /// var settings = new DotNetCleanSettings + /// { + /// Framework = "netcoreapp2.0", + /// Configuration = "Debug", + /// OutputDirectory = "./artifacts/" + /// }; + /// + /// DotNetClean("./src/project", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Clean")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Clean")] + public static void DotNetClean(this ICakeContext context, string project, DotNetCleanSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetCleanSettings(); + } + + var cleaner = new DotNetCoreCleaner(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + cleaner.Clean(project, settings); + } + + /// + /// Delete a NuGet Package from a server. + /// + /// The context. + /// + /// + /// DotNetNuGetDelete(); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Delete")] + public static void DotNetNuGetDelete(this ICakeContext context) + { + context.DotNetNuGetDelete(null, null, null); + } + + /// + /// Deletes a package from nuget.org. + /// + /// The context. + /// Name of package to delete. + /// + /// + /// DotNetNuGetDelete("Microsoft.AspNetCore.Mvc"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Delete")] + public static void DotNetNuGetDelete(this ICakeContext context, string packageName) + { + context.DotNetNuGetDelete(packageName, null, null); + } + + /// + /// Deletes a specific version of a package from nuget.org. + /// + /// The context. + /// Name of package to delete. + /// Version of package to delete. + /// + /// + /// DotNetRestore("Microsoft.AspNetCore.Mvc", "1.0"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Delete")] + public static void DotNetNuGetDelete(this ICakeContext context, string packageName, string packageVersion) + { + context.DotNetNuGetDelete(packageName, packageVersion, null); + } + + /// + /// Deletes a package from a server. + /// + /// The context. + /// Name of package to delete. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetDeleteSettings + /// { + /// Source = "https://www.example.com/nugetfeed", + /// NonInteractive = true + /// }; + /// + /// DotNetNuGetDelete("Microsoft.AspNetCore.Mvc", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Delete")] + public static void DotNetNuGetDelete(this ICakeContext context, string packageName, DotNetNuGetDeleteSettings settings) + { + context.DotNetNuGetDelete(packageName, null, settings); + } + + /// + /// Deletes a package from a server using the specified settings. + /// + /// The context. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetDeleteSettings + /// { + /// Source = "https://www.example.com/nugetfeed", + /// NonInteractive = true + /// }; + /// + /// DotNetNuGetDelete(settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Delete")] + public static void DotNetNuGetDelete(this ICakeContext context, DotNetNuGetDeleteSettings settings) + { + context.DotNetNuGetDelete(null, null, settings); + } + + /// + /// Deletes a package from a server using the specified settings. + /// + /// The context. + /// Name of package to delete. + /// Version of package to delete. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetDeleteSettings + /// { + /// Source = "https://www.example.com/nugetfeed", + /// NonInteractive = true + /// }; + /// + /// DotNetNuGetDelete("Microsoft.AspNetCore.Mvc", "1.0", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Delete")] + public static void DotNetNuGetDelete(this ICakeContext context, string packageName, string packageVersion, DotNetNuGetDeleteSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetNuGetDeleteSettings(); + } + + var nugetDeleter = new DotNetCoreNuGetDeleter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + nugetDeleter.Delete(packageName, packageVersion, settings); + } + + /// + /// Pushes one or more packages to a server. + /// + /// The context. + /// of the package to push. + /// + /// + /// // With FilePath instance + /// var packageFilePath = GetFiles("*.nupkg").Single(); + /// DotNetNuGetPush(packageFilePath); + /// // With string parameter + /// DotNetNuGetPush("foo*.nupkg"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Push")] + public static void DotNetNuGetPush(this ICakeContext context, FilePath packageFilePath) + { + context.DotNetNuGetPush(packageFilePath, null); + } + + /// + /// Pushes one or more packages to a server using the specified settings. + /// + /// The context. + /// of the package to push. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetPushSettings + /// { + /// Source = "https://www.example.com/nugetfeed", + /// ApiKey = "4003d786-cc37-4004-bfdf-c4f3e8ef9b3a" + /// }; + /// // With FilePath instance + /// var packageFilePath = GetFiles("foo*.nupkg").Single(); + /// DotNetNuGetPush(packageFilePath); + /// // With string parameter + /// DotNetNuGetPush("foo*.nupkg", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Push")] + public static void DotNetNuGetPush(this ICakeContext context, FilePath packageFilePath, DotNetNuGetPushSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetNuGetPushSettings(); + } + + var restorer = new DotNetCoreNuGetPusher(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + restorer.Push(packageFilePath?.FullPath, settings); + } + + /// + /// Add the specified NuGet source. + /// + /// The context. + /// The name of the source. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetSourceSettings + /// { + /// Source = "https://www.example.com/nugetfeed", + /// UserName = "username", + /// Password = "password", + /// StorePasswordInClearText = true, + /// ValidAuthenticationTypes = "basic,negotiate" + /// }; + /// + /// DotNetNuGetAddSource("example", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static void DotNetNuGetAddSource(this ICakeContext context, string name, DotNetNuGetSourceSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + sourcer.AddSource(name, settings); + } + + /// + /// Disable the specified NuGet source. + /// + /// The context. + /// The name of the source. + /// + /// + /// DotNetNuGetDisableSource("example"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static void DotNetNuGetDisableSource(this ICakeContext context, string name) + { + context.DotNetNuGetDisableSource(name, null); + } + + /// + /// Disable the specified NuGet source. + /// + /// The context. + /// The name of the source. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetSourceSettings + /// { + /// ConfigFile = "NuGet.config" + /// }; + /// + /// DotNetNuGetDisableSource("example", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static void DotNetNuGetDisableSource(this ICakeContext context, string name, DotNetNuGetSourceSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + sourcer.DisableSource(name, settings ?? new DotNetNuGetSourceSettings()); + } + + /// + /// Enable the specified NuGet source. + /// + /// The context. + /// The name of the source. + /// + /// + /// DotNetNuGetEnableSource("example"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static void DotNetNuGetEnableSource(this ICakeContext context, string name) + { + context.DotNetNuGetEnableSource(name, null); + } + + /// + /// Enable the specified NuGet source. + /// + /// The context. + /// The name of the source. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetSourceSettings + /// { + /// ConfigFile = "NuGet.config" + /// }; + /// + /// DotNetNuGetEnableSource("example", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static void DotNetNuGetEnableSource(this ICakeContext context, string name, DotNetNuGetSourceSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + sourcer.EnableSource(name, settings ?? new DotNetNuGetSourceSettings()); + } + + /// + /// Determines whether the specified NuGet source exists. + /// + /// The context. + /// The name of the source. + /// Whether the specified NuGet source exists. + /// + /// + /// var exists = DotNetNuGetHasSource("example"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static bool DotNetNuGetHasSource(this ICakeContext context, string name) + { + return context.DotNetNuGetHasSource(name, null); + } + + /// + /// Determines whether the specified NuGet source exists. + /// + /// The context. + /// The name of the source. + /// The settings. + /// Whether the specified NuGet source exists. + /// + /// + /// var settings = new DotNetNuGetSourceSettings + /// { + /// ConfigFile = "NuGet.config" + /// }; + /// + /// var exists = DotNetNuGetHasSource("example", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static bool DotNetNuGetHasSource(this ICakeContext context, string name, DotNetNuGetSourceSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + return sourcer.HasSource(name, settings ?? new DotNetNuGetSourceSettings()); + } + + /// + /// Remove the specified NuGet source. + /// + /// The context. + /// The name of the source. + /// + /// + /// DotNetNuGetRemoveSource("example"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static void DotNetNuGetRemoveSource(this ICakeContext context, string name) + { + context.DotNetNuGetRemoveSource(name, null); + } + + /// + /// Remove the specified NuGet source. + /// + /// The context. + /// The name of the source. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetSourceSettings + /// { + /// ConfigFile = "NuGet.config" + /// }; + /// + /// DotNetNuGetRemoveSource("example", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static void DotNetNuGetRemoveSource(this ICakeContext context, string name, DotNetNuGetSourceSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + sourcer.RemoveSource(name, settings ?? new DotNetNuGetSourceSettings()); + } + + /// + /// Update the specified NuGet source. + /// + /// The context. + /// The name of the source. + /// The settings. + /// + /// + /// var settings = new DotNetNuGetSourceSettings + /// { + /// Source = "https://www.example.com/nugetfeed", + /// UserName = "username", + /// Password = "password", + /// StorePasswordInClearText = true, + /// ValidAuthenticationTypes = "basic,negotiate" + /// }; + /// + /// DotNetNuGetUpdateSource("example", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("NuGet")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.NuGet.Source")] + public static void DotNetNuGetUpdateSource(this ICakeContext context, string name, DotNetNuGetSourceSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + sourcer.UpdateSource(name, settings); + } + + /// + /// Package all projects. + /// + /// The context. + /// The projects path. + /// + /// + /// DotNetPack("./src/*"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Pack")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Pack")] + public static void DotNetPack(this ICakeContext context, string project) + { + context.DotNetPack(project, null); + } + + /// + /// Package all projects. + /// + /// The context. + /// The projects path. + /// The settings. + /// + /// + /// var settings = new DotNetPackSettings + /// { + /// Configuration = "Release", + /// OutputDirectory = "./artifacts/" + /// }; + /// + /// DotNetPack("./src/*", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Pack")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Pack")] + public static void DotNetPack(this ICakeContext context, string project, DotNetPackSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetPackSettings(); + } + + var packer = new DotNetCorePacker(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + packer.Pack(project, settings); + } + + /// + /// Run all projects. + /// + /// The context. + /// + /// + /// DotNetRun(); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Run")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Run")] + public static void DotNetRun(this ICakeContext context) + { + context.DotNetRun(null, null, null); + } + + /// + /// Run project. + /// + /// The context. + /// The project path. + /// + /// + /// DotNetRun("./src/Project"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Run")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Run")] + public static void DotNetRun(this ICakeContext context, string project) + { + context.DotNetRun(project, null, null); + } + + /// + /// Run project with path and arguments. + /// + /// The context. + /// The project path. + /// The arguments. + /// + /// + /// DotNetRun("./src/Project", "--args"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Run")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Run")] + public static void DotNetRun(this ICakeContext context, string project, ProcessArgumentBuilder arguments) + { + context.DotNetRun(project, arguments, null); + } + + /// + /// Run project with settings. + /// + /// The context. + /// The project path. + /// The arguments. + /// The settings. + /// + /// + /// var settings = new DotNetRunSettings + /// { + /// Framework = "netcoreapp2.0", + /// Configuration = "Release" + /// }; + /// + /// DotNetRun("./src/Project", "--args", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Run")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Run")] + public static void DotNetRun(this ICakeContext context, string project, ProcessArgumentBuilder arguments, DotNetRunSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetRunSettings(); + } + + var runner = new DotNetCoreRunner(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + runner.Run(project, arguments, settings); + } + + /// + /// Run project with settings. + /// + /// The context. + /// The project path. + /// The settings. + /// + /// + /// var settings = new DotNetRunSettings + /// { + /// Framework = "netcoreapp2.0", + /// Configuration = "Release" + /// }; + /// + /// DotNetRun("./src/Project", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Run")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Run")] + public static void DotNetRun(this ICakeContext context, string project, DotNetRunSettings settings) + { + context.DotNetRun(project, null, settings); + } + + /// + /// Builds the specified targets in a project file found in the current working directory. + /// + /// The context. + /// + /// + /// DotNetMSBuild(); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("MSBuild")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.MSBuild")] + public static void DotNetMSBuild(this ICakeContext context) + { + context.DotNetMSBuild(null, null); + } + + /// + /// Builds the specified targets in the project file. + /// + /// The context. + /// Project file or directory to search for project file. + /// + /// + /// DotNetMSBuild("foobar.proj"); + /// + /// + /// + /// If a directory is specified, MSBuild searches that directory for a project file. + /// + [CakeMethodAlias] + [CakeAliasCategory("MSBuild")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.MSBuild")] + public static void DotNetMSBuild(this ICakeContext context, string projectOrDirectory) + { + if (string.IsNullOrWhiteSpace(projectOrDirectory)) + { + throw new ArgumentNullException(nameof(projectOrDirectory)); + } + + context.DotNetMSBuild(projectOrDirectory, null); + } + + /// + /// Builds the specified targets in a project file found in the current working directory. + /// + /// The context. + /// The settings. + /// + /// + /// var settings = new DotNetMSBuildSettings + /// { + /// NoLogo = true, + /// MaxCpuCount = -1 + /// }; + /// + /// DotNetMSBuild(settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("MSBuild")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.MSBuild")] + public static void DotNetMSBuild(this ICakeContext context, DotNetMSBuildSettings settings) + { + context.DotNetMSBuild(null, settings); + } + + /// + /// Builds the specified targets in the project file. + /// + /// The context. + /// Project file or directory to search for project file. + /// The settings. + /// + /// + /// var settings = new DotNetMSBuildSettings + /// { + /// NoLogo = true, + /// MaxCpuCount = -1 + /// }; + /// + /// DotNetMSBuild("foobar.proj", settings); + /// + /// + /// + /// If a project file is not specified, MSBuild searches the current working directory for a file that has a file + /// extension that ends in "proj" and uses that file. If a directory is specified, MSBuild searches that directory for a project file. + /// + [CakeMethodAlias] + [CakeAliasCategory("MSBuild")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.MSBuild")] + public static void DotNetMSBuild(this ICakeContext context, string projectOrDirectory, DotNetMSBuildSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetMSBuildSettings(); + } + + var builder = new DotNetCoreMSBuildBuilder(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + builder.Build(projectOrDirectory, settings); + } + + /// + /// Test one or more projects specified by a path or glob pattern using the VS Test host runner. + /// + /// The context. + /// A path to the test file or glob for one or more test files. + /// + /// Specify the path to the .csproj file in the test project. + /// + /// DotNetVSTest("./test/Project.Tests/bin/Release/netcoreapp2.1/Project.Tests.dll"); + /// + /// You could also specify a glob pattern to run multiple test projects. + /// + /// DotNetVSTest("./**/bin/Release/netcoreapp2.1/*.Tests.dll"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Test")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.VSTest")] + public static void DotNetVSTest(this ICakeContext context, GlobPattern testFile) => context.DotNetVSTest(testFile, null); + + /// + /// Test one or more projects specified by a path or glob pattern with settings using the VS Test host runner. + /// + /// The context. + /// A path to the test file or glob for one or more test files. + /// The settings. + /// + /// Specify the path to the .csproj file in the test project. + /// + /// var settings = new DotNetVSTestSettings + /// { + /// Framework = "FrameworkCore10", + /// Platform = "x64" + /// }; + /// + /// DotNetTest("./test/Project.Tests/bin/Release/netcoreapp2.1/Project.Tests.dll", settings); + /// + /// You could also specify a glob pattern to run multiple test projects. + /// + /// var settings = new DotNetVSTestSettings + /// { + /// Framework = "FrameworkCore10", + /// Platform = "x64", + /// Parallel = true + /// }; + /// + /// DotNetVSTest("./**/bin/Release/netcoreapp2.1/*.Tests.dll", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Test")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.VSTest")] + public static void DotNetVSTest(this ICakeContext context, GlobPattern testFile, DotNetVSTestSettings settings) + { + var testFiles = context.GetFiles(testFile); + + context.DotNetVSTest(testFiles, settings); + } + + /// + /// Test one or more specified projects with settings using the VS Test host runner. + /// + /// The context. + /// The project paths to test. + /// The settings. + /// + /// + /// var settings = new DotNetVSTestSettings + /// { + /// Framework = "FrameworkCore10", + /// Platform = "x64" + /// }; + /// + /// DotNetVSTest(new[] { (FilePath)"./test/Project.Tests/bin/Release/netcoreapp2.1/Project.Tests.dll" }, settings); + /// + /// You could also specify a task that runs multiple test projects. + /// Cake task: + /// + /// Task("Test") + /// .Does(() => + /// { + /// var settings = new DotNetVSTestSettings + /// { + /// Framework = "FrameworkCore10", + /// Platform = "x64", + /// Parallel = true + /// }; + /// + /// var testFiles = GetFiles("./test/**/bin/Release/netcoreapp2.1/*.Test.dll"); + /// + /// DotNetVSTest(testFiles, settings); + /// }); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Test")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.VSTest")] + public static void DotNetVSTest(this ICakeContext context, IEnumerable testFiles, DotNetVSTestSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetVSTestSettings(); + } + + var tester = new DotNetCoreVSTester(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + tester.Test(testFiles, settings); + } + + /// + /// Execute an .NET Core Extensibility Tool. + /// + /// The context. + /// The command to execute. + /// + /// + /// DotNetTool("cake"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Tool")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Tool")] + public static void DotNetTool(this ICakeContext context, string command) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var arguments = new ProcessArgumentBuilder(); + var settings = new DotNetToolSettings(); + + context.DotNetTool(null, command, arguments, settings); + } + + /// + /// Execute an .NET Core Extensibility Tool. + /// + /// The context. + /// The command to execute. + /// The settings. + /// + /// + /// var settings = new DotNetToolSettings + /// { + /// DiagnosticOutput = true + /// }; + /// + /// DotNetTool("cake", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Tool")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Tool")] + public static void DotNetTool(this ICakeContext context, string command, DotNetToolSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var arguments = new ProcessArgumentBuilder(); + + context.DotNetTool(null, command, arguments, settings); + } + + /// + /// Execute an .NET Core Extensibility Tool. + /// + /// The context. + /// The project path. + /// The command to execute. + /// + /// + /// DotNetTool("./src/project", "xunit", "-xml report.xml"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Tool")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Tool")] + public static void DotNetTool(this ICakeContext context, FilePath projectPath, string command) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var arguments = new ProcessArgumentBuilder(); + var settings = new DotNetToolSettings(); + + context.DotNetTool(projectPath, command, arguments, settings); + } + + /// + /// Execute an .NET Core Extensibility Tool. + /// + /// The context. + /// The project path. + /// The command to execute. + /// The arguments. + /// + /// + /// DotNetTool("./src/project", "xunit", "-xml report.xml"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Tool")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Tool")] + public static void DotNetTool(this ICakeContext context, FilePath projectPath, string command, ProcessArgumentBuilder arguments) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var settings = new DotNetToolSettings(); + + context.DotNetTool(projectPath, command, arguments, settings); + } + + /// + /// Execute an .NET Core Extensibility Tool. + /// + /// The context. + /// The project path. + /// The command to execute. + /// The arguments. + /// The settings. + /// + /// + /// DotNetTool("./src/project", "xunit", "-xml report.xml"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Tool")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Tool")] + public static void DotNetTool(this ICakeContext context, FilePath projectPath, string command, ProcessArgumentBuilder arguments, DotNetToolSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var runner = new DotNetCoreToolRunner(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + + runner.Execute(projectPath, command, arguments, settings); + } + + /// + /// Shuts down build servers that are started from dotnet. + /// + /// The context. + /// + /// + /// DotNetBuildServerShutdown(); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Build Server")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.BuildServer")] + public static void DotNetBuildServerShutdown(this ICakeContext context) + { + context.DotNetBuildServerShutdown(null); + } + + /// + /// Shuts down build servers that are started from dotnet. + /// + /// The context. + /// The settings. + /// + /// + /// var settings = new DotNetBuildServerShutdownSettings + /// { + /// MSBuild = true + /// }; + /// + /// DotNetBuildServerShutdown(settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Build Server")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.BuildServer")] + public static void DotNetBuildServerShutdown(this ICakeContext context, DotNetBuildServerShutdownSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var buildServer = new DotNetCoreBuildServer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + + buildServer.Shutdown(settings ?? new DotNetBuildServerShutdownSettings()); + } + + /// + /// Formats code to match editorconfig settings. + /// + /// The context. + /// The project or solution path. + /// + /// + /// DotNetFormat("./src/project"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Format")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Format")] + public static void DotNetFormat(this ICakeContext context, string root) + { + context.DotNetFormat(root, null); + } + + /// + /// Formats code to match editorconfig settings. + /// + /// The context. + /// The project or solution path. + /// The settings. + /// + /// + /// var settings = new DotNetFormatSettings + /// { + /// NoRestore = true, + /// Include = "Program.cs Utility\Logging.cs", + /// Severity = DotNetFormatSeverity.Error + /// }; + /// + /// DotNetFormat("./src/project", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Format")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Format")] + public static void DotNetFormat(this ICakeContext context, string root, DotNetFormatSettings settings) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings is null) + { + settings = new DotNetFormatSettings(); + } + + var formatter = new DotNetFormatter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + formatter.Format(root, null, settings); + } + + /// + /// Format code to match editorconfig settings for whitespace. + /// + /// The context. + /// The project or solution path. + /// + /// + /// DotNetFormatWhitespace("./src/*"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Format")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Format")] + public static void DotNetFormatWhitespace(this ICakeContext context, string root) + { + context.DotNetFormatWhitespace(root, null); + } + + /// + /// Format code to match editorconfig settings for whitespace. + /// + /// The context. + /// The project or solution path. + /// The settings. + /// + /// + /// var settings = new DotNetFormatSettings + /// { + /// NoRestore = true, + /// Include = "Program.cs Utility\Logging.cs" + /// }; + /// + /// DotNetFormatWhitespace("./src/*", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Format")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Format")] + public static void DotNetFormatWhitespace(this ICakeContext context, string root, DotNetFormatSettings settings) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings == null) + { + settings = new DotNetFormatSettings(); + } + + var formatter = new DotNetFormatter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + formatter.Format(root, "whitespace", settings); + } + + /// + /// Format code to match editorconfig settings for code style. + /// + /// The context. + /// The project or solution path. + /// + /// + /// DotNetFormatStyle("./src/*"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Format")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Format")] + public static void DotNetFormatStyle(this ICakeContext context, string root) + { + context.DotNetFormatStyle(root, null); + } + + /// + /// Format code to match editorconfig settings for code style. + /// + /// The context. + /// The project or solution path. + /// The settings. + /// + /// + /// var settings = new DotNetFormatSettings + /// { + /// NoRestore = true, + /// Include = "Program.cs Utility\Logging.cs" + /// }; + /// + /// DotNetFormatStyle("./src/*", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Format")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Format")] + public static void DotNetFormatStyle(this ICakeContext context, string root, DotNetFormatSettings settings) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings == null) + { + settings = new DotNetFormatSettings(); + } + + var formatter = new DotNetFormatter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + formatter.Format(root, "style", settings); + } + + /// + /// Format code to match editorconfig settings for analyzers. + /// + /// The context. + /// The project or solution path. + /// + /// + /// DotNetFormatAnalyzers("./src/*"); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Format")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Format")] + public static void DotNetFormatAnalyzers(this ICakeContext context, string project) + { + context.DotNetFormatAnalyzers(project, null); + } + + /// + /// Format code to match editorconfig settings for analyzers. + /// + /// The context. + /// The project or solution path. + /// The settings. + /// + /// + /// var settings = new DotNetFormatSettings + /// { + /// NoRestore = true, + /// Include = "Program.cs Utility\Logging.cs" + /// }; + /// + /// DotNetFormatAnalyzers("./src/*", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Format")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.Format")] + public static void DotNetFormatAnalyzers(this ICakeContext context, string root, DotNetFormatSettings settings) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (settings == null) + { + settings = new DotNetFormatSettings(); + } + + var formatter = new DotNetFormatter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + formatter.Format(root, "analyzers", settings); + } + + /// + /// Lists the latest available version of the .NET SDK and .NET Runtime. + /// + /// The context. + /// + /// + /// DotNetSDKCheck(); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("SDK")] + [CakeNamespaceImport("Cake.Common.Tools.DotNet.SDKCheck")] + public static void DotNetSDKCheck(this ICakeContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + var checker = new DotNetSDKChecker(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); + checker.Check(); + } + } +} diff --git a/src/Cake.Common/Tools/DotNet/DotNetRollForward.cs b/src/Cake.Common/Tools/DotNet/DotNetRollForward.cs new file mode 100644 index 0000000000..66c03dc589 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/DotNetRollForward.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Cake.Common.Tools.DotNet +{ + /// + /// Contains the roll forward policy to be used. + /// + public enum DotNetRollForward + { + /// + /// Roll forward to the lowest higher minor version, if requested minor version is missing. + /// + Minor, + + /// + /// Roll forward to the highest patch version. This disables minor version roll forward. + /// + LatestPatch, + + /// + /// Roll forward to lowest higher major version, and lowest minor version, if requested major version is missing. + /// + Major, + + /// + /// Roll forward to highest minor version, even if requested minor version is present. + /// + LatestMinor, + + /// + /// Roll forward to highest major and highest minor version, even if requested major is present. + /// + LatestMajor, + + /// + /// Don't roll forward. Only bind to specified version. + /// + Disable, + } +} diff --git a/src/Cake.Common/Tools/DotNet/DotNetSettings.cs b/src/Cake.Common/Tools/DotNet/DotNetSettings.cs new file mode 100644 index 0000000000..7ad53356f2 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/DotNetSettings.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Core.Tooling; + +namespace Cake.Common.Tools.DotNet +{ + /// + /// Contains common settings used by . + /// + public abstract class DotNetSettings : ToolSettings + { + /// + /// Gets or sets the verbosity of logging to use. + /// + public DotNetVerbosity? Verbosity { get; set; } + + /// + /// Gets or sets a value indicating whether to not enable diagnostic output. + /// + public bool DiagnosticOutput { get; set; } + + /// + /// Gets or sets the dotnet roll forward policy. + /// + public DotNetRollForward? RollForward { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/DotNetTool.cs b/src/Cake.Common/Tools/DotNet/DotNetTool.cs new file mode 100644 index 0000000000..5d473e01f3 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/DotNetTool.cs @@ -0,0 +1,131 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using Cake.Core; +using Cake.Core.IO; +using Cake.Core.Tooling; + +namespace Cake.Common.Tools.DotNet +{ + /// + /// Base class for all .NET Core related tools. + /// + /// The settings type. + public abstract class DotNetTool : Tool + where TSettings : DotNetSettings + { + /// + /// Initializes a new instance of the class. + /// + /// The file system. + /// The environment. + /// The process runner. + /// The tool locator. + protected DotNetTool( + IFileSystem fileSystem, + ICakeEnvironment environment, + IProcessRunner processRunner, + IToolLocator tools) + : base(fileSystem, environment, processRunner, tools) + { + } + + /// + /// Gets the name of the tool. + /// + /// The name of the tool. + protected override string GetToolName() + { + return ".NET CLI"; + } + + /// + /// Gets the possible names of the tool executable. + /// + /// The tool executable name. + protected override IEnumerable GetToolExecutableNames() + { + return new[] { "dotnet", "dotnet.exe" }; + } + + /// + /// Runs the dotnet cli command using the specified settings and arguments. + /// + /// The settings. + /// The arguments. + protected void RunCommand(TSettings settings, ProcessArgumentBuilder arguments) + { + // add arguments common to all commands last + AppendCommonArguments(arguments, settings); + + Run(settings, arguments, null, null); + } + + /// + /// Runs the dotnet cli command using the specified settings and arguments. + /// + /// The settings. + /// The arguments. + /// The processSettings. + protected void RunCommand(TSettings settings, ProcessArgumentBuilder arguments, ProcessSettings processSettings) + { + // add arguments common to all commands last + AppendCommonArguments(arguments, settings); + + Run(settings, arguments, processSettings, null); + } + + /// + /// Runs the dotnet cli command using the specified settings and arguments. + /// + /// The settings. + /// The arguments. + /// The processSettings. + /// If specified called after process exit. + protected void RunCommand(TSettings settings, ProcessArgumentBuilder arguments, ProcessSettings processSettings, Action postAction) + { + // add arguments common to all commands last + AppendCommonArguments(arguments, settings); + + Run(settings, arguments, processSettings, postAction); + } + + /// + /// Creates a and adds common commandline arguments. + /// + /// The settings. + /// Instance of . + protected ProcessArgumentBuilder CreateArgumentBuilder(TSettings settings) + { + var builder = new ProcessArgumentBuilder(); + + if (settings.DiagnosticOutput) + { + builder.Append("--diagnostics"); + } + + return builder; + } + + /// + /// Adds common commandline arguments. + /// + /// Process argument builder to update. + /// The settings. + /// Returns updated with common commandline arguments. + private ProcessArgumentBuilder AppendCommonArguments(ProcessArgumentBuilder builder, TSettings settings) + { + // Verbosity + if (settings.Verbosity.HasValue) + { + builder.Append("--verbosity"); + builder.Append(settings.Verbosity.ToString().ToLower()); + } + + return builder; + } + } +} diff --git a/src/Cake.Common/Build/TFBuild/Data/TFBuildTaskResult.cs b/src/Cake.Common/Tools/DotNet/DotNetVerbosity.cs similarity index 55% rename from src/Cake.Common/Build/TFBuild/Data/TFBuildTaskResult.cs rename to src/Cake.Common/Tools/DotNet/DotNetVerbosity.cs index 01d30b6b8b..4445ccbf17 100644 --- a/src/Cake.Common/Build/TFBuild/Data/TFBuildTaskResult.cs +++ b/src/Cake.Common/Tools/DotNet/DotNetVerbosity.cs @@ -2,36 +2,36 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Cake.Common.Build.TFBuild.Data +namespace Cake.Common.Tools.DotNet { /// - /// Provides the result of a TF Build task record. + /// Contains the verbosity of logging to use. /// - public enum TFBuildTaskResult + public enum DotNetVerbosity { /// - /// Succeeded status. + /// Quiet level. /// - Succeeded, + Quiet, /// - /// Succeeded with issues status. + /// Minimal level. /// - SucceededWithIssues, + Minimal, /// - /// Failed status. + /// Normal level. /// - Failed, + Normal, /// - /// Cancelled status. + /// Detailed level. /// - Cancelled, + Detailed, /// - /// Skipped status. + /// Diagnostic level. /// - Skipped + Diagnostic, } } diff --git a/src/Cake.Common/Tools/DotNet/Execute/DotNetExecuteSettings.cs b/src/Cake.Common/Tools/DotNet/Execute/DotNetExecuteSettings.cs new file mode 100644 index 0000000000..5bda04ca2c --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Execute/DotNetExecuteSettings.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.Execute; + +namespace Cake.Common.Tools.DotNet.Execute +{ + /// + /// Contains settings used by . + /// + public class DotNetExecuteSettings : DotNetSettings + { + /// + /// Gets or sets the version of the installed Shared Framework to use to run the application. + /// + public string FrameworkVersion { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/Format/DotNetFormatSettings.cs b/src/Cake.Common/Tools/DotNet/Format/DotNetFormatSettings.cs new file mode 100644 index 0000000000..7bd4c4ed09 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Format/DotNetFormatSettings.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.Format +{ + /// + /// Contains settings used by . + /// + public class DotNetFormatSettings : DotNetSettings + { + /// + /// Gets or sets a space-separated list of diagnostic IDs to use as a filter when fixing code style or third-party issues. + /// + public ICollection Diagnostics { get; set; } = new List(); + + /// + /// Gets or sets the minimum severity of diagnostics to fix. + /// + public DotNetFormatSeverity? Severity { get; set; } + + /// + /// Gets or sets a value indicating whether to not do implicit NuGet package restore. + /// This makes build faster, but requires restore to be done before build is executed. + /// + public bool NoRestore { get; set; } + + /// + /// Gets or sets a value indicating whether to verify that no formatting changes would be performed. + /// Terminates with a non zero exit code if any files would have been formatted. + /// + public bool VerifyNoChanges { get; set; } + + /// + /// Gets or sets a space-separated list of relative file or folder paths to include in formatting. + /// All files in the solution or project are formatted if empty. + /// + public ICollection Include { get; set; } = new List(); + + /// + /// Gets or sets a space-separated list of relative file or folder paths to exclude from formatting. The default is none. + /// + public ICollection Exclude { get; set; } = new List(); + + /// + /// Gets or sets a value indicating whether to format files generated by the SDK. + /// + public bool IncludeGenerated { get; set; } + + /// + /// Gets or sets a value indicating whether to log all project or solution load information to a binary log file. + /// + public FilePath BinaryLog { get; set; } + + /// + /// Gets or sets a path to a JSON report. + /// + public FilePath Report { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/Format/DotNetFormatSeverity.cs b/src/Cake.Common/Tools/DotNet/Format/DotNetFormatSeverity.cs new file mode 100644 index 0000000000..b501c8ef71 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Format/DotNetFormatSeverity.cs @@ -0,0 +1,23 @@ +namespace Cake.Common.Tools.DotNet.Format +{ + /// + /// Severity of dotnet format. + /// + public enum DotNetFormatSeverity + { + /// + /// Information + /// + Info, + + /// + /// Warning + /// + Warning, + + /// + /// Error + /// + Error + } +} diff --git a/src/Cake.Common/Tools/DotNet/Format/DotNetFormatter.cs b/src/Cake.Common/Tools/DotNet/Format/DotNetFormatter.cs new file mode 100644 index 0000000000..225893a7f0 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Format/DotNetFormatter.cs @@ -0,0 +1,144 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Linq; +using Cake.Core; +using Cake.Core.IO; +using Cake.Core.Tooling; + +namespace Cake.Common.Tools.DotNet.Format +{ + /// + /// .NET project formatter. + /// + public sealed class DotNetFormatter : DotNetTool + { + private readonly ICakeEnvironment _environment; + + /// + /// Initializes a new instance of the class. + /// + /// The file system. + /// The environment. + /// The process runner. + /// The tool locator. + public DotNetFormatter( + IFileSystem fileSystem, + ICakeEnvironment environment, + IProcessRunner processRunner, + IToolLocator tools) : base(fileSystem, environment, processRunner, tools) + { + _environment = environment; + } + + /// + /// Format the project or solution using the specified path and settings. + /// + /// The target project or solution path. + /// The sub command. + /// The settings. + public void Format(string root, string subcommand, DotNetFormatSettings settings) + { + if (root == null) + { + throw new ArgumentNullException(nameof(root)); + } + + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + RunCommand(settings, GetArguments(root, subcommand, settings)); + } + + private ProcessArgumentBuilder GetArguments(string root, string subcommand, DotNetFormatSettings settings) + { + var builder = CreateArgumentBuilder(settings); + + builder.Append("format"); + + // Subcommand + if (!string.IsNullOrWhiteSpace(subcommand)) + { + builder.Append(subcommand); + } + + // Specific path? + if (root != null) + { + builder.AppendQuoted(root); + } + + // Diagnostics + if (settings.Diagnostics != null && settings.Diagnostics.Any()) + { + builder.AppendSwitch("--diagnostics", string.Join(" ", settings.Diagnostics)); + } + + // Severity + if (settings.Severity.HasValue) + { + builder.Append("--severity"); + builder.Append(GetSeverityValue(settings.Severity.Value)); + } + + // No Restore + if (settings.NoRestore) + { + builder.Append("--no-restore"); + } + + // Verify No Changes + if (settings.VerifyNoChanges) + { + builder.Append("--verify-no-changes"); + } + + // Include + if (settings.Include != null && settings.Include.Any()) + { + builder.AppendSwitch("--include", string.Join(" ", settings.Include)); + } + + // Exclude + if (settings.Exclude != null && settings.Exclude.Any()) + { + builder.AppendSwitch("--exclude", string.Join(" ", settings.Exclude)); + } + + // Include Generated + if (settings.IncludeGenerated) + { + builder.Append("--include-generated"); + } + + // Binary Log + if (settings.BinaryLog != null) + { + builder.AppendSwitchQuoted($"--binarylog", settings.BinaryLog.MakeAbsolute(_environment).FullPath); + } + + // Report + if (settings.Report != null) + { + builder.AppendSwitchQuoted($"--report", settings.Report.MakeAbsolute(_environment).FullPath); + } + + return builder; + } + + private static string GetSeverityValue(DotNetFormatSeverity value) + { + return value switch + { + DotNetFormatSeverity.Info => "info", + DotNetFormatSeverity.Warning => "warn", + DotNetFormatSeverity.Error => "error", + _ => throw new InvalidOperationException($"Unknown severity value '{value}'"), + }; + } + } +} diff --git a/src/Cake.Common/Tools/DotNet/MSBuild/DotNetMSBuildSettings.cs b/src/Cake.Common/Tools/DotNet/MSBuild/DotNetMSBuildSettings.cs new file mode 100644 index 0000000000..93f31ea2ae --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/MSBuild/DotNetMSBuildSettings.cs @@ -0,0 +1,245 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using Cake.Common.Tools.DotNetCore.MSBuild; +using Cake.Common.Tools.MSBuild; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.MSBuild +{ + /// + /// Contains settings used by . + /// + public class DotNetMSBuildSettings : DotNetSettings + { + /// + /// Gets or sets a value indicating whether to show detailed information at the end of the build log about the configurations that were built and how they were scheduled to nodes. + /// + public bool DetailedSummary { get; set; } + + /// + /// Gets or sets extensions to ignore when determining which project file to build. + /// + public ICollection IgnoreProjectExtensions { get; set; } + + /// + /// Gets or sets the maximum number of concurrent processes to use when building. + /// + /// + /// If you don't include this switch, the default value is 1. If you specifying a value that is zero or less, MSBuild will use up to the number of processors in the computer. + /// + public int? MaxCpuCount { get; set; } + + /// + /// Gets or sets a value indicating whether to exclude any MSBuild.rsp files automatically. + /// + public bool ExcludeAutoResponseFiles { get; set; } + + /// + /// Gets or sets a value indicating whether to display the startup banner and the copyright message. + /// + public bool NoLogo { get; set; } + + /// + /// Gets or sets the default value of all the version numbers embedded in the build output. + /// + public string Version + { + get => GetPropertyValueOrDefault("Version"); + set => this.WithProperty("Version", value); + } + + /// + /// Gets or sets the base version number embedded in the build output. + /// + public string VersionPrefix + { + get => GetPropertyValueOrDefault("VersionPrefix"); + set => this.WithProperty("VersionPrefix", value); + } + + /// + /// Gets or sets the pre-release label of the version number embedded in the build output. + /// + public string VersionSuffix + { + get => GetPropertyValueOrDefault("VersionSuffix"); + set => this.WithProperty("VersionSuffix", value); + } + + /// + /// Gets or sets the file version number embedded in the build output. + /// + public string FileVersion + { + get => GetPropertyValueOrDefault("FileVersion"); + set => this.WithProperty("FileVersion", value); + } + + /// + /// Gets or sets the assembly version number embedded in the build output. + /// + public string AssemblyVersion + { + get => GetPropertyValueOrDefault("AssemblyVersion"); + set => this.WithProperty("AssemblyVersion", value); + } + + /// + /// Gets or sets the assembly informational version number embedded in the build output. + /// + public string InformationalVersion + { + get => GetPropertyValueOrDefault("InformationalVersion"); + set => this.WithProperty("InformationalVersion", value); + } + + /// + /// Gets or sets the version number of the NuGet package generated. + /// + public string PackageVersion + { + get => GetPropertyValueOrDefault("PackageVersion"); + set => this.WithProperty("PackageVersion", value); + } + + /// + /// Gets or sets the release notes of the NuGet package generated. + /// + public string PackageReleaseNotes + { + get => GetPropertyValueOrDefault("PackageReleaseNotes"); + set => this.WithProperty("PackageReleaseNotes", value); + } + + /// + /// Gets or sets a value indicating whether to normalize stored file paths used when producing deterministic builds. + /// + /// + /// For more information see https://devblogs.microsoft.com/dotnet/producing-packages-with-source-link/#deterministic-builds. + /// + public bool? ContinuousIntegrationBuild { get; set; } + + /// + /// Gets the project-level properties to set or override. + /// + public IDictionary> Properties { get; } + + /// + /// Gets the targets to build in the project. + /// + /// + /// If you specify any targets, they are run instead of any targets in the DefaultTargets attribute in the project file. + /// + public ICollection Targets { get; } + + /// + /// Gets or sets the version of the Toolset to use to build the project. + /// + public MSBuildVersion? ToolVersion { get; set; } + + /// + /// Gets or sets a value indicating whether to validate the project file and, if validation succeeds, build the project. + /// + public bool ValidateProjectFile { get; set; } + + /// + /// Gets the response files to use. + /// + /// + /// A response file is a text file that is used to insert command-line switches. For more information see https://docs.microsoft.com/en-gb/visualstudio/msbuild/msbuild-response-files. + /// + public ICollection ResponseFiles { get; } + + /// + /// Gets or sets a value indicating whether to log the build output of each MSBuild node to its own file. + /// + /// + /// The initial location for these files is the current directory. By default, the files are named "MSBuildNodeId.log". You can use the /fileLoggerParameters switch to specify the location of the files and other parameters for the fileLogger. + /// If you name a log file by using the /fileLoggerParameters switch, the distributed logger will use that name as a template and append the node ID to that name when creating a log file for each node. + /// + public bool DistributedFileLogger { get; set; } + + /// + /// Gets the distributed loggers to use. + /// + /// + /// A distributed logger consists of a central and forwarding logger. MSBuild will attach an instance of the forwarding logger to each secondary node. + /// For more information see https://msdn.microsoft.com/en-us/library/bb383987.aspx. + /// + public ICollection DistributedLoggers { get; } + + /// + /// Gets or sets the parameters for the console logger. + /// + public MSBuildLoggerSettings ConsoleLoggerSettings { get; set; } + + /// + /// Gets the file loggers to use. + /// + public ICollection FileLoggers { get; } + + /// + /// Gets or sets the binary logging options. + /// + public MSBuildBinaryLoggerSettings BinaryLogger { get; set; } + + /// + /// Gets the loggers to use to log events from MSBuild. + /// + public ICollection Loggers { get; } + + /// + /// Gets or sets a value indicating whether to disable the default console logger, and not log events to the console. + /// + public bool DisableConsoleLogger { get; set; } + + /// + /// Gets the warning codes to treats as errors. + /// + /// + /// When a warning is treated as an error the target will continue to execute as if it was a warning but the overall build will fail. + /// + public IList WarningCodesAsError { get; } + + /// + /// Gets or sets a value indicating how all warnings should be treated. + /// + public MSBuildTreatAllWarningsAs TreatAllWarningsAs { get; set; } + + /// + /// Gets the warning codes to treats as low importance messages. + /// + public IList WarningCodesAsMessage { get; } + + /// + /// Initializes a new instance of the class. + /// + public DotNetMSBuildSettings() + { + Properties = new Dictionary>(StringComparer.OrdinalIgnoreCase); + Targets = new List(); + ResponseFiles = new List(); + DistributedLoggers = new List(); + FileLoggers = new List(); + Loggers = new List(); + WarningCodesAsError = new List(); + WarningCodesAsMessage = new List(); + IgnoreProjectExtensions = new List(); + } + + private string GetPropertyValueOrDefault(string propertyName, string @default = null) + { + if (!Properties.TryGetValue(propertyName, out var propertyValues)) + { + return @default; + } + + var propertyValue = string.Join(";", propertyValues); + return propertyValue; + } + } +} diff --git a/src/Cake.Common/Tools/DotNet/MSBuild/DotNetMSBuildSettingsExtensions.cs b/src/Cake.Common/Tools/DotNet/MSBuild/DotNetMSBuildSettingsExtensions.cs new file mode 100644 index 0000000000..a68b155511 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/MSBuild/DotNetMSBuildSettingsExtensions.cs @@ -0,0 +1,572 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Cake.Common.Tools.DotNetCore.MSBuild; +using Cake.Common.Tools.MSBuild; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.MSBuild +{ + /// + /// Contains functionality related to .NET MSBuild settings. + /// + public static class DotNetMSBuildSettingsExtensions + { + /// + /// Adds a MSBuild target to the configuration. + /// + /// The settings. + /// The MSBuild target. + /// The same instance so that multiple calls can be chained. + /// Ignores a target if already added. + public static DotNetMSBuildSettings WithTarget(this DotNetMSBuildSettings settings, string target) + { + EnsureSettings(settings); + + if (!settings.Targets.Contains(target)) + { + settings.Targets.Add(target); + } + + return settings; + } + + /// + /// Adds a property to the configuration. + /// + /// The settings. + /// The property name. + /// The property values. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings WithProperty(this DotNetMSBuildSettings settings, string name, params string[] values) + { + EnsureSettings(settings); + + ICollection currentValue; + + // try to get existing values of properties and add new property values + currentValue = settings.Properties.TryGetValue(name, out currentValue) && currentValue != null + ? currentValue.Concat(values).ToList() + : new List(values); + + settings.Properties[name] = currentValue; + + return settings; + } + + /// + /// Shows detailed information at the end of the build log about the configurations that were built and how they were scheduled to nodes. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings ShowDetailedSummary(this DotNetMSBuildSettings settings) + { + EnsureSettings(settings); + + settings.DetailedSummary = true; + return settings; + } + + /// + /// Adds a extension to ignore when determining which project file to build. + /// + /// The settings. + /// The extension to ignore. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings WithIgnoredProjectExtension(this DotNetMSBuildSettings settings, string extension) + { + EnsureSettings(settings); + + settings.IgnoreProjectExtensions.Add(extension); + return settings; + } + + /// + /// Sets the maximum CPU count. Without this set MSBuild will compile projects in this solution one at a time. + /// + /// The settings. + /// The maximum CPU count. Set this value to zero to use as many MSBuild processes as available CPUs. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetMaxCpuCount(this DotNetMSBuildSettings settings, int? maxCpuCount) + { + EnsureSettings(settings); + + settings.MaxCpuCount = maxCpuCount.HasValue + ? Math.Max(0, maxCpuCount.Value) + : 0; + return settings; + } + + /// + /// Exclude any MSBuild.rsp files automatically. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings ExcludeAutoResponseFiles(this DotNetMSBuildSettings settings) + { + EnsureSettings(settings); + + settings.ExcludeAutoResponseFiles = true; + return settings; + } + + /// + /// Hide the startup banner and the copyright message. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings HideLogo(this DotNetMSBuildSettings settings) + { + EnsureSettings(settings); + + settings.NoLogo = true; + return settings; + } + + /// + /// Sets a value indicating whether to normalize stored file paths used when producing deterministic builds. + /// + /// + /// For more information see https://devblogs.microsoft.com/dotnet/producing-packages-with-source-link/#deterministic-builds. + /// + /// The settings. + /// A value indicating whether to normalize stored file paths used when producing deterministic builds. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetContinuousIntegrationBuild(this DotNetMSBuildSettings settings, bool? continuousIntegrationBuild = true) + { + EnsureSettings(settings); + + settings.ContinuousIntegrationBuild = continuousIntegrationBuild; + return settings; + } + + /// + /// Sets the version of the Toolset to use to build the project. + /// + /// The settings. + /// The version. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings UseToolVersion(this DotNetMSBuildSettings settings, MSBuildVersion version) + { + EnsureSettings(settings); + + settings.ToolVersion = version; + return settings; + } + + /// + /// Validate the project file and, if validation succeeds, build the project. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings ValidateProjectFile(this DotNetMSBuildSettings settings) + { + EnsureSettings(settings); + + settings.ValidateProjectFile = true; + return settings; + } + + /// + /// Adds a response file to use. + /// + /// The settings. + /// The response file to add. + /// The same instance so that multiple calls can be chained. + /// + /// A response file is a text file that is used to insert command-line switches. For more information see https://docs.microsoft.com/en-gb/visualstudio/msbuild/msbuild-response-files. + /// + public static DotNetMSBuildSettings WithResponseFile(this DotNetMSBuildSettings settings, FilePath responseFile) + { + EnsureSettings(settings); + + settings.ResponseFiles.Add(responseFile); + return settings; + } + + /// + /// Log the build output of each MSBuild node to its own file. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings UseDistributedFileLogger(this DotNetMSBuildSettings settings) + { + EnsureSettings(settings); + + settings.DistributedFileLogger = true; + return settings; + } + + /// + /// Adds a distributed loggers to use. + /// + /// The settings. + /// The response file to add. + /// The same instance so that multiple calls can be chained. + /// + /// A distributed logger consists of a central and forwarding logger. MSBuild will attach an instance of the forwarding logger to each secondary node. + /// For more information see https://msdn.microsoft.com/en-us/library/bb383987.aspx. + /// + public static DotNetMSBuildSettings WithDistributedLogger(this DotNetMSBuildSettings settings, MSBuildDistributedLogger logger) + { + EnsureSettings(settings); + + settings.DistributedLoggers.Add(logger); + return settings; + } + + /// + /// Sets the parameters for the console logger. + /// + /// The settings. + /// The console logger parameters to set. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetConsoleLoggerSettings(this DotNetMSBuildSettings settings, MSBuildLoggerSettings consoleLoggerParameters) + { + EnsureSettings(settings); + + settings.ConsoleLoggerSettings = consoleLoggerParameters ?? throw new ArgumentNullException(nameof(consoleLoggerParameters)); + + return settings; + } + + /// + /// Adds a file logger with all the default settings. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + /// + /// Each file logger will be declared in the order added. + /// The first file logger will match up to the /fl parameter. + /// The next nine (max) file loggers will match up to the /fl1 through /fl9 respectively. + /// + public static DotNetMSBuildSettings AddFileLogger(this DotNetMSBuildSettings settings) + { + return AddFileLogger(settings, new MSBuildFileLoggerSettings()); + } + + /// + /// Adds a file logger. + /// + /// The settings. + /// Parameters to be passed to the logger. + /// The same instance so that multiple calls can be chained. + /// + /// Each file logger will be declared in the order added. + /// The first file logger will match up to the /fl parameter. + /// The next nine (max) file loggers will match up to the /fl1 through /fl9 respectively. + /// + public static DotNetMSBuildSettings AddFileLogger(this DotNetMSBuildSettings settings, MSBuildFileLoggerSettings fileLoggerParameters) + { + EnsureSettings(settings); + + if (fileLoggerParameters == null) + { + throw new ArgumentNullException(nameof(fileLoggerParameters)); + } + + settings.FileLoggers.Add(fileLoggerParameters); + + return settings; + } + + /// + /// Enables the binary logger with all the default settings. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings EnableBinaryLogger(this DotNetMSBuildSettings settings) + { + return EnableBinaryLogger(settings, MSBuildBinaryLoggerImports.Unspecified); + } + + /// + /// Enables the binary logger with the specified imports and default file name. + /// + /// The settings. + /// The imports. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings EnableBinaryLogger(this DotNetMSBuildSettings settings, MSBuildBinaryLoggerImports imports) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + settings.BinaryLogger = new MSBuildBinaryLoggerSettings + { + Enabled = true, + Imports = imports, + }; + + return settings; + } + + /// + /// Enables the binary logger with the specified log file name and no imports. + /// + /// The settings. + /// The log file name. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings EnableBinaryLogger(this DotNetMSBuildSettings settings, string fileName) + { + return EnableBinaryLogger(settings, fileName, MSBuildBinaryLoggerImports.Unspecified); + } + + /// + /// Enables the binary logger with the specified log file name and imports. + /// + /// The settings. + /// The log file name. + /// The imports. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings EnableBinaryLogger(this DotNetMSBuildSettings settings, string fileName, MSBuildBinaryLoggerImports imports) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + settings.BinaryLogger = new MSBuildBinaryLoggerSettings + { + Enabled = true, + FileName = fileName, + Imports = imports, + }; + + return settings; + } + + /// + /// Adds a custom logger. + /// + /// The settings. + /// The assembly containing the logger. Should match the format {AssemblyName[,StrongName] | AssemblyFile}. + /// The class implementing the logger. Should match the format [PartialOrFullNamespace.]LoggerClassName. If the assembly contains only one logger, class does not need to be specified. + /// Parameters to be passed to the logger. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings WithLogger(this DotNetMSBuildSettings settings, string loggerAssembly, string loggerClass = null, string loggerParameters = null) + { + EnsureSettings(settings); + + if (string.IsNullOrWhiteSpace(loggerAssembly)) + { + throw new ArgumentException(nameof(loggerAssembly)); + } + + settings.Loggers.Add(new MSBuildLogger + { + Assembly = loggerAssembly, + Class = loggerClass, + Parameters = loggerParameters + }); + + return settings; + } + + /// + /// Disables the default console logger, and not log events to the console. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings DisableConsoleLogger(this DotNetMSBuildSettings settings) + { + EnsureSettings(settings); + + settings.DisableConsoleLogger = true; + + return settings; + } + + /// + /// Sets the warning code to treats as an error. + /// + /// The settings. + /// The warning code to treat as an error. + /// The same instance so that multiple calls can be chained. + /// + /// When a warning is treated as an error the target will continue to execute as if it was a warning but the overall build will fail. + /// + public static DotNetMSBuildSettings SetWarningCodeAsError(this DotNetMSBuildSettings settings, string warningCode) + { + EnsureSettings(settings); + + if (string.IsNullOrWhiteSpace(warningCode)) + { + throw new ArgumentException("Warning code cannot be null or empty", nameof(warningCode)); + } + + settings.WarningCodesAsError.Add(warningCode); + + return settings; + } + + /// + /// Sets the warning code to treats as a message. + /// + /// The settings. + /// The warning code to treat as a message. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetWarningCodeAsMessage(this DotNetMSBuildSettings settings, string warningCode) + { + EnsureSettings(settings); + + if (string.IsNullOrWhiteSpace(warningCode)) + { + throw new ArgumentException("Warning code cannot be null or empty", nameof(warningCode)); + } + + settings.WarningCodesAsMessage.Add(warningCode); + + return settings; + } + + /// + /// Sets how all warnings should be treated. + /// + /// The settings. + /// How all warning should be treated. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings TreatAllWarningsAs(this DotNetMSBuildSettings settings, MSBuildTreatAllWarningsAs behaviour) + { + EnsureSettings(settings); + + settings.TreatAllWarningsAs = behaviour; + + return settings; + } + + /// + /// Sets the configuration. + /// + /// The settings. + /// The configuration. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetConfiguration(this DotNetMSBuildSettings settings, string configuration) + => settings.WithProperty("configuration", configuration); + + /// + /// Sets the version. + /// + /// The settings. + /// The version. + /// The same instance so that multiple calls can be chained. + /// + /// Version will override VersionPrefix and VersionSuffix if set. + /// This may also override version settings during packaging. + /// + public static DotNetMSBuildSettings SetVersion(this DotNetMSBuildSettings settings, string version) + => settings.WithProperty("Version", version); + + /// + /// Sets the file version. + /// + /// The settings. + /// The file version. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetFileVersion(this DotNetMSBuildSettings settings, string fileVersion) + => settings.WithProperty("FileVersion", fileVersion); + + /// + /// Sets the assembly version. + /// + /// The settings. + /// The assembly version. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetAssemblyVersion(this DotNetMSBuildSettings settings, string assemblyVersion) + => settings.WithProperty("AssemblyVersion", assemblyVersion); + + /// + /// Sets the informational version. + /// + /// The settings. + /// The informational version. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetInformationalVersion(this DotNetMSBuildSettings settings, string informationalVersion) + => settings.WithProperty("InformationalVersion", informationalVersion); + + /// + /// Sets the package version. + /// + /// The settings. + /// The package version. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetPackageVersion(this DotNetMSBuildSettings settings, string packageVersion) + => settings.WithProperty("PackageVersion", packageVersion); + + /// + /// Sets the package release notes. + /// + /// The settings. + /// The package release notes. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetPackageReleaseNotes(this DotNetMSBuildSettings settings, string packageReleaseNotes) + => settings.WithProperty("PackageReleaseNotes", packageReleaseNotes); + + /// + /// Suppress warning CS7035. + /// This is useful when using semantic versioning and either the file or informational version + /// doesn't match the recommended format. + /// The recommended format is: major.minor.build.revision where + /// each is an integer between 0 and 65534 (inclusive). + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SuppressVersionRecommendedFormatWarning(this DotNetMSBuildSettings settings) + => settings.WithProperty("nowarn", "7035"); + + /// + /// Sets the version prefix. + /// + /// The settings. + /// The version prefix. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetVersionPrefix(this DotNetMSBuildSettings settings, string versionPrefix) + => settings.WithProperty("VersionPrefix", versionPrefix); + + /// + /// Sets the version Suffix. + /// + /// The settings. + /// The version prefix. + /// The same instance so that multiple calls can be chained. + public static DotNetMSBuildSettings SetVersionSuffix(this DotNetMSBuildSettings settings, string versionSuffix) + => settings.WithProperty("VersionSuffix", versionSuffix); + + /// + /// Adds a framework to target. + /// + /// The settings. + /// The framework to target. + /// The same instance so that multiple calls can be chained. + /// + /// For list of target frameworks see https://docs.microsoft.com/en-us/dotnet/standard/frameworks. + /// + public static DotNetMSBuildSettings SetTargetFramework(this DotNetMSBuildSettings settings, string targetFramework) + => settings.WithProperty("TargetFrameworks", targetFramework); + + /// + /// Sets a target operating systems where the application or assembly will run. + /// + /// The settings. + /// The runtime id of the operating system. + /// The same instance so that multiple calls can be chained. + /// + /// For list of runtime ids see https://docs.microsoft.com/en-us/dotnet/core/rid-catalog. + /// + public static DotNetMSBuildSettings SetRuntime(this DotNetMSBuildSettings settings, string runtimeId) + => settings.WithProperty("RuntimeIdentifiers", runtimeId); + + private static void EnsureSettings(DotNetMSBuildSettings settings) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + } + } +} diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Delete/DotNetNuGetDeleteSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Delete/DotNetNuGetDeleteSettings.cs new file mode 100644 index 0000000000..6635c04ba3 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Delete/DotNetNuGetDeleteSettings.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Delete; + +namespace Cake.Common.Tools.DotNet.NuGet.Delete +{ + /// + /// Contains settings used by . + /// + public class DotNetNuGetDeleteSettings : DotNetSettings + { + /// + /// Gets or sets a value indicating the server URL. + /// + /// + /// Supported URLs for nuget.org include http://www.nuget.org, http://www.nuget.org/api/v3, + /// and http://www.nuget.org/api/v2/package. For private feeds, substitute the host name + /// (for example, %hostname%/api/v3). + /// + public string Source { get; set; } + + /// + /// Gets or sets a value indicating whether to append "api/v2/package" to the source URL. + /// + /// + /// Available since .NET Core 2.1 SDK. + /// + public bool NoServiceEndpoint { get; set; } + + /// + /// Gets or sets a value indicating whether to block and require manual action for operations like authentication. + /// + /// + /// Available since .NET Core 2.2 SDK. + /// + public bool Interactive { get; set; } + + /// + /// Gets or sets a value indicating whether to prompt for user input or confirmations. + /// + public bool NonInteractive { get; set; } + + /// + /// Gets or sets a value indicating the API key for the server. + /// + public string ApiKey { get; set; } + + /// + /// Gets or sets a value indicating whether to force command-line output in English. + /// + public bool ForceEnglishOutput { get; set; } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Push/DotNetNuGetPushSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Push/DotNetNuGetPushSettings.cs new file mode 100644 index 0000000000..0a0c13a76b --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Push/DotNetNuGetPushSettings.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Push; + +namespace Cake.Common.Tools.DotNet.NuGet.Push +{ + /// + /// Contains settings used by . + /// + public class DotNetNuGetPushSettings : DotNetSettings + { + /// + /// Gets or sets a value indicating the server URL. + /// + /// + /// This option is required unless DefaultPushSource config value is set in the NuGet config file. + /// + public string Source { get; set; } + + /// + /// Gets or sets a value indicating the symbol server URL. + /// + public string SymbolSource { get; set; } + + /// + /// Gets or sets a value indicating whether to append "api/v2/package" to the source URL. + /// + /// + /// Available since .NET Core 2.1 SDK. + /// + public bool NoServiceEndpoint { get; set; } + + /// + /// Gets or sets a value indicating whether to block and require manual action for operations like authentication. + /// + /// + /// Available since .NET Core 2.2 SDK. + /// + public bool Interactive { get; set; } + + /// + /// Gets or sets a value indicating timeout for pushing to a server in seconds. + /// + /// Defaults to 300 seconds (5 minutes). Specifying 0 (zero seconds) applies the default value. + /// + /// + public int? Timeout { get; set; } + + /// + /// Gets or sets a value indicating the API key for the server. + /// + public string ApiKey { get; set; } + + /// + /// Gets or sets a value indicating the API key for the symbol server. + /// + public string SymbolApiKey { get; set; } + + /// + /// Gets or sets a value indicating whether buffering is disabled when pushing to an HTTP(S) server. + /// + /// + /// This decreases memory usage. + /// + public bool DisableBuffering { get; set; } + + /// + /// Gets or sets a value indicating whether symbols should be not be pushed if present. + /// + public bool IgnoreSymbols { get; set; } + + /// + /// Gets or sets a value indicating whether, when pushing multiple packages to an HTTP(S) server, + /// to treat any 409 Conflict response as a warning so that the push can continue. + /// + /// + /// Available since .NET Core 3.1 SDK. + /// + public bool SkipDuplicate { get; set; } + + /// + /// Gets or sets a value indicating whether to force command-line output in English. + /// + public bool ForceEnglishOutput { get; set; } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetAddSourceSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetAddSourceSettings.cs new file mode 100644 index 0000000000..c51284fb4c --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetAddSourceSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Source; + +namespace Cake.Common.Tools.DotNet.NuGet.Source +{ + /// + /// Contains settings used by for adding new sources. + /// + public class DotNetNuGetAddSourceSettings : DotNetNuGetSourceSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetDisableSourceSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetDisableSourceSettings.cs new file mode 100644 index 0000000000..2464af9b0e --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetDisableSourceSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Source; + +namespace Cake.Common.Tools.DotNet.NuGet.Source +{ + /// + /// Contains settings used by for disabling NuGet sources. + /// + public class DotNetNuGetDisableSourceSettings : DotNetNuGetSourceSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetEnableSourceSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetEnableSourceSettings.cs new file mode 100644 index 0000000000..dc8bd85209 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetEnableSourceSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Source; + +namespace Cake.Common.Tools.DotNet.NuGet.Source +{ + /// + /// Contains settings used by for enabling a NuGet source. + /// + public class DotNetNuGetEnableSourceSettings : DotNetNuGetSourceSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetHasSourceSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetHasSourceSettings.cs new file mode 100644 index 0000000000..3ce0b17e4f --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetHasSourceSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Source; + +namespace Cake.Common.Tools.DotNet.NuGet.Source +{ + /// + /// Contains settings used by for checking if a NuGet source exists. + /// + public class DotNetNuGetHasSourceSettings : DotNetNuGetSourceSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetListSourceSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetListSourceSettings.cs new file mode 100644 index 0000000000..b6d49ae80b --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetListSourceSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Source; + +namespace Cake.Common.Tools.DotNet.NuGet.Source +{ + /// + /// Contains settings used by for listing NuGet sources. + /// + public class DotNetNuGetListSourceSettings : DotNetNuGetSourceSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetRemoveSourceSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetRemoveSourceSettings.cs new file mode 100644 index 0000000000..bcbea85980 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetRemoveSourceSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Source; + +namespace Cake.Common.Tools.DotNet.NuGet.Source +{ + /// + /// Contains settings used by for removing a NuGet source. + /// + public class DotNetNuGetRemoveSourceSettings : DotNetNuGetSourceSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetSourceSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetSourceSettings.cs new file mode 100644 index 0000000000..4b48f7b486 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetSourceSettings.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Source; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.NuGet.Source +{ + /// + /// Contains settings used by . + /// + public class DotNetNuGetSourceSettings : DotNetSettings + { + /// + /// Gets or sets the path to the package(s) source. + /// + public string Source { get; set; } + + /// + /// Gets or sets a value indicating whether this source contains sensitive data, i.e. authentication token in url. + /// + public bool IsSensitiveSource { get; set; } + + /// + /// Gets or sets the user name to be used when connecting to an authenticated source. + /// + public string UserName { get; set; } + + /// + /// Gets or sets the password to be used when connecting to an authenticated source. + /// + public string Password { get; set; } + + /// + /// Gets or sets a value indicating whether to enable storing portable package source credentials by disabling password encryption. + /// + public bool StorePasswordInClearText { get; set; } + + /// + /// Gets or sets the comma-separated list of valid authentication types for this source. + /// + /// + /// By default, all authentication types are valid. Example: basic,negotiate. + /// + public string ValidAuthenticationTypes { get; set; } + + /// + /// Gets or sets the NuGet configuration file. + /// + public FilePath ConfigFile { get; set; } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetUpdateSourceSettings.cs b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetUpdateSourceSettings.cs new file mode 100644 index 0000000000..eafba39283 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/NuGet/Source/DotNetNuGetUpdateSourceSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.NuGet.Source; + +namespace Cake.Common.Tools.DotNet.NuGet.Source +{ + /// + /// Contains settings used by for updating a NuGet source. + /// + public class DotNetNuGetUpdateSourceSettings : DotNetNuGetSourceSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/Pack/DotNetPackSettings.cs b/src/Cake.Common/Tools/DotNet/Pack/DotNetPackSettings.cs new file mode 100644 index 0000000000..2395fc5058 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Pack/DotNetPackSettings.cs @@ -0,0 +1,105 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Cake.Common.Tools.DotNet.MSBuild; +using Cake.Common.Tools.DotNetCore.Pack; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.Pack +{ + /// + /// Contains settings used by . + /// + public class DotNetPackSettings : DotNetSettings + { + /// + /// Gets or sets the output directory. + /// + public DirectoryPath OutputDirectory { get; set; } + + /// + /// Gets or sets the configuration under which to build. + /// + public string Configuration { get; set; } + + /// + /// Gets or sets the value that defines what `*` should be replaced with in version field in project.json. + /// + public string VersionSuffix { get; set; } + + /// + /// Gets or sets a value indicating whether to not build project before packing. + /// + public bool NoBuild { get; set; } + + /// + /// Gets or sets a value indicating whether to ignore project to project references and only build the root project. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public bool NoDependencies { get; set; } + + /// + /// Gets or sets a value indicating whether to not do implicit NuGet package restore. + /// This makes build faster, but requires restore to be done before build is executed. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public bool NoRestore { get; set; } + + /// + /// Gets or sets a value indicating whether to display the startup banner or the copyright message. + /// + /// + /// Available since .NET Core 3.0 SDK. + /// + public bool NoLogo { get; set; } + + /// + /// Gets or sets a value indicating whether to generate the symbols package. + /// + public bool IncludeSymbols { get; set; } + + /// + /// Gets or sets the symbol package format. + /// + /// The symbol package format. + public string SymbolPackageFormat { get; set; } + + /// + /// Gets or sets a value indicating whether to includes the source files in the NuGet package. + /// The sources files are included in the src folder within the nupkg. + /// + public bool IncludeSource { get; set; } + + /// + /// Gets or sets a value indicating whether to set the serviceable flag in the package. + /// + /// + /// For more information, see https://aka.ms/nupkgservicing. + /// + public bool Serviceable { get; set; } + + /// + /// Gets or sets the target runtime. + /// + public string Runtime { get; set; } + + /// + /// Gets or sets the specified NuGet package sources to use during the packing. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public ICollection Sources { get; set; } = new List(); + + /// + /// Gets or sets additional arguments to be passed to MSBuild. + /// + public DotNetMSBuildSettings MSBuildSettings { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/Publish/DotNetPublishSettings.cs b/src/Cake.Common/Tools/DotNet/Publish/DotNetPublishSettings.cs new file mode 100644 index 0000000000..69de1172d3 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Publish/DotNetPublishSettings.cs @@ -0,0 +1,179 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Cake.Common.Tools.DotNet.MSBuild; +using Cake.Common.Tools.DotNetCore.Publish; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.Publish +{ + /// + /// Contains settings used by . + /// + public class DotNetPublishSettings : DotNetSettings + { + /// + /// Gets or sets the output directory. + /// + public DirectoryPath OutputDirectory { get; set; } + + /// + /// Gets or sets the target runtime. + /// + public string Runtime { get; set; } + + /// + /// Gets or sets a specific framework to compile. + /// + public string Framework { get; set; } + + /// + /// Gets or sets the configuration under which to build. + /// + public string Configuration { get; set; } + + /// + /// Gets or sets the value that defines what `*` should be replaced with in version field in project.json. + /// + public string VersionSuffix { get; set; } + + /// + /// Gets or sets a value indicating whether to not to build the project before publishing. + /// This makes build faster, but requires build to be done before publish is executed. + /// + /// + /// Requires .NET Core 2.1 or newer. + /// + public bool NoBuild { get; set; } + + /// + /// Gets or sets a value indicating whether to ignore project to project references and only build the root project. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public bool NoDependencies { get; set; } + + /// + /// Gets or sets a value indicating whether to not do implicit NuGet package restore. + /// This makes build faster, but requires restore to be done before build is executed. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public bool NoRestore { get; set; } + + /// + /// Gets or sets a value indicating whether to display the startup banner or the copyright message. + /// + /// + /// Available since .NET Core 3.0 SDK. + /// + public bool NoLogo { get; set; } + + /// + /// Gets or sets a value indicating whether to force all dependencies to be resolved even if the last restore was successful. This is equivalent to deleting project.assets.json. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public bool Force { get; set; } + + /// + /// Gets or sets a value indicating whether Publish the .NET Core runtime with your application so the runtime doesn't need to be installed on the target machine. Defaults to 'true' if a runtime identifier is specified. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public bool? SelfContained { get; set; } + + /// + /// Gets or sets a value indicating whether to package your app into a platform-specific single-file executable. + /// + /// + /// Requires .NET Core 3.x or newer. + /// + public bool? PublishSingleFile { get; set; } + + /// + /// Gets or sets a value indicating whether to reduce the size of apps by analyzing IL and trimming unused assemblies. + /// + /// + /// Requires .NET Core 3.x or newer. + /// + public bool? PublishTrimmed { get; set; } + + /// + /// Gets or sets a value as to whether tiered compilation quick JIT is enabled. + /// + /// + /// Requires .NET Core 3.x or newer. Tiered compilation is enabled by default in .NET Core 3. + /// Code generated by Quick JIT may run slower, allocate more memory, or use more stack space. + /// + public bool? TieredCompilationQuickJit { get; set; } + + /// + /// Gets or sets a value indicating whether tiered compilation is enabled. + /// + /// + /// Requires .NET Core 3.x or newer. Tiered compilation is enabled by default in .NET Core 3. + /// + public bool? TieredCompilation { get; set; } + + /// + /// Gets or sets a value indicating whether to compile your application assemblies as ReadyToRun (R2R) format. + /// + /// + /// Requires .NET Core 3.x or newer. Tiered compilation is enabled by default in .NET Core 3. + /// + public bool? PublishReadyToRun { get; set; } + + /// + /// Gets or sets a value indicating whether to show warnings emitted by ReadyToRun (R2R) compilation. + /// + /// + /// Requires .NET Core 3.x or newer. Tiered compilation is enabled by default in .NET Core 3. + /// + public bool? PublishReadyToRunShowWarnings { get; set; } + + /// + /// Gets or sets a value indicating whether to bundle native libraries when publishing a platform-specific single-file executable. + /// + /// + /// Requires .NET 5 or newer. + /// + public bool? IncludeNativeLibrariesForSelfExtract { get; set; } + + /// + /// Gets or sets a value indicating whether to bundle all content when publishing a platform-specific single-file executable. + /// This will extract all files before running the executable and preserves the original .NET Core single-file deployment behavior. + /// + /// + /// Requires .NET 5 or newer. + /// + public bool? IncludeAllContentForSelfExtract { get; set; } + + /// + /// Gets or sets a value indicating whether to enable compression on the embedded assemblies when publishing a single-file executable. + /// + /// + /// Requires .NET 6 or newer. + /// + public bool? EnableCompressionInSingleFile { get; set; } + + /// + /// Gets or sets the specified NuGet package sources to use during the restore. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public ICollection Sources { get; set; } = new List(); + + /// + /// Gets or sets additional arguments to be passed to MSBuild. + /// + public DotNetMSBuildSettings MSBuildSettings { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/Restore/DotNetRestoreSettings.cs b/src/Cake.Common/Tools/DotNet/Restore/DotNetRestoreSettings.cs new file mode 100644 index 0000000000..9e8c3d42ad --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Restore/DotNetRestoreSettings.cs @@ -0,0 +1,117 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Cake.Common.Tools.DotNet.MSBuild; +using Cake.Common.Tools.DotNetCore.Restore; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.Restore +{ + /// + /// Contains settings used by . + /// + public class DotNetRestoreSettings : DotNetSettings + { + /// + /// Gets or sets the specified NuGet package sources to use during the restore. + /// + public ICollection Sources { get; set; } = new List(); + + /// + /// Gets or sets the NuGet configuration file to use. + /// + public FilePath ConfigFile { get; set; } + + /// + /// Gets or sets the directory to install packages in. + /// + public DirectoryPath PackagesDirectory { get; set; } + + /// + /// Gets or sets a value indicating whether to do not cache packages and http requests. + /// + public bool NoCache { get; set; } + + /// + /// Gets or sets a value indicating whether to disable restoring multiple projects in parallel. + /// + public bool DisableParallel { get; set; } + + /// + /// Gets or sets a value indicating whether to only warning failed sources if there are packages meeting version requirement. + /// + public bool IgnoreFailedSources { get; set; } + + /// + /// Gets or sets the target runtime to restore packages for. + /// + public string Runtime { get; set; } + + /// + /// Gets or sets a value indicating whether to ignore project to project references and restore only the root project. + /// + public bool NoDependencies { get; set; } + + /// + /// Gets or sets a value indicating whether to force all dependencies to be resolved even if the last restore was successful. + /// This is equivalent to deleting the project.assets.json file. + /// + /// Note: This flag was introduced with the .NET Core 2.x release. + /// + public bool Force { get; set; } + + /// + /// Gets or sets a value indicating whether to stop and wait for user input or action (for example to complete authentication). + /// + /// + /// Supported by .NET SDK version 2.1.400 and above. + /// + public bool Interactive { get; set; } + + /// + /// Gets or sets a value indicating whether to enable project lock file to be generated and used with restore. + /// + /// + /// Supported by .NET SDK version 2.1.500 and above. + /// + public bool UseLockFile { get; set; } + + /// + /// Gets or sets a value indicating whether to not allow updating project lock file. + /// + /// + /// When set to true, restore will fail if the lock file is out of sync. + /// Useful for CI builds when you do not want the build to continue if the package closure has changed than what is present in the lock file. + /// + /// Supported by .NET SDK version 2.1.500 and above. + /// + /// + public bool LockedMode { get; set; } + + /// + /// Gets or sets a value indicating output location where project lock file is written. + /// + /// + /// If not set, 'dotnet restore' defaults to 'PROJECT_ROOT\packages.lock.json'. + /// + /// Supported by .NET SDK version 2.1.500 and above. + /// + /// + public FilePath LockFilePath { get; set; } + + /// + /// Gets or sets a value indicating whether to force restore to reevaluate all dependencies even if a lock file already exists. + /// + /// + /// Supported by .NET SDK version 2.1.500 and above. + /// + public bool ForceEvaluate { get; set; } + + /// + /// Gets or sets additional arguments to be passed to MSBuild. + /// + public DotNetMSBuildSettings MSBuildSettings { get; set; } + } +} diff --git a/src/Cake.Common/Tools/DotNet/Run/DotNetRunSettings.cs b/src/Cake.Common/Tools/DotNet/Run/DotNetRunSettings.cs new file mode 100644 index 0000000000..e45b775212 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Run/DotNetRunSettings.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Cake.Common.Tools.DotNetCore.Run; + +namespace Cake.Common.Tools.DotNet.Run +{ + /// + /// Contains settings used by . + /// + public class DotNetRunSettings : DotNetSettings + { + /// + /// Gets or sets a specific framework to compile. + /// + public string Framework { get; set; } + + /// + /// Gets or sets the configuration under which to build. + /// + public string Configuration { get; set; } + + /// + /// Gets or sets a value indicating whether to not do implicit NuGet package restore. + /// This makes run faster, but requires restore to be done before run is executed. + /// + public bool NoRestore { get; set; } + + /// + /// Gets or sets a value indicating whether to not do implicit build. + /// This makes run faster, but requires build to be done before run is executed. + /// + public bool NoBuild { get; set; } + + /// + /// Gets or sets the specified NuGet package sources to use during the run is executed. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public ICollection Sources { get; set; } = new List(); + + /// + /// Gets or sets the target runtime. + /// + public string Runtime { get; set; } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNet/SDKCheck/DotNetSDKCheckSettings.cs b/src/Cake.Common/Tools/DotNet/SDKCheck/DotNetSDKCheckSettings.cs new file mode 100644 index 0000000000..a326da9534 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/SDKCheck/DotNetSDKCheckSettings.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Cake.Common.Tools.DotNet.SDKCheck +{ + /// + /// Contains settings used by . + /// + public sealed class DotNetSDKCheckSettings : DotNetSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/SDKCheck/DotNetSDKChecker.cs b/src/Cake.Common/Tools/DotNet/SDKCheck/DotNetSDKChecker.cs new file mode 100644 index 0000000000..c130736457 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/SDKCheck/DotNetSDKChecker.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Core; +using Cake.Core.IO; +using Cake.Core.Tooling; + +namespace Cake.Common.Tools.DotNet.SDKCheck +{ + /// + /// .NET SDK checker. + /// + public sealed class DotNetSDKChecker : DotNetTool + { + /// + /// Initializes a new instance of the class. + /// + /// The file system. + /// The environment. + /// The process runner. + /// The tool locator. + public DotNetSDKChecker( + IFileSystem fileSystem, + ICakeEnvironment environment, + IProcessRunner processRunner, + IToolLocator tools) : base(fileSystem, environment, processRunner, tools) + { + } + + /// + /// Lists the latest available version of the .NET SDK and .NET Runtime, for each feature band. + /// + public void Check() + { + var settings = new DotNetSDKCheckSettings(); + RunCommand(settings, GetArguments(settings)); + } + + private ProcessArgumentBuilder GetArguments(DotNetSDKCheckSettings settings) + { + var builder = CreateArgumentBuilder(settings); + + builder.Append("sdk check"); + + return builder; + } + } +} diff --git a/src/Cake.Common/Tools/DotNet/Test/DotNetTestSettings.cs b/src/Cake.Common/Tools/DotNet/Test/DotNetTestSettings.cs new file mode 100644 index 0000000000..8f35942673 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Test/DotNetTestSettings.cs @@ -0,0 +1,122 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using Cake.Common.Tools.DotNetCore.Test; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.Test +{ + /// + /// Contains settings used by . + /// + public class DotNetTestSettings : DotNetSettings + { + /// + /// Gets or sets the settings file to use when running tests. + /// + public FilePath Settings { get; set; } + + /// + /// Gets or sets the filter expression to filter out tests in the current project. + /// + /// + /// For more information on filtering support, see https://aka.ms/vstest-filtering. + /// + public string Filter { get; set; } + + /// + /// Gets or sets the path to use for the custom test adapter in the test run. + /// + public DirectoryPath TestAdapterPath { get; set; } + + /// + /// Gets or sets a logger for test results. + /// + [Obsolete("Please use Loggers instead.")] + public string Logger { get; set; } + + /// + /// Gets or sets the loggers for test results. + /// + public ICollection Loggers { get; set; } = new List(); + + /// + /// Gets or sets the output directory. + /// + public DirectoryPath OutputDirectory { get; set; } + + /// + /// Gets or sets the configuration under which to build. + /// + public string Configuration { get; set; } + + /// + /// Gets or sets the data collectors for the test run. + /// + public ICollection Collectors { get; set; } = new List(); + + /// + /// Gets or sets specific framework to compile. + /// + public string Framework { get; set; } + + /// + /// Gets or sets a value indicating whether to not build the project before testing. + /// + public bool NoBuild { get; set; } + + /// + /// Gets or sets a value indicating whether to not do implicit NuGet package restore. + /// This makes build faster, but requires restore to be done before build is executed. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public bool NoRestore { get; set; } + + /// + /// Gets or sets a value indicating whether to run tests without displaying the Microsoft TestPlatform banner. + /// + /// + /// Available since .NET Core 3.0 SDK. + /// + public bool NoLogo { get; set; } + + /// + /// Gets or sets a file to write diagnostic messages to. + /// + public FilePath DiagnosticFile { get; set; } + + /// + /// Gets or sets the results directory. This setting is only available from 2.0.0 upward. + /// + public DirectoryPath ResultsDirectory { get; set; } + + /// + /// Gets or sets the file path to write VSTest reports to. + /// + public FilePath VSTestReportPath { get; set; } + + /// + /// Gets or sets the target runtime to test for. This setting is only available from .NET Core 3.x upward. + /// + public string Runtime { get; set; } + + /// + /// Gets or sets a value indicating whether to run the tests in blame mode. This option is helpful in isolating a problematic test causing the test host to crash. + /// Outputs a 'Sequence.xml' file in the current directory that captures the order of execution of test before the crash. + /// + public bool Blame { get; set; } + + /// + /// Gets or sets the specified NuGet package sources to use during testing. + /// + /// + /// Requires .NET Core 2.x or newer. + /// + public ICollection Sources { get; set; } = new List(); + } +} diff --git a/src/Cake.Common/Tools/DotNet/Tool/DotNetToolSettings.cs b/src/Cake.Common/Tools/DotNet/Tool/DotNetToolSettings.cs new file mode 100644 index 0000000000..202b50ca5d --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/Tool/DotNetToolSettings.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Cake.Common.Tools.DotNetCore.Tool; + +namespace Cake.Common.Tools.DotNet.Tool +{ + /// + /// Contains settings used by . + /// + public class DotNetToolSettings : DotNetSettings + { + } +} diff --git a/src/Cake.Common/Tools/DotNet/VSTest/DotNetVSTestSettings.cs b/src/Cake.Common/Tools/DotNet/VSTest/DotNetVSTestSettings.cs new file mode 100644 index 0000000000..db69d98cc6 --- /dev/null +++ b/src/Cake.Common/Tools/DotNet/VSTest/DotNetVSTestSettings.cs @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Cake.Common.Tools.DotNetCore.VSTest; +using Cake.Common.Tools.VSTest; +using Cake.Core.IO; + +namespace Cake.Common.Tools.DotNet.VSTest +{ + /// + /// Contains settings used by . + /// + public class DotNetVSTestSettings : DotNetSettings + { + /// + /// Gets or sets the settings file to use when running tests. + /// + public FilePath Settings { get; set; } + + /// + /// Gets or sets the a list tests to run. + /// + public ICollection TestsToRun { get; set; } + + /// + /// Gets or sets the path to use for the custom test adapter in the test run. + /// + public DirectoryPath TestAdapterPath { get; set; } + + /// + /// Gets or sets the target platform architecture to be used for test execution. + /// + public VSTestPlatform Platform { get; set; } + + /// + /// Gets or sets specific .Net Framework version to be used for test execution. + /// + /// + /// Valid values are ".NETFramework,Version=v4.6", ".NETCoreApp,Version=v1.0" etc. + /// Other supported values are Framework35, Framework40, Framework45 and FrameworkCore10. + /// + public string Framework { get; set; } + + /// + /// Gets or sets a value indicating whether the tests should be executed in parallel. + /// + /// + /// By default up to all available cores on the machine may be used. The number of cores to use may be configured using a settings file. + /// + public bool Parallel { get; set; } + + /// + /// Gets or sets the filter expression to run test that match. + /// + /// + /// For more information on filtering support, see https://aka.ms/vstest-filtering. + /// + public string TestCaseFilter { get; set; } + + /// + /// Gets or sets a logger for test results. + /// + public string Logger { get; set; } + + /// + /// Gets or sets the Process Id of the Parent Process responsible for launching current process. + /// + public string ParentProcessId { get; set; } + + /// + /// Gets or sets the Port for socket connection and receiving the event messages. + /// + public int? Port { get; set; } + + /// + /// Gets or sets a file to write diagnostic messages to. + /// + public FilePath DiagnosticFile { get; set; } + + /// + /// Gets or sets the path to put the test results in. + /// + public DirectoryPath ResultsDirectory { get; set; } + + /// + /// Gets or sets a list of extra arguments that should be passed to adapter. + /// + public IDictionary Arguments { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public DotNetVSTestSettings() + { + TestsToRun = new List(); + Arguments = new Dictionary(); + } + } +} diff --git a/src/Cake.Common/Tools/DotNetBuildAliases.cs b/src/Cake.Common/Tools/DotNetBuildAliases.cs deleted file mode 100644 index 76a3947aa4..0000000000 --- a/src/Cake.Common/Tools/DotNetBuildAliases.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Cake.Common.Tools.MSBuild; -using Cake.Common.Tools.XBuild; -using Cake.Core; -using Cake.Core.Annotations; -using Cake.Core.IO; - -namespace Cake.Common.Tools -{ - /// - /// Contains functionality to run either MSBuild on Windows or XBuild on Mac/Linux/Unix. - /// - [CakeAliasCategory("DotNetBuild")] - public static class DotNetBuildAliases - { - /// - /// Builds the specified solution using MSBuild or XBuild. - /// - /// - /// - /// DotNetBuild("./project/project.sln"); - /// - /// - /// The context. - /// The solution. - [CakeMethodAlias] - [Obsolete("Use MSBuild or XBuild instead.")] - public static void DotNetBuild(this ICakeContext context, FilePath solution) - { - DotNetBuild(context, solution, settings => { }); - } - - /// - /// Builds the specified solution using MSBuild or XBuild. - /// - /// - /// - /// DotNetBuild("./project/project.sln", settings => - /// settings.SetConfiguration("Debug") - /// .SetVerbosity(Core.Diagnostics.Verbosity.Minimal) - /// .WithTarget("Build") - /// .WithProperty("TreatWarningsAsErrors","true")); - /// - /// - /// The context. - /// The solution. - /// The configurator. - [CakeMethodAlias] - [Obsolete("Use MSBuild or XBuild instead.")] - public static void DotNetBuild(this ICakeContext context, FilePath solution, Action configurator) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - if (configurator == null) - { - throw new ArgumentNullException(nameof(configurator)); - } - - // Create the settings using the delegate. - var dotNetSettings = new DotNetBuildSettings(solution); - configurator(dotNetSettings); - - // Running on Mac/Linux/Unix? - if (context.Environment.Platform.IsUnix()) - { - // Use XBuild. - XBuildAliases.XBuild(context, solution, settings => - { - settings.Configuration = dotNetSettings.Configuration; - settings.Verbosity = dotNetSettings.Verbosity; - - foreach (var target in dotNetSettings.Targets) - { - settings.Targets.Add(target); - } - - foreach (var property in dotNetSettings.Properties) - { - settings.Properties.Add(property); - } - }); - } - else - { - // Use MSBuild. - MSBuildAliases.MSBuild(context, solution, settings => - { - settings.Configuration = dotNetSettings.Configuration; - settings.Verbosity = dotNetSettings.Verbosity; - - foreach (var target in dotNetSettings.Targets) - { - settings.Targets.Add(target); - } - - foreach (var property in dotNetSettings.Properties) - { - settings.Properties.Add(property); - } - }); - } - } - } -} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetBuildSettings.cs b/src/Cake.Common/Tools/DotNetBuildSettings.cs deleted file mode 100644 index da98ea3052..0000000000 --- a/src/Cake.Common/Tools/DotNetBuildSettings.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using Cake.Core.Diagnostics; -using Cake.Core.IO; - -namespace Cake.Common.Tools -{ - /// - /// Contains settings used by the DotNetBuild alias. - /// - public sealed class DotNetBuildSettings - { - private readonly HashSet _targets; - private readonly Dictionary> _properties; - - /// - /// Gets the solution path. - /// - /// The solution. - public FilePath Solution { get; } - - /// - /// Gets the targets. - /// - /// The targets. - public ISet Targets => _targets; - - /// - /// Gets the properties. - /// - /// The properties. - public IDictionary> Properties => _properties; - - /// - /// Gets or sets the configuration. - /// - /// The configuration. - public string Configuration { get; set; } - - /// - /// Gets or sets the amount of information to display in the build log. - /// Each logger displays events based on the verbosity level that you set for that logger. - /// - /// The build log verbosity. - public Verbosity Verbosity { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The solution. - public DotNetBuildSettings(FilePath solution) - { - if (solution == null) - { - throw new ArgumentNullException(nameof(solution)); - } - - Solution = solution; - _targets = new HashSet(StringComparer.OrdinalIgnoreCase); - _properties = new Dictionary>(StringComparer.OrdinalIgnoreCase); - - Configuration = string.Empty; - Verbosity = Verbosity.Normal; - } - } -} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetBuildSettingsExtensions.cs b/src/Cake.Common/Tools/DotNetBuildSettingsExtensions.cs deleted file mode 100644 index 550bed8dc3..0000000000 --- a/src/Cake.Common/Tools/DotNetBuildSettingsExtensions.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Cake.Core.Diagnostics; - -namespace Cake.Common.Tools -{ - /// - /// Contains functionality related to .NET build settings. - /// - public static class DotNetBuildSettingsExtensions - { - /// - /// Adds a .NET build target to the configuration. - /// - /// The settings. - /// The .NET build target. - /// The same instance so that multiple calls can be chained. - public static DotNetBuildSettings WithTarget(this DotNetBuildSettings settings, string target) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - settings.Targets.Add(target); - return settings; - } - - /// - /// Adds a property to the configuration. - /// - /// The settings. - /// The property name. - /// The property values. - /// The same instance so that multiple calls can be chained. - public static DotNetBuildSettings WithProperty(this DotNetBuildSettings settings, string name, params string[] values) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - - IList currentValue; - currentValue = new List( - settings.Properties.TryGetValue(name, out currentValue) && currentValue != null - ? currentValue.Concat(values) - : values); - - settings.Properties[name] = currentValue; - - return settings; - } - - /// - /// Sets the configuration. - /// - /// The settings. - /// The configuration. - /// The same instance so that multiple calls can be chained. - public static DotNetBuildSettings SetConfiguration(this DotNetBuildSettings settings, string configuration) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - settings.Configuration = configuration; - return settings; - } - - /// - /// Sets the build log verbosity. - /// - /// The settings. - /// The build log verbosity. - /// The same instance so that multiple calls can be chained. - public static DotNetBuildSettings SetVerbosity(this DotNetBuildSettings settings, Verbosity verbosity) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - settings.Verbosity = verbosity; - return settings; - } - } -} \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuildSettings.cs b/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuildSettings.cs index 785231f0c0..40fbe0ac59 100644 --- a/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuildSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuildSettings.cs @@ -2,72 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Cake.Common.Tools.DotNetCore.MSBuild; -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.Build; namespace Cake.Common.Tools.DotNetCore.Build { /// /// Contains settings used by . /// - public sealed class DotNetCoreBuildSettings : DotNetCoreSettings + public sealed class DotNetCoreBuildSettings : DotNetBuildSettings { - /// - /// Gets or sets the output directory. - /// - public DirectoryPath OutputDirectory { get; set; } - - /// - /// Gets or sets the target runtime. - /// - public string Runtime { get; set; } - - /// - /// Gets or sets the configuration under which to build. - /// - public string Configuration { get; set; } - - /// - /// Gets or sets the specific framework to compile. - /// - public string Framework { get; set; } - - /// - /// Gets or sets the value that defines what `*` should be replaced with in version field in project.json. - /// - public string VersionSuffix { get; set; } - - /// - /// Gets or sets a value indicating whether to mark the build as unsafe for incrementality. - /// This turns off incremental compilation and forces a clean rebuild of the project dependency graph. - /// - public bool NoIncremental { get; set; } - - /// - /// Gets or sets a value indicating whether to ignore project to project references and only build the root project. - /// - public bool NoDependencies { get; set; } - - /// - /// Gets or sets a value indicating whether to not do implicit NuGet package restore. - /// This makes build faster, but requires restore to be done before build is executed. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public bool NoRestore { get; set; } - - /// - /// Gets or sets a value indicating whether to display the startup banner or the copyright message. - /// - /// - /// Available since .NET Core 3.0 SDK. - /// - public bool NoLogo { get; set; } - - /// - /// Gets or sets additional arguments to be passed to MSBuild. - /// - public DotNetCoreMSBuildSettings MSBuildSettings { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuilder.cs b/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuilder.cs index b3d0ea037d..e7ba896047 100644 --- a/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuilder.cs +++ b/src/Cake.Common/Tools/DotNetCore/Build/DotNetCoreBuilder.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.Build; using Cake.Common.Tools.DotNetCore.MSBuild; using Cake.Core; using Cake.Core.IO; @@ -13,7 +14,7 @@ namespace Cake.Common.Tools.DotNetCore.Build /// /// .NET Core project builder. /// - public sealed class DotNetCoreBuilder : DotNetCoreTool + public sealed class DotNetCoreBuilder : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -38,7 +39,7 @@ public DotNetCoreBuilder( /// /// The target project path. /// The settings. - public void Build(string project, DotNetCoreBuildSettings settings) + public void Build(string project, DotNetBuildSettings settings) { if (project == null) { @@ -52,7 +53,7 @@ public void Build(string project, DotNetCoreBuildSettings settings) RunCommand(settings, GetArguments(project, settings)); } - private ProcessArgumentBuilder GetArguments(string project, DotNetCoreBuildSettings settings) + private ProcessArgumentBuilder GetArguments(string project, DotNetBuildSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -128,6 +129,16 @@ private ProcessArgumentBuilder GetArguments(string project, DotNetCoreBuildSetti builder.AppendMSBuildSettings(settings.MSBuildSettings, _environment); } + // Sources + if (settings.Sources != null) + { + foreach (var source in settings.Sources) + { + builder.Append("--source"); + builder.AppendQuoted(source); + } + } + return builder; } } diff --git a/src/Cake.Common/Tools/DotNetCore/BuildServer/DotNetCoreBuildServer.cs b/src/Cake.Common/Tools/DotNetCore/BuildServer/DotNetCoreBuildServer.cs index b1b0d75857..d9997b350b 100644 --- a/src/Cake.Common/Tools/DotNetCore/BuildServer/DotNetCoreBuildServer.cs +++ b/src/Cake.Common/Tools/DotNetCore/BuildServer/DotNetCoreBuildServer.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.BuildServer; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -12,7 +13,7 @@ namespace Cake.Common.Tools.DotNetCore.BuildServer /// /// .NET Core project builder. /// - public sealed class DotNetCoreBuildServer : DotNetCoreTool + public sealed class DotNetCoreBuildServer : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -36,7 +37,7 @@ public DotNetCoreBuildServer( /// Build the project using the specified path and settings. /// /// The settings. - public void Shutdown(DotNetCoreBuildServerSettings settings) + public void Shutdown(DotNetBuildServerShutdownSettings settings) { if (settings == null) { @@ -46,7 +47,7 @@ public void Shutdown(DotNetCoreBuildServerSettings settings) RunCommand(settings, GetArguments(settings)); } - private ProcessArgumentBuilder GetArguments(DotNetCoreBuildServerSettings settings) + private ProcessArgumentBuilder GetArguments(DotNetBuildServerShutdownSettings settings) { var builder = CreateArgumentBuilder(settings); diff --git a/src/Cake.Common/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerSettings.cs b/src/Cake.Common/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerSettings.cs index f6918660fa..7c97de3f90 100644 --- a/src/Cake.Common/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/BuildServer/DotNetCoreBuildServerSettings.cs @@ -2,26 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.BuildServer; + namespace Cake.Common.Tools.DotNetCore.BuildServer { /// /// Contains settings used by . /// - public sealed class DotNetCoreBuildServerSettings : DotNetCoreSettings + public sealed class DotNetCoreBuildServerSettings : DotNetBuildServerShutdownSettings { - /// - /// Gets or sets if to shuts down the MSBuild build server. - /// - public bool? MSBuild { get; set; } - - /// - /// Gets or sets if to shuts down the the Razor build server. - /// - public bool? Razor { get; set; } - - /// - /// Gets or sets if to shuts down the VB/C# compiler build server. - /// - public bool? VBCSCompiler { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/Clean/DotNetCoreCleanSettings.cs b/src/Cake.Common/Tools/DotNetCore/Clean/DotNetCoreCleanSettings.cs index 8d08f25d03..2f0a965c61 100644 --- a/src/Cake.Common/Tools/DotNetCore/Clean/DotNetCoreCleanSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Clean/DotNetCoreCleanSettings.cs @@ -2,47 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Cake.Common.Tools.DotNetCore.MSBuild; -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.Clean; namespace Cake.Common.Tools.DotNetCore.Clean { /// /// Contains settings used by . /// - public sealed class DotNetCoreCleanSettings : DotNetCoreSettings + public sealed class DotNetCoreCleanSettings : DotNetCleanSettings { - /// - /// Gets or sets the output directory. - /// - public DirectoryPath OutputDirectory { get; set; } - - /// - /// Gets or sets the configuration under which to build. - /// - public string Configuration { get; set; } - - /// - /// Gets or sets the specific framework to compile. - /// - public string Framework { get; set; } - - /// - /// Gets or sets the target runtime. - /// - public string Runtime { get; set; } - - /// - /// Gets or sets a value indicating whether to display the startup banner or the copyright message. - /// - /// - /// Available since .NET Core 3.0 SDK. - /// - public bool NoLogo { get; set; } - - /// - /// Gets or sets additional arguments to be passed to MSBuild. - /// - public DotNetCoreMSBuildSettings MSBuildSettings { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/Clean/DotNetCoreCleaner.cs b/src/Cake.Common/Tools/DotNetCore/Clean/DotNetCoreCleaner.cs index 17fcf5f01b..ae04f61078 100644 --- a/src/Cake.Common/Tools/DotNetCore/Clean/DotNetCoreCleaner.cs +++ b/src/Cake.Common/Tools/DotNetCore/Clean/DotNetCoreCleaner.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.Clean; using Cake.Common.Tools.DotNetCore.MSBuild; using Cake.Core; using Cake.Core.IO; @@ -13,7 +14,7 @@ namespace Cake.Common.Tools.DotNetCore.Clean /// /// .NET Core project cleaner. /// - public sealed class DotNetCoreCleaner : DotNetCoreTool + public sealed class DotNetCoreCleaner : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -38,7 +39,7 @@ public DotNetCoreCleaner( /// /// The target project path. /// The settings. - public void Clean(string project, DotNetCoreCleanSettings settings) + public void Clean(string project, DotNetCleanSettings settings) { if (project == null) { @@ -52,7 +53,7 @@ public void Clean(string project, DotNetCoreCleanSettings settings) RunCommand(settings, GetArguments(project, settings)); } - private ProcessArgumentBuilder GetArguments(string project, DotNetCoreCleanSettings settings) + private ProcessArgumentBuilder GetArguments(string project, DotNetCleanSettings settings) { var builder = CreateArgumentBuilder(settings); diff --git a/src/Cake.Common/Tools/DotNetCore/DotNetCoreAliases.cs b/src/Cake.Common/Tools/DotNetCore/DotNetCoreAliases.cs index e68cc1b9f9..82e6787a12 100644 --- a/src/Cake.Common/Tools/DotNetCore/DotNetCoreAliases.cs +++ b/src/Cake.Common/Tools/DotNetCore/DotNetCoreAliases.cs @@ -5,6 +5,22 @@ using System; using System.Collections.Generic; using Cake.Common.IO; +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.Build; +using Cake.Common.Tools.DotNet.BuildServer; +using Cake.Common.Tools.DotNet.Clean; +using Cake.Common.Tools.DotNet.Execute; +using Cake.Common.Tools.DotNet.MSBuild; +using Cake.Common.Tools.DotNet.NuGet.Delete; +using Cake.Common.Tools.DotNet.NuGet.Push; +using Cake.Common.Tools.DotNet.NuGet.Source; +using Cake.Common.Tools.DotNet.Pack; +using Cake.Common.Tools.DotNet.Publish; +using Cake.Common.Tools.DotNet.Restore; +using Cake.Common.Tools.DotNet.Run; +using Cake.Common.Tools.DotNet.Test; +using Cake.Common.Tools.DotNet.Tool; +using Cake.Common.Tools.DotNet.VSTest; using Cake.Common.Tools.DotNetCore.Build; using Cake.Common.Tools.DotNetCore.BuildServer; using Cake.Common.Tools.DotNetCore.Clean; @@ -38,6 +54,7 @@ namespace Cake.Common.Tools.DotNetCore public static class DotNetCoreAliases { /// + /// [deprecated] DotNetCoreExecute is obsolete and will be removed in a future release. Use instead. /// Execute an assembly. /// /// The context. @@ -50,12 +67,14 @@ public static class DotNetCoreAliases [CakeMethodAlias] [CakeAliasCategory("Execute")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Execute")] + [Obsolete("DotNetCoreExecute is obsolete and will be removed in a future release. Use DotNetExecute instead.")] public static void DotNetCoreExecute(this ICakeContext context, FilePath assemblyPath) { - context.DotNetCoreExecute(assemblyPath, null); + context.DotNetExecute(assemblyPath); } /// + /// [deprecated] DotNetCoreExecute is obsolete and will be removed in a future release. Use instead. /// Execute an assembly with arguments in the specific path. /// /// The context. @@ -69,12 +88,14 @@ public static void DotNetCoreExecute(this ICakeContext context, FilePath assembl [CakeMethodAlias] [CakeAliasCategory("Execute")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Execute")] + [Obsolete("DotNetCoreExecute is obsolete and will be removed in a future release. Use DotNetExecute instead.")] public static void DotNetCoreExecute(this ICakeContext context, FilePath assemblyPath, ProcessArgumentBuilder arguments) { - context.DotNetCoreExecute(assemblyPath, arguments, null); + context.DotNetExecute(assemblyPath, arguments); } /// + /// [deprecated] DotNetCoreExecute is obsolete and will be removed in a future release. Use instead. /// Execute an assembly with arguments in the specific path with settings. /// /// The context. @@ -94,28 +115,14 @@ public static void DotNetCoreExecute(this ICakeContext context, FilePath assembl [CakeMethodAlias] [CakeAliasCategory("Execute")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Execute")] + [Obsolete("DotNetCoreExecute is obsolete and will be removed in a future release. Use DotNetExecute instead.")] public static void DotNetCoreExecute(this ICakeContext context, FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetCoreExecuteSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (assemblyPath == null) - { - throw new ArgumentNullException(nameof(assemblyPath)); - } - - if (settings == null) - { - settings = new DotNetCoreExecuteSettings(); - } - - var executor = new DotNetCoreExecutor(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - executor.Execute(assemblyPath, arguments, settings); + context.DotNetExecute(assemblyPath, arguments, settings); } /// + /// [deprecated] DotNetCoreRestore is obsolete and will be removed in a future release. Use instead. /// Restore all NuGet Packages. /// /// The context. @@ -127,30 +134,34 @@ public static void DotNetCoreExecute(this ICakeContext context, FilePath assembl [CakeMethodAlias] [CakeAliasCategory("Restore")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Restore")] + [Obsolete("DotNetCoreRestore is obsolete and will be removed in a future release. Use DotNetRestore instead.")] public static void DotNetCoreRestore(this ICakeContext context) { - context.DotNetCoreRestore(null, null); + context.DotNetRestore(); } /// + /// [deprecated] DotNetCoreRestore is obsolete and will be removed in a future release. Use instead. /// Restore all NuGet Packages in the specified path. /// /// The context. - /// List of projects and project folders to restore. Each value can be: a path to a project.json or global.json file, or a folder to recursively search for project.json files. + /// Path to the project file to restore. /// /// - /// DotNetCoreRestore("./src/*"); + /// DotNetCoreRestore("./src/MyProject/MyProject.csproj"); /// /// [CakeMethodAlias] [CakeAliasCategory("Restore")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Restore")] + [Obsolete("DotNetCoreRestore is obsolete and will be removed in a future release. Use DotNetRestore instead.")] public static void DotNetCoreRestore(this ICakeContext context, string root) { - context.DotNetCoreRestore(root, null); + context.DotNetRestore(root); } /// + /// [deprecated] DotNetCoreRestore is obsolete and will be removed in a future release. Use instead. /// Restore all NuGet Packages with the settings. /// /// The context. @@ -173,16 +184,18 @@ public static void DotNetCoreRestore(this ICakeContext context, string root) [CakeMethodAlias] [CakeAliasCategory("Restore")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Restore")] + [Obsolete("DotNetCoreRestore is obsolete and will be removed in a future release. Use DotNetRestore instead.")] public static void DotNetCoreRestore(this ICakeContext context, DotNetCoreRestoreSettings settings) { - context.DotNetCoreRestore(null, settings); + context.DotNetRestore(settings); } /// + /// [deprecated] DotNetCoreRestore is obsolete and will be removed in a future release. Use instead. /// Restore all NuGet Packages in the specified path with settings. /// /// The context. - /// List of projects and project folders to restore. Each value can be: a path to a project.json or global.json file, or a folder to recursively search for project.json files. + /// Path to the project file to restore. /// The settings. /// /// @@ -196,29 +209,20 @@ public static void DotNetCoreRestore(this ICakeContext context, DotNetCoreRestor /// InferRuntimes = new[] {"runtime1", "runtime2"} /// }; /// - /// DotNetCoreRestore("./src/*", settings); + /// DotNetCoreRestore("./src/MyProject/MyProject.csproj", settings); /// /// [CakeMethodAlias] [CakeAliasCategory("Restore")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Restore")] + [Obsolete("DotNetCoreRestore is obsolete and will be removed in a future release. Use DotNetRestore instead.")] public static void DotNetCoreRestore(this ICakeContext context, string root, DotNetCoreRestoreSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreRestoreSettings(); - } - - var restorer = new DotNetCoreRestorer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools, context.Log); - restorer.Restore(root, settings); + context.DotNetRestore(root, settings); } /// + /// [deprecated] DotNetCoreBuild is obsolete and will be removed in a future release. Use instead. /// Build all projects. /// /// The context. @@ -231,12 +235,14 @@ public static void DotNetCoreRestore(this ICakeContext context, string root, Dot [CakeMethodAlias] [CakeAliasCategory("Build")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Build")] + [Obsolete("DotNetCoreBuild is obsolete and will be removed in a future release. Use DotNetBuild instead.")] public static void DotNetCoreBuild(this ICakeContext context, string project) { - context.DotNetCoreBuild(project, null); + context.DotNetBuild(project); } /// + /// [deprecated] DotNetCoreBuild is obsolete and will be removed in a future release. Use instead. /// Build all projects. /// /// The context. @@ -246,7 +252,7 @@ public static void DotNetCoreBuild(this ICakeContext context, string project) /// /// var settings = new DotNetCoreBuildSettings /// { - /// Framework = "netcoreapp2.0", + /// Framework = "netcoreapp3.1", /// Configuration = "Debug", /// OutputDirectory = "./artifacts/" /// }; @@ -257,23 +263,14 @@ public static void DotNetCoreBuild(this ICakeContext context, string project) [CakeMethodAlias] [CakeAliasCategory("Build")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Build")] + [Obsolete("DotNetCoreBuild is obsolete and will be removed in a future release. Use DotNetBuild instead.")] public static void DotNetCoreBuild(this ICakeContext context, string project, DotNetCoreBuildSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreBuildSettings(); - } - - var builder = new DotNetCoreBuilder(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - builder.Build(project, settings); + context.DotNetBuild(project, settings); } /// + /// [deprecated] DotNetCorePack is obsolete and will be removed in a future release. Use instead. /// Package all projects. /// /// The context. @@ -286,12 +283,14 @@ public static void DotNetCoreBuild(this ICakeContext context, string project, Do [CakeMethodAlias] [CakeAliasCategory("Pack")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Pack")] + [Obsolete("DotNetCorePack is obsolete and will be removed in a future release. Use DotNetPack instead.")] public static void DotNetCorePack(this ICakeContext context, string project) { - context.DotNetCorePack(project, null); + context.DotNetPack(project); } /// + /// [deprecated] DotNetCorePack is obsolete and will be removed in a future release. Use instead. /// Package all projects. /// /// The context. @@ -311,23 +310,14 @@ public static void DotNetCorePack(this ICakeContext context, string project) [CakeMethodAlias] [CakeAliasCategory("Pack")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Pack")] + [Obsolete("DotNetCorePack is obsolete and will be removed in a future release. Use DotNetPack instead.")] public static void DotNetCorePack(this ICakeContext context, string project, DotNetCorePackSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCorePackSettings(); - } - - var packer = new DotNetCorePacker(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - packer.Pack(project, settings); + context.DotNetPack(project, settings); } /// + /// [deprecated] DotNetCoreRun is obsolete and will be removed in a future release. Use instead. /// Run all projects. /// /// The context. @@ -339,12 +329,14 @@ public static void DotNetCorePack(this ICakeContext context, string project, Dot [CakeMethodAlias] [CakeAliasCategory("Run")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Run")] + [Obsolete("DotNetCoreRun is obsolete and will be removed in a future release. Use DotNetRun instead.")] public static void DotNetCoreRun(this ICakeContext context) { - context.DotNetCoreRun(null, null, null); + context.DotNetRun(); } /// + /// [deprecated] DotNetCoreRun is obsolete and will be removed in a future release. Use instead. /// Run project. /// /// The context. @@ -357,12 +349,14 @@ public static void DotNetCoreRun(this ICakeContext context) [CakeMethodAlias] [CakeAliasCategory("Run")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Run")] + [Obsolete("DotNetCoreRun is obsolete and will be removed in a future release. Use DotNetRun instead.")] public static void DotNetCoreRun(this ICakeContext context, string project) { - context.DotNetCoreRun(project, null, null); + context.DotNetRun(project); } /// + /// [deprecated] DotNetCoreRun is obsolete and will be removed in a future release. Use instead. /// Run project with path and arguments. /// /// The context. @@ -376,12 +370,14 @@ public static void DotNetCoreRun(this ICakeContext context, string project) [CakeMethodAlias] [CakeAliasCategory("Run")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Run")] + [Obsolete("DotNetCoreRun is obsolete and will be removed in a future release. Use DotNetRun instead.")] public static void DotNetCoreRun(this ICakeContext context, string project, ProcessArgumentBuilder arguments) { - context.DotNetCoreRun(project, arguments, null); + context.DotNetRun(project, arguments); } /// + /// [deprecated] DotNetCoreRun is obsolete and will be removed in a future release. Use instead. /// Run project with settings. /// /// The context. @@ -392,7 +388,7 @@ public static void DotNetCoreRun(this ICakeContext context, string project, Proc /// /// var settings = new DotNetCoreRunSettings /// { - /// Framework = "netcoreapp2.0", + /// Framework = "netcoreapp3.1", /// Configuration = "Release" /// }; /// @@ -402,23 +398,41 @@ public static void DotNetCoreRun(this ICakeContext context, string project, Proc [CakeMethodAlias] [CakeAliasCategory("Run")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Run")] + [Obsolete("DotNetCoreRun is obsolete and will be removed in a future release. Use DotNetRun instead.")] public static void DotNetCoreRun(this ICakeContext context, string project, ProcessArgumentBuilder arguments, DotNetCoreRunSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreRunSettings(); - } + context.DotNetRun(project, arguments, settings); + } - var runner = new DotNetCoreRunner(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - runner.Run(project, arguments, settings); + /// + /// [deprecated] DotNetCoreRun is obsolete and will be removed in a future release. Use instead. + /// Run project with settings. + /// + /// The context. + /// The project path. + /// The settings. + /// + /// + /// var settings = new DotNetCoreRunSettings + /// { + /// Framework = "netcoreapp2.0", + /// Configuration = "Release" + /// }; + /// + /// DotNetCoreRun("./src/Project", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Run")] + [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Run")] + [Obsolete("DotNetCoreRun is obsolete and will be removed in a future release. Use DotNetRun instead.")] + public static void DotNetCoreRun(this ICakeContext context, string project, DotNetCoreRunSettings settings) + { + context.DotNetRun(project, settings); } /// + /// [deprecated] DotNetCorePublish is obsolete and will be removed in a future release. Use instead. /// Publish all projects. /// /// The context. @@ -431,12 +445,14 @@ public static void DotNetCoreRun(this ICakeContext context, string project, Proc [CakeMethodAlias] [CakeAliasCategory("Publish")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Publish")] + [Obsolete("DotNetCorePublish is obsolete and will be removed in a future release. Use DotNetPublish instead.")] public static void DotNetCorePublish(this ICakeContext context, string project) { - context.DotNetCorePublish(project, null); + context.DotNetPublish(project); } /// + /// [deprecated] DotNetCorePublish is obsolete and will be removed in a future release. Use instead. /// Publish all projects. /// /// The context. @@ -446,7 +462,7 @@ public static void DotNetCorePublish(this ICakeContext context, string project) /// /// var settings = new DotNetCorePublishSettings /// { - /// Framework = "netcoreapp2.0", + /// Framework = "netcoreapp3.1", /// Configuration = "Release", /// OutputDirectory = "./artifacts/" /// }; @@ -457,23 +473,14 @@ public static void DotNetCorePublish(this ICakeContext context, string project) [CakeMethodAlias] [CakeAliasCategory("Publish")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Publish")] + [Obsolete("DotNetCorePublish is obsolete and will be removed in a future release. Use DotNetPublish instead.")] public static void DotNetCorePublish(this ICakeContext context, string project, DotNetCorePublishSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCorePublishSettings(); - } - - var publisher = new DotNetCorePublisher(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - publisher.Publish(project, settings); + context.DotNetPublish(project, settings); } /// + /// [deprecated] DotNetCoreTest is obsolete and will be removed in a future release. Use instead. /// Test project. /// /// The context. @@ -485,12 +492,14 @@ public static void DotNetCorePublish(this ICakeContext context, string project, [CakeMethodAlias] [CakeAliasCategory("Test")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Test")] + [Obsolete("DotNetCoreTest is obsolete and will be removed in a future release. Use DotNetTest instead.")] public static void DotNetCoreTest(this ICakeContext context) { - context.DotNetCoreTest(null, null); + context.DotNetTest(); } /// + /// [deprecated] DotNetCoreTest is obsolete and will be removed in a future release. Use instead. /// Test project with path. /// /// The context. @@ -521,12 +530,14 @@ public static void DotNetCoreTest(this ICakeContext context) [CakeMethodAlias] [CakeAliasCategory("Test")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Test")] + [Obsolete("DotNetCoreTest is obsolete and will be removed in a future release. Use DotNetTest instead.")] public static void DotNetCoreTest(this ICakeContext context, string project) { - context.DotNetCoreTest(project, null); + context.DotNetTest(project); } /// + /// [deprecated] DotNetCoreTest is obsolete and will be removed in a future release. Use instead. /// Test project with settings. /// /// The context. @@ -572,23 +583,68 @@ public static void DotNetCoreTest(this ICakeContext context, string project) [CakeMethodAlias] [CakeAliasCategory("Test")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Test")] + [Obsolete("DotNetCoreTest is obsolete and will be removed in a future release. Use DotNetTest instead.")] public static void DotNetCoreTest(this ICakeContext context, string project, DotNetCoreTestSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreTestSettings(); - } + context.DotNetTest(project, settings); + } - var tester = new DotNetCoreTester(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - tester.Test(project, settings); + /// + /// [deprecated] DotNetCoreTest is obsolete and will be removed in a future release. Use instead. + /// Test project with settings. + /// + /// The context. + /// The project path. + /// The arguments. + /// The settings. + /// + /// + /// var settings = new DotNetCoreTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// DotNetCoreTest("./test/Project.Tests/Project.Tests.csproj", settings); + /// + /// You could also specify a task that runs multiple test projects. + /// Cake task: + /// + /// Task("Test") + /// .Does(() => + /// { + /// var settings = new DotNetCoreTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// var projectFiles = GetFiles("./test/**/*.csproj"); + /// foreach(var file in projectFiles) + /// { + /// DotNetCoreTest(file.FullPath, "MSTest.MapInconclusiveToFailed=true", settings); + /// } + /// }); + /// + /// If your test project is using project.json, the project parameter should just be the directory path. + /// + /// var settings = new DotNetCoreTestSettings + /// { + /// Configuration = "Release" + /// }; + /// + /// DotNetCoreTest("./test/Project.Tests/", "MSTest.MapInconclusiveToFailed=true", settings); + /// + /// + [CakeMethodAlias] + [CakeAliasCategory("Test")] + [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Test")] + [Obsolete("DotNetCoreTest is obsolete and will be removed in a future release. Use DotNetTest instead.")] + public static void DotNetCoreTest(this ICakeContext context, string project, ProcessArgumentBuilder arguments, DotNetCoreTestSettings settings) + { + context.DotNetTest(project, arguments, settings); } /// + /// [deprecated] DotNetCoreClean is obsolete and will be removed in a future release. Use instead. /// Cleans a project's output. /// /// The context. @@ -601,12 +657,14 @@ public static void DotNetCoreTest(this ICakeContext context, string project, Dot [CakeMethodAlias] [CakeAliasCategory("Clean")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Clean")] + [Obsolete("DotNetCoreClean is obsolete and will be removed in a future release. Use DotNetClean instead.")] public static void DotNetCoreClean(this ICakeContext context, string project) { - context.DotNetCoreClean(project, null); + context.DotNetClean(project); } /// + /// [deprecated] DotNetCoreClean is obsolete and will be removed in a future release. Use instead. /// Cleans a project's output. /// /// The context. @@ -616,7 +674,7 @@ public static void DotNetCoreClean(this ICakeContext context, string project) /// /// var settings = new DotNetCoreCleanSettings /// { - /// Framework = "netcoreapp2.0", + /// Framework = "netcoreapp3.1", /// Configuration = "Debug", /// OutputDirectory = "./artifacts/" /// }; @@ -627,23 +685,14 @@ public static void DotNetCoreClean(this ICakeContext context, string project) [CakeMethodAlias] [CakeAliasCategory("Clean")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Clean")] + [Obsolete("DotNetCoreClean is obsolete and will be removed in a future release. Use DotNetClean instead.")] public static void DotNetCoreClean(this ICakeContext context, string project, DotNetCoreCleanSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreCleanSettings(); - } - - var cleaner = new DotNetCoreCleaner(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - cleaner.Clean(project, settings); + context.DotNetClean(project, settings); } /// + /// [deprecated] DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use instead. /// Delete a NuGet Package from a server. /// /// The context. @@ -655,12 +704,14 @@ public static void DotNetCoreClean(this ICakeContext context, string project, Do [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Delete")] + [Obsolete("DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use DotNetNuGetDelete instead.")] public static void DotNetCoreNuGetDelete(this ICakeContext context) { - context.DotNetCoreNuGetDelete(null, null, null); + context.DotNetNuGetDelete(); } /// + /// [deprecated] DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use instead. /// Deletes a package from nuget.org. /// /// The context. @@ -673,12 +724,14 @@ public static void DotNetCoreNuGetDelete(this ICakeContext context) [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Delete")] + [Obsolete("DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use DotNetNuGetDelete instead.")] public static void DotNetCoreNuGetDelete(this ICakeContext context, string packageName) { - context.DotNetCoreNuGetDelete(packageName, null, null); + context.DotNetNuGetDelete(packageName); } /// + /// [deprecated] DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use instead. /// Deletes a specific version of a package from nuget.org. /// /// The context. @@ -692,12 +745,14 @@ public static void DotNetCoreNuGetDelete(this ICakeContext context, string packa [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Delete")] + [Obsolete("DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use DotNetNuGetDelete instead.")] public static void DotNetCoreNuGetDelete(this ICakeContext context, string packageName, string packageVersion) { - context.DotNetCoreNuGetDelete(packageName, packageVersion, null); + context.DotNetNuGetDelete(packageName, packageVersion); } /// + /// [deprecated] DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use instead. /// Deletes a package from a server. /// /// The context. @@ -717,12 +772,14 @@ public static void DotNetCoreNuGetDelete(this ICakeContext context, string packa [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Delete")] + [Obsolete("DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use DotNetNuGetDelete instead.")] public static void DotNetCoreNuGetDelete(this ICakeContext context, string packageName, DotNetCoreNuGetDeleteSettings settings) { - context.DotNetCoreNuGetDelete(packageName, null, settings); + context.DotNetNuGetDelete(packageName, settings); } /// + /// [deprecated] DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use instead. /// Deletes a package from a server using the specified settings. /// /// The context. @@ -741,12 +798,14 @@ public static void DotNetCoreNuGetDelete(this ICakeContext context, string packa [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Delete")] + [Obsolete("DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use DotNetNuGetDelete instead.")] public static void DotNetCoreNuGetDelete(this ICakeContext context, DotNetCoreNuGetDeleteSettings settings) { - context.DotNetCoreNuGetDelete(null, null, settings); + context.DotNetNuGetDelete(settings); } /// + /// [deprecated] DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use instead. /// Deletes a package from a server using the specified settings. /// /// The context. @@ -767,45 +826,42 @@ public static void DotNetCoreNuGetDelete(this ICakeContext context, DotNetCoreNu [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Delete")] + [Obsolete("DotNetCoreNuGetDelete is obsolete and will be removed in a future release. Use DotNetNuGetDelete instead.")] public static void DotNetCoreNuGetDelete(this ICakeContext context, string packageName, string packageVersion, DotNetCoreNuGetDeleteSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreNuGetDeleteSettings(); - } - - var nugetDeleter = new DotNetCoreNuGetDeleter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - nugetDeleter.Delete(packageName, packageVersion, settings); + context.DotNetNuGetDelete(packageName, packageVersion, settings); } /// + /// [deprecated] DotNetCoreNuGetPush is obsolete and will be removed in a future release. Use instead. /// Pushes one or more packages to a server. /// /// The context. - /// Name of package to push. + /// of the package to push. /// /// - /// DotNetCoreNuGetPush("*.nupkg"); + /// // With FilePath instance + /// var packageFilePath = GetFiles("*.nupkg").Single(); + /// DotNetCoreNuGetPush(packageFilePath); + /// // With string parameter + /// DotNetCoreNuGetPush("foo*.nupkg"); /// /// [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Push")] - public static void DotNetCoreNuGetPush(this ICakeContext context, string packageName) + [Obsolete("DotNetCoreNuGetPush is obsolete and will be removed in a future release. Use DotNetNuGetPush instead.")] + public static void DotNetCoreNuGetPush(this ICakeContext context, FilePath packageFilePath) { - context.DotNetCoreNuGetPush(packageName, null); + context.DotNetNuGetPush(packageFilePath); } /// + /// [deprecated] DotNetCoreNuGetPush is obsolete and will be removed in a future release. Use instead. /// Pushes one or more packages to a server using the specified settings. /// /// The context. - /// Name of package to push. + /// of the package to push. /// The settings. /// /// @@ -814,30 +870,24 @@ public static void DotNetCoreNuGetPush(this ICakeContext context, string package /// Source = "https://www.example.com/nugetfeed", /// ApiKey = "4003d786-cc37-4004-bfdf-c4f3e8ef9b3a" /// }; - /// + /// // With FilePath instance + /// var packageFilePath = GetFiles("foo*.nupkg").Single(); + /// DotNetCoreNuGetPush(packageFilePath); + /// // With string parameter /// DotNetCoreNuGetPush("foo*.nupkg", settings); /// /// [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Push")] - public static void DotNetCoreNuGetPush(this ICakeContext context, string packageName, DotNetCoreNuGetPushSettings settings) + [Obsolete("DotNetCoreNuGetPush is obsolete and will be removed in a future release. Use DotNetNuGetPush instead.")] + public static void DotNetCoreNuGetPush(this ICakeContext context, FilePath packageFilePath, DotNetCoreNuGetPushSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreNuGetPushSettings(); - } - - var restorer = new DotNetCoreNuGetPusher(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - restorer.Push(packageName, settings); + context.DotNetNuGetPush(packageFilePath, settings); } /// + /// [deprecated] DotNetCoreNuGetAddSource is obsolete and will be removed in a future release. Use instead. /// Add the specified NuGet source. /// /// The context. @@ -860,18 +910,14 @@ public static void DotNetCoreNuGetPush(this ICakeContext context, string package [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetAddSource is obsolete and will be removed in a future release. Use DotNetNuGetAddSource instead.")] public static void DotNetCoreNuGetAddSource(this ICakeContext context, string name, DotNetCoreNuGetSourceSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - sourcer.AddSource(name, settings); + context.DotNetNuGetAddSource(name, settings); } /// + /// [deprecated] DotNetCoreNuGetDisableSource is obsolete and will be removed in a future release. Use instead. /// Disable the specified NuGet source. /// /// The context. @@ -884,12 +930,14 @@ public static void DotNetCoreNuGetAddSource(this ICakeContext context, string na [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetDisableSource is obsolete and will be removed in a future release. Use DotNetNuGetDisableSource instead.")] public static void DotNetCoreNuGetDisableSource(this ICakeContext context, string name) { - context.DotNetCoreNuGetDisableSource(name, null); + context.DotNetNuGetDisableSource(name); } /// + /// [deprecated] DotNetCoreNuGetDisableSource is obsolete and will be removed in a future release. Use instead. /// Disable the specified NuGet source. /// /// The context. @@ -908,18 +956,14 @@ public static void DotNetCoreNuGetDisableSource(this ICakeContext context, strin [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetDisableSource is obsolete and will be removed in a future release. Use DotNetNuGetDisableSource instead.")] public static void DotNetCoreNuGetDisableSource(this ICakeContext context, string name, DotNetCoreNuGetSourceSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - sourcer.DisableSource(name, settings ?? new DotNetCoreNuGetSourceSettings()); + context.DotNetNuGetDisableSource(name, settings); } /// + /// [deprecated] DotNetCoreNuGetEnableSource is obsolete and will be removed in a future release. Use instead. /// Enable the specified NuGet source. /// /// The context. @@ -932,12 +976,14 @@ public static void DotNetCoreNuGetDisableSource(this ICakeContext context, strin [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetEnableSource is obsolete and will be removed in a future release. Use DotNetNuGetEnableSource instead.")] public static void DotNetCoreNuGetEnableSource(this ICakeContext context, string name) { - context.DotNetCoreNuGetEnableSource(name, null); + context.DotNetNuGetEnableSource(name); } /// + /// [deprecated] DotNetCoreNuGetEnableSource is obsolete and will be removed in a future release. Use instead. /// Enable the specified NuGet source. /// /// The context. @@ -956,18 +1002,14 @@ public static void DotNetCoreNuGetEnableSource(this ICakeContext context, string [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetEnableSource is obsolete and will be removed in a future release. Use DotNetNuGetEnableSource instead.")] public static void DotNetCoreNuGetEnableSource(this ICakeContext context, string name, DotNetCoreNuGetSourceSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - sourcer.EnableSource(name, settings ?? new DotNetCoreNuGetSourceSettings()); + context.DotNetNuGetEnableSource(name, settings); } /// + /// [deprecated] DotNetCoreNuGetHasSource is obsolete and will be removed in a future release. Use instead. /// Determines whether the specified NuGet source exists. /// /// The context. @@ -981,12 +1023,14 @@ public static void DotNetCoreNuGetEnableSource(this ICakeContext context, string [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetHasSource is obsolete and will be removed in a future release. Use DotNetNuGetHasSource instead.")] public static bool DotNetCoreNuGetHasSource(this ICakeContext context, string name) { - return context.DotNetCoreNuGetHasSource(name, null); + return context.DotNetNuGetHasSource(name); } /// + /// [deprecated] DotNetCoreNuGetHasSource is obsolete and will be removed in a future release. Use instead. /// Determines whether the specified NuGet source exists. /// /// The context. @@ -1006,18 +1050,14 @@ public static bool DotNetCoreNuGetHasSource(this ICakeContext context, string na [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetHasSource is obsolete and will be removed in a future release. Use DotNetNuGetHasSource instead.")] public static bool DotNetCoreNuGetHasSource(this ICakeContext context, string name, DotNetCoreNuGetSourceSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - return sourcer.HasSource(name, settings ?? new DotNetCoreNuGetSourceSettings()); + return context.DotNetNuGetHasSource(name, settings); } /// + /// [deprecated] DotNetCoreNuGetRemoveSource is obsolete and will be removed in a future release. Use instead. /// Remove the specified NuGet source. /// /// The context. @@ -1030,12 +1070,14 @@ public static bool DotNetCoreNuGetHasSource(this ICakeContext context, string na [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetRemoveSource is obsolete and will be removed in a future release. Use DotNetNuGetRemoveSource instead.")] public static void DotNetCoreNuGetRemoveSource(this ICakeContext context, string name) { - context.DotNetCoreNuGetRemoveSource(name, null); + context.DotNetNuGetRemoveSource(name); } /// + /// [deprecated] DotNetCoreNuGetRemoveSource is obsolete and will be removed in a future release. Use instead. /// Remove the specified NuGet source. /// /// The context. @@ -1054,18 +1096,14 @@ public static void DotNetCoreNuGetRemoveSource(this ICakeContext context, string [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetRemoveSource is obsolete and will be removed in a future release. Use DotNetNuGetRemoveSource instead.")] public static void DotNetCoreNuGetRemoveSource(this ICakeContext context, string name, DotNetCoreNuGetSourceSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - sourcer.RemoveSource(name, settings ?? new DotNetCoreNuGetSourceSettings()); + context.DotNetNuGetRemoveSource(name, settings); } /// + /// [deprecated] DotNetCoreNuGetUpdateSource is obsolete and will be removed in a future release. Use instead. /// Update the specified NuGet source. /// /// The context. @@ -1088,18 +1126,14 @@ public static void DotNetCoreNuGetRemoveSource(this ICakeContext context, string [CakeMethodAlias] [CakeAliasCategory("NuGet")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.NuGet.Source")] + [Obsolete("DotNetCoreNuGetUpdateSource is obsolete and will be removed in a future release. Use DotNetNuGetUpdateSource instead.")] public static void DotNetCoreNuGetUpdateSource(this ICakeContext context, string name, DotNetCoreNuGetSourceSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var sourcer = new DotNetCoreNuGetSourcer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - sourcer.UpdateSource(name, settings); + context.DotNetNuGetUpdateSource(name, settings); } /// + /// [deprecated] DotNetCoreMSBuild is obsolete and will be removed in a future release. Use instead. /// Builds the specified targets in a project file found in the current working directory. /// /// The context. @@ -1111,12 +1145,14 @@ public static void DotNetCoreNuGetUpdateSource(this ICakeContext context, string [CakeMethodAlias] [CakeAliasCategory("MSBuild")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.MSBuild")] + [Obsolete("DotNetCoreMSBuild is obsolete and will be removed in a future release. Use DotNetMSBuild instead.")] public static void DotNetCoreMSBuild(this ICakeContext context) { - context.DotNetCoreMSBuild(null, null); + context.DotNetMSBuild(); } /// + /// [deprecated] DotNetCoreMSBuild is obsolete and will be removed in a future release. Use instead. /// Builds the specified targets in the project file. /// /// The context. @@ -1132,17 +1168,14 @@ public static void DotNetCoreMSBuild(this ICakeContext context) [CakeMethodAlias] [CakeAliasCategory("MSBuild")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.MSBuild")] + [Obsolete("DotNetCoreMSBuild is obsolete and will be removed in a future release. Use DotNetMSBuild instead.")] public static void DotNetCoreMSBuild(this ICakeContext context, string projectOrDirectory) { - if (string.IsNullOrWhiteSpace(projectOrDirectory)) - { - throw new ArgumentNullException(nameof(projectOrDirectory)); - } - - context.DotNetCoreMSBuild(projectOrDirectory, null); + context.DotNetMSBuild(projectOrDirectory); } /// + /// [deprecated] DotNetCoreMSBuild is obsolete and will be removed in a future release. Use instead. /// Builds the specified targets in a project file found in the current working directory. /// /// The context. @@ -1161,12 +1194,14 @@ public static void DotNetCoreMSBuild(this ICakeContext context, string projectOr [CakeMethodAlias] [CakeAliasCategory("MSBuild")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.MSBuild")] + [Obsolete("DotNetCoreMSBuild is obsolete and will be removed in a future release. Use DotNetMSBuild instead.")] public static void DotNetCoreMSBuild(this ICakeContext context, DotNetCoreMSBuildSettings settings) { - context.DotNetCoreMSBuild(null, settings); + context.DotNetMSBuild(settings); } /// + /// [deprecated] DotNetCoreMSBuild is obsolete and will be removed in a future release. Use instead. /// Builds the specified targets in the project file. /// /// The context. @@ -1190,23 +1225,14 @@ public static void DotNetCoreMSBuild(this ICakeContext context, DotNetCoreMSBuil [CakeMethodAlias] [CakeAliasCategory("MSBuild")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.MSBuild")] + [Obsolete("DotNetCoreMSBuild is obsolete and will be removed in a future release. Use DotNetMSBuild instead.")] public static void DotNetCoreMSBuild(this ICakeContext context, string projectOrDirectory, DotNetCoreMSBuildSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreMSBuildSettings(); - } - - var builder = new DotNetCoreMSBuildBuilder(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - builder.Build(projectOrDirectory, settings); + context.DotNetMSBuild(projectOrDirectory, settings); } /// + /// [deprecated] DotNetCoreVSTest is obsolete and will be removed in a future release. Use instead. /// Test one or more projects specified by a path or glob pattern using the VS Test host runner. /// /// The context. @@ -1224,9 +1250,11 @@ public static void DotNetCoreMSBuild(this ICakeContext context, string projectOr [CakeMethodAlias] [CakeAliasCategory("Test")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.VSTest")] - public static void DotNetCoreVSTest(this ICakeContext context, string testFile) => context.DotNetCoreVSTest(testFile, null); + [Obsolete("DotNetCoreVSTest is obsolete and will be removed in a future release. Use DotNetVSTest instead.")] + public static void DotNetCoreVSTest(this ICakeContext context, GlobPattern testFile) => context.DotNetVSTest(testFile); /// + /// [deprecated] DotNetCoreVSTest is obsolete and will be removed in a future release. Use instead. /// Test one or more projects specified by a path or glob pattern with settings using the VS Test host runner. /// /// The context. @@ -1258,14 +1286,14 @@ public static void DotNetCoreMSBuild(this ICakeContext context, string projectOr [CakeMethodAlias] [CakeAliasCategory("Test")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.VSTest")] - public static void DotNetCoreVSTest(this ICakeContext context, string testFile, DotNetCoreVSTestSettings settings) + [Obsolete("DotNetCoreVSTest is obsolete and will be removed in a future release. Use DotNetVSTest instead.")] + public static void DotNetCoreVSTest(this ICakeContext context, GlobPattern testFile, DotNetCoreVSTestSettings settings) { - var testFiles = context.GetFiles(testFile); - - context.DotNetCoreVSTest(testFiles, settings); + context.DotNetVSTest(testFile, settings); } /// + /// [deprecated] DotNetCoreVSTest is obsolete and will be removed in a future release. Use instead. /// Test one or more specified projects with settings using the VS Test host runner. /// /// The context. @@ -1303,23 +1331,14 @@ public static void DotNetCoreVSTest(this ICakeContext context, string testFile, [CakeMethodAlias] [CakeAliasCategory("Test")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.VSTest")] + [Obsolete("DotNetCoreVSTest is obsolete and will be removed in a future release. Use DotNetVSTest instead.")] public static void DotNetCoreVSTest(this ICakeContext context, IEnumerable testFiles, DotNetCoreVSTestSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (settings == null) - { - settings = new DotNetCoreVSTestSettings(); - } - - var tester = new DotNetCoreVSTester(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - tester.Test(testFiles, settings); + context.DotNetVSTest(testFiles, settings); } /// + /// [deprecated] DotNetCoreTool is obsolete and will be removed in a future release. Use instead. /// Execute an .NET Core Extensibility Tool. /// /// The context. @@ -1332,20 +1351,14 @@ public static void DotNetCoreVSTest(this ICakeContext context, IEnumerable + /// [deprecated] DotNetCoreTool is obsolete and will be removed in a future release. Use instead. /// Execute an .NET Core Extensibility Tool. /// /// The context. @@ -1364,19 +1377,14 @@ public static void DotNetCoreTool(this ICakeContext context, string command) [CakeMethodAlias] [CakeAliasCategory("Tool")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Tool")] + [Obsolete("DotNetCoreTool is obsolete and will be removed in a future release. Use DotNetTool instead.")] public static void DotNetCoreTool(this ICakeContext context, string command, DotNetCoreToolSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var arguments = new ProcessArgumentBuilder(); - - context.DotNetCoreTool(null, command, arguments, settings); + context.DotNetTool(command, settings); } /// + /// [deprecated] DotNetCoreTool is obsolete and will be removed in a future release. Use instead. /// Execute an .NET Core Extensibility Tool. /// /// The context. @@ -1390,20 +1398,14 @@ public static void DotNetCoreTool(this ICakeContext context, string command, Dot [CakeMethodAlias] [CakeAliasCategory("Tool")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Tool")] + [Obsolete("DotNetCoreTool is obsolete and will be removed in a future release. Use DotNetTool instead.")] public static void DotNetCoreTool(this ICakeContext context, FilePath projectPath, string command) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var arguments = new ProcessArgumentBuilder(); - var settings = new DotNetCoreToolSettings(); - - context.DotNetCoreTool(projectPath, command, arguments, settings); + context.DotNetTool(projectPath, command); } /// + /// [deprecated] DotNetCoreTool is obsolete and will be removed in a future release. Use instead. /// Execute an .NET Core Extensibility Tool. /// /// The context. @@ -1418,19 +1420,14 @@ public static void DotNetCoreTool(this ICakeContext context, FilePath projectPat [CakeMethodAlias] [CakeAliasCategory("Tool")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Tool")] + [Obsolete("DotNetCoreTool is obsolete and will be removed in a future release. Use DotNetTool instead.")] public static void DotNetCoreTool(this ICakeContext context, FilePath projectPath, string command, ProcessArgumentBuilder arguments) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var settings = new DotNetCoreToolSettings(); - - context.DotNetCoreTool(projectPath, command, arguments, settings); + context.DotNetTool(projectPath, command, arguments); } /// + /// [deprecated] DotNetCoreTool is obsolete and will be removed in a future release. Use instead. /// Execute an .NET Core Extensibility Tool. /// /// The context. @@ -1446,19 +1443,14 @@ public static void DotNetCoreTool(this ICakeContext context, FilePath projectPat [CakeMethodAlias] [CakeAliasCategory("Tool")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.Tool")] + [Obsolete("DotNetCoreTool is obsolete and will be removed in a future release. Use DotNetTool instead.")] public static void DotNetCoreTool(this ICakeContext context, FilePath projectPath, string command, ProcessArgumentBuilder arguments, DotNetCoreToolSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var runner = new DotNetCoreToolRunner(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - - runner.Execute(projectPath, command, arguments, settings); + context.DotNetTool(projectPath, command, arguments, settings); } /// + /// [deprecated] DotNetCoreBuildServerShutdown is obsolete and will be removed in a future release. Use instead. /// Shuts down build servers that are started from dotnet. /// /// The context. @@ -1470,12 +1462,14 @@ public static void DotNetCoreTool(this ICakeContext context, FilePath projectPat [CakeMethodAlias] [CakeAliasCategory("Build Server")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.BuildServer")] + [Obsolete("DotNetCoreBuildServerShutdown is obsolete and will be removed in a future release. Use DotNetBuildServerShutdown instead.")] public static void DotNetCoreBuildServerShutdown(this ICakeContext context) { - context.DotNetCoreBuildServerShutdown(null); + context.DotNetBuildServerShutdown(); } /// + /// [deprecated] DotNetCoreBuildServerShutdown is obsolete and will be removed in a future release. Use instead. /// Shuts down build servers that are started from dotnet. /// /// The context. @@ -1493,16 +1487,10 @@ public static void DotNetCoreBuildServerShutdown(this ICakeContext context) [CakeMethodAlias] [CakeAliasCategory("Build Server")] [CakeNamespaceImport("Cake.Common.Tools.DotNetCore.BuildServer")] + [Obsolete("DotNetCoreBuildServerShutdown is obsolete and will be removed in a future release. Use DotNetBuildServerShutdown instead.")] public static void DotNetCoreBuildServerShutdown(this ICakeContext context, DotNetCoreBuildServerSettings settings) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var buildServer = new DotNetCoreBuildServer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - - buildServer.Shutdown(settings ?? new DotNetCoreBuildServerSettings()); + context.DotNetBuildServerShutdown(settings); } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/DotNetCoreRollForward.cs b/src/Cake.Common/Tools/DotNetCore/DotNetCoreRollForward.cs new file mode 100644 index 0000000000..18945d69a6 --- /dev/null +++ b/src/Cake.Common/Tools/DotNetCore/DotNetCoreRollForward.cs @@ -0,0 +1,308 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using Cake.Common.Tools.DotNet; + +namespace Cake.Common.Tools.DotNetCore +{ + /// + /// Contains the roll forward policy to be used. + /// + [TypeConverter(typeof(DotNetCoreRollForwardConverter))] + public sealed class DotNetCoreRollForward : IEquatable, IComparable, IConvertible, IFormattable + { + private readonly DotNetRollForward _value; + + /// + /// Initializes a new instance of the class. + /// + public DotNetCoreRollForward() + { + _value = default; + } + + internal DotNetCoreRollForward(string stringValue) + { + _value = (DotNetRollForward)Enum.Parse(typeof(DotNetRollForward), stringValue); + } + + private DotNetCoreRollForward(DotNetRollForward value) + { + _value = value; + } + + /// + /// Roll forward to the lowest higher minor version, if requested minor version is missing. + /// + public static readonly DotNetCoreRollForward Minor = new DotNetCoreRollForward(DotNetRollForward.Minor); + + /// + /// Roll forward to the highest patch version. This disables minor version roll forward. + /// + public static readonly DotNetCoreRollForward LatestPatch = new DotNetCoreRollForward(DotNetRollForward.LatestPatch); + + /// + /// Roll forward to lowest higher major version, and lowest minor version, if requested major version is missing. + /// + public static readonly DotNetCoreRollForward Major = new DotNetCoreRollForward(DotNetRollForward.Major); + + /// + /// Roll forward to highest minor version, even if requested minor version is present. + /// + public static readonly DotNetCoreRollForward LatestMinor = new DotNetCoreRollForward(DotNetRollForward.LatestMinor); + + /// + /// Roll forward to highest major and highest minor version, even if requested major is present. + /// + public static readonly DotNetCoreRollForward LatestMajor = new DotNetCoreRollForward(DotNetRollForward.LatestMajor); + + /// + /// Don't roll forward. Only bind to specified version. + /// + public static readonly DotNetCoreRollForward Disable = new DotNetCoreRollForward(DotNetRollForward.Disable); + + /// + /// Explicitly converts to . + /// + /// The . + public static explicit operator int(DotNetCoreRollForward rollForward) + { + return (int)rollForward._value; + } + + /// + /// Implicitly converts to . + /// + /// The . + public static implicit operator DotNetRollForward(DotNetCoreRollForward rollForward) + { + return rollForward._value; + } + + /// + /// Implicitly converts to . + /// + /// The . + public static implicit operator DotNetCoreRollForward(DotNetRollForward rollForward) + { + return rollForward switch + { + DotNetRollForward.Minor => Minor, + DotNetRollForward.LatestPatch => LatestPatch, + DotNetRollForward.Major => Major, + DotNetRollForward.LatestMinor => LatestMinor, + DotNetRollForward.LatestMajor => LatestMajor, + DotNetRollForward.Disable => Disable, + _ => new DotNetCoreRollForward(rollForward), + }; + } + + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The object to compare with the right-hand side object. + /// The object to compare with the left-hand side object. + /// if the specified object is equal to the current object; otherwise, . + public static bool operator ==(DotNetCoreRollForward left, DotNetCoreRollForward right) + { + return left.Equals(right); + } + + /// + /// Determines whether the specified object is not equal to the current object. + /// + /// The object to compare with the right-hand side object. + /// The object to compare with the left-hand side object. + /// if the specified object is not equal to the current object; otherwise, . + public static bool operator !=(DotNetCoreRollForward left, DotNetCoreRollForward right) + { + return !(left == right); + } + + /// + public override string ToString() + { + return _value.ToString(); + } + + /// + public override int GetHashCode() + { + return _value.GetHashCode(); + } + + /// + public override bool Equals(object obj) + { + if (obj is null) + { + return false; + } + + if (!(obj is DotNetCoreRollForward)) + { + return false; + } + + return Equals((DotNetCoreRollForward)obj); + } + + /// + public bool Equals(DotNetCoreRollForward other) + { + return _value.Equals(other._value); + } + + /// + /// Determines whether one or more bit fields are set in the current instance. + /// + /// An enumeration value. + /// + /// if the bit field or bit fields that are set in flag are also set in the + /// current instance; otherwise, . + /// + public bool HasFlag(DotNetCoreRollForward flag) + { + return _value.HasFlag(flag._value); + } + + /// + /// Determines whether one or more bit fields are set in the current instance. + /// + /// An enumeration value. + /// + /// if the bit field or bit fields that are set in flag are also set in the + /// current instance; otherwise, . + /// + public bool HasFlag(Enum flag) + { + return _value.HasFlag(flag); + } + + /// + public int CompareTo(object obj) + { + return _value.CompareTo(obj); + } + + /// + public TypeCode GetTypeCode() + { + return Convert.GetTypeCode(_value); + } + + /// + bool IConvertible.ToBoolean(IFormatProvider provider) + { + return Convert.ToBoolean(_value, provider); + } + + /// + byte IConvertible.ToByte(IFormatProvider provider) + { + return Convert.ToByte(_value, provider); + } + + /// + char IConvertible.ToChar(IFormatProvider provider) + { + return Convert.ToChar(_value, provider); + } + + /// + DateTime IConvertible.ToDateTime(IFormatProvider provider) + { + return Convert.ToDateTime(_value, provider); + } + + /// + decimal IConvertible.ToDecimal(IFormatProvider provider) + { + return Convert.ToDecimal(_value, provider); + } + + /// + double IConvertible.ToDouble(IFormatProvider provider) + { + return Convert.ToDouble(_value, provider); + } + + /// + short IConvertible.ToInt16(IFormatProvider provider) + { + return Convert.ToInt16(_value, provider); + } + + /// + int IConvertible.ToInt32(IFormatProvider provider) + { + return Convert.ToInt32(_value, provider); + } + + /// + long IConvertible.ToInt64(IFormatProvider provider) + { + return Convert.ToInt64(_value, provider); + } + + /// +#pragma warning disable CS3002 // Return type is not CLS-compliant + sbyte IConvertible.ToSByte(IFormatProvider provider) +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + return Convert.ToSByte(_value, provider); + } + + /// + float IConvertible.ToSingle(IFormatProvider provider) + { + return Convert.ToSingle(_value, provider); + } + + /// + string IConvertible.ToString(IFormatProvider provider) + { + return Convert.ToString(_value, provider); + } + + /// + object IConvertible.ToType(Type conversionType, IFormatProvider provider) + { + return Convert.ChangeType(_value, conversionType, provider); + } + + /// +#pragma warning disable CS3002 // Return type is not CLS-compliant + ushort IConvertible.ToUInt16(IFormatProvider provider) +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + return Convert.ToUInt16(_value, provider); + } + + /// +#pragma warning disable CS3002 // Return type is not CLS-compliant + uint IConvertible.ToUInt32(IFormatProvider provider) +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + return Convert.ToUInt32(_value, provider); + } + + /// +#pragma warning disable CS3002 // Return type is not CLS-compliant + ulong IConvertible.ToUInt64(IFormatProvider provider) +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + return Convert.ToUInt64(_value, provider); + } + + /// + [Obsolete("The provider argument is not used. Please use ToString(String).")] + public string ToString(string format, IFormatProvider formatProvider) + { + return _value.ToString(format, formatProvider); + } + } +} diff --git a/src/Cake.Common/Tools/DotNetCore/DotNetCoreRollForwardConverter.cs b/src/Cake.Common/Tools/DotNetCore/DotNetCoreRollForwardConverter.cs new file mode 100644 index 0000000000..9063195e46 --- /dev/null +++ b/src/Cake.Common/Tools/DotNetCore/DotNetCoreRollForwardConverter.cs @@ -0,0 +1,46 @@ +using System; +using System.ComponentModel; +using System.Globalization; + +namespace Cake.Common.Tools.DotNetCore +{ + /// + /// A type converter for . + /// + public class DotNetCoreRollForwardConverter : TypeConverter + { + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string stringValue) + { + return new DotNetCoreRollForward(stringValue); + } + + return base.ConvertFrom(context, culture, value); + } + + /// + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return destinationType == typeof(DotNetCoreRollForward) || base.CanConvertTo(context, destinationType); + } + + /// + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(string) && value is DotNetCoreRollForward dotNetRollForwardValue) + { + return dotNetRollForwardValue.ToString(); + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } +} diff --git a/src/Cake.Common/Tools/DotNetCore/DotNetCoreSettings.cs b/src/Cake.Common/Tools/DotNetCore/DotNetCoreSettings.cs index cd72d27124..e1c9cc61bc 100644 --- a/src/Cake.Common/Tools/DotNetCore/DotNetCoreSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/DotNetCoreSettings.cs @@ -2,23 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Cake.Core.Tooling; +using Cake.Common.Tools.DotNet; namespace Cake.Common.Tools.DotNetCore { /// /// Contains common settings used by . /// - public abstract class DotNetCoreSettings : ToolSettings + public abstract class DotNetCoreSettings : DotNetSettings { - /// - /// Gets or sets the verbosity of logging to use. - /// - public DotNetCoreVerbosity? Verbosity { get; set; } - - /// - /// Gets or sets a value indicating whether to not enable diagnostic output. - /// - public bool DiagnosticOutput { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/DotNetCoreTool.cs b/src/Cake.Common/Tools/DotNetCore/DotNetCoreTool.cs index 185a5dd3b2..da15b30cbe 100644 --- a/src/Cake.Common/Tools/DotNetCore/DotNetCoreTool.cs +++ b/src/Cake.Common/Tools/DotNetCore/DotNetCoreTool.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; +using Cake.Common.Tools.DotNet; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -13,8 +13,8 @@ namespace Cake.Common.Tools.DotNetCore /// Base class for all .NET Core related tools. /// /// The settings type. - public abstract class DotNetCoreTool : Tool - where TSettings : DotNetCoreSettings + public abstract class DotNetCoreTool : DotNetTool + where TSettings : DotNetSettings { /// /// Initializes a new instance of the class. @@ -31,85 +31,5 @@ protected DotNetCoreTool( : base(fileSystem, environment, processRunner, tools) { } - - /// - /// Gets the name of the tool. - /// - /// The name of the tool. - protected override string GetToolName() - { - return ".NET Core CLI"; - } - - /// - /// Gets the possible names of the tool executable. - /// - /// The tool executable name. - protected override IEnumerable GetToolExecutableNames() - { - return new[] { "dotnet", "dotnet.exe" }; - } - - /// - /// Runs the dotnet cli command using the specified settings and arguments. - /// - /// The settings. - /// The arguments. - protected void RunCommand(TSettings settings, ProcessArgumentBuilder arguments) - { - // add arguments common to all commands last - AppendCommonArguments(arguments, settings); - - Run(settings, arguments, null, null); - } - - /// - /// Runs the dotnet cli command using the specified settings and arguments. - /// - /// The settings. - /// The arguments. - /// The processSettings. - protected void RunCommand(TSettings settings, ProcessArgumentBuilder arguments, ProcessSettings processSettings) - { - // add arguments common to all commands last - AppendCommonArguments(arguments, settings); - - Run(settings, arguments, processSettings, null); - } - - /// - /// Creates a and adds common commandline arguments. - /// - /// The settings. - /// Instance of . - protected ProcessArgumentBuilder CreateArgumentBuilder(TSettings settings) - { - var builder = new ProcessArgumentBuilder(); - - if (settings.DiagnosticOutput) - { - builder.Append("--diagnostics"); - } - - return builder; - } - - /// - /// Adds common commandline arguments. - /// - /// Process argument builder to update. - /// The settings. - /// Returns updated with common commandline arguments. - private ProcessArgumentBuilder AppendCommonArguments(ProcessArgumentBuilder builder, TSettings settings) - { - // Verbosity - if (settings.Verbosity.HasValue) - { - builder.Append("--verbosity"); - builder.Append(settings.Verbosity.ToString().ToLower()); - } - - return builder; - } } } diff --git a/src/Cake.Common/Tools/DotNetCore/DotNetCoreVerbosity.cs b/src/Cake.Common/Tools/DotNetCore/DotNetCoreVerbosity.cs index 4f9b26302f..57b0ec9df3 100644 --- a/src/Cake.Common/Tools/DotNetCore/DotNetCoreVerbosity.cs +++ b/src/Cake.Common/Tools/DotNetCore/DotNetCoreVerbosity.cs @@ -2,36 +2,301 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.ComponentModel; +using Cake.Common.Tools.DotNet; + namespace Cake.Common.Tools.DotNetCore { /// - /// Contains the verbosity of logging to use.. + /// Contains the verbosity of logging to use. /// - public enum DotNetCoreVerbosity + [TypeConverter(typeof(DotNetCoreVerbosityConverter))] + public sealed class DotNetCoreVerbosity : IEquatable, IComparable, IConvertible, IFormattable { + private readonly DotNetVerbosity _value; + + /// + /// Initializes a new instance of the class. + /// + public DotNetCoreVerbosity() + { + _value = default; + } + + internal DotNetCoreVerbosity(string stringValue) + { + _value = (DotNetVerbosity)Enum.Parse(typeof(DotNetVerbosity), stringValue); + } + + private DotNetCoreVerbosity(DotNetVerbosity value) + { + _value = value; + } + /// /// Quiet level. /// - Quiet, + public static readonly DotNetCoreVerbosity Quiet = new DotNetCoreVerbosity(DotNetVerbosity.Quiet); /// /// Minimal level. /// - Minimal, + public static readonly DotNetCoreVerbosity Minimal = new DotNetCoreVerbosity(DotNetVerbosity.Minimal); /// /// Normal level. /// - Normal, + public static readonly DotNetCoreVerbosity Normal = new DotNetCoreVerbosity(DotNetVerbosity.Normal); /// /// Detailed level. /// - Detailed, + public static readonly DotNetCoreVerbosity Detailed = new DotNetCoreVerbosity(DotNetVerbosity.Detailed); /// /// Diagnostic level. /// - Diagnostic + public static readonly DotNetCoreVerbosity Diagnostic = new DotNetCoreVerbosity(DotNetVerbosity.Diagnostic); + + /// + /// Explicitly converts to . + /// + /// The . + public static explicit operator int(DotNetCoreVerbosity verbosity) + { + return (int)verbosity._value; + } + + /// + /// Implicitly converts to . + /// + /// The . + public static implicit operator DotNetVerbosity(DotNetCoreVerbosity verbosity) + { + return verbosity._value; + } + + /// + /// Implicitly converts to . + /// + /// The . + public static implicit operator DotNetCoreVerbosity(DotNetVerbosity verbosity) + { + return verbosity switch + { + DotNetVerbosity.Quiet => Quiet, + DotNetVerbosity.Minimal => Minimal, + DotNetVerbosity.Normal => Normal, + DotNetVerbosity.Detailed => Detailed, + DotNetVerbosity.Diagnostic => Diagnostic, + _ => new DotNetCoreVerbosity(verbosity), + }; + } + + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The object to compare with the right-hand side object. + /// The object to compare with the left-hand side object. + /// if the specified object is equal to the current object; otherwise, . + public static bool operator ==(DotNetCoreVerbosity left, DotNetCoreVerbosity right) + { + return left.Equals(right); + } + + /// + /// Determines whether the specified object is not equal to the current object. + /// + /// The object to compare with the right-hand side object. + /// The object to compare with the left-hand side object. + /// if the specified object is not equal to the current object; otherwise, . + public static bool operator !=(DotNetCoreVerbosity left, DotNetCoreVerbosity right) + { + return !(left == right); + } + + /// + public override string ToString() + { + return _value.ToString(); + } + + /// + public override int GetHashCode() + { + return _value.GetHashCode(); + } + + /// + public override bool Equals(object obj) + { + if (obj is null) + { + return false; + } + + if (!(obj is DotNetCoreVerbosity)) + { + return false; + } + + return Equals((DotNetCoreVerbosity)obj); + } + + /// + public bool Equals(DotNetCoreVerbosity other) + { + return _value.Equals(other._value); + } + + /// + /// Determines whether one or more bit fields are set in the current instance. + /// + /// An enumeration value. + /// + /// if the bit field or bit fields that are set in flag are also set in the + /// current instance; otherwise, . + /// + public bool HasFlag(DotNetCoreVerbosity flag) + { + return _value.HasFlag(flag._value); + } + + /// + /// Determines whether one or more bit fields are set in the current instance. + /// + /// An enumeration value. + /// + /// if the bit field or bit fields that are set in flag are also set in the + /// current instance; otherwise, . + /// + public bool HasFlag(Enum flag) + { + return _value.HasFlag(flag); + } + + /// + public int CompareTo(object obj) + { + return _value.CompareTo(obj); + } + + /// + public TypeCode GetTypeCode() + { + return Convert.GetTypeCode(_value); + } + + /// + bool IConvertible.ToBoolean(IFormatProvider provider) + { + return Convert.ToBoolean(_value, provider); + } + + /// + byte IConvertible.ToByte(IFormatProvider provider) + { + return Convert.ToByte(_value, provider); + } + + /// + char IConvertible.ToChar(IFormatProvider provider) + { + return Convert.ToChar(_value, provider); + } + + /// + DateTime IConvertible.ToDateTime(IFormatProvider provider) + { + return Convert.ToDateTime(_value, provider); + } + + /// + decimal IConvertible.ToDecimal(IFormatProvider provider) + { + return Convert.ToDecimal(_value, provider); + } + + /// + double IConvertible.ToDouble(IFormatProvider provider) + { + return Convert.ToDouble(_value, provider); + } + + /// + short IConvertible.ToInt16(IFormatProvider provider) + { + return Convert.ToInt16(_value, provider); + } + + /// + int IConvertible.ToInt32(IFormatProvider provider) + { + return Convert.ToInt32(_value, provider); + } + + /// + long IConvertible.ToInt64(IFormatProvider provider) + { + return Convert.ToInt64(_value, provider); + } + + /// +#pragma warning disable CS3002 // Return type is not CLS-compliant + sbyte IConvertible.ToSByte(IFormatProvider provider) +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + return Convert.ToSByte(_value, provider); + } + + /// + float IConvertible.ToSingle(IFormatProvider provider) + { + return Convert.ToSingle(_value, provider); + } + + /// + string IConvertible.ToString(IFormatProvider provider) + { + return Convert.ToString(_value, provider); + } + + /// + object IConvertible.ToType(Type conversionType, IFormatProvider provider) + { + return Convert.ChangeType(_value, conversionType, provider); + } + + /// +#pragma warning disable CS3002 // Return type is not CLS-compliant + ushort IConvertible.ToUInt16(IFormatProvider provider) +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + return Convert.ToUInt16(_value, provider); + } + + /// +#pragma warning disable CS3002 // Return type is not CLS-compliant + uint IConvertible.ToUInt32(IFormatProvider provider) +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + return Convert.ToUInt32(_value, provider); + } + + /// +#pragma warning disable CS3002 // Return type is not CLS-compliant + ulong IConvertible.ToUInt64(IFormatProvider provider) +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + return Convert.ToUInt64(_value, provider); + } + + /// + [Obsolete("The provider argument is not used. Please use ToString(String).")] + public string ToString(string format, IFormatProvider formatProvider) + { + return _value.ToString(format, formatProvider); + } } } diff --git a/src/Cake.Common/Tools/DotNetCore/DotNetCoreVerbosityConverter.cs b/src/Cake.Common/Tools/DotNetCore/DotNetCoreVerbosityConverter.cs new file mode 100644 index 0000000000..c3b3793de1 --- /dev/null +++ b/src/Cake.Common/Tools/DotNetCore/DotNetCoreVerbosityConverter.cs @@ -0,0 +1,46 @@ +using System; +using System.ComponentModel; +using System.Globalization; + +namespace Cake.Common.Tools.DotNetCore +{ + /// + /// A type converter for . + /// + public class DotNetCoreVerbosityConverter : TypeConverter + { + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); + } + + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string stringValue) + { + return new DotNetCoreVerbosity(stringValue); + } + + return base.ConvertFrom(context, culture, value); + } + + /// + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return destinationType == typeof(DotNetCoreVerbosity) || base.CanConvertTo(context, destinationType); + } + + /// + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(string) && value is DotNetCoreVerbosity dotNetVerbosityValue) + { + return dotNetVerbosityValue.ToString(); + } + + return base.ConvertTo(context, culture, value, destinationType); + } + } +} diff --git a/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecuteSettings.cs b/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecuteSettings.cs index 66bf338c55..e4fa612483 100644 --- a/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecuteSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecuteSettings.cs @@ -2,16 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.Execute; + namespace Cake.Common.Tools.DotNetCore.Execute { /// /// Contains settings used by . /// - public sealed class DotNetCoreExecuteSettings : DotNetCoreSettings + public sealed class DotNetCoreExecuteSettings : DotNetExecuteSettings { - /// - /// Gets or sets the version of the installed Shared Framework to use to run the application. - /// - public string FrameworkVersion { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecutor.cs b/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecutor.cs index d7a6fe6309..d024603dfb 100644 --- a/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecutor.cs +++ b/src/Cake.Common/Tools/DotNetCore/Execute/DotNetCoreExecutor.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.Execute; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -12,7 +14,7 @@ namespace Cake.Common.Tools.DotNetCore.Execute /// /// .NET Core assembly executor. /// - public sealed class DotNetCoreExecutor : DotNetCoreTool + public sealed class DotNetCoreExecutor : DotNetTool { private readonly ICakeEnvironment _environment; @@ -38,7 +40,7 @@ public DotNetCoreExecutor( /// The assembly path. /// The arguments. /// The settings. - public void Execute(FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetCoreExecuteSettings settings) + public void Execute(FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetExecuteSettings settings) { if (assemblyPath == null) { @@ -52,7 +54,7 @@ public void Execute(FilePath assemblyPath, ProcessArgumentBuilder arguments, Dot RunCommand(settings, GetArguments(assemblyPath, arguments, settings)); } - private ProcessArgumentBuilder GetArguments(FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetCoreExecuteSettings settings) + private ProcessArgumentBuilder GetArguments(FilePath assemblyPath, ProcessArgumentBuilder arguments, DotNetExecuteSettings settings) { var builder = CreateArgumentBuilder(settings); diff --git a/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildBuilder.cs b/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildBuilder.cs index ec356c5bf4..01e69f746c 100644 --- a/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildBuilder.cs +++ b/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildBuilder.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.MSBuild; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -12,7 +13,7 @@ namespace Cake.Common.Tools.DotNetCore.MSBuild /// /// .NET Core project builder. /// - public sealed class DotNetCoreMSBuildBuilder : DotNetCoreTool + public sealed class DotNetCoreMSBuildBuilder : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -37,7 +38,7 @@ public DotNetCoreMSBuildBuilder( /// /// The target project path. /// The settings. - public void Build(string projectOrDirectory, DotNetCoreMSBuildSettings settings) + public void Build(string projectOrDirectory, DotNetMSBuildSettings settings) { if (settings == null) { @@ -47,7 +48,7 @@ public void Build(string projectOrDirectory, DotNetCoreMSBuildSettings settings) RunCommand(settings, GetArguments(projectOrDirectory, settings)); } - private ProcessArgumentBuilder GetArguments(string projectOrDirectory, DotNetCoreMSBuildSettings settings) + private ProcessArgumentBuilder GetArguments(string projectOrDirectory, DotNetMSBuildSettings settings) { var builder = CreateArgumentBuilder(settings); diff --git a/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettings.cs b/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettings.cs index fe232ce8de..f80b4c0e56 100644 --- a/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettings.cs @@ -2,152 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using Cake.Common.Tools.MSBuild; -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.MSBuild; namespace Cake.Common.Tools.DotNetCore.MSBuild { /// /// Contains settings used by . /// - public sealed class DotNetCoreMSBuildSettings : DotNetCoreSettings + public sealed class DotNetCoreMSBuildSettings : DotNetMSBuildSettings { - /// - /// Gets or sets a value indicating whether to show detailed information at the end of the build log about the configurations that were built and how they were scheduled to nodes. - /// - public bool DetailedSummary { get; set; } - - /// - /// Gets or sets extensions to ignore when determining which project file to build. - /// - public ICollection IgnoreProjectExtensions { get; set; } - - /// - /// Gets or sets the maximum number of concurrent processes to use when building. - /// - /// - /// If you don't include this switch, the default value is 1. If you specifying a value that is zero or less, MSBuild will use up to the number of processors in the computer. - /// - public int? MaxCpuCount { get; set; } - - /// - /// Gets or sets a value indicating whether to exclude any MSBuild.rsp files automatically. - /// - public bool ExcludeAutoResponseFiles { get; set; } - - /// - /// Gets or sets a value indicating whether to display the startup banner and the copyright message. - /// - public bool NoLogo { get; set; } - - /// - /// Gets the project-level properties to set or override. - /// - public IDictionary> Properties { get; } - - /// - /// Gets the targets to build in the project. - /// - /// - /// If you specify any targets, they are run instead of any targets in the DefaultTargets attribute in the project file. - /// - public ICollection Targets { get; } - - /// - /// Gets or sets the version of the Toolset to use to build the project. - /// - public MSBuildVersion? ToolVersion { get; set; } - - /// - /// Gets or sets a value indicating whether to validate the project file and, if validation succeeds, build the project. - /// - public bool ValidateProjectFile { get; set; } - - /// - /// Gets the response files to use. - /// - /// - /// A response file is a text file that is used to insert command-line switches. For more information see https://docs.microsoft.com/en-gb/visualstudio/msbuild/msbuild-response-files. - /// - public ICollection ResponseFiles { get; } - - /// - /// Gets or sets a value indicating whether to log the build output of each MSBuild node to its own file. - /// - /// - /// The initial location for these files is the current directory. By default, the files are named "MSBuildNodeId.log". You can use the /fileLoggerParameters switch to specify the location of the files and other parameters for the fileLogger. - /// If you name a log file by using the /fileLoggerParameters switch, the distributed logger will use that name as a template and append the node ID to that name when creating a log file for each node. - /// - public bool DistributedFileLogger { get; set; } - - /// - /// Gets the distributed loggers to use. - /// - /// - /// A distributed logger consists of a central and forwarding logger. MSBuild will attach an instance of the forwarding logger to each secondary node. - /// For more information see https://msdn.microsoft.com/en-us/library/bb383987.aspx. - /// - public ICollection DistributedLoggers { get; } - - /// - /// Gets or sets the parameters for the console logger. - /// - public MSBuildLoggerSettings ConsoleLoggerSettings { get; set; } - - /// - /// Gets the file loggers to use. - /// - public ICollection FileLoggers { get; } - - /// - /// Gets or sets the binary logging options. - /// - public MSBuildBinaryLoggerSettings BinaryLogger { get; set; } - - /// - /// Gets the loggers to use to log events from MSBuild. - /// - public ICollection Loggers { get; } - - /// - /// Gets or sets a value indicating whether to disable the default console logger, and not log events to the console. - /// - public bool DisableConsoleLogger { get; set; } - - /// - /// Gets the warning codes to treats as errors. - /// - /// - /// When a warning is treated as an error the target will continue to execute as if it was a warning but the overall build will fail. - /// - public IList WarningCodesAsError { get; } - - /// - /// Gets or sets a value indicating how all warnings should be treated. - /// - public MSBuildTreatAllWarningsAs TreatAllWarningsAs { get; set; } - - /// - /// Gets the warning codes to treats as low importance messages. - /// - public IList WarningCodesAsMessage { get; } - - /// - /// Initializes a new instance of the class. - /// - public DotNetCoreMSBuildSettings() - { - Properties = new Dictionary>(StringComparer.OrdinalIgnoreCase); - Targets = new List(); - ResponseFiles = new List(); - DistributedLoggers = new List(); - FileLoggers = new List(); - Loggers = new List(); - WarningCodesAsError = new List(); - WarningCodesAsMessage = new List(); - IgnoreProjectExtensions = new List(); - } } } diff --git a/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsExtensions.cs b/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsExtensions.cs index c2f1ca8e12..83bd0aa2ec 100644 --- a/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsExtensions.cs +++ b/src/Cake.Common/Tools/DotNetCore/MSBuild/DotNetCoreMSBuildSettingsExtensions.cs @@ -2,9 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using System.Linq; using Cake.Common.Tools.MSBuild; using Cake.Core.IO; @@ -24,14 +21,7 @@ public static class DotNetCoreMSBuildSettingsExtensions /// Ignores a target if already added. public static DotNetCoreMSBuildSettings WithTarget(this DotNetCoreMSBuildSettings settings, string target) { - EnsureSettings(settings); - - if (!settings.Targets.Contains(target)) - { - settings.Targets.Add(target); - } - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.WithTarget(settings, target); } /// @@ -43,18 +33,7 @@ public static DotNetCoreMSBuildSettings WithTarget(this DotNetCoreMSBuildSetting /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings WithProperty(this DotNetCoreMSBuildSettings settings, string name, params string[] values) { - EnsureSettings(settings); - - ICollection currentValue; - - // try to get existing values of properties and add new property values - currentValue = settings.Properties.TryGetValue(name, out currentValue) && currentValue != null - ? currentValue.Concat(values).ToList() - : new List(values); - - settings.Properties[name] = currentValue; - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.WithProperty(settings, name, values); } /// @@ -64,10 +43,7 @@ public static DotNetCoreMSBuildSettings WithProperty(this DotNetCoreMSBuildSetti /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings ShowDetailedSummary(this DotNetCoreMSBuildSettings settings) { - EnsureSettings(settings); - - settings.DetailedSummary = true; - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.ShowDetailedSummary(settings); } /// @@ -78,10 +54,7 @@ public static DotNetCoreMSBuildSettings ShowDetailedSummary(this DotNetCoreMSBui /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings WithIgnoredProjectExtension(this DotNetCoreMSBuildSettings settings, string extension) { - EnsureSettings(settings); - - settings.IgnoreProjectExtensions.Add(extension); - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.WithIgnoredProjectExtension(settings, extension); } /// @@ -92,12 +65,7 @@ public static DotNetCoreMSBuildSettings WithIgnoredProjectExtension(this DotNetC /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SetMaxCpuCount(this DotNetCoreMSBuildSettings settings, int? maxCpuCount) { - EnsureSettings(settings); - - settings.MaxCpuCount = maxCpuCount.HasValue - ? Math.Max(0, maxCpuCount.Value) - : 0; - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetMaxCpuCount(settings, maxCpuCount); } /// @@ -107,10 +75,7 @@ public static DotNetCoreMSBuildSettings SetMaxCpuCount(this DotNetCoreMSBuildSet /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings ExcludeAutoResponseFiles(this DotNetCoreMSBuildSettings settings) { - EnsureSettings(settings); - - settings.ExcludeAutoResponseFiles = true; - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.ExcludeAutoResponseFiles(settings); } /// @@ -120,10 +85,21 @@ public static DotNetCoreMSBuildSettings ExcludeAutoResponseFiles(this DotNetCore /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings HideLogo(this DotNetCoreMSBuildSettings settings) { - EnsureSettings(settings); + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.HideLogo(settings); + } - settings.NoLogo = true; - return settings; + /// + /// Sets a value indicating whether to normalize stored file paths used when producing deterministic builds. + /// + /// + /// For more information see https://devblogs.microsoft.com/dotnet/producing-packages-with-source-link/#deterministic-builds. + /// + /// The settings. + /// A value indicating whether to normalize stored file paths used when producing deterministic builds. + /// The same instance so that multiple calls can be chained. + public static DotNetCoreMSBuildSettings SetContinuousIntegrationBuild(this DotNetCoreMSBuildSettings settings, bool? continuousIntegrationBuild = true) + { + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetContinuousIntegrationBuild(settings, continuousIntegrationBuild); } /// @@ -134,10 +110,7 @@ public static DotNetCoreMSBuildSettings HideLogo(this DotNetCoreMSBuildSettings /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings UseToolVersion(this DotNetCoreMSBuildSettings settings, MSBuildVersion version) { - EnsureSettings(settings); - - settings.ToolVersion = version; - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.UseToolVersion(settings, version); } /// @@ -147,10 +120,7 @@ public static DotNetCoreMSBuildSettings UseToolVersion(this DotNetCoreMSBuildSet /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings ValidateProjectFile(this DotNetCoreMSBuildSettings settings) { - EnsureSettings(settings); - - settings.ValidateProjectFile = true; - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.ValidateProjectFile(settings); } /// @@ -164,10 +134,7 @@ public static DotNetCoreMSBuildSettings ValidateProjectFile(this DotNetCoreMSBui /// public static DotNetCoreMSBuildSettings WithResponseFile(this DotNetCoreMSBuildSettings settings, FilePath responseFile) { - EnsureSettings(settings); - - settings.ResponseFiles.Add(responseFile); - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.WithResponseFile(settings, responseFile); } /// @@ -177,10 +144,7 @@ public static DotNetCoreMSBuildSettings WithResponseFile(this DotNetCoreMSBuildS /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings UseDistributedFileLogger(this DotNetCoreMSBuildSettings settings) { - EnsureSettings(settings); - - settings.DistributedFileLogger = true; - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.UseDistributedFileLogger(settings); } /// @@ -195,10 +159,7 @@ public static DotNetCoreMSBuildSettings UseDistributedFileLogger(this DotNetCore /// public static DotNetCoreMSBuildSettings WithDistributedLogger(this DotNetCoreMSBuildSettings settings, MSBuildDistributedLogger logger) { - EnsureSettings(settings); - - settings.DistributedLoggers.Add(logger); - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.WithDistributedLogger(settings, logger); } /// @@ -209,11 +170,7 @@ public static DotNetCoreMSBuildSettings WithDistributedLogger(this DotNetCoreMSB /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SetConsoleLoggerSettings(this DotNetCoreMSBuildSettings settings, MSBuildLoggerSettings consoleLoggerParameters) { - EnsureSettings(settings); - - settings.ConsoleLoggerSettings = consoleLoggerParameters ?? throw new ArgumentNullException(nameof(consoleLoggerParameters)); - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetConsoleLoggerSettings(settings, consoleLoggerParameters); } /// @@ -228,7 +185,7 @@ public static DotNetCoreMSBuildSettings SetConsoleLoggerSettings(this DotNetCore /// public static DotNetCoreMSBuildSettings AddFileLogger(this DotNetCoreMSBuildSettings settings) { - return AddFileLogger(settings, new MSBuildFileLoggerSettings()); + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.AddFileLogger(settings); } /// @@ -244,16 +201,7 @@ public static DotNetCoreMSBuildSettings AddFileLogger(this DotNetCoreMSBuildSett /// public static DotNetCoreMSBuildSettings AddFileLogger(this DotNetCoreMSBuildSettings settings, MSBuildFileLoggerSettings fileLoggerParameters) { - EnsureSettings(settings); - - if (fileLoggerParameters == null) - { - throw new ArgumentNullException(nameof(fileLoggerParameters)); - } - - settings.FileLoggers.Add(fileLoggerParameters); - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.AddFileLogger(settings, fileLoggerParameters); } /// @@ -263,7 +211,7 @@ public static DotNetCoreMSBuildSettings AddFileLogger(this DotNetCoreMSBuildSett /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings EnableBinaryLogger(this DotNetCoreMSBuildSettings settings) { - return EnableBinaryLogger(settings, MSBuildBinaryLoggerImports.Unspecified); + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.EnableBinaryLogger(settings); } /// @@ -274,18 +222,7 @@ public static DotNetCoreMSBuildSettings EnableBinaryLogger(this DotNetCoreMSBuil /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings EnableBinaryLogger(this DotNetCoreMSBuildSettings settings, MSBuildBinaryLoggerImports imports) { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - - settings.BinaryLogger = new MSBuildBinaryLoggerSettings - { - Enabled = true, - Imports = imports, - }; - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.EnableBinaryLogger(settings, imports); } /// @@ -296,7 +233,7 @@ public static DotNetCoreMSBuildSettings EnableBinaryLogger(this DotNetCoreMSBuil /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings EnableBinaryLogger(this DotNetCoreMSBuildSettings settings, string fileName) { - return EnableBinaryLogger(settings, fileName, MSBuildBinaryLoggerImports.Unspecified); + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.EnableBinaryLogger(settings, fileName); } /// @@ -308,19 +245,7 @@ public static DotNetCoreMSBuildSettings EnableBinaryLogger(this DotNetCoreMSBuil /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings EnableBinaryLogger(this DotNetCoreMSBuildSettings settings, string fileName, MSBuildBinaryLoggerImports imports) { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - - settings.BinaryLogger = new MSBuildBinaryLoggerSettings - { - Enabled = true, - FileName = fileName, - Imports = imports, - }; - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.EnableBinaryLogger(settings, fileName, imports); } /// @@ -333,21 +258,7 @@ public static DotNetCoreMSBuildSettings EnableBinaryLogger(this DotNetCoreMSBuil /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings WithLogger(this DotNetCoreMSBuildSettings settings, string loggerAssembly, string loggerClass = null, string loggerParameters = null) { - EnsureSettings(settings); - - if (string.IsNullOrWhiteSpace(loggerAssembly)) - { - throw new ArgumentException(nameof(loggerAssembly)); - } - - settings.Loggers.Add(new MSBuildLogger - { - Assembly = loggerAssembly, - Class = loggerClass, - Parameters = loggerParameters - }); - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.WithLogger(settings, loggerAssembly, loggerClass, loggerParameters); } /// @@ -357,11 +268,7 @@ public static DotNetCoreMSBuildSettings WithLogger(this DotNetCoreMSBuildSetting /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings DisableConsoleLogger(this DotNetCoreMSBuildSettings settings) { - EnsureSettings(settings); - - settings.DisableConsoleLogger = true; - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.DisableConsoleLogger(settings); } /// @@ -375,16 +282,7 @@ public static DotNetCoreMSBuildSettings DisableConsoleLogger(this DotNetCoreMSBu /// public static DotNetCoreMSBuildSettings SetWarningCodeAsError(this DotNetCoreMSBuildSettings settings, string warningCode) { - EnsureSettings(settings); - - if (string.IsNullOrWhiteSpace(warningCode)) - { - throw new ArgumentException("Warning code cannot be null or empty", nameof(warningCode)); - } - - settings.WarningCodesAsError.Add(warningCode); - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetWarningCodeAsError(settings, warningCode); } /// @@ -395,16 +293,7 @@ public static DotNetCoreMSBuildSettings SetWarningCodeAsError(this DotNetCoreMSB /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SetWarningCodeAsMessage(this DotNetCoreMSBuildSettings settings, string warningCode) { - EnsureSettings(settings); - - if (string.IsNullOrWhiteSpace(warningCode)) - { - throw new ArgumentException("Warning code cannot be null or empty", nameof(warningCode)); - } - - settings.WarningCodesAsMessage.Add(warningCode); - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetWarningCodeAsMessage(settings, warningCode); } /// @@ -415,11 +304,7 @@ public static DotNetCoreMSBuildSettings SetWarningCodeAsMessage(this DotNetCoreM /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings TreatAllWarningsAs(this DotNetCoreMSBuildSettings settings, MSBuildTreatAllWarningsAs behaviour) { - EnsureSettings(settings); - - settings.TreatAllWarningsAs = behaviour; - - return settings; + return (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.TreatAllWarningsAs(settings, behaviour); } /// @@ -429,7 +314,7 @@ public static DotNetCoreMSBuildSettings TreatAllWarningsAs(this DotNetCoreMSBuil /// The configuration. /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SetConfiguration(this DotNetCoreMSBuildSettings settings, string configuration) - => settings.WithProperty("configuration", configuration); + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetConfiguration(settings, configuration); /// /// Sets the version. @@ -442,7 +327,7 @@ public static DotNetCoreMSBuildSettings SetConfiguration(this DotNetCoreMSBuildS /// This may also override version settings during packaging. /// public static DotNetCoreMSBuildSettings SetVersion(this DotNetCoreMSBuildSettings settings, string version) - => settings.WithProperty("Version", version); + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetVersion(settings, version); /// /// Sets the file version. @@ -451,7 +336,16 @@ public static DotNetCoreMSBuildSettings SetVersion(this DotNetCoreMSBuildSetting /// The file version. /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SetFileVersion(this DotNetCoreMSBuildSettings settings, string fileVersion) - => settings.WithProperty("FileVersion", fileVersion); + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetFileVersion(settings, fileVersion); + + /// + /// Sets the assembly version. + /// + /// The settings. + /// The assembly version. + /// The same instance so that multiple calls can be chained. + public static DotNetCoreMSBuildSettings SetAssemblyVersion(this DotNetCoreMSBuildSettings settings, string assemblyVersion) + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetAssemblyVersion(settings, assemblyVersion); /// /// Sets the informational version. @@ -460,7 +354,25 @@ public static DotNetCoreMSBuildSettings SetFileVersion(this DotNetCoreMSBuildSet /// The informational version. /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SetInformationalVersion(this DotNetCoreMSBuildSettings settings, string informationalVersion) - => settings.WithProperty("InformationalVersion", informationalVersion); + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetInformationalVersion(settings, informationalVersion); + + /// + /// Sets the package version. + /// + /// The settings. + /// The package version. + /// The same instance so that multiple calls can be chained. + public static DotNetCoreMSBuildSettings SetPackageVersion(this DotNetCoreMSBuildSettings settings, string packageVersion) + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetPackageVersion(settings, packageVersion); + + /// + /// Sets the package release notes. + /// + /// The settings. + /// The package release notes. + /// The same instance so that multiple calls can be chained. + public static DotNetCoreMSBuildSettings SetPackageReleaseNotes(this DotNetCoreMSBuildSettings settings, string packageReleaseNotes) + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetPackageReleaseNotes(settings, packageReleaseNotes); /// /// Suppress warning CS7035. @@ -472,7 +384,7 @@ public static DotNetCoreMSBuildSettings SetInformationalVersion(this DotNetCoreM /// The settings. /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SuppressVersionRecommendedFormatWarning(this DotNetCoreMSBuildSettings settings) - => settings.WithProperty("nowarn", "7035"); + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SuppressVersionRecommendedFormatWarning(settings); /// /// Sets the version prefix. @@ -481,7 +393,7 @@ public static DotNetCoreMSBuildSettings SuppressVersionRecommendedFormatWarning( /// The version prefix. /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SetVersionPrefix(this DotNetCoreMSBuildSettings settings, string versionPrefix) - => settings.WithProperty("VersionPrefix", versionPrefix); + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetVersionPrefix(settings, versionPrefix); /// /// Sets the version Suffix. @@ -490,7 +402,7 @@ public static DotNetCoreMSBuildSettings SetVersionPrefix(this DotNetCoreMSBuildS /// The version prefix. /// The same instance so that multiple calls can be chained. public static DotNetCoreMSBuildSettings SetVersionSuffix(this DotNetCoreMSBuildSettings settings, string versionSuffix) - => settings.WithProperty("VersionSuffix", versionSuffix); + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetVersionSuffix(settings, versionSuffix); /// /// Adds a framework to target. @@ -502,7 +414,7 @@ public static DotNetCoreMSBuildSettings SetVersionSuffix(this DotNetCoreMSBuildS /// For list of target frameworks see https://docs.microsoft.com/en-us/dotnet/standard/frameworks. /// public static DotNetCoreMSBuildSettings SetTargetFramework(this DotNetCoreMSBuildSettings settings, string targetFramework) - => settings.WithProperty("TargetFrameworks", targetFramework); + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetTargetFramework(settings, targetFramework); /// /// Sets a target operating systems where the application or assembly will run. @@ -514,14 +426,6 @@ public static DotNetCoreMSBuildSettings SetTargetFramework(this DotNetCoreMSBuil /// For list of runtime ids see https://docs.microsoft.com/en-us/dotnet/core/rid-catalog. /// public static DotNetCoreMSBuildSettings SetRuntime(this DotNetCoreMSBuildSettings settings, string runtimeId) - => settings.WithProperty("RuntimeIdentifiers", runtimeId); - - private static void EnsureSettings(DotNetCoreMSBuildSettings settings) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - } + => (DotNetCoreMSBuildSettings)DotNet.MSBuild.DotNetMSBuildSettingsExtensions.SetRuntime(settings, runtimeId); } } diff --git a/src/Cake.Common/Tools/DotNetCore/MSBuild/MSBuildArgumentBuilderExtensions.cs b/src/Cake.Common/Tools/DotNetCore/MSBuild/MSBuildArgumentBuilderExtensions.cs index 879e5258ee..54a6a51603 100644 --- a/src/Cake.Common/Tools/DotNetCore/MSBuild/MSBuildArgumentBuilderExtensions.cs +++ b/src/Cake.Common/Tools/DotNetCore/MSBuild/MSBuildArgumentBuilderExtensions.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Cake.Common.Tools.DotNet.MSBuild; using Cake.Common.Tools.MSBuild; using Cake.Core; using Cake.Core.IO; @@ -24,7 +25,7 @@ public static class MSBuildArgumentBuilderExtensions /// MSBuild settings to add. /// The environment. /// Throws if 10 or more file loggers specified. - public static void AppendMSBuildSettings(this ProcessArgumentBuilder builder, DotNetCoreMSBuildSettings settings, ICakeEnvironment environment) + public static void AppendMSBuildSettings(this ProcessArgumentBuilder builder, DotNetMSBuildSettings settings, ICakeEnvironment environment) { // Got any targets? if (settings.Targets.Any()) @@ -110,7 +111,7 @@ public static void AppendMSBuildSettings(this ProcessArgumentBuilder builder, Do string binaryOptions = null; if (!string.IsNullOrEmpty(settings.BinaryLogger.FileName)) { - binaryOptions = settings.BinaryLogger.FileName; + binaryOptions = settings.BinaryLogger.FileName.Quote(); } if (settings.BinaryLogger.Imports != MSBuildBinaryLoggerImports.Unspecified) @@ -188,6 +189,13 @@ public static void AppendMSBuildSettings(this ProcessArgumentBuilder builder, Do { builder.AppendMSBuildSwitch("nologo"); } + + // Set Continuous Integration Build? + if (settings.ContinuousIntegrationBuild.HasValue) + { + var continuousIntegrationBuild = settings.ContinuousIntegrationBuild.Value ? "true" : "false"; + builder.AppendMSBuildSwitch("property", $"ContinuousIntegrationBuild={continuousIntegrationBuild}"); + } } private static string GetLoggerValue(MSBuildLogger logger) @@ -248,6 +256,8 @@ private static string GetToolVersionValue(MSBuildVersion toolVersion) return "15.0"; case MSBuildVersion.MSBuild16: return "16.0"; + case MSBuildVersion.MSBuild17: + return "17.0"; default: throw new ArgumentOutOfRangeException(nameof(toolVersion), toolVersion, "Invalid value"); } diff --git a/src/Cake.Common/Tools/DotNetCore/MSBuild/MSBuildLoggerSettings.cs b/src/Cake.Common/Tools/DotNetCore/MSBuild/MSBuildLoggerSettings.cs index 3594fcc4a5..c63abb49e2 100644 --- a/src/Cake.Common/Tools/DotNetCore/MSBuild/MSBuildLoggerSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/MSBuild/MSBuildLoggerSettings.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet; + namespace Cake.Common.Tools.DotNetCore.MSBuild { /// @@ -63,6 +65,6 @@ public class MSBuildLoggerSettings /// /// Gets or sets a value that overrides the /verbosity setting for this logger. /// - public DotNetCoreVerbosity? Verbosity { get; set; } + public DotNetVerbosity? Verbosity { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleteSettings.cs b/src/Cake.Common/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleteSettings.cs index 77c64d1c0f..be5462c8f9 100644 --- a/src/Cake.Common/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleteSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleteSettings.cs @@ -2,52 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.NuGet.Delete; + namespace Cake.Common.Tools.DotNetCore.NuGet.Delete { /// /// Contains settings used by . /// - public sealed class DotNetCoreNuGetDeleteSettings : DotNetCoreSettings + public sealed class DotNetCoreNuGetDeleteSettings : DotNetNuGetDeleteSettings { - /// - /// Gets or sets a value indicating the server URL. - /// - /// - /// Supported URLs for nuget.org include http://www.nuget.org, http://www.nuget.org/api/v3, - /// and http://www.nuget.org/api/v2/package. For private feeds, substitute the host name - /// (for example, %hostname%/api/v3). - /// - public string Source { get; set; } - - /// - /// Gets or sets a value indicating whether to append "api/v2/package" to the source URL. - /// - /// - /// Available since .NET Core 2.1 SDK. - /// - public bool NoServiceEndpoint { get; set; } - - /// - /// Gets or sets a value indicating whether to block and require manual action for operations like authentication. - /// - /// - /// Available since .NET Core 2.2 SDK. - /// - public bool Interactive { get; set; } - - /// - /// Gets or sets a value indicating whether to prompt for user input or confirmations. - /// - public bool NonInteractive { get; set; } - - /// - /// Gets or sets a value indicating the API key for the server. - /// - public string ApiKey { get; set; } - - /// - /// Gets or sets a value indicating whether to force command-line output in English. - /// - public bool ForceEnglishOutput { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleter.cs b/src/Cake.Common/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleter.cs index 670626657c..1ac7e920f1 100644 --- a/src/Cake.Common/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleter.cs +++ b/src/Cake.Common/Tools/DotNetCore/NuGet/Delete/DotNetCoreNuGetDeleter.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.NuGet.Delete; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -12,7 +13,7 @@ namespace Cake.Common.Tools.DotNetCore.NuGet.Delete /// /// .NET Core NuGet deleter. Deletes or unlists a package from the server. /// - public sealed class DotNetCoreNuGetDeleter : DotNetCoreTool + public sealed class DotNetCoreNuGetDeleter : DotNetCoreTool { /// /// Initializes a new instance of the class. @@ -35,7 +36,7 @@ public DotNetCoreNuGetDeleter( /// The name of the target package. /// Version of the package. /// The settings. - public void Delete(string packageName, string version, DotNetCoreNuGetDeleteSettings settings) + public void Delete(string packageName, string version, DotNetNuGetDeleteSettings settings) { if (settings == null) { @@ -45,7 +46,7 @@ public void Delete(string packageName, string version, DotNetCoreNuGetDeleteSett RunCommand(settings, GetArguments(packageName, version, settings)); } - private ProcessArgumentBuilder GetArguments(string packageName, string packageVersion, DotNetCoreNuGetDeleteSettings settings) + private ProcessArgumentBuilder GetArguments(string packageName, string packageVersion, DotNetNuGetDeleteSettings settings) { var builder = CreateArgumentBuilder(settings); diff --git a/src/Cake.Common/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPushSettings.cs b/src/Cake.Common/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPushSettings.cs index 128fdc784c..35d0ce0ca5 100644 --- a/src/Cake.Common/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPushSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPushSettings.cs @@ -2,85 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.NuGet.Push; + namespace Cake.Common.Tools.DotNetCore.NuGet.Push { /// /// Contains settings used by . /// - public sealed class DotNetCoreNuGetPushSettings : DotNetCoreSettings + public sealed class DotNetCoreNuGetPushSettings : DotNetNuGetPushSettings { - /// - /// Gets or sets a value indicating the server URL. - /// - /// - /// This option is required unless DefaultPushSource config value is set in the NuGet config file. - /// - public string Source { get; set; } - - /// - /// Gets or sets a value indicating the symbol server URL. - /// - public string SymbolSource { get; set; } - - /// - /// Gets or sets a value indicating whether to append "api/v2/package" to the source URL. - /// - /// - /// Available since .NET Core 2.1 SDK. - /// - public bool NoServiceEndpoint { get; set; } - - /// - /// Gets or sets a value indicating whether to block and require manual action for operations like authentication. - /// - /// - /// Available since .NET Core 2.2 SDK. - /// - public bool Interactive { get; set; } - - /// - /// Gets or sets a value indicating timeout for pushing to a server in seconds. - /// - /// Defaults to 300 seconds (5 minutes). Specifying 0 (zero seconds) applies the default value. - /// - /// - public int? Timeout { get; set; } - - /// - /// Gets or sets a value indicating the API key for the server. - /// - public string ApiKey { get; set; } - - /// - /// Gets or sets a value indicating the API key for the symbol server. - /// - public string SymbolApiKey { get; set; } - - /// - /// Gets or sets a value indicating whether buffering is disabled when pushing to an HTTP(S) server. - /// - /// - /// This decreases memory usage. - /// - public bool DisableBuffering { get; set; } - - /// - /// Gets or sets a value indicating whether symbols should be not be pushed if present. - /// - public bool IgnoreSymbols { get; set; } - - /// - /// Gets or sets a value indicating whether, when pushing multiple packages to an HTTP(S) server, - /// to treat any 409 Conflict response as a warning so that the push can continue. - /// - /// - /// Available since .NET Core 3.1 SDK. - /// - public bool SkipDuplicate { get; set; } - - /// - /// Gets or sets a value indicating whether to force command-line output in English. - /// - public bool ForceEnglishOutput { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPusher.cs b/src/Cake.Common/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPusher.cs index e30502bbb8..6c296fb33b 100644 --- a/src/Cake.Common/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPusher.cs +++ b/src/Cake.Common/Tools/DotNetCore/NuGet/Push/DotNetCoreNuGetPusher.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.NuGet.Push; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -12,7 +13,7 @@ namespace Cake.Common.Tools.DotNetCore.NuGet.Push /// /// .NET Core nuget pusher. Pushes a package and its symbols to the server. /// - public sealed class DotNetCoreNuGetPusher : DotNetCoreTool + public sealed class DotNetCoreNuGetPusher : DotNetCoreTool { /// /// Initializes a new instance of the class. @@ -34,7 +35,7 @@ public DotNetCoreNuGetPusher( /// /// The name of the target package. /// The settings. - public void Push(string packageName, DotNetCoreNuGetPushSettings settings) + public void Push(string packageName, DotNetNuGetPushSettings settings) { if (settings == null) { @@ -44,7 +45,7 @@ public void Push(string packageName, DotNetCoreNuGetPushSettings settings) RunCommand(settings, GetArguments(packageName, settings)); } - private ProcessArgumentBuilder GetArguments(string packageName, DotNetCoreNuGetPushSettings settings) + private ProcessArgumentBuilder GetArguments(string packageName, DotNetNuGetPushSettings settings) { if (string.IsNullOrWhiteSpace(packageName)) { diff --git a/src/Cake.Common/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourceSettings.cs b/src/Cake.Common/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourceSettings.cs index 5640263d7f..487bead022 100644 --- a/src/Cake.Common/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourceSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourceSettings.cs @@ -2,51 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.NuGet.Source; namespace Cake.Common.Tools.DotNetCore.NuGet.Source { /// /// Contains settings used by . /// - public sealed class DotNetCoreNuGetSourceSettings : DotNetCoreSettings + public sealed class DotNetCoreNuGetSourceSettings : DotNetNuGetSourceSettings { - /// - /// Gets or sets the path to the package(s) source. - /// - public string Source { get; set; } - - /// - /// Gets or sets a value indicating whether this source contains sensitive data, i.e. authentication token in url. - /// - public bool IsSensitiveSource { get; set; } - - /// - /// Gets or sets the user name to be used when connecting to an authenticated source. - /// - public string UserName { get; set; } - - /// - /// Gets or sets the password to be used when connecting to an authenticated source. - /// - public string Password { get; set; } - - /// - /// Gets or sets a value indicating whether to enable storing portable package source credentials by disabling password encryption. - /// - public bool StorePasswordInClearText { get; set; } - - /// - /// Gets or sets the comma-separated list of valid authentication types for this source. - /// - /// - /// By default, all authentication types are valid. Example: basic,negotiate. - /// - public string ValidAuthenticationTypes { get; set; } - - /// - /// Gets or sets the NuGet configuration file. - /// - public FilePath ConfigFile { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourcer.cs b/src/Cake.Common/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourcer.cs index 5bfd7fa20e..5edb32a7c8 100644 --- a/src/Cake.Common/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourcer.cs +++ b/src/Cake.Common/Tools/DotNetCore/NuGet/Source/DotNetCoreNuGetSourcer.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using System.Text.RegularExpressions; +using Cake.Common.Tools.DotNet.NuGet.Source; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -14,7 +15,7 @@ namespace Cake.Common.Tools.DotNetCore.NuGet.Source /// /// .NET Core NuGet sourcer. /// - public sealed class DotNetCoreNuGetSourcer : DotNetCoreTool + public sealed class DotNetCoreNuGetSourcer : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -39,7 +40,7 @@ public DotNetCoreNuGetSourcer( /// /// The name of the source. /// The settings. - public void AddSource(string name, DotNetCoreNuGetSourceSettings settings) + public void AddSource(string name, DotNetNuGetSourceSettings settings) { if (string.IsNullOrWhiteSpace(name)) { @@ -64,7 +65,7 @@ public void AddSource(string name, DotNetCoreNuGetSourceSettings settings) /// /// The name of the source. /// The settings. - public void DisableSource(string name, DotNetCoreNuGetSourceSettings settings) + public void DisableSource(string name, DotNetNuGetSourceSettings settings) { if (string.IsNullOrWhiteSpace(name)) { @@ -84,7 +85,7 @@ public void DisableSource(string name, DotNetCoreNuGetSourceSettings settings) /// /// The name of the source. /// The settings. - public void EnableSource(string name, DotNetCoreNuGetSourceSettings settings) + public void EnableSource(string name, DotNetNuGetSourceSettings settings) { if (string.IsNullOrWhiteSpace(name)) { @@ -105,7 +106,7 @@ public void EnableSource(string name, DotNetCoreNuGetSourceSettings settings) /// The name of the source. /// The settings. /// Whether the specified NuGet source exists. - public bool HasSource(string name, DotNetCoreNuGetSourceSettings settings) + public bool HasSource(string name, DotNetNuGetSourceSettings settings) { if (string.IsNullOrWhiteSpace(name)) { @@ -129,7 +130,7 @@ public bool HasSource(string name, DotNetCoreNuGetSourceSettings settings) /// The output format. Accepts two values: detailed (the default) and short. /// The settings. /// The NuGet sources. - public string ListSource(string format, DotNetCoreNuGetSourceSettings settings) + public string ListSource(string format, DotNetNuGetSourceSettings settings) { if (settings == null) { @@ -148,7 +149,7 @@ public string ListSource(string format, DotNetCoreNuGetSourceSettings settings) /// /// The name of the source. /// The settings. - public void RemoveSource(string name, DotNetCoreNuGetSourceSettings settings) + public void RemoveSource(string name, DotNetNuGetSourceSettings settings) { if (string.IsNullOrWhiteSpace(name)) { @@ -168,7 +169,7 @@ public void RemoveSource(string name, DotNetCoreNuGetSourceSettings settings) /// /// The name of the source. /// The settings. - public void UpdateSource(string name, DotNetCoreNuGetSourceSettings settings) + public void UpdateSource(string name, DotNetNuGetSourceSettings settings) { if (string.IsNullOrWhiteSpace(name)) { @@ -183,7 +184,7 @@ public void UpdateSource(string name, DotNetCoreNuGetSourceSettings settings) RunCommand(settings, GetUpdateSourceArguments(name, settings)); } - private ProcessArgumentBuilder GetAddSourceArguments(string name, DotNetCoreNuGetSourceSettings settings) + private ProcessArgumentBuilder GetAddSourceArguments(string name, DotNetNuGetSourceSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -222,7 +223,7 @@ private ProcessArgumentBuilder GetAddSourceArguments(string name, DotNetCoreNuGe return builder; } - private ProcessArgumentBuilder GetDisableSourceArguments(string name, DotNetCoreNuGetSourceSettings settings) + private ProcessArgumentBuilder GetDisableSourceArguments(string name, DotNetNuGetSourceSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -233,7 +234,7 @@ private ProcessArgumentBuilder GetDisableSourceArguments(string name, DotNetCore return builder; } - private ProcessArgumentBuilder GetEnableSourceArguments(string name, DotNetCoreNuGetSourceSettings settings) + private ProcessArgumentBuilder GetEnableSourceArguments(string name, DotNetNuGetSourceSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -244,7 +245,7 @@ private ProcessArgumentBuilder GetEnableSourceArguments(string name, DotNetCoreN return builder; } - private ProcessArgumentBuilder GetListSourceArguments(string format, DotNetCoreNuGetSourceSettings settings) + private ProcessArgumentBuilder GetListSourceArguments(string format, DotNetNuGetSourceSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -259,7 +260,7 @@ private ProcessArgumentBuilder GetListSourceArguments(string format, DotNetCoreN return builder; } - private ProcessArgumentBuilder GetRemoveSourceArguments(string name, DotNetCoreNuGetSourceSettings settings) + private ProcessArgumentBuilder GetRemoveSourceArguments(string name, DotNetNuGetSourceSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -270,7 +271,7 @@ private ProcessArgumentBuilder GetRemoveSourceArguments(string name, DotNetCoreN return builder; } - private ProcessArgumentBuilder GetUpdateSourceArguments(string name, DotNetCoreNuGetSourceSettings settings) + private ProcessArgumentBuilder GetUpdateSourceArguments(string name, DotNetNuGetSourceSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -312,7 +313,7 @@ private ProcessArgumentBuilder GetUpdateSourceArguments(string name, DotNetCoreN return builder; } - private void AddCommonArguments(DotNetCoreNuGetSourceSettings settings, ProcessArgumentBuilder builder) + private void AddCommonArguments(DotNetNuGetSourceSettings settings, ProcessArgumentBuilder builder) { if (settings.ConfigFile != null) { diff --git a/src/Cake.Common/Tools/DotNetCore/Pack/DotNetCorePackSettings.cs b/src/Cake.Common/Tools/DotNetCore/Pack/DotNetCorePackSettings.cs index 3db6abf33d..f9eeb86e10 100644 --- a/src/Cake.Common/Tools/DotNetCore/Pack/DotNetCorePackSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Pack/DotNetCorePackSettings.cs @@ -2,88 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Cake.Common.Tools.DotNetCore.MSBuild; -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.Pack; namespace Cake.Common.Tools.DotNetCore.Pack { /// /// Contains settings used by . /// - public sealed class DotNetCorePackSettings : DotNetCoreSettings + public sealed class DotNetCorePackSettings : DotNetPackSettings { - /// - /// Gets or sets the output directory. - /// - public DirectoryPath OutputDirectory { get; set; } - - /// - /// Gets or sets the configuration under which to build. - /// - public string Configuration { get; set; } - - /// - /// Gets or sets the value that defines what `*` should be replaced with in version field in project.json. - /// - public string VersionSuffix { get; set; } - - /// - /// Gets or sets a value indicating whether to not build project before packing. - /// - public bool NoBuild { get; set; } - - /// - /// Gets or sets a value indicating whether to ignore project to project references and only build the root project. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public bool NoDependencies { get; set; } - - /// - /// Gets or sets a value indicating whether to not do implicit NuGet package restore. - /// This makes build faster, but requires restore to be done before build is executed. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public bool NoRestore { get; set; } - - /// - /// Gets or sets a value indicating whether to display the startup banner or the copyright message. - /// - /// - /// Available since .NET Core 3.0 SDK. - /// - public bool NoLogo { get; set; } - - /// - /// Gets or sets a value indicating whether to generate the symbols nupkg. - /// - public bool IncludeSymbols { get; set; } - - /// - /// Gets or sets a value indicating whether to includes the source files in the NuGet package. - /// The sources files are included in the src folder within the nupkg. - /// - public bool IncludeSource { get; set; } - - /// - /// Gets or sets a value indicating whether to set the serviceable flag in the package. - /// - /// - /// For more information, see https://aka.ms/nupkgservicing. - /// - public bool Serviceable { get; set; } - - /// - /// Gets or sets the target runtime. - /// - public string Runtime { get; set; } - - /// - /// Gets or sets additional arguments to be passed to MSBuild. - /// - public DotNetCoreMSBuildSettings MSBuildSettings { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/Pack/DotNetCorePacker.cs b/src/Cake.Common/Tools/DotNetCore/Pack/DotNetCorePacker.cs index 64b96d04c7..e3f880403a 100644 --- a/src/Cake.Common/Tools/DotNetCore/Pack/DotNetCorePacker.cs +++ b/src/Cake.Common/Tools/DotNetCore/Pack/DotNetCorePacker.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.Pack; using Cake.Common.Tools.DotNetCore.MSBuild; using Cake.Core; using Cake.Core.IO; @@ -13,7 +14,7 @@ namespace Cake.Common.Tools.DotNetCore.Pack /// /// .NET Core project packer. /// - public sealed class DotNetCorePacker : DotNetCoreTool + public sealed class DotNetCorePacker : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -38,7 +39,7 @@ public DotNetCorePacker( /// /// The target file path. /// The settings. - public void Pack(string project, DotNetCorePackSettings settings) + public void Pack(string project, DotNetPackSettings settings) { if (settings == null) { @@ -48,7 +49,7 @@ public void Pack(string project, DotNetCorePackSettings settings) RunCommand(settings, GetArguments(project, settings)); } - private ProcessArgumentBuilder GetArguments(string project, DotNetCorePackSettings settings) + private ProcessArgumentBuilder GetArguments(string project, DotNetPackSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -97,6 +98,12 @@ private ProcessArgumentBuilder GetArguments(string project, DotNetCorePackSettin builder.Append("--include-symbols"); } + // Symbol package format + if (!string.IsNullOrWhiteSpace(settings.SymbolPackageFormat)) + { + builder.Append(string.Concat("-p:SymbolPackageFormat=", settings.SymbolPackageFormat)); + } + // Include source if (settings.IncludeSource) { @@ -130,6 +137,16 @@ private ProcessArgumentBuilder GetArguments(string project, DotNetCorePackSettin builder.Append(settings.Runtime); } + // Sources + if (settings.Sources != null) + { + foreach (var source in settings.Sources) + { + builder.Append("--source"); + builder.AppendQuoted(source); + } + } + if (settings.MSBuildSettings != null) { builder.AppendMSBuildSettings(settings.MSBuildSettings, _environment); diff --git a/src/Cake.Common/Tools/DotNetCore/Publish/DotNetCorePublishSettings.cs b/src/Cake.Common/Tools/DotNetCore/Publish/DotNetCorePublishSettings.cs index 384533d615..8a94d013c3 100644 --- a/src/Cake.Common/Tools/DotNetCore/Publish/DotNetCorePublishSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Publish/DotNetCorePublishSettings.cs @@ -2,144 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; -using Cake.Common.Tools.DotNetCore.MSBuild; -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.Publish; namespace Cake.Common.Tools.DotNetCore.Publish { /// /// Contains settings used by . /// - public sealed class DotNetCorePublishSettings : DotNetCoreSettings + public sealed class DotNetCorePublishSettings : DotNetPublishSettings { - /// - /// Gets or sets the output directory. - /// - public DirectoryPath OutputDirectory { get; set; } - - /// - /// Gets or sets the target runtime. - /// - public string Runtime { get; set; } - - /// - /// Gets or sets a specific framework to compile. - /// - public string Framework { get; set; } - - /// - /// Gets or sets the configuration under which to build. - /// - public string Configuration { get; set; } - - /// - /// Gets or sets the value that defines what `*` should be replaced with in version field in project.json. - /// - public string VersionSuffix { get; set; } - - /// - /// Gets or sets a value indicating whether to not to build the project before publishing. - /// This makes build faster, but requires build to be done before publish is executed. - /// - /// - /// Requires .NET Core 2.1 or newer. - /// - public bool NoBuild { get; set; } - - /// - /// Gets or sets a value indicating whether to ignore project to project references and only build the root project. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public bool NoDependencies { get; set; } - - /// - /// Gets or sets a value indicating whether to not do implicit NuGet package restore. - /// This makes build faster, but requires restore to be done before build is executed. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public bool NoRestore { get; set; } - - /// - /// Gets or sets a value indicating whether to display the startup banner or the copyright message. - /// - /// - /// Available since .NET Core 3.0 SDK. - /// - public bool NoLogo { get; set; } - - /// - /// Gets or sets a value indicating whether to force all dependencies to be resolved even if the last restore was successful. This is equivalent to deleting project.assets.json. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public bool Force { get; set; } - - /// - /// Gets or sets a value indicating whether Publish the .NET Core runtime with your application so the runtime doesn't need to be installed on the target machine. Defaults to 'true' if a runtime identifier is specified. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public bool? SelfContained { get; set; } - - /// - /// Gets or sets a value indicating whether to package your app into a platform-specific single-file executable. - /// - /// - /// Requires .NET Core 3.x or newer. - /// - public bool? PublishSingleFile { get; set; } - - /// - /// Gets or sets a value indicating whether to reduce the size of apps by analyzing IL and trimming unused assemblies. - /// - /// - /// Requires .NET Core 3.x or newer. - /// - public bool? PublishTrimmed { get; set; } - - /// - /// Gets or sets a value as to whether tiered compilation quick JIT is enabled. - /// - /// - /// Requires .NET Core 3.x or newer. Tiered compilation is enabled by default in .NET Core 3. - /// Code generated by Quick JIT may run slower, allocate more memory, or use more stack space. - /// - public bool? TieredCompilationQuickJit { get; set; } - - /// - /// Gets or sets a value indicating whether tiered compilation is enabled. - /// - /// - /// Requires .NET Core 3.x or newer. Tiered compilation is enabled by default in .NET Core 3. - /// - public bool? TieredCompilation { get; set; } - - /// - /// Gets or sets a value indicating whether to compile your application assemblies as ReadyToRun (R2R) format. - /// - /// - /// Requires .NET Core 3.x or newer. Tiered compilation is enabled by default in .NET Core 3. - /// - public bool? PublishReadyToRun { get; set; } - - /// - /// Gets or sets the specified NuGet package sources to use during the restore. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public ICollection Sources { get; set; } = new List(); - - /// - /// Gets or sets additional arguments to be passed to MSBuild. - /// - public DotNetCoreMSBuildSettings MSBuildSettings { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/Publish/DotNetCorePublisher.cs b/src/Cake.Common/Tools/DotNetCore/Publish/DotNetCorePublisher.cs index 637b1345bd..dd76edd791 100644 --- a/src/Cake.Common/Tools/DotNetCore/Publish/DotNetCorePublisher.cs +++ b/src/Cake.Common/Tools/DotNetCore/Publish/DotNetCorePublisher.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.Publish; using Cake.Common.Tools.DotNetCore.MSBuild; using Cake.Core; using Cake.Core.IO; @@ -13,7 +14,7 @@ namespace Cake.Common.Tools.DotNetCore.Publish /// /// .NET Core project runner. /// - public sealed class DotNetCorePublisher : DotNetCoreTool + public sealed class DotNetCorePublisher : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -38,7 +39,7 @@ public DotNetCorePublisher( /// /// The target file path. /// The settings. - public void Publish(string path, DotNetCorePublishSettings settings) + public void Publish(string path, DotNetPublishSettings settings) { if (settings == null) { @@ -48,7 +49,7 @@ public void Publish(string path, DotNetCorePublishSettings settings) RunCommand(settings, GetArguments(path, settings)); } - private ProcessArgumentBuilder GetArguments(string path, DotNetCorePublishSettings settings) + private ProcessArgumentBuilder GetArguments(string path, DotNetPublishSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -204,6 +205,58 @@ private ProcessArgumentBuilder GetArguments(string path, DotNetCorePublishSettin } } + // Publish ReadyToRunShowWarnings + if (settings.PublishReadyToRunShowWarnings.HasValue) + { + if (settings.PublishReadyToRunShowWarnings.Value) + { + builder.Append("-p:PublishReadyToRunShowWarnings=true"); + } + else + { + builder.Append("-p:PublishReadyToRunShowWarnings=false"); + } + } + + // Include Native Libraries For Self-Extract + if (settings.IncludeNativeLibrariesForSelfExtract.HasValue) + { + if (settings.IncludeNativeLibrariesForSelfExtract.Value) + { + builder.Append("-p:IncludeNativeLibrariesForSelfExtract=true"); + } + else + { + builder.Append("-p:IncludeNativeLibrariesForSelfExtract=false"); + } + } + + // Include All Content For Self-Extract + if (settings.IncludeAllContentForSelfExtract.HasValue) + { + if (settings.IncludeAllContentForSelfExtract.Value) + { + builder.Append("-p:IncludeAllContentForSelfExtract=true"); + } + else + { + builder.Append("-p:IncludeAllContentForSelfExtract=false"); + } + } + + // Enable compression on the embedded assemblies + if (settings.EnableCompressionInSingleFile.HasValue) + { + if (settings.EnableCompressionInSingleFile.Value) + { + builder.Append("-p:EnableCompressionInSingleFile=true"); + } + else + { + builder.Append("-p:EnableCompressionInSingleFile=false"); + } + } + // Sources if (settings.Sources != null) { diff --git a/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestoreSettings.cs b/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestoreSettings.cs index b04895396e..01b3e68353 100644 --- a/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestoreSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestoreSettings.cs @@ -2,115 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; -using Cake.Common.Tools.DotNetCore.MSBuild; -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.Restore; namespace Cake.Common.Tools.DotNetCore.Restore { /// /// Contains settings used by . /// - public sealed class DotNetCoreRestoreSettings : DotNetCoreSettings + public sealed class DotNetCoreRestoreSettings : DotNetRestoreSettings { - /// - /// Gets or sets the specified NuGet package sources to use during the restore. - /// - public ICollection Sources { get; set; } = new List(); - - /// - /// Gets or sets the NuGet configuration file to use. - /// - public FilePath ConfigFile { get; set; } - - /// - /// Gets or sets the directory to install packages in. - /// - public DirectoryPath PackagesDirectory { get; set; } - - /// - /// Gets or sets a value indicating whether to do not cache packages and http requests. - /// - public bool NoCache { get; set; } - - /// - /// Gets or sets a value indicating whether to disable restoring multiple projects in parallel. - /// - public bool DisableParallel { get; set; } - - /// - /// Gets or sets a value indicating whether to only warning failed sources if there are packages meeting version requirement. - /// - public bool IgnoreFailedSources { get; set; } - - /// - /// Gets or sets the target runtime to restore packages for. - /// - public string Runtime { get; set; } - - /// - /// Gets or sets a value indicating whether to ignore project to project references and restore only the root project. - /// - public bool NoDependencies { get; set; } - - /// - /// Gets or sets a value indicating whether to force all dependencies to be resolved even if the last restore was successful. - /// This is equivalent to deleting the project.assets.json file. - /// - /// Note: This flag was introduced with the .NET Core 2.x release. - /// - public bool Force { get; set; } - - /// - /// Gets or sets a value indicating whether to stop and wait for user input or action (for example to complete authentication). - /// - /// - /// Supported by .NET SDK version 2.1.400 and above. - /// - public bool Interactive { get; set; } - - /// - /// Gets or sets a value indicating whether to enable project lock file to be generated and used with restore. - /// - /// - /// Supported by .NET SDK version 2.1.500 and above. - /// - public bool UseLockFile { get; set; } - - /// - /// Gets or sets a value indicating whether to not allow updating project lock file. - /// - /// - /// When set to true, restore will fail if the lock file is out of sync. - /// Useful for CI builds when you do not want the build to continue if the package closure has changed than what is present in the lock file. - /// - /// Supported by .NET SDK version 2.1.500 and above. - /// - /// - public bool LockedMode { get; set; } - - /// - /// Gets or sets a value indicating output location where project lock file is written. - /// - /// - /// If not set, 'dotnet restore' defaults to 'PROJECT_ROOT\packages.lock.json'. - /// - /// Supported by .NET SDK version 2.1.500 and above. - /// - /// - public FilePath LockFilePath { get; set; } - - /// - /// Gets or sets a value indicating whether to force restore to reevaluate all dependencies even if a lock file already exists. - /// - /// - /// Supported by .NET SDK version 2.1.500 and above. - /// - public bool ForceEvaluate { get; set; } - - /// - /// Gets or sets additional arguments to be passed to MSBuild. - /// - public DotNetCoreMSBuildSettings MSBuildSettings { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestorer.cs b/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestorer.cs index abc49f0684..a262bd0a0b 100644 --- a/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestorer.cs +++ b/src/Cake.Common/Tools/DotNetCore/Restore/DotNetCoreRestorer.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.Restore; using Cake.Common.Tools.DotNetCore.MSBuild; using Cake.Core; using Cake.Core.Diagnostics; @@ -14,7 +15,7 @@ namespace Cake.Common.Tools.DotNetCore.Restore /// /// .NET Core project restorer. /// - public sealed class DotNetCoreRestorer : DotNetCoreTool + public sealed class DotNetCoreRestorer : DotNetCoreTool { private readonly ICakeEnvironment _environment; private readonly ICakeLog _log; @@ -43,7 +44,7 @@ public DotNetCoreRestorer( /// /// List of projects and project folders to restore. Each value can be: a path to a project.json or global.json file, or a folder to recursively search for project.json files. /// The settings. - public void Restore(string root, DotNetCoreRestoreSettings settings) + public void Restore(string root, DotNetRestoreSettings settings) { if (settings == null) { @@ -53,7 +54,7 @@ public void Restore(string root, DotNetCoreRestoreSettings settings) RunCommand(settings, GetArguments(root, settings)); } - private ProcessArgumentBuilder GetArguments(string root, DotNetCoreRestoreSettings settings) + private ProcessArgumentBuilder GetArguments(string root, DotNetRestoreSettings settings) { var builder = CreateArgumentBuilder(settings); diff --git a/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunSettings.cs b/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunSettings.cs index dfad3b3b11..f8d0043b73 100644 --- a/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunSettings.cs @@ -2,38 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.Run; + namespace Cake.Common.Tools.DotNetCore.Run { /// /// Contains settings used by . /// - public sealed class DotNetCoreRunSettings : DotNetCoreSettings + public sealed class DotNetCoreRunSettings : DotNetRunSettings { - /// - /// Gets or sets a specific framework to compile. - /// - public string Framework { get; set; } - - /// - /// Gets or sets the configuration under which to build. - /// - public string Configuration { get; set; } - - /// - /// Gets or sets a value indicating whether to not do implicit NuGet package restore. - /// This makes run faster, but requires restore to be done before run is executed. - /// - public bool NoRestore { get; set; } - - /// - /// Gets or sets a value indicating whether to not do implicit build. - /// This makes run faster, but requires build to be done before run is executed. - /// - public bool NoBuild { get; set; } - - /// - /// Gets or sets the target runtime. - /// - public string Runtime { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunner.cs b/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunner.cs index 2ab1ac0b4c..1e6936f8bd 100644 --- a/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunner.cs +++ b/src/Cake.Common/Tools/DotNetCore/Run/DotNetCoreRunner.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.Run; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -12,7 +13,7 @@ namespace Cake.Common.Tools.DotNetCore.Run /// /// .NET Core project runner. /// - public sealed class DotNetCoreRunner : DotNetCoreTool + public sealed class DotNetCoreRunner : DotNetCoreTool { /// /// Initializes a new instance of the class. @@ -35,7 +36,7 @@ public DotNetCoreRunner( /// The target project path. /// The arguments. /// The settings. - public void Run(string project, ProcessArgumentBuilder arguments, DotNetCoreRunSettings settings) + public void Run(string project, ProcessArgumentBuilder arguments, DotNetRunSettings settings) { if (settings == null) { @@ -45,7 +46,7 @@ public void Run(string project, ProcessArgumentBuilder arguments, DotNetCoreRunS RunCommand(settings, GetArguments(project, arguments, settings)); } - private ProcessArgumentBuilder GetArguments(string project, ProcessArgumentBuilder arguments, DotNetCoreRunSettings settings) + private ProcessArgumentBuilder GetArguments(string project, ProcessArgumentBuilder arguments, DotNetRunSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -91,6 +92,23 @@ private ProcessArgumentBuilder GetArguments(string project, ProcessArgumentBuild builder.Append(settings.Runtime); } + // Sources + if (settings.Sources != null) + { + foreach (var source in settings.Sources) + { + builder.Append("--source"); + builder.AppendQuoted(source); + } + } + + // Roll Forward Policy + if (!(settings.RollForward is null)) + { + builder.Append("--roll-forward"); + builder.Append(settings.RollForward.Value.ToString("F")); + } + // Arguments if (!arguments.IsNullOrEmpty()) { diff --git a/src/Cake.Common/Tools/DotNetCore/Test/DotNetCoreTestSettings.cs b/src/Cake.Common/Tools/DotNetCore/Test/DotNetCoreTestSettings.cs index a74760d91c..36e1b7f653 100644 --- a/src/Cake.Common/Tools/DotNetCore/Test/DotNetCoreTestSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Test/DotNetCoreTestSettings.cs @@ -2,93 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.Test; namespace Cake.Common.Tools.DotNetCore.Test { /// /// Contains settings used by . /// - public sealed class DotNetCoreTestSettings : DotNetCoreSettings + public sealed class DotNetCoreTestSettings : DotNetTestSettings { - /// - /// Gets or sets the settings file to use when running tests. - /// - public FilePath Settings { get; set; } - - /// - /// Gets or sets the filter expression to filter out tests in the current project. - /// - /// - /// For more information on filtering support, see https://aka.ms/vstest-filtering. - /// - public string Filter { get; set; } - - /// - /// Gets or sets the path to use for the custom test adapter in the test run. - /// - public DirectoryPath TestAdapterPath { get; set; } - - /// - /// Gets or sets a logger for test results. - /// - public string Logger { get; set; } - - /// - /// Gets or sets the output directory. - /// - public DirectoryPath OutputDirectory { get; set; } - - /// - /// Gets or sets the configuration under which to build. - /// - public string Configuration { get; set; } - - /// - /// Gets or sets specific framework to compile. - /// - public string Framework { get; set; } - - /// - /// Gets or sets a value indicating whether to not build the project before testing. - /// - public bool NoBuild { get; set; } - - /// - /// Gets or sets a value indicating whether to not do implicit NuGet package restore. - /// This makes build faster, but requires restore to be done before build is executed. - /// - /// - /// Requires .NET Core 2.x or newer. - /// - public bool NoRestore { get; set; } - - /// - /// Gets or sets a value indicating whether to run tests without displaying the Microsoft TestPlatform banner. - /// - /// - /// Available since .NET Core 3.0 SDK. - /// - public bool NoLogo { get; set; } - - /// - /// Gets or sets a file to write diagnostic messages to. - /// - public FilePath DiagnosticFile { get; set; } - - /// - /// Gets or sets the results directory. This setting is only available from 2.0.0 upward. - /// - public DirectoryPath ResultsDirectory { get; set; } - - /// - /// Gets or sets the file path to write VSTest reports to. - /// - public FilePath VSTestReportPath { get; set; } - - /// - /// Gets or sets the target runtime to test for. This setting is only available from .NET Core 3.x upward. - /// - public string Runtime { get; set; } } } diff --git a/src/Cake.Common/Tools/DotNetCore/Test/DotNetCoreTester.cs b/src/Cake.Common/Tools/DotNetCore/Test/DotNetCoreTester.cs index 6b7fed8b4e..735cb0d280 100644 --- a/src/Cake.Common/Tools/DotNetCore/Test/DotNetCoreTester.cs +++ b/src/Cake.Common/Tools/DotNetCore/Test/DotNetCoreTester.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet.Test; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -12,7 +13,7 @@ namespace Cake.Common.Tools.DotNetCore.Test /// /// .NET Core project tester. /// - public sealed class DotNetCoreTester : DotNetCoreTool + public sealed class DotNetCoreTester : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -36,18 +37,19 @@ public DotNetCoreTester( /// Tests the project using the specified path with arguments and settings. /// /// The target project path. + /// The arguments. /// The settings. - public void Test(string project, DotNetCoreTestSettings settings) + public void Test(string project, ProcessArgumentBuilder arguments, DotNetTestSettings settings) { if (settings == null) { throw new ArgumentNullException(nameof(settings)); } - RunCommand(settings, GetArguments(project, settings)); + RunCommand(settings, GetArguments(project, arguments, settings)); } - private ProcessArgumentBuilder GetArguments(string project, DotNetCoreTestSettings settings) + private ProcessArgumentBuilder GetArguments(string project, ProcessArgumentBuilder arguments, DotNetTestSettings settings) { var builder = CreateArgumentBuilder(settings); @@ -80,12 +82,24 @@ private ProcessArgumentBuilder GetArguments(string project, DotNetCoreTestSettin builder.AppendQuoted(settings.TestAdapterPath.MakeAbsolute(_environment).FullPath); } - // Filter + // Logger +#pragma warning disable CS0618 if (!string.IsNullOrWhiteSpace(settings.Logger)) { builder.Append("--logger"); builder.AppendQuoted(settings.Logger); } +#pragma warning restore CS0618 + + // Loggers + if (settings.Loggers != null) + { + foreach (var logger in settings.Loggers) + { + builder.Append("--logger"); + builder.AppendQuoted(logger); + } + } // Output directory if (settings.OutputDirectory != null) @@ -108,7 +122,17 @@ private ProcessArgumentBuilder GetArguments(string project, DotNetCoreTestSettin builder.Append(settings.Configuration); } - // Output directory + // Collectors + if (settings.Collectors != null) + { + foreach (var collector in settings.Collectors) + { + builder.Append("--collect"); + builder.AppendQuoted(collector); + } + } + + // Diagnostic file if (settings.DiagnosticFile != null) { builder.Append("--diag"); @@ -150,6 +174,28 @@ private ProcessArgumentBuilder GetArguments(string project, DotNetCoreTestSettin builder.Append(settings.Runtime); } + // Sources + if (settings.Sources != null) + { + foreach (var source in settings.Sources) + { + builder.Append("--source"); + builder.AppendQuoted(source); + } + } + + // Blame + if (settings.Blame) + { + builder.Append("--blame"); + } + + if (!arguments.IsNullOrEmpty()) + { + builder.Append("--"); + arguments.CopyTo(builder); + } + return builder; } } diff --git a/src/Cake.Common/Tools/DotNetCore/Tool/DotNetCoreToolRunner.cs b/src/Cake.Common/Tools/DotNetCore/Tool/DotNetCoreToolRunner.cs index 2a4fe83e34..caa8eb5acd 100644 --- a/src/Cake.Common/Tools/DotNetCore/Tool/DotNetCoreToolRunner.cs +++ b/src/Cake.Common/Tools/DotNetCore/Tool/DotNetCoreToolRunner.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.Tool; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -12,7 +14,7 @@ namespace Cake.Common.Tools.DotNetCore.Tool /// /// .NET Core Extensibility Commands Runner. /// - public sealed class DotNetCoreToolRunner : DotNetCoreTool + public sealed class DotNetCoreToolRunner : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -39,7 +41,7 @@ public DotNetCoreToolRunner( /// The command to execute. /// The arguments. /// The settings. - public void Execute(FilePath projectPath, string command, ProcessArgumentBuilder arguments, DotNetCoreToolSettings settings) + public void Execute(FilePath projectPath, string command, ProcessArgumentBuilder arguments, DotNetToolSettings settings) { if (string.IsNullOrWhiteSpace(command)) { @@ -51,17 +53,15 @@ public void Execute(FilePath projectPath, string command, ProcessArgumentBuilder throw new ArgumentNullException(nameof(settings)); } - var processSettings = new ProcessSettings(); - - if (projectPath != null) + var processSettings = new ProcessSettings { - processSettings.WorkingDirectory = projectPath.GetDirectory(); - } + WorkingDirectory = settings.WorkingDirectory ?? projectPath?.GetDirectory() + }; RunCommand(settings, GetArguments(command, arguments, settings), processSettings); } - private ProcessArgumentBuilder GetArguments(string command, ProcessArgumentBuilder arguments, DotNetCoreToolSettings settings) + private ProcessArgumentBuilder GetArguments(string command, ProcessArgumentBuilder arguments, DotNetToolSettings settings) { var builder = CreateArgumentBuilder(settings); diff --git a/src/Cake.Common/Tools/DotNetCore/Tool/DotNetCoreToolSettings.cs b/src/Cake.Common/Tools/DotNetCore/Tool/DotNetCoreToolSettings.cs index 2698601c92..fc1324a18c 100644 --- a/src/Cake.Common/Tools/DotNetCore/Tool/DotNetCoreToolSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/Tool/DotNetCoreToolSettings.cs @@ -2,12 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Cake.Common.Tools.DotNet.Tool; + namespace Cake.Common.Tools.DotNetCore.Tool { /// /// Contains settings used by . /// - public sealed class DotNetCoreToolSettings : DotNetCoreSettings + public sealed class DotNetCoreToolSettings : DotNetToolSettings { } } diff --git a/src/Cake.Common/Tools/DotNetCore/VSTest/DotNetCoreVSTestSettings.cs b/src/Cake.Common/Tools/DotNetCore/VSTest/DotNetCoreVSTestSettings.cs index 936c707284..24bc2955d8 100644 --- a/src/Cake.Common/Tools/DotNetCore/VSTest/DotNetCoreVSTestSettings.cs +++ b/src/Cake.Common/Tools/DotNetCore/VSTest/DotNetCoreVSTestSettings.cs @@ -2,99 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Collections.Generic; -using Cake.Common.Tools.VSTest; -using Cake.Core.IO; +using Cake.Common.Tools.DotNet.VSTest; namespace Cake.Common.Tools.DotNetCore.VSTest { /// /// Contains settings used by . /// - public sealed class DotNetCoreVSTestSettings : DotNetCoreSettings + public sealed class DotNetCoreVSTestSettings : DotNetVSTestSettings { - /// - /// Gets or sets the settings file to use when running tests. - /// - public FilePath Settings { get; set; } - - /// - /// Gets or sets the a list tests to run. - /// - public ICollection TestsToRun { get; set; } - - /// - /// Gets or sets the path to use for the custom test adapter in the test run. - /// - public DirectoryPath TestAdapterPath { get; set; } - - /// - /// Gets or sets the target platform architecture to be used for test execution. - /// - public VSTestPlatform Platform { get; set; } - - /// - /// Gets or sets specific .Net Framework version to be used for test execution. - /// - /// - /// Valid values are ".NETFramework,Version=v4.6", ".NETCoreApp,Version=v1.0" etc. - /// Other supported values are Framework35, Framework40, Framework45 and FrameworkCore10. - /// - public string Framework { get; set; } - - /// - /// Gets or sets a value indicating whether the tests should be executed in parallel. - /// - /// - /// By default up to all available cores on the machine may be used. The number of cores to use may be configured using a settings file. - /// - public bool Parallel { get; set; } - - /// - /// Gets or sets the filter expression to run test that match. - /// - /// - /// For more information on filtering support, see https://aka.ms/vstest-filtering. - /// - public string TestCaseFilter { get; set; } - - /// - /// Gets or sets a logger for test results. - /// - public string Logger { get; set; } - - /// - /// Gets or sets the Process Id of the Parent Process responsible for launching current process. - /// - public string ParentProcessId { get; set; } - - /// - /// Gets or sets the Port for socket connection and receiving the event messages. - /// - public int? Port { get; set; } - - /// - /// Gets or sets a file to write diagnostic messages to. - /// - public FilePath DiagnosticFile { get; set; } - - /// - /// Gets or sets the path to put the test results in. - /// - public DirectoryPath ResultsDirectory { get; set; } - - /// - /// Gets or sets a list of extra arguments that should be passed to adapter. - /// - public IDictionary Arguments { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public DotNetCoreVSTestSettings() - { - TestsToRun = new List(); - Arguments = new Dictionary(); - } } } diff --git a/src/Cake.Common/Tools/DotNetCore/VSTest/DotNetCoreVSTester.cs b/src/Cake.Common/Tools/DotNetCore/VSTest/DotNetCoreVSTester.cs index 54612ab156..b16b7abe03 100644 --- a/src/Cake.Common/Tools/DotNetCore/VSTest/DotNetCoreVSTester.cs +++ b/src/Cake.Common/Tools/DotNetCore/VSTest/DotNetCoreVSTester.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Cake.Common.Tools.DotNet.VSTest; using Cake.Common.Tools.VSTest; using Cake.Core; using Cake.Core.IO; @@ -15,7 +16,7 @@ namespace Cake.Common.Tools.DotNetCore.VSTest /// /// .NET Core VSTest tester. /// - public sealed class DotNetCoreVSTester : DotNetCoreTool + public sealed class DotNetCoreVSTester : DotNetCoreTool { private readonly ICakeEnvironment _environment; @@ -40,7 +41,7 @@ public DotNetCoreVSTester( /// /// A list of test files to run. /// The settings. - public void Test(IEnumerable testFiles, DotNetCoreVSTestSettings settings) + public void Test(IEnumerable testFiles, DotNetVSTestSettings settings) { if (settings == null) { @@ -55,7 +56,7 @@ public void Test(IEnumerable testFiles, DotNetCoreVSTestSettings setti RunCommand(settings, GetArguments(testFiles, settings)); } - private ProcessArgumentBuilder GetArguments(IEnumerable testFiles, DotNetCoreVSTestSettings settings) + private ProcessArgumentBuilder GetArguments(IEnumerable testFiles, DotNetVSTestSettings settings) { var builder = CreateArgumentBuilder(settings); diff --git a/src/Cake.Common/Tools/DupFinder/DupFinderAliases.cs b/src/Cake.Common/Tools/DupFinder/DupFinderAliases.cs index b3a53511d4..20303b890f 100644 --- a/src/Cake.Common/Tools/DupFinder/DupFinderAliases.cs +++ b/src/Cake.Common/Tools/DupFinder/DupFinderAliases.cs @@ -145,7 +145,7 @@ public static void DupFinder(this ICakeContext context, IEnumerable fi /// [CakeMethodAlias] [CakeAliasCategory("DupFinder")] - public static void DupFinder(this ICakeContext context, string pattern) + public static void DupFinder(this ICakeContext context, GlobPattern pattern) { DupFinder(context, pattern, new DupFinderSettings()); } @@ -169,7 +169,7 @@ public static void DupFinder(this ICakeContext context, string pattern) /// [CakeMethodAlias] [CakeAliasCategory("DupFinder")] - public static void DupFinder(this ICakeContext context, string pattern, DupFinderSettings settings) + public static void DupFinder(this ICakeContext context, GlobPattern pattern, DupFinderSettings settings) { if (context == null) { diff --git a/src/Cake.Common/Tools/Fixie/FixieAliases.cs b/src/Cake.Common/Tools/Fixie/FixieAliases.cs index 1c2b4b5356..ad377208ac 100644 --- a/src/Cake.Common/Tools/Fixie/FixieAliases.cs +++ b/src/Cake.Common/Tools/Fixie/FixieAliases.cs @@ -36,7 +36,7 @@ public static class FixieAliases /// The context. /// The pattern. [CakeMethodAlias] - public static void Fixie(this ICakeContext context, string pattern) + public static void Fixie(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -68,7 +68,7 @@ public static void Fixie(this ICakeContext context, string pattern) /// The pattern. /// The settings. [CakeMethodAlias] - public static void Fixie(this ICakeContext context, string pattern, FixieSettings settings) + public static void Fixie(this ICakeContext context, GlobPattern pattern, FixieSettings settings) { if (context == null) { diff --git a/src/Cake.Common/Tools/GitReleaseManager/Create/GitReleaseManagerCreateSettings.cs b/src/Cake.Common/Tools/GitReleaseManager/Create/GitReleaseManagerCreateSettings.cs index c647b477be..1d21e11737 100644 --- a/src/Cake.Common/Tools/GitReleaseManager/Create/GitReleaseManagerCreateSettings.cs +++ b/src/Cake.Common/Tools/GitReleaseManager/Create/GitReleaseManagerCreateSettings.cs @@ -37,7 +37,7 @@ public sealed class GitReleaseManagerCreateSettings : GitReleaseManagerSettings public string Assets { get; set; } /// - /// Gets or sets the commit to tag. Can be a branch or SHA. Defaults to repository's default branch.. + /// Gets or sets the commit to tag. Can be a branch or SHA. Defaults to repository's default branch. /// public string TargetCommitish { get; set; } } diff --git a/src/Cake.Common/Tools/GitReleaseManager/GitReleaseManagerAliases.cs b/src/Cake.Common/Tools/GitReleaseManager/GitReleaseManagerAliases.cs index ed80fc9ab2..b27bd99633 100644 --- a/src/Cake.Common/Tools/GitReleaseManager/GitReleaseManagerAliases.cs +++ b/src/Cake.Common/Tools/GitReleaseManager/GitReleaseManagerAliases.cs @@ -30,28 +30,6 @@ namespace Cake.Common.Tools.GitReleaseManager [CakeAliasCategory("GitReleaseManager")] public static class GitReleaseManagerAliases { - /// - /// Creates a Package Release. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// - /// - /// GitReleaseManagerCreate("user", "password", "owner", "repo"); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Create")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Create")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerCreate(this ICakeContext context, string userName, string password, string owner, string repository) - { - GitReleaseManagerCreate(context, userName, password, owner, repository, new GitReleaseManagerCreateSettings()); - } - /// /// Creates a Package Release. /// @@ -72,55 +50,6 @@ public static void GitReleaseManagerCreate(this ICakeContext context, string tok GitReleaseManagerCreate(context, token, owner, repository, new GitReleaseManagerCreateSettings()); } - /// - /// Creates a Package Release using the specified settings. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The settings. - /// - /// - /// GitReleaseManagerCreate("user", "password", "owner", "repo", new GitReleaseManagerCreateSettings { - /// Milestone = "0.1.0", - /// Prerelease = false, - /// Assets = "c:/temp/asset1.txt,c:/temp/asset2.txt", - /// TargetCommitish = "master", - /// TargetDirectory = "c:/repo", - /// LogFilePath = "c:/temp/grm.log" - /// }); - /// - /// - /// - /// - /// GitReleaseManagerCreate("user", "password", "owner", "repo", new GitReleaseManagerCreateSettings { - /// Name = "0.1.0", - /// InputFilePath = "c:/repo/releasenotes.md", - /// Prerelease = false, - /// Assets = "c:/temp/asset1.txt,c:/temp/asset2.txt", - /// TargetCommitish = "master", - /// TargetDirectory = "c:/repo", - /// LogFilePath = "c:/temp/grm.log" - /// }); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Create")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Create")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerCreate(this ICakeContext context, string userName, string password, string owner, string repository, GitReleaseManagerCreateSettings settings) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var creator = new GitReleaseManagerCreator(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - creator.Create(userName, password, owner, repository, settings); - } - /// /// Creates a Package Release using the specified settings. /// @@ -168,30 +97,6 @@ public static void GitReleaseManagerCreate(this ICakeContext context, string tok creator.Create(token, owner, repository, settings); } - /// - /// Add Assets to an existing release. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The tag name. - /// The assets. - /// - /// - /// GitReleaseManagerAddAssets("user", "password", "owner", "repo", "0.1.0", "c:/temp/asset1.txt,c:/temp/asset2.txt"); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("AddAssets")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.AddAssets")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerAddAssets(this ICakeContext context, string userName, string password, string owner, string repository, string tagName, string assets) - { - GitReleaseManagerAddAssets(context, userName, password, owner, repository, tagName, assets, new GitReleaseManagerAddAssetsSettings()); - } - /// /// Add Assets to an existing release. /// @@ -214,40 +119,6 @@ public static void GitReleaseManagerAddAssets(this ICakeContext context, string GitReleaseManagerAddAssets(context, token, owner, repository, tagName, assets, new GitReleaseManagerAddAssetsSettings()); } - /// - /// Add Assets to an existing release using the specified settings. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The tag name. - /// The assets. - /// The settings. - /// - /// - /// GitReleaseManagerAddAssets("user", "password", "owner", "repo", "0.1.0", "c:/temp/asset1.txt,c:/temp/asset2.txt" new GitReleaseManagerAddAssetsSettings { - /// TargetDirectory = "c:/repo", - /// LogFilePath = "c:/temp/grm.log" - /// }); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("AddAssets")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.AddAssets")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerAddAssets(this ICakeContext context, string userName, string password, string owner, string repository, string tagName, string assets, GitReleaseManagerAddAssetsSettings settings) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var assetsAdder = new GitReleaseManagerAssetsAdder(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - assetsAdder.AddAssets(userName, password, owner, repository, tagName, assets, settings); - } - /// /// Add Assets to an existing release using the specified settings. /// @@ -260,7 +131,7 @@ public static void GitReleaseManagerAddAssets(this ICakeContext context, string /// The settings. /// /// - /// GitReleaseManagerAddAssets("token", "owner", "repo", "0.1.0", "c:/temp/asset1.txt,c:/temp/asset2.txt" new GitReleaseManagerAddAssetsSettings { + /// GitReleaseManagerAddAssets("token", "owner", "repo", "0.1.0", "c:/temp/asset1.txt,c:/temp/asset2.txt", new GitReleaseManagerAddAssetsSettings { /// TargetDirectory = "c:/repo", /// LogFilePath = "c:/temp/grm.log" /// }); @@ -280,29 +151,6 @@ public static void GitReleaseManagerAddAssets(this ICakeContext context, string assetsAdder.AddAssets(token, owner, repository, tagName, assets, settings); } - /// - /// Closes the milestone associated with a release. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The milestone. - /// - /// - /// GitReleaseManagerClose("user", "password", "owner", "repo", "0.1.0"); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Close")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Close")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerClose(this ICakeContext context, string userName, string password, string owner, string repository, string milestone) - { - GitReleaseManagerClose(context, userName, password, owner, repository, milestone, new GitReleaseManagerCloseMilestoneSettings()); - } - /// /// Closes the milestone associated with a release. /// @@ -324,39 +172,6 @@ public static void GitReleaseManagerClose(this ICakeContext context, string toke GitReleaseManagerClose(context, token, owner, repository, milestone, new GitReleaseManagerCloseMilestoneSettings()); } - /// - /// Closes the milestone associated with a release using the specified settings. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The milestone. - /// The settings. - /// - /// - /// GitReleaseManagerClose("user", "password", "owner", "repo", "0.1.0", new GitReleaseManagerCloseMilestoneSettings { - /// TargetDirectory = "c:/repo", - /// LogFilePath = "c:/temp/grm.log" - /// }); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Close")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Close")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerClose(this ICakeContext context, string userName, string password, string owner, string repository, string milestone, GitReleaseManagerCloseMilestoneSettings settings) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var milestoneCloser = new GitReleaseManagerMilestoneCloser(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - milestoneCloser.Close(userName, password, owner, repository, milestone, settings); - } - /// /// Closes the milestone associated with a release using the specified settings. /// @@ -388,29 +203,6 @@ public static void GitReleaseManagerClose(this ICakeContext context, string toke milestoneCloser.Close(token, owner, repository, milestone, settings); } - /// - /// Publishes the release. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The tag name. - /// - /// - /// GitReleaseManagerPublish("user", "password", "owner", "repo", "0.1.0"); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Publish")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Publish")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerPublish(this ICakeContext context, string userName, string password, string owner, string repository, string tagName) - { - GitReleaseManagerPublish(context, userName, password, owner, repository, tagName, new GitReleaseManagerPublishSettings()); - } - /// /// Publishes the release. /// @@ -432,39 +224,6 @@ public static void GitReleaseManagerPublish(this ICakeContext context, string to GitReleaseManagerPublish(context, token, owner, repository, tagName, new GitReleaseManagerPublishSettings()); } - /// - /// Publishes the release using the specified settings. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The tag name. - /// The settings. - /// - /// - /// GitReleaseManagerPublish("token", "owner", "repo", "0.1.0", new GitReleaseManagerPublishSettings { - /// TargetDirectory = "c:/repo", - /// LogFilePath = "c:/temp/grm.log" - /// }); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Publish")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Publish")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerPublish(this ICakeContext context, string userName, string password, string owner, string repository, string tagName, GitReleaseManagerPublishSettings settings) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var publisher = new GitReleaseManagerPublisher(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - publisher.Publish(userName, password, owner, repository, tagName, settings); - } - /// /// Publishes the release using the specified settings. /// @@ -496,30 +255,6 @@ public static void GitReleaseManagerPublish(this ICakeContext context, string to publisher.Publish(token, owner, repository, tagName, settings); } - /// - /// Exports the release notes. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The output file path. - /// - /// - /// GitReleaseManagerExport("user", "password", "owner", "repo", "c:/temp/releasenotes.md") - /// }); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Export")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Export")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerExport(this ICakeContext context, string userName, string password, string owner, string repository, FilePath fileOutputPath) - { - GitReleaseManagerExport(context, userName, password, owner, repository, fileOutputPath, new GitReleaseManagerExportSettings()); - } - /// /// Exports the release notes. /// @@ -542,40 +277,6 @@ public static void GitReleaseManagerExport(this ICakeContext context, string tok GitReleaseManagerExport(context, token, owner, repository, fileOutputPath, new GitReleaseManagerExportSettings()); } - /// - /// Exports the release notes using the specified settings. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The output file path. - /// The settings. - /// - /// - /// GitReleaseManagerExport("user", "password", "owner", "repo", "c:/temp/releasenotes.md", new GitReleaseManagerExportSettings { - /// TagName = "0.1.0", - /// TargetDirectory = "c:/repo", - /// LogFilePath = "c:/temp/grm.log" - /// }); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Export")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Export")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerExport(this ICakeContext context, string userName, string password, string owner, string repository, FilePath fileOutputPath, GitReleaseManagerExportSettings settings) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var publisher = new GitReleaseManagerExporter(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - publisher.Export(userName, password, owner, repository, fileOutputPath, settings); - } - /// /// Exports the release notes using the specified settings. /// @@ -608,29 +309,6 @@ public static void GitReleaseManagerExport(this ICakeContext context, string tok publisher.Export(token, owner, repository, fileOutputPath, settings); } - /// - /// Deletes and creates labels. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// - /// - /// GitReleaseManagerLabel("user", "password", "owner", "repo") - /// }); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Label")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Label")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerLabel(this ICakeContext context, string userName, string password, string owner, string repository) - { - GitReleaseManagerLabel(context, userName, password, owner, repository, new GitReleaseManagerLabelSettings()); - } - /// /// Deletes and creates labels. /// @@ -640,8 +318,7 @@ public static void GitReleaseManagerLabel(this ICakeContext context, string user /// The repository. /// /// - /// GitReleaseManagerLabel("token", "owner", "repo") - /// }); + /// GitReleaseManagerLabel("token", "owner", "repo"); /// /// [CakeMethodAlias] @@ -652,37 +329,6 @@ public static void GitReleaseManagerLabel(this ICakeContext context, string toke GitReleaseManagerLabel(context, token, owner, repository, new GitReleaseManagerLabelSettings()); } - /// - /// Deletes and creates labels using the specified settings. - /// - /// The context. - /// The user name. - /// The password. - /// The owner. - /// The repository. - /// The settings. - /// - /// - /// GitReleaseManagerLabel("user", "password", "owner", "repo", new GitReleaseManagerLabelSettings { - /// LogFilePath = "c:/temp/grm.log" - /// }); - /// - /// - [CakeMethodAlias] - [CakeAliasCategory("Label")] - [CakeNamespaceImport("Cake.Common.Tools.GitReleaseManager.Label")] - [Obsolete("Use the overload that accepts a token instead.")] - public static void GitReleaseManagerLabel(this ICakeContext context, string userName, string password, string owner, string repository, GitReleaseManagerLabelSettings settings) - { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - var labeller = new GitReleaseManagerLabeller(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - labeller.Label(userName, password, owner, repository, settings); - } - /// /// Deletes and creates labels using the specified settings. /// diff --git a/src/Cake.Common/Tools/GitVersion/GitVersionAliases.cs b/src/Cake.Common/Tools/GitVersion/GitVersionAliases.cs index 5958ff9048..6aed529340 100644 --- a/src/Cake.Common/Tools/GitVersion/GitVersionAliases.cs +++ b/src/Cake.Common/Tools/GitVersion/GitVersionAliases.cs @@ -14,7 +14,7 @@ namespace Cake.Common.Tools.GitVersion /// In order to use the commands for this alias, include the following in your build.cake file to download and /// install from nuget.org, or specify the ToolPath within the class: /// - /// #tool "nuget:?package=GitVersion.CommandLine" + /// #tool "dotnet:?package=GitVersion.Tool" /// /// /// diff --git a/src/Cake.Common/Tools/GitVersion/GitVersionRunner.cs b/src/Cake.Common/Tools/GitVersion/GitVersionRunner.cs index 2372e09548..731d5201db 100644 --- a/src/Cake.Common/Tools/GitVersion/GitVersionRunner.cs +++ b/src/Cake.Common/Tools/GitVersion/GitVersionRunner.cs @@ -174,25 +174,25 @@ private ProcessArgumentBuilder GetArguments(GitVersionSettings settings) { switch (settings.Verbosity.Value) { - case GitVersionVerbosity.None: + case GitVersionVerbosity.Quiet: builder.Append("-verbosity"); - builder.Append(nameof(GitVersionVerbosity.None)); + builder.Append(nameof(Verbosity.Quiet)); break; - case GitVersionVerbosity.Debug: + case GitVersionVerbosity.Diagnostic: builder.Append("-verbosity"); - builder.Append(nameof(GitVersionVerbosity.Debug)); + builder.Append(nameof(Verbosity.Diagnostic)); break; - case GitVersionVerbosity.Info: + case GitVersionVerbosity.Verbose: builder.Append("-verbosity"); - builder.Append(nameof(GitVersionVerbosity.Info)); + builder.Append(nameof(Verbosity.Verbose)); break; - case GitVersionVerbosity.Warn: + case GitVersionVerbosity.Normal: builder.Append("-verbosity"); - builder.Append(nameof(GitVersionVerbosity.Warn)); + builder.Append(nameof(Verbosity.Normal)); break; - case GitVersionVerbosity.Error: + case GitVersionVerbosity.Minimal: builder.Append("-verbosity"); - builder.Append(nameof(GitVersionVerbosity.Error)); + builder.Append(nameof(Verbosity.Minimal)); break; } } @@ -202,16 +202,19 @@ private ProcessArgumentBuilder GetArguments(GitVersionSettings settings) { case Verbosity.Quiet: builder.Append("-verbosity"); - builder.Append(nameof(GitVersionVerbosity.None)); + builder.Append(nameof(Verbosity.Quiet)); break; case Verbosity.Diagnostic: + builder.Append("-verbosity"); + builder.Append(nameof(Verbosity.Diagnostic)); + break; case Verbosity.Verbose: builder.Append("-verbosity"); - builder.Append(nameof(GitVersionVerbosity.Debug)); + builder.Append(nameof(Verbosity.Verbose)); break; case Verbosity.Minimal: builder.Append("-verbosity"); - builder.Append(nameof(GitVersionVerbosity.Error)); + builder.Append(nameof(Verbosity.Minimal)); break; } } diff --git a/src/Cake.Common/Tools/GitVersion/GitVersionVerbosity.cs b/src/Cake.Common/Tools/GitVersion/GitVersionVerbosity.cs index ea3bce7110..f746ecea69 100644 --- a/src/Cake.Common/Tools/GitVersion/GitVersionVerbosity.cs +++ b/src/Cake.Common/Tools/GitVersion/GitVersionVerbosity.cs @@ -5,33 +5,33 @@ namespace Cake.Common.Tools.GitVersion { /// - /// The GitVersion verbosity. + /// The GitVersion verbosity. Default is . /// public enum GitVersionVerbosity { /// - /// No messages will be logged. + /// Quiet verbosity. /// - None, + Quiet = 0, /// - /// Log error messages. + /// Minimal verbosity. /// - Error, + Minimal = 1, /// - /// Log error and warning messages. + /// Normal verbosity (Default). /// - Warn, + Normal = 2, /// - /// Log error, warning and info messages. + /// Verbose verbosity. /// - Info, + Verbose = 3, /// - /// Log error, warning, info and debug messages (log all). + /// Diagnostic verbosity. /// - Debug + Diagnostic = 4, } } diff --git a/src/Cake.Common/Tools/InspectCode/InspectCodeRunner.cs b/src/Cake.Common/Tools/InspectCode/InspectCodeRunner.cs index 06a30adf57..db582520f8 100644 --- a/src/Cake.Common/Tools/InspectCode/InspectCodeRunner.cs +++ b/src/Cake.Common/Tools/InspectCode/InspectCodeRunner.cs @@ -208,6 +208,11 @@ private ProcessArgumentBuilder GetArguments(InspectCodeSettings settings, FilePa builder.AppendQuoted(string.Format(CultureInfo.InvariantCulture, "/severity={0}", settings.Severity.ToString().ToUpper(CultureInfo.InvariantCulture))); } + if (settings.Build.HasValue) + { + builder.Append(settings.Build.Value ? "--build" : "--no-build"); + } + builder.AppendQuoted(solution.MakeAbsolute(_environment).FullPath); return builder; diff --git a/src/Cake.Common/Tools/InspectCode/InspectCodeSettings.cs b/src/Cake.Common/Tools/InspectCode/InspectCodeSettings.cs index 2bad417300..0b3329cdc6 100644 --- a/src/Cake.Common/Tools/InspectCode/InspectCodeSettings.cs +++ b/src/Cake.Common/Tools/InspectCode/InspectCodeSettings.cs @@ -18,8 +18,8 @@ public sealed class InspectCodeSettings : ToolSettings Not (yet) supported options: - /toolset MsBuild toolset version. Highest available is used by default. Example: /toolset=12.0. - /dumpIssuesTypes (/it) Dump issues types (default: False). - - /targets-for-references MSBuild targets. These targets will be executed to get referenced assemblies of projects.. - - /targets-for-items MSBuild targets. These targets will be executed to get other items (e.g. Compile item) of projects.. + - /targets-for-references MSBuild targets. These targets will be executed to get referenced assemblies of projects. + - /targets-for-items MSBuild targets. These targets will be executed to get other items (e.g. Compile item) of projects. */ /// @@ -120,5 +120,32 @@ public sealed class InspectCodeSettings : ToolSettings /// that was output by the command line tool or not. /// public bool SkipOutputAnalysis { get; set; } + + /// + /// Gets or sets a value indicating whether to build or not-build the + /// sources before running the tool. Setting this value is only valid + /// for InspectCode version 2021.2.0 and later. + /// + /// + /// + /// Setting this property to true will result in passing the '--build' option. + /// + /// + /// Setting this property to false will result in passing the '--no-build' option. + /// + /// + /// Setting this property to null will result in no changes to the options. This is the default + /// and the only valid setting for versions before 2021.2. + /// + /// + /// + /// + /// + /// Starting from version 2021.2, InspectCode builds the target solution before starting the analysis + /// to make sure it only finds relevant code issues. + /// To explicitly accept the new behavior and suppress this warning, use the '--build' option. + /// To match the behavior in previous versions and skip the build, use '--no-build'. + /// + public bool? Build { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/MSBuild/MSBuildResolver.cs b/src/Cake.Common/Tools/MSBuild/MSBuildResolver.cs index c845c61ddd..82c279a1ee 100644 --- a/src/Cake.Common/Tools/MSBuild/MSBuildResolver.cs +++ b/src/Cake.Common/Tools/MSBuild/MSBuildResolver.cs @@ -10,7 +10,7 @@ namespace Cake.Common.Tools.MSBuild { internal static class MSBuildResolver { - public static FilePath GetMSBuildPath(IFileSystem fileSystem, ICakeEnvironment environment, MSBuildToolVersion version, MSBuildPlatform buildPlatform) + public static FilePath GetMSBuildPath(IFileSystem fileSystem, ICakeEnvironment environment, MSBuildPlatform buildPlatform, MSBuildSettings settings) { if (environment.Platform.Family == PlatformFamily.OSX) { @@ -42,9 +42,9 @@ public static FilePath GetMSBuildPath(IFileSystem fileSystem, ICakeEnvironment e throw new CakeException("Could not resolve MSBuild."); } - var binPath = version == MSBuildToolVersion.Default - ? GetHighestAvailableMSBuildVersion(fileSystem, environment, buildPlatform) - : GetMSBuildPath(fileSystem, environment, (MSBuildVersion)version, buildPlatform); + var binPath = settings.ToolVersion == MSBuildToolVersion.Default + ? GetHighestAvailableMSBuildVersion(fileSystem, environment, buildPlatform, settings.AllowPreviewVersion) + : GetMSBuildPath(fileSystem, environment, (MSBuildVersion)settings.ToolVersion, buildPlatform, settings.CustomVersion, settings.AllowPreviewVersion); if (binPath == null) { @@ -55,22 +55,23 @@ public static FilePath GetMSBuildPath(IFileSystem fileSystem, ICakeEnvironment e return binPath.CombineWithFilePath("MSBuild.exe"); } - private static DirectoryPath GetHighestAvailableMSBuildVersion(IFileSystem fileSystem, ICakeEnvironment environment, MSBuildPlatform buildPlatform) + private static DirectoryPath GetHighestAvailableMSBuildVersion(IFileSystem fileSystem, ICakeEnvironment environment, MSBuildPlatform buildPlatform, bool allowPreview) { var versions = new[] { + MSBuildVersion.MSBuild17, MSBuildVersion.MSBuild16, MSBuildVersion.MSBuild15, MSBuildVersion.MSBuild14, MSBuildVersion.MSBuild12, MSBuildVersion.MSBuild4, MSBuildVersion.MSBuild35, - MSBuildVersion.MSBuild20 + MSBuildVersion.MSBuild20, }; foreach (var version in versions) { - var path = GetMSBuildPath(fileSystem, environment, version, buildPlatform); + var path = GetMSBuildPath(fileSystem, environment, version, buildPlatform, null, allowPreview); if (fileSystem.Exist(path)) { return path; @@ -79,24 +80,40 @@ private static DirectoryPath GetHighestAvailableMSBuildVersion(IFileSystem fileS return null; } - private static DirectoryPath GetMSBuildPath(IFileSystem fileSystem, ICakeEnvironment environment, MSBuildVersion version, MSBuildPlatform buildPlatform) + private static DirectoryPath GetMSBuildPath( + IFileSystem fileSystem, + ICakeEnvironment environment, + MSBuildVersion version, + MSBuildPlatform buildPlatform, + string customVersion, + bool allowPreview) { switch (version) { + case MSBuildVersion.MSBuild17: + return GetVisualStudio2022Path(fileSystem, environment, buildPlatform, allowPreview); case MSBuildVersion.MSBuild16: - return GetVisualStudio2019Path(fileSystem, environment, buildPlatform); + return GetVisualStudio2019Path(fileSystem, environment, buildPlatform, allowPreview); case MSBuildVersion.MSBuild15: - return GetVisualStudio2017Path(fileSystem, environment, buildPlatform); + return GetVisualStudio2017Path(fileSystem, environment, buildPlatform, allowPreview); case MSBuildVersion.MSBuild14: return GetVisualStudioPath(environment, buildPlatform, "14.0"); case MSBuildVersion.MSBuild12: return GetVisualStudioPath(environment, buildPlatform, "12.0"); + case MSBuildVersion.MSBuildCustomVS: + return GetVisualStudioPath(environment, buildPlatform, customVersion); case MSBuildVersion.MSBuild4: return GetFrameworkPath(environment, buildPlatform, "v4.0.30319"); case MSBuildVersion.MSBuild35: return GetFrameworkPath(environment, buildPlatform, "v3.5"); case MSBuildVersion.MSBuild20: return GetFrameworkPath(environment, buildPlatform, "v2.0.50727"); + case MSBuildVersion.MSBuildNETCustom: + if (!customVersion.Contains("v")) + { + customVersion = "v" + customVersion; + } + return GetFrameworkPath(environment, buildPlatform, customVersion); default: return null; } @@ -122,22 +139,14 @@ private static DirectoryPath GetVisualStudioPath(ICakeEnvironment environment, M } private static DirectoryPath GetVisualStudio2017Path(IFileSystem fileSystem, ICakeEnvironment environment, - MSBuildPlatform buildPlatform) + MSBuildPlatform buildPlatform, bool allowPreviewVersion) { - var vsEditions = new[] - { - "Enterprise", - "Professional", - "Community", - "BuildTools" - }; - - var visualStudio2017Path = environment.GetSpecialPath(SpecialPath.ProgramFilesX86); - - foreach (var edition in vsEditions) + foreach (var edition in allowPreviewVersion + ? VisualStudio.Editions.All + : VisualStudio.Editions.Stable) { // Get the bin path. - var binPath = visualStudio2017Path.Combine(string.Concat("Microsoft Visual Studio/2017/", edition, "/MSBuild/15.0/Bin")); + var binPath = VisualStudio.GetYearAndEditionRootPath(environment, "2017", edition).Combine("MSBuild/15.0/Bin"); if (fileSystem.Exist(binPath)) { if (buildPlatform == MSBuildPlatform.Automatic) @@ -154,26 +163,46 @@ private static DirectoryPath GetVisualStudio2017Path(IFileSystem fileSystem, ICa return binPath; } } - return visualStudio2017Path.Combine("Microsoft Visual Studio/2017/Professional/MSBuild/15.0/Bin"); + return VisualStudio.GetYearAndEditionRootPath(environment, "2017", "Professional").Combine("MSBuild/15.0/Bin"); } private static DirectoryPath GetVisualStudio2019Path(IFileSystem fileSystem, ICakeEnvironment environment, - MSBuildPlatform buildPlatform) + MSBuildPlatform buildPlatform, bool allowPreviewVersion) { - var vsEditions = new[] + foreach (var edition in allowPreviewVersion + ? VisualStudio.Editions.All + : VisualStudio.Editions.Stable) { - "Enterprise", - "Professional", - "Community", - "BuildTools" - }; - - var visualStudio2019Path = environment.GetSpecialPath(SpecialPath.ProgramFilesX86); + // Get the bin path. + var binPath = VisualStudio.GetYearAndEditionRootPath(environment, "2019", edition).Combine("MSBuild/Current/Bin"); + if (fileSystem.Exist(binPath)) + { + if (buildPlatform == MSBuildPlatform.Automatic) + { + if (environment.Platform.Is64Bit) + { + binPath = binPath.Combine("amd64"); + } + } + if (buildPlatform == MSBuildPlatform.x64) + { + binPath = binPath.Combine("amd64"); + } + return binPath; + } + } + return VisualStudio.GetYearAndEditionRootPath(environment, "2019", "Professional").Combine("MSBuild/Current/Bin"); + } - foreach (var edition in vsEditions) + private static DirectoryPath GetVisualStudio2022Path(IFileSystem fileSystem, ICakeEnvironment environment, + MSBuildPlatform buildPlatform, bool allowPreviewVersion) + { + foreach (var edition in allowPreviewVersion + ? VisualStudio.Editions.All + : VisualStudio.Editions.Stable) { // Get the bin path. - var binPath = visualStudio2019Path.Combine(string.Concat("Microsoft Visual Studio/2019/", edition, "/MSBuild/Current/Bin")); // Change from Current to 16.0 after stable version released + var binPath = VisualStudio.GetYearAndEditionRootPath(environment, "2022", edition).Combine("MSBuild/Current/Bin"); if (fileSystem.Exist(binPath)) { if (buildPlatform == MSBuildPlatform.Automatic) @@ -183,14 +212,17 @@ private static DirectoryPath GetVisualStudio2019Path(IFileSystem fileSystem, ICa binPath = binPath.Combine("amd64"); } } + if (buildPlatform == MSBuildPlatform.x64) { binPath = binPath.Combine("amd64"); } + return binPath; } } - return visualStudio2019Path.Combine("Microsoft Visual Studio/2019/Professional/MSBuild/16.0/Bin"); + + return VisualStudio.GetYearAndEditionRootPath(environment, "2022", "Professional").Combine("MSBuild/Current/Bin"); } private static DirectoryPath GetFrameworkPath(ICakeEnvironment environment, MSBuildPlatform buildPlatform, string version) diff --git a/src/Cake.Common/Tools/MSBuild/MSBuildRunner.cs b/src/Cake.Common/Tools/MSBuild/MSBuildRunner.cs index 817b6721b9..2b134a7660 100644 --- a/src/Cake.Common/Tools/MSBuild/MSBuildRunner.cs +++ b/src/Cake.Common/Tools/MSBuild/MSBuildRunner.cs @@ -99,6 +99,25 @@ private ProcessArgumentBuilder GetArguments(FilePath projectFile, MSBuildSetting builder.Append(string.Concat("/p:Platform=", GetPlatformName(platform, isSolution))); } + // Set include symbols? + if (settings.IncludeSymbols.HasValue) + { + builder.Append(string.Concat("/p:IncludeSymbols=", settings.IncludeSymbols.Value ? "true" : "false")); + } + + // Set symbol package format? + if (!string.IsNullOrWhiteSpace(settings.SymbolPackageFormat)) + { + builder.Append(string.Concat("/p:SymbolPackageFormat=", settings.SymbolPackageFormat)); + } + + // Set Continuous Integration Build? + if (settings.ContinuousIntegrationBuild.HasValue) + { + var continuousIntegrationBuild = settings.ContinuousIntegrationBuild.Value ? "true" : "false"; + builder.Append(string.Concat("/p:ContinuousIntegrationBuild=", continuousIntegrationBuild)); + } + // Got any properties? if (settings.Properties.Count > 0) { @@ -150,7 +169,7 @@ private ProcessArgumentBuilder GetArguments(FilePath projectFile, MSBuildSetting string binaryOptions = null; if (!string.IsNullOrEmpty(settings.BinaryLogger.FileName)) { - binaryOptions = settings.BinaryLogger.FileName; + binaryOptions = settings.BinaryLogger.FileName.Quote(); } if (settings.BinaryLogger.Imports != MSBuildBinaryLogImports.Unspecified) @@ -332,7 +351,7 @@ protected override IEnumerable GetAlternativeToolPaths(MSBuildSettings } } - var path = MSBuildResolver.GetMSBuildPath(_fileSystem, _environment, settings.ToolVersion, buildPlatform); + var path = MSBuildResolver.GetMSBuildPath(_fileSystem, _environment, buildPlatform, settings); if (path != null) { return new[] { path }; diff --git a/src/Cake.Common/Tools/MSBuild/MSBuildSettings.cs b/src/Cake.Common/Tools/MSBuild/MSBuildSettings.cs index ed65068fb7..301a4b5181 100644 --- a/src/Cake.Common/Tools/MSBuild/MSBuildSettings.cs +++ b/src/Cake.Common/Tools/MSBuild/MSBuildSettings.cs @@ -21,6 +21,7 @@ public sealed class MSBuildSettings : ToolSettings private readonly HashSet _warningsAsErrorCodes; private readonly HashSet _warningsAsMessageCodes; private readonly HashSet _consoleLoggerParameters; + internal string CustomVersion { get; set; } /// /// Gets the targets. @@ -94,6 +95,86 @@ public sealed class MSBuildSettings : ToolSettings /// public bool? NoLogo { get; set; } + /// + /// Gets or sets the default value of all the version numbers embedded in the build output. + /// + public string Version + { + get => GetPropertyValueOrDefault("Version"); + set => this.WithProperty("Version", value); + } + + /// + /// Gets or sets the base version number embedded in the build output. + /// + public string VersionPrefix + { + get => GetPropertyValueOrDefault("VersionPrefix"); + set => this.WithProperty("VersionPrefix", value); + } + + /// + /// Gets or sets the pre-release label of the version number embedded in the build output. + /// + public string VersionSuffix + { + get => GetPropertyValueOrDefault("VersionSuffix"); + set => this.WithProperty("VersionSuffix", value); + } + + /// + /// Gets or sets the file version number embedded in the build output. + /// + public string FileVersion + { + get => GetPropertyValueOrDefault("FileVersion"); + set => this.WithProperty("FileVersion", value); + } + + /// + /// Gets or sets the assembly version number embedded in the build output. + /// + public string AssemblyVersion + { + get => GetPropertyValueOrDefault("AssemblyVersion"); + set => this.WithProperty("AssemblyVersion", value); + } + + /// + /// Gets or sets the assembly informational version number embedded in the build output. + /// + public string InformationalVersion + { + get => GetPropertyValueOrDefault("InformationalVersion"); + set => this.WithProperty("InformationalVersion", value); + } + + /// + /// Gets or sets the version number of the NuGet package generated. + /// + public string PackageVersion + { + get => GetPropertyValueOrDefault("PackageVersion"); + set => this.WithProperty("PackageVersion", value); + } + + /// + /// Gets or sets the release notes of the NuGet package generated. + /// + public string PackageReleaseNotes + { + get => GetPropertyValueOrDefault("PackageReleaseNotes"); + set => this.WithProperty("PackageReleaseNotes", value); + } + + /// + /// Gets or sets a value indicating whether to normalize stored file paths used when producing deterministic builds. + /// + /// + /// For more information see https://devblogs.microsoft.com/dotnet/producing-packages-with-source-link/#deterministic-builds. + /// + public bool? ContinuousIntegrationBuild { get; set; } + /// /// Gets or sets a value indicating whether implicit target should be passed to MSBuild. /// If set to true, no targets will be specified. @@ -108,6 +189,17 @@ public sealed class MSBuildSettings : ToolSettings /// The build log verbosity. public Verbosity Verbosity { get; set; } + /// + /// Gets or sets a value indicating whether a symbol package should be created. + /// + public bool? IncludeSymbols { get; set; } + + /// + /// Gets or sets the symbol package format. + /// + /// The symbol package format. + public string SymbolPackageFormat { get; set; } + /// /// Gets the loggers. /// @@ -151,7 +243,7 @@ public sealed class MSBuildSettings : ToolSettings /// /// Gets or sets a value indicating whether or not to lock the package dependency graph while /// restoring, using the packages.lock.json file. - /// This setting is available with atleast Visual Studio 2017 version 15.9 and above or NET SDK version 2.1.500 and above. + /// This setting is available with at least Visual Studio 2017 version 15.9 and above or NET SDK version 2.1.500 and above. /// public bool? RestoreLockedMode { get; set; } @@ -160,6 +252,15 @@ public sealed class MSBuildSettings : ToolSettings /// public ISet ConsoleLoggerParameters => _consoleLoggerParameters; + /// + /// Gets or sets a value indicating whether tools from a preview edition of Visual Studio should be used. + /// + /// If set to true, MSBuildTools from a Preview edition + /// (e.g. Visual Studio 2022 Preview) will be considered to be used. + /// + /// + public bool AllowPreviewVersion { get; set; } = false; + /// /// Initializes a new instance of the class. /// @@ -178,5 +279,16 @@ public MSBuildSettings() Verbosity = Verbosity.Normal; MSBuildPlatform = MSBuildPlatform.Automatic; } + + private string GetPropertyValueOrDefault(string propertyName, string @default = null) + { + if (!Properties.TryGetValue(propertyName, out var propertyValues)) + { + return @default; + } + + var propertyValue = string.Join(";", propertyValues); + return propertyValue; + } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/MSBuild/MSBuildSettingsExtensions.cs b/src/Cake.Common/Tools/MSBuild/MSBuildSettingsExtensions.cs index 4df22bfc95..9b63667a16 100644 --- a/src/Cake.Common/Tools/MSBuild/MSBuildSettingsExtensions.cs +++ b/src/Cake.Common/Tools/MSBuild/MSBuildSettingsExtensions.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; using Cake.Core.Diagnostics; namespace Cake.Common.Tools.MSBuild @@ -46,6 +47,86 @@ public static MSBuildSettings UseToolVersion(this MSBuildSettings settings, MSBu return settings; } + /// + /// Sets the tool version. + /// + /// The settings. + /// The string version. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings UseToolVersion(this MSBuildSettings settings, string version) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + // check to see if the version is null/empty or is not a num + if (string.IsNullOrEmpty(version)) + { + throw new ArgumentException(nameof(version)); + } + var sanitizeVersion = version.Replace(" ", string.Empty); + var mSBuildToolVersion = GetMSBuildToolVersionFromString(sanitizeVersion.ToUpper()); + if (mSBuildToolVersion == MSBuildToolVersion.NETCustom || mSBuildToolVersion == MSBuildToolVersion.VSCustom) + { + settings.CustomVersion = version; + } + settings.ToolVersion = mSBuildToolVersion; + return settings; + } + + /// + /// Helper that gets the MSBuildToolVersion from the version string. + /// + /// The string version. + /// The matched MSBuildToolVersion enum . + private static MSBuildToolVersion GetMSBuildToolVersionFromString(string version) + { + switch (version) + { + case "2": + case "2.0": + case "NET20": return MSBuildToolVersion.NET20; + case "3": + case "3.0": + case "NET30": return MSBuildToolVersion.NET30; + case "3.5": + case "NET35": return MSBuildToolVersion.NET35; + case "4": + case "4.0": + case "NET40": return MSBuildToolVersion.NET40; + case "4.5": + case "NET45": return MSBuildToolVersion.NET45; + case "4.5.1": + case "NET451": return MSBuildToolVersion.NET451; + case "4.6": + case "NET46": return MSBuildToolVersion.NET46; + case "4.5.2": + case "NET452": return MSBuildToolVersion.NET452; + case "2005": + case "VS2005": return MSBuildToolVersion.VS2005; + case "2008": + case "VS2008": return MSBuildToolVersion.VS2008; + case "2010": + case "VS2010": return MSBuildToolVersion.VS2010; + case "2011": + case "VS2011": return MSBuildToolVersion.VS2011; + case "2012": + case "VS2012": return MSBuildToolVersion.VS2011; + case "2013": + case "VS2013": return MSBuildToolVersion.VS2013; + case "2015": + case "VS2015": return MSBuildToolVersion.VS2015; + case "2017": + case "VS2017": return MSBuildToolVersion.VS2017; + case "2019": + case "VS2019": return MSBuildToolVersion.VS2019; + case string vs when vs.Contains("VS") || Regex.Match(vs, @"\d{4}").Success: return MSBuildToolVersion.VSCustom; + case string dotNet when Regex.Match(dotNet, @"^[0-9,.]*$").Success: return MSBuildToolVersion.NETCustom; + default: return MSBuildToolVersion.Default; + } + } + /// /// Sets the platform target. /// @@ -62,6 +143,23 @@ public static MSBuildSettings SetPlatformTarget(this MSBuildSettings settings, P return settings; } + /// + /// Sets the platform target. + /// + /// The settings. + /// The target. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetPlatformTarget(this MSBuildSettings settings, string target) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + + settings.WithProperty("Platform", target); + return settings; + } + /// /// Sets the MSBuild platform. /// @@ -206,6 +304,102 @@ public static MSBuildSettings SetNoLogo(this MSBuildSettings settings, bool noLo return settings; } + /// + /// Sets the version. + /// + /// The settings. + /// The version. + /// The same instance so that multiple calls can be chained. + /// + /// Version will override VersionPrefix and VersionSuffix if set. + /// This may also override version settings during packaging. + /// + public static MSBuildSettings SetVersion(this MSBuildSettings settings, string version) + => settings.WithProperty("Version", version); + + /// + /// Sets the version prefix. + /// + /// The settings. + /// The version prefix. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetVersionPrefix(this MSBuildSettings settings, string versionPrefix) + => settings.WithProperty("VersionPrefix", versionPrefix); + + /// + /// Sets the version suffix. + /// + /// The settings. + /// The version suffix. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetVersionSuffix(this MSBuildSettings settings, string versionSuffix) + => settings.WithProperty("VersionSuffix", versionSuffix); + + /// + /// Sets the file version. + /// + /// The settings. + /// The file version. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetFileVersion(this MSBuildSettings settings, string fileVersion) + => settings.WithProperty("FileVersion", fileVersion); + + /// + /// Sets the assembly version. + /// + /// The settings. + /// The assembly version. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetAssemblyVersion(this MSBuildSettings settings, string assemblyVersion) + => settings.WithProperty("AssemblyVersion", assemblyVersion); + + /// + /// Sets the informational version. + /// + /// The settings. + /// The informational version. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetInformationalVersion(this MSBuildSettings settings, string informationalVersion) + => settings.WithProperty("InformationalVersion", informationalVersion); + + /// + /// Sets the package version. + /// + /// The settings. + /// The package version. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetPackageVersion(this MSBuildSettings settings, string packageVersion) + => settings.WithProperty("PackageVersion", packageVersion); + + /// + /// Sets the package release notes. + /// + /// The settings. + /// The package release notes. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetPackageReleaseNotes(this MSBuildSettings settings, string packageReleaseNotes) + => settings.WithProperty("PackageReleaseNotes", packageReleaseNotes); + + /// + /// Sets a value indicating whether to normalize stored file paths used when producing deterministic builds. + /// + /// + /// For more information see https://devblogs.microsoft.com/dotnet/producing-packages-with-source-link/#deterministic-builds. + /// + /// The settings. + /// A value indicating whether to normalize stored file paths used when producing deterministic builds. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetContinuousIntegrationBuild(this MSBuildSettings settings, bool? continuousIntegrationBuild = true) + { + if (settings is null) + { + throw new ArgumentNullException(nameof(settings)); + } + + settings.ContinuousIntegrationBuild = continuousIntegrationBuild; + return settings; + } + /// /// Sets whether or not any targets should be passed to MSBuild. /// @@ -222,6 +416,38 @@ public static MSBuildSettings SetNoImplicitTarget(this MSBuildSettings settings, return settings; } + /// + /// Sets whether or not a symbol package should be created. + /// + /// The settings. + /// true if a symbol package should be created; otherwise false. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetIncludeSymbols(this MSBuildSettings settings, bool includeSymbols) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + settings.IncludeSymbols = includeSymbols; + return settings; + } + + /// + /// Sets the symbol package format. + /// + /// The settings. + /// The symbol package format. + /// The same instance so that multiple calls can be chained. + public static MSBuildSettings SetSymbolPackageFormat(this MSBuildSettings settings, string symbolPackageFormat) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + settings.SymbolPackageFormat = symbolPackageFormat; + return settings; + } + /// /// Sets the build log verbosity. /// diff --git a/src/Cake.Common/Tools/MSBuild/MSBuildToolVersion.cs b/src/Cake.Common/Tools/MSBuild/MSBuildToolVersion.cs index 3688a0dd5f..c6431ea069 100644 --- a/src/Cake.Common/Tools/MSBuild/MSBuildToolVersion.cs +++ b/src/Cake.Common/Tools/MSBuild/MSBuildToolVersion.cs @@ -97,6 +97,21 @@ public enum MSBuildToolVersion /// /// MSBuild tool version: Visual Studio 2019 /// - VS2019 = 7 + VS2019 = 7, + + /// + /// Custom Visual Studio build + /// + VSCustom = 8, + + /// + /// Custom Visual Studio build + /// + NETCustom = 9, + + /// + /// MSBuild tool version: Visual Studio 2022 + /// + VS2022 = 10 } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/MSBuild/MSBuildVersion.cs b/src/Cake.Common/Tools/MSBuild/MSBuildVersion.cs index 33da43c19f..6698d7ac27 100644 --- a/src/Cake.Common/Tools/MSBuild/MSBuildVersion.cs +++ b/src/Cake.Common/Tools/MSBuild/MSBuildVersion.cs @@ -28,6 +28,19 @@ public enum MSBuildVersion MSBuild15 = 6, /// Version 16.0 - MSBuild16 = 7 + MSBuild16 = 7, + + /// + /// Custom VS Version + /// + MSBuildCustomVS = 8, + + /// + /// Custom .NET Version + /// + MSBuildNETCustom = 9, + + /// Version 17.0 + MSBuild17 = 10 } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/MSBuild/PlatformTarget.cs b/src/Cake.Common/Tools/MSBuild/PlatformTarget.cs index 6cfdbba8cd..9bbdffb154 100644 --- a/src/Cake.Common/Tools/MSBuild/PlatformTarget.cs +++ b/src/Cake.Common/Tools/MSBuild/PlatformTarget.cs @@ -41,6 +41,24 @@ public enum PlatformTarget /// Platform target: ARM64 /// // ReSharper disable once InconsistentNaming - ARM64 = 5 + ARM64 = 5, + + /// + /// Platform target: ARMv6 + /// + // ReSharper disable once InconsistentNaming + ARMv6 = 6, + + /// + /// Platform target: ARMv7 + /// + // ReSharper disable once InconsistentNaming + ARMv7 = 7, + + /// + /// Platform target: ARMv7s + /// + // ReSharper disable once InconsistentNaming + ARMv7s = 8, } } diff --git a/src/Cake.Common/Tools/MSTest/MSTestAliases.cs b/src/Cake.Common/Tools/MSTest/MSTestAliases.cs index 74f48c9c25..58b3385e32 100644 --- a/src/Cake.Common/Tools/MSTest/MSTestAliases.cs +++ b/src/Cake.Common/Tools/MSTest/MSTestAliases.cs @@ -34,7 +34,7 @@ public static class MSTestAliases /// The context. /// The pattern. [CakeMethodAlias] - public static void MSTest(this ICakeContext context, string pattern) + public static void MSTest(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -63,7 +63,7 @@ public static void MSTest(this ICakeContext context, string pattern) /// The pattern. /// The settings. [CakeMethodAlias] - public static void MSTest(this ICakeContext context, string pattern, MSTestSettings settings) + public static void MSTest(this ICakeContext context, GlobPattern pattern, MSTestSettings settings) { if (context == null) { diff --git a/src/Cake.Common/Tools/MSTest/MSTestRunner.cs b/src/Cake.Common/Tools/MSTest/MSTestRunner.cs index 21e9915a30..a7a5bd1883 100644 --- a/src/Cake.Common/Tools/MSTest/MSTestRunner.cs +++ b/src/Cake.Common/Tools/MSTest/MSTestRunner.cs @@ -114,18 +114,24 @@ protected override IEnumerable GetToolExecutableNames() /// The default tool path. protected override IEnumerable GetAlternativeToolPaths(MSTestSettings settings) { - foreach (var yearAndEdition in new[] { "2019/Enterprise", "2019/Professional", "2019/Community", "2017/Enterprise", "2017/Professional", "2017/Community" }) + var vsRootRelativeToolPath = FilePath.FromString("Common7/IDE/mstest.exe"); + foreach (var year in VisualStudio.Versions.TwentySeventeenAndLater) { - var path = GetYearAndEditionToolPath(yearAndEdition); - if (_fileSystem.Exist(path)) + foreach (var edition in settings.AllowPreviewVersion + ? VisualStudio.Editions.All + : VisualStudio.Editions.Stable) { - yield return path; + var path = VisualStudio.GetYearAndEditionToolPath(_environment, year, edition, vsRootRelativeToolPath); + if (_fileSystem.Exist(path)) + { + yield return path; + } } } - foreach (var version in new[] { "14.0", "12.0", "11.0", "10.0" }) + foreach (var version in VisualStudio.Versions.TenToFourteen) { - var path = GetVersionNumberToolPath(version); + var path = VisualStudio.GetVersionNumberToolPath(_environment, version, vsRootRelativeToolPath); if (_fileSystem.Exist(path)) { yield return path; @@ -142,20 +148,6 @@ protected override IEnumerable GetAlternativeToolPaths(MSTestSettings } } - private FilePath GetVersionNumberToolPath(string version) - { - var programFiles = _environment.GetSpecialPath(SpecialPath.ProgramFilesX86); - var root = programFiles.Combine(string.Concat("Microsoft Visual Studio ", version, "/Common7/IDE")); - return root.CombineWithFilePath("mstest.exe"); - } - - private FilePath GetYearAndEditionToolPath(string yearAndEdition) - { - var programFiles = _environment.GetSpecialPath(SpecialPath.ProgramFilesX86); - var root = programFiles.Combine(string.Concat("Microsoft Visual Studio/", yearAndEdition, "/Common7/IDE")); - return root.CombineWithFilePath("mstest.exe"); - } - private FilePath GetCommonToolPath(string environmentVariable) { var visualStudioCommonToolsPath = _environment.GetEnvironmentVariable(environmentVariable); diff --git a/src/Cake.Common/Tools/MSTest/MSTestSettings.cs b/src/Cake.Common/Tools/MSTest/MSTestSettings.cs index 590afbe4f2..9ea17208b8 100644 --- a/src/Cake.Common/Tools/MSTest/MSTestSettings.cs +++ b/src/Cake.Common/Tools/MSTest/MSTestSettings.cs @@ -46,5 +46,14 @@ public MSTestSettings() { NoIsolation = true; } + + /// + /// Gets or sets a value indicating whether tools from a preview edition of Visual Studio should be used. + /// + /// If set to true, MSTest from a Preview edition + /// (e.g. Visual Studio 2022 Preview) will be considered to be used. + /// + /// + public bool AllowPreviewVersion { get; set; } = false; } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/MSpec/MSpecAliases.cs b/src/Cake.Common/Tools/MSpec/MSpecAliases.cs index fae4fcdccb..f3542cc99c 100644 --- a/src/Cake.Common/Tools/MSpec/MSpecAliases.cs +++ b/src/Cake.Common/Tools/MSpec/MSpecAliases.cs @@ -36,7 +36,7 @@ public static class MSpecAliases /// /// [CakeMethodAlias] - public static void MSpec(this ICakeContext context, string pattern) + public static void MSpec(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -71,7 +71,7 @@ public static void MSpec(this ICakeContext context, string pattern) /// /// [CakeMethodAlias] - public static void MSpec(this ICakeContext context, string pattern, MSpecSettings settings) + public static void MSpec(this ICakeContext context, GlobPattern pattern, MSpecSettings settings) { if (context == null) { diff --git a/src/Cake.Common/Tools/MSpec/MspecSettings.cs b/src/Cake.Common/Tools/MSpec/MspecSettings.cs index a17925ca06..6e08a8e45f 100644 --- a/src/Cake.Common/Tools/MSpec/MspecSettings.cs +++ b/src/Cake.Common/Tools/MSpec/MspecSettings.cs @@ -97,25 +97,11 @@ public sealed class MSpecSettings : ToolSettings /// public bool AppVeyor { get; set; } - /// - /// Gets or sets a value indicating whether to enable reporting for AppVeyor CI integration (also auto-detected). - /// - [Obsolete("Please use the AppVeyor property instead (note the capitalization). This property will be removed in a future version.")] - [CLSCompliant(false)] // Identifier differs only in case - public bool Appveyor { get => AppVeyor; set => AppVeyor = value; } - /// /// Gets or sets a value indicating whether to disable AppVeyor autodetection. /// public bool NoAppVeyor { get; set; } - /// - /// Gets or sets a value indicating whether to disable AppVeyor autodetection. - /// - [Obsolete("Please use the NoAppVeyor property instead (note the capitalization). This property will be removed in a future version.")] - [CLSCompliant(false)] // Identifier differs only in case - public bool NoAppveyor { get => NoAppVeyor; set => NoAppVeyor = value; } - /// /// Gets or sets output directory for reports. /// diff --git a/src/Cake.Common/Tools/NUnit/NUnit3Aliases.cs b/src/Cake.Common/Tools/NUnit/NUnit3Aliases.cs index a2cf0e8ec2..d9da0bbe1b 100644 --- a/src/Cake.Common/Tools/NUnit/NUnit3Aliases.cs +++ b/src/Cake.Common/Tools/NUnit/NUnit3Aliases.cs @@ -36,7 +36,7 @@ public static class NUnit3Aliases /// /// [CakeMethodAlias] - public static void NUnit3(this ICakeContext context, string pattern) + public static void NUnit3(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -68,7 +68,7 @@ public static void NUnit3(this ICakeContext context, string pattern) /// /// [CakeMethodAlias] - public static void NUnit3(this ICakeContext context, string pattern, NUnit3Settings settings) + public static void NUnit3(this ICakeContext context, GlobPattern pattern, NUnit3Settings settings) { if (context == null) { diff --git a/src/Cake.Common/Tools/NUnit/NUnit3Runner.cs b/src/Cake.Common/Tools/NUnit/NUnit3Runner.cs index 162033410e..cb9bb5891b 100644 --- a/src/Cake.Common/Tools/NUnit/NUnit3Runner.cs +++ b/src/Cake.Common/Tools/NUnit/NUnit3Runner.cs @@ -114,18 +114,6 @@ private ProcessArgumentBuilder GetArguments(IEnumerable assemblyPaths, builder.AppendQuoted(string.Format(CultureInfo.InvariantCulture, "--out={0}", settings.OutputFile.MakeAbsolute(_environment).FullPath)); } - #pragma warning disable 0618 - if (settings.ErrorOutputFile != null) - { - builder.AppendQuoted(string.Format(CultureInfo.InvariantCulture, "--err={0}", settings.ErrorOutputFile.MakeAbsolute(_environment).FullPath)); - } - - if (settings.Full) - { - builder.Append("--full"); - } - #pragma warning restore 0618 - if (HasResults(settings) && settings.NoResults) { throw new ArgumentException( @@ -173,13 +161,6 @@ private ProcessArgumentBuilder GetArguments(IEnumerable assemblyPaths, builder.Append("--nocolor"); } - #pragma warning disable 0618 - if (settings.Verbose) - { - builder.Append("--verbose"); - } - #pragma warning restore 0618 - if (settings.Configuration != null) { builder.AppendQuoted("--config=" + settings.Configuration); @@ -239,6 +220,14 @@ private ProcessArgumentBuilder GetArguments(IEnumerable assemblyPaths, } } + if (settings.TestParams != null && settings.TestParams.Count > 0) + { + foreach (var testParam in settings.TestParams) + { + builder.AppendQuoted(string.Format(CultureInfo.InvariantCulture, "--testparam:{0}={1}", testParam.Key, testParam.Value)); + } + } + return builder; } diff --git a/src/Cake.Common/Tools/NUnit/NUnit3Settings.cs b/src/Cake.Common/Tools/NUnit/NUnit3Settings.cs index 4ed2f06547..c96545e271 100644 --- a/src/Cake.Common/Tools/NUnit/NUnit3Settings.cs +++ b/src/Cake.Common/Tools/NUnit/NUnit3Settings.cs @@ -105,23 +105,6 @@ public sealed class NUnit3Settings : ToolSettings /// The location that NUnit should write test output. public FilePath OutputFile { get; set; } - /// - /// Gets or sets the location that NUnit should write test error output. - /// - /// The location that NUnit should write test error output. - [Obsolete("This argument was removed from NUnit3", false)] - public FilePath ErrorOutputFile { get; set; } - - /// - /// Gets or sets a value indicating whether to print full report of all test results. - /// - /// - /// true if a full report of test results should be printed; - /// otherwise, false. - /// - [Obsolete("This argument was removed from NUnit3", false)] - public bool Full { get; set; } - /// /// Gets or sets the results that should be saved. /// @@ -170,15 +153,6 @@ public sealed class NUnit3Settings : ToolSettings /// public bool NoColor { get; set; } - /// - /// Gets or sets a value indicating whether to show additional information as the tests run. - /// - /// - /// true shows additional information as the tests run; otherwise, false. - /// - [Obsolete("This argument was removed from NUnit3", false)] - public bool Verbose { get; set; } - /// /// Gets or sets the name of a project configuration to load (e.g.:Debug). /// This selects the configuration within the NUnit project file. @@ -262,6 +236,16 @@ public sealed class NUnit3Settings : ToolSettings // “Case-sensitive.” https://github.com/nunit/docs/wiki/Console-Command-Line#options new Dictionary(StringComparer.Ordinal); + /// + /// Gets or sets the test parameters that should be passed to the runner. + /// + /// + /// List of test parameters (key/value) which are passed to the runner. + /// + public IDictionary TestParams { get; set; } = + // “Case-sensitive.” https://github.com/nunit/docs/wiki/Console-Command-Line#options + new Dictionary(StringComparer.Ordinal); + /// /// Gets or sets the level of detail at which the runner should write to its internal trace log. /// Corresponds to the -trace=LEVEL command line argument. diff --git a/src/Cake.Common/Tools/NUnit/NUnitAliases.cs b/src/Cake.Common/Tools/NUnit/NUnitAliases.cs index d87e029123..f8f2a8eb51 100644 --- a/src/Cake.Common/Tools/NUnit/NUnitAliases.cs +++ b/src/Cake.Common/Tools/NUnit/NUnitAliases.cs @@ -36,7 +36,7 @@ public static class NUnitAliases /// The context. /// The pattern. [CakeMethodAlias] - public static void NUnit(this ICakeContext context, string pattern) + public static void NUnit(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -69,7 +69,7 @@ public static void NUnit(this ICakeContext context, string pattern) /// The pattern. /// The settings. [CakeMethodAlias] - public static void NUnit(this ICakeContext context, string pattern, NUnitSettings settings) + public static void NUnit(this ICakeContext context, GlobPattern pattern, NUnitSettings settings) { if (context == null) { diff --git a/src/Cake.Common/Tools/NuGet/NuGetAliases.cs b/src/Cake.Common/Tools/NuGet/NuGetAliases.cs index 43326aea3f..2cb275500b 100644 --- a/src/Cake.Common/Tools/NuGet/NuGetAliases.cs +++ b/src/Cake.Common/Tools/NuGet/NuGetAliases.cs @@ -1018,7 +1018,7 @@ public static void NuGetAdd(this ICakeContext context, string packageId, string /// The settings. /// /// - /// NuGetAdd("MyNuGetPackage", new NuGetAddSettings({ + /// NuGetAdd("MyNuGetPackage", new NuGetAddSettings { /// Source = "//bar/packages/" /// }); /// diff --git a/src/Cake.Common/Tools/NuGet/NuGetMSBuildVersion.cs b/src/Cake.Common/Tools/NuGet/NuGetMSBuildVersion.cs index 6396f29b3a..c826f203a9 100644 --- a/src/Cake.Common/Tools/NuGet/NuGetMSBuildVersion.cs +++ b/src/Cake.Common/Tools/NuGet/NuGetMSBuildVersion.cs @@ -26,15 +26,6 @@ public enum NuGetMSBuildVersion /// MSBuild14 = 14, - /// - /// MSBuildVersion : 15 - /// - /// - /// MSBuildVersion 15 isn't an valid option and will be removed in the futute. - /// - [Obsolete("MSBuildVersion 15 isn't an valid option and will be removed in the future.")] - MSBuild15 = 15, - /// /// MSBuildVersion : 15.1 /// diff --git a/src/Cake.Common/Tools/NuGet/NuGetMSBuildVersionExtensions.cs b/src/Cake.Common/Tools/NuGet/NuGetMSBuildVersionExtensions.cs index 530ccc5bb0..9c776ea4c7 100644 --- a/src/Cake.Common/Tools/NuGet/NuGetMSBuildVersionExtensions.cs +++ b/src/Cake.Common/Tools/NuGet/NuGetMSBuildVersionExtensions.cs @@ -25,11 +25,6 @@ public static string GetNuGetMSBuildVersionString(this NuGetMSBuildVersion nuGet case NuGetMSBuildVersion.MSBuild14: return "14"; -#pragma warning disable CS0618 - case NuGetMSBuildVersion.MSBuild15: - return "15"; -#pragma warning restore CS0618 - case NuGetMSBuildVersion.MSBuild15_1: return "15.1"; diff --git a/src/Cake.Common/Tools/NuGet/Pack/NuGetPackSettings.cs b/src/Cake.Common/Tools/NuGet/Pack/NuGetPackSettings.cs index 66b50d7651..732c38dd82 100644 --- a/src/Cake.Common/Tools/NuGet/Pack/NuGetPackSettings.cs +++ b/src/Cake.Common/Tools/NuGet/Pack/NuGetPackSettings.cs @@ -53,6 +53,12 @@ public sealed class NuGetPackSettings : ToolSettings /// public bool Symbols { get; set; } + /// + /// Gets or sets the symbol package format. + /// + /// The symbol package format. + public string SymbolPackageFormat { get; set; } + /// /// Gets or sets the package ID. /// @@ -107,6 +113,12 @@ public sealed class NuGetPackSettings : ToolSettings /// The package project URL. public Uri ProjectUrl { get; set; } + /// + /// Gets or sets the Icon path. + /// + /// The path to the icon file contained within the NuGet package. + public string Icon { get; set; } + /// /// Gets or sets the package icon URL. /// diff --git a/src/Cake.Common/Tools/NuGet/Pack/NuGetPacker.cs b/src/Cake.Common/Tools/NuGet/Pack/NuGetPacker.cs index 7e12fe7018..abfcb818c6 100644 --- a/src/Cake.Common/Tools/NuGet/Pack/NuGetPacker.cs +++ b/src/Cake.Common/Tools/NuGet/Pack/NuGetPacker.cs @@ -190,6 +190,13 @@ private ProcessArgumentBuilder GetArguments(FilePath filePath, NuGetPackSettings builder.Append("-Symbols"); } + // SymbolPackageFormat + if (!string.IsNullOrWhiteSpace(settings.SymbolPackageFormat)) + { + builder.Append("-SymbolPackageFormat"); + builder.Append(settings.SymbolPackageFormat); + } + // Verbosity if (settings.Verbosity != null) { diff --git a/src/Cake.Common/Tools/NuGet/Pack/NuspecTransformer.cs b/src/Cake.Common/Tools/NuGet/Pack/NuspecTransformer.cs index 303cbef728..c10e625cd6 100644 --- a/src/Cake.Common/Tools/NuGet/Pack/NuspecTransformer.cs +++ b/src/Cake.Common/Tools/NuGet/Pack/NuspecTransformer.cs @@ -45,6 +45,7 @@ private static IDictionary> CreateMappin { "owners", x => ToCommaSeparatedString(settings.Owners) }, { "licenseUrl", x => ToString(settings.LicenseUrl) }, { "projectUrl", x => ToString(settings.ProjectUrl) }, + { "icon", x => ToString(settings.Icon) }, { "iconUrl", x => ToString(settings.IconUrl) }, { "requireLicenseAcceptance", x => ToString(settings.RequireLicenseAcceptance) }, { "developmentDependency", x => ToString(settings.DevelopmentDependency) }, diff --git a/src/Cake.Common/Tools/NuGet/Sources/NuGetSources.cs b/src/Cake.Common/Tools/NuGet/Sources/NuGetSources.cs index efa8f23afd..19b7099ee3 100644 --- a/src/Cake.Common/Tools/NuGet/Sources/NuGetSources.cs +++ b/src/Cake.Common/Tools/NuGet/Sources/NuGetSources.cs @@ -138,8 +138,8 @@ public bool HasSource(string source, NuGetSourcesSettings settings) var result = false; - Run(settings, GetHasArguments(settings), processSettings, - process => result = process.GetStandardOutput().Any(line => line.TrimStart() == source)); + Run(settings, GetHasArguments(settings), processSettings, + process => result = process.GetStandardOutput().Any(line => line.TrimStart().Equals(source, StringComparison.OrdinalIgnoreCase))); // Return whether or not the source exist. return result; diff --git a/src/Cake.Common/Tools/OctopusDeploy/CreateReleaseArgumentBuilder.cs b/src/Cake.Common/Tools/OctopusDeploy/CreateReleaseArgumentBuilder.cs index 3eb0c9c94e..aca88bc446 100644 --- a/src/Cake.Common/Tools/OctopusDeploy/CreateReleaseArgumentBuilder.cs +++ b/src/Cake.Common/Tools/OctopusDeploy/CreateReleaseArgumentBuilder.cs @@ -35,6 +35,7 @@ public ProcessArgumentBuilder Get() AppendArgumentIfNotNull("releasenotes", _settings.ReleaseNotes); AppendArgumentIfNotNull("releasenotesfile", _settings.ReleaseNotesFile); AppendArgumentIfNotNull("channel", _settings.Channel); + AppendArgumentIfNotNull("excludemachines", _settings.ExcludeMachines); if (_settings.IgnoreChannelRules) { @@ -58,11 +59,20 @@ public ProcessArgumentBuilder Get() private void AppendDeploymnetArguments() { - AppendArgumentIfNotNull("deployto", _settings.DeployTo); AppendConditionalFlag(_settings.ShowProgress, "--progress"); AppendConditionalFlag(_settings.ForcePackageDownload, "--forcepackagedownload"); AppendConditionalFlag(_settings.WaitForDeployment, "--waitfordeployment"); + AppendArgumentIfNotNull("deployto", _settings.DeployTo); + + if (_settings.DeployToMultiple != null) + { + foreach (var target in _settings.DeployToMultiple) + { + AppendArgumentIfNotNull("deployto", target); + } + } + if (_settings.DeploymentTimeout.HasValue) { Builder.AppendSwitchQuoted("--deploymenttimeout", "=", _settings.DeploymentTimeout.Value.ToString("hh\\:mm\\:ss")); diff --git a/src/Cake.Common/Tools/OctopusDeploy/CreateReleaseSettings.cs b/src/Cake.Common/Tools/OctopusDeploy/CreateReleaseSettings.cs index 40b71111f6..27442da86c 100644 --- a/src/Cake.Common/Tools/OctopusDeploy/CreateReleaseSettings.cs +++ b/src/Cake.Common/Tools/OctopusDeploy/CreateReleaseSettings.cs @@ -62,6 +62,11 @@ public CreateReleaseSettings() /// public string DeployTo { get; set; } + /// + /// Gets or sets multiple environments to automatically deploy to, e.g., Production, Staging, etc. + /// + public string[] DeployToMultiple { get; set; } + /// /// Gets or sets a value indicating whether progress of the deployment should be followed. (Sets --waitfordeployment and --norawlog to true.) /// @@ -157,5 +162,10 @@ public CreateReleaseSettings() /// Gets or sets a value indicating whether progress of the deployment will be shown. /// public bool DeploymentProgress { get; set; } + + /// + /// Gets or sets the comma-separated list of machine names to exclude in the deployed environment.If not specified all machines in the environment will be considered. + /// + public string ExcludeMachines { get; set; } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/OctopusDeploy/DeployReleaseArgumentBuilder.cs b/src/Cake.Common/Tools/OctopusDeploy/DeployReleaseArgumentBuilder.cs index 604591103e..e8ce13b21a 100644 --- a/src/Cake.Common/Tools/OctopusDeploy/DeployReleaseArgumentBuilder.cs +++ b/src/Cake.Common/Tools/OctopusDeploy/DeployReleaseArgumentBuilder.cs @@ -14,11 +14,11 @@ internal sealed class DeployReleaseArgumentBuilder : OctopusDeployArgumentBuilde private readonly ICakeEnvironment _environment; private readonly string _projectName; - private readonly string _deployTo; + private readonly string[] _deployTo; private readonly string _releaseNumber; private readonly OctopusDeployReleaseDeploymentSettings _settings; - public DeployReleaseArgumentBuilder(string server, string apiKey, string projectName, string deployTo, string releaseNumber, OctopusDeployReleaseDeploymentSettings settings, ICakeEnvironment environment) + public DeployReleaseArgumentBuilder(string server, string apiKey, string projectName, string[] deployTo, string releaseNumber, OctopusDeployReleaseDeploymentSettings settings, ICakeEnvironment environment) : base(server, apiKey, environment, settings) { _projectName = projectName; @@ -34,9 +34,13 @@ public ProcessArgumentBuilder Get() Builder.Append("deploy-release"); Builder.AppendSwitchQuoted("--project", "=", _projectName); - Builder.AppendSwitchQuoted("--deployto", "=", _deployTo); Builder.AppendSwitchQuoted("--releasenumber", "=", _releaseNumber); + foreach (var environment in _deployTo) + { + Builder.AppendSwitchQuoted("--deployto", "=", environment); + } + AppendCommonArguments(); AppendDeploymentParameters(); @@ -100,6 +104,8 @@ private void AppendDeploymentParameters() AppendMultipleTimes("tenanttag", _settings.TenantTags); AppendArgumentIfNotNull("channel", _settings.Channel); + + AppendArgumentIfNotNull("excludemachines", _settings.ExcludeMachines); } } } diff --git a/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployAliases.cs b/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployAliases.cs index f44aacfbe6..7fc8d59a29 100644 --- a/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployAliases.cs +++ b/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployAliases.cs @@ -194,6 +194,49 @@ public static void OctoPack(this ICakeContext context, string id, OctopusPackSet /// [CakeMethodAlias] public static void OctoDeployRelease(this ICakeContext context, string server, string apiKey, string projectName, string deployTo, string releaseNumber, OctopusDeployReleaseDeploymentSettings settings) + { + OctoDeployRelease(context, server, apiKey, projectName, new string[] { deployTo }, releaseNumber, settings); + } + + /// + /// Deploys the specified already existing release into a specified environment + /// See Octopus Documentation for more details. + /// + /// The cake context. + /// The Octopus server URL. + /// The user's API key. + /// Name of the target project. + /// Multiple target environment names. + /// Version number of the release to deploy. Specify "latest" for the latest release. + /// Deployment settings. + /// + /// + /// // bare minimum + /// OctoDeployRelease("http://octopus-deploy.example", "API-XXXXXXXXXXXXXXXXXXXX", "MyGreatProject", "Testing", "2.1.15-RC" new OctopusDeployReleaseDeploymentSettings()); + /// + /// // All of deployment arguments + /// OctoDeployRelease("http://octopus-deploy.example", "API-XXXXXXXXXXXXXXXXXXXX", "MyGreatProject", new string[] {"Testing", "Testing2"}, "2.1.15-RC" new OctopusDeployReleaseDeploymentSettings { + /// ShowProgress = true, + /// ForcePackageDownload = true, + /// WaitForDeployment = true, + /// DeploymentTimeout = TimeSpan.FromMinutes(1), + /// CancelOnTimeout = true, + /// DeploymentChecksLeapCycle = TimeSpan.FromMinutes(77), + /// GuidedFailure = true, + /// SpecificMachines = new string[] { "Machine1", "Machine2" }, + /// Force = true, + /// SkipSteps = new[] { "Step1", "Step2" }, + /// NoRawLog = true, + /// RawLogFile = "someFile.txt", + /// DeployAt = new DateTime(2010, 6, 15).AddMinutes(1), + /// Tenant = new[] { "Tenant1", "Tenant2" }, + /// TenantTags = new[] { "Tag1", "Tag2" }, + /// + /// }); + /// + /// + [CakeMethodAlias] + public static void OctoDeployRelease(this ICakeContext context, string server, string apiKey, string projectName, string[] deployToMultiple, string releaseNumber, OctopusDeployReleaseDeploymentSettings settings) { if (context == null) { @@ -201,7 +244,7 @@ public static void OctoDeployRelease(this ICakeContext context, string server, s } var releaseDeployer = new OctopusDeployReleaseDeployer(context.FileSystem, context.Environment, context.ProcessRunner, context.Tools); - releaseDeployer.DeployRelease(server, apiKey, projectName, deployTo, releaseNumber, settings); + releaseDeployer.DeployRelease(server, apiKey, projectName, deployToMultiple, releaseNumber, settings); } /// diff --git a/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployReleaseDeployer.cs b/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployReleaseDeployer.cs index 98ce4f0ad6..6f771b92d3 100644 --- a/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployReleaseDeployer.cs +++ b/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployReleaseDeployer.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Linq; using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -39,7 +40,7 @@ public OctopusDeployReleaseDeployer( /// Environment to deploy to, e.g., Production. /// Release number to be deployed to. /// Settings for the deployment. - public void DeployRelease(string server, string apiKey, string projectName, string deployTo, string releaseNumber, OctopusDeployReleaseDeploymentSettings settings) + public void DeployRelease(string server, string apiKey, string projectName, string[] deployTo, string releaseNumber, OctopusDeployReleaseDeploymentSettings settings) { if (String.IsNullOrEmpty(server)) { @@ -56,7 +57,7 @@ public void DeployRelease(string server, string apiKey, string projectName, stri throw new ArgumentNullException(nameof(projectName)); } - if (String.IsNullOrEmpty(deployTo)) + if (deployTo == null || deployTo.Length == 0 || deployTo.Any(environment => string.IsNullOrEmpty(environment))) { throw new ArgumentNullException(nameof(deployTo)); } diff --git a/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployReleaseDeploymentSettings.cs b/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployReleaseDeploymentSettings.cs index b6bce0bfb2..a8e0f7b504 100644 --- a/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployReleaseDeploymentSettings.cs +++ b/src/Cake.Common/Tools/OctopusDeploy/OctopusDeployReleaseDeploymentSettings.cs @@ -106,5 +106,10 @@ public OctopusDeployReleaseDeploymentSettings() /// Gets or sets the channel to use when getting the release to deploy. /// public string Channel { get; set; } + + /// + /// Gets or sets the comma-separated list of machine names to exclude in the deployed environment.If not specified all machines in the environment will be considered. + /// + public string ExcludeMachines { get; set; } } } diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverContext.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverContext.cs index 3f881730d4..980ee6a749 100644 --- a/src/Cake.Common/Tools/OpenCover/OpenCoverContext.cs +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverContext.cs @@ -10,38 +10,20 @@ namespace Cake.Common.Tools.OpenCover { - internal sealed class OpenCoverContext : ICakeContext + internal sealed class OpenCoverContext : CakeContextAdapter { - private readonly ICakeContext _context; private readonly OpenCoverProcessRunner _runner; - public IFileSystem FileSystem => _context.FileSystem; + public override ICakeLog Log { get; } - public ICakeEnvironment Environment => _context.Environment; - - public IGlobber Globber => _context.Globber; - - public ICakeLog Log { get; } - - public ICakeArguments Arguments => _context.Arguments; - - public IProcessRunner ProcessRunner => _runner; - - public IRegistry Registry => _context.Registry; - - public IToolLocator Tools => _context.Tools; - - public ICakeDataResolver Data => _context.Data; + public override IProcessRunner ProcessRunner => _runner; public FilePath FilePath => _runner.FilePath; public ProcessSettings Settings => _runner.ProcessSettings; - public ICakeConfiguration Configuration => _context.Configuration; - - public OpenCoverContext(ICakeContext context) + public OpenCoverContext(ICakeContext context) : base(context) { - _context = context; Log = new NullLog(); _runner = new OpenCoverProcessRunner(); } diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverHideSkippedOption.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverHideSkippedOption.cs new file mode 100644 index 0000000000..c41d753cb6 --- /dev/null +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverHideSkippedOption.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Cake.Common.Tools.OpenCover +{ + using System; + + /// + /// Represents the hide skipped option for OpenCover. + /// + [Flags] + public enum OpenCoverHideSkippedOption + { + /// + /// Removes no information from output file. + /// + None = 0, + + /// + /// Removes information from output files that relates to classes/modules that have been skipped (filtered) due to use of the -excludebyfile -switch. + /// + File = 1, + + /// + /// Removes information from output files that relates to classes/modules that have been skipped (filtered) due to use of the -filter -switch. + /// + Filter = 2, + + /// + /// Removes information from output files that relates to classes/modules that have been skipped (filtered) due to use of the -excludebyattribute -switch. + /// + Attribute = 4, + + /// + /// Removes missing Pdb information from output file. + /// + MissingPdb = 8, + + /// + /// Removes all information from output file. + /// + All = File | Filter | Attribute | MissingPdb + } +} diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverHideSkippedOptionExtensions.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverHideSkippedOptionExtensions.cs new file mode 100644 index 0000000000..f0cb016a1f --- /dev/null +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverHideSkippedOptionExtensions.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Cake.Common.Tools.OpenCover +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + + /// + /// Extensions class for . + /// + public static class OpenCoverHideSkippedOptionExtensions + { + /// + /// Get flags. + /// + /// + /// The input. + /// + /// + /// The . + /// + public static IEnumerable GetFlags(this OpenCoverHideSkippedOption openCoverHideSkippedOption) + { + foreach (OpenCoverHideSkippedOption value in Enum.GetValues(openCoverHideSkippedOption.GetType())) + { + if (openCoverHideSkippedOption.HasFlag(value)) + { + yield return value; + } + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverRegisterOption.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverRegisterOption.cs new file mode 100644 index 0000000000..2de5c92942 --- /dev/null +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverRegisterOption.cs @@ -0,0 +1,145 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +using Cake.Core.IO; + +namespace Cake.Common.Tools.OpenCover +{ + /// + /// Represents the register-options: + /// + /// + /// empty + /// Registers and de-register the code coverage profiler. (Administrative permissions to the registry are required.) + /// + /// + /// "user" + /// Does per-user registration where the user account does not have administrative permissions. + /// + /// + /// path + /// If you do not want to use the registry entries, use -register:path to select the profiler. + /// + /// + /// + public abstract class OpenCoverRegisterOption + { + private readonly string commandLineValue; + + /// + /// Initializes a new instance of the class. + /// + /// The value, as required for the commandline. + /// + /// Note that no value (null or string.Empty) is valid. + /// However, if a value exists it NEEDS to start with a colon (":"). + /// + protected OpenCoverRegisterOption(string commandLineValue) + { + if (string.IsNullOrEmpty(commandLineValue)) + { + commandLineValue = string.Empty; + } + + if (!string.IsNullOrEmpty(commandLineValue)) + { + if (!commandLineValue.StartsWith(":", StringComparison.Ordinal)) + { + throw new ArgumentException(nameof(commandLineValue), "if a non-empty value is given, it needs to start with ':'"); + } + } + + this.commandLineValue = commandLineValue; + } + + /// + /// Converts to string. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return commandLineValue; + } + + /// + /// Performs an implicit conversion from to . + /// (Since the switch from pure string to is a breaking change.) + /// + /// The option. + /// + /// The result of the conversion. + /// + [Obsolete("use new OpenCoverRegisterOption() instead.")] + public static implicit operator OpenCoverRegisterOption(string option) + { + if (string.IsNullOrEmpty(option)) + { + return new OpenCoverRegisterOptionAdmin(); + } + + if (option.Equals("user", StringComparison.InvariantCultureIgnoreCase)) + { + return new OpenCoverRegisterOptionUser(); + } + + return new OpenCoverRegisterOptionDll(new FilePath(option)); + } + } + + /// + /// Gets the register-option representing the "user"-mode. + /// (This will translate to "-register:user".) + /// + /// + public class OpenCoverRegisterOptionUser + : OpenCoverRegisterOption + { + /// + /// Initializes a new instance of the class. + /// + public OpenCoverRegisterOptionUser() + : base(":user") + { + } + } + + /// + /// Gets the register-option representing the "admin"-mode. + /// (This will translate to "-register".) + /// + /// + public class OpenCoverRegisterOptionAdmin + : OpenCoverRegisterOption + { + /// + /// Initializes a new instance of the class. + /// + public OpenCoverRegisterOptionAdmin() + : base(string.Empty) + { + } + } + + /// + /// Gets a register-option pointing to a dll. + /// (This will translate to "-register:[path-to-dll]".) + /// + /// + public class OpenCoverRegisterOptionDll + : OpenCoverRegisterOption + { + /// + /// Initializes a new instance of the class. + /// + /// Path to the dll. + public OpenCoverRegisterOptionDll(FilePath pathToDll) + : base($":{pathToDll.FullPath}") + { + } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverRunner.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverRunner.cs index b80b7f42b2..b65d150290 100644 --- a/src/Cake.Common/Tools/OpenCover/OpenCoverRunner.cs +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverRunner.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; + using Cake.Core; using Cake.Core.IO; using Cake.Core.Tooling; @@ -16,6 +17,7 @@ namespace Cake.Common.Tools.OpenCover /// public sealed class OpenCoverRunner : Tool { + private const string HideSkippedConstant = "-hideskipped"; private readonly ICakeEnvironment _environment; /// @@ -141,7 +143,12 @@ private ProcessArgumentBuilder GetArguments( builder.Append("-mergeoutput"); } - builder.AppendSwitch("-register", ":", settings.Register); + if (settings.Register != null) + { + // due to the fact that register sometimes needs a colon-separator and sometimes it does not + // there is no separator here but instead it's added in OpenCoverRegisterOption.ToString() + builder.AppendSwitch("-register", string.Empty, settings.Register.ToString()); + } if (settings.ReturnTargetCodeOffset != null) { @@ -165,6 +172,20 @@ private ProcessArgumentBuilder GetArguments( builder.AppendSwitch("-log", ":", settings.LogLevel.ToString()); } + // HideSkipped Option + if (settings.HideSkippedOption != OpenCoverHideSkippedOption.None) + { + if (settings.HideSkippedOption == OpenCoverHideSkippedOption.All) + { + builder.AppendSwitch(HideSkippedConstant, ":", "All"); + } + else + { + var hideSkippedOptions = string.Join(";", settings.HideSkippedOption.GetFlags()); + builder.AppendSwitch(HideSkippedConstant, ":", hideSkippedOptions); + } + } + // Merge by hash if (settings.MergeByHash) { diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverSettings.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverSettings.cs index 0dc7606d34..38ea7e3cc4 100644 --- a/src/Cake.Common/Tools/OpenCover/OpenCoverSettings.cs +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverSettings.cs @@ -49,7 +49,7 @@ public sealed class OpenCoverSettings : ToolSettings /// /// Gets or sets the register option. /// - public string Register { get; set; } + public OpenCoverRegisterOption Register { get; set; } /// /// Gets or sets the Return target code offset to be used. @@ -76,6 +76,11 @@ public sealed class OpenCoverSettings : ToolSettings /// public OpenCoverLogLevel LogLevel { get; set; } + /// + /// Gets or sets the hide skipped option of OpenCover. + /// + public OpenCoverHideSkippedOption HideSkippedOption { get; set; } + /// /// Gets or sets a value indicating whether to merge the coverage results for an assembly /// regardless of where it was loaded assuming it has the same file-hash in each location. @@ -113,8 +118,9 @@ public OpenCoverSettings() _filters = new HashSet(StringComparer.OrdinalIgnoreCase); _excludedAttributeFilters = new HashSet(StringComparer.OrdinalIgnoreCase); _excludedFileFilters = new HashSet(StringComparer.Ordinal); - Register = "user"; + Register = new OpenCoverRegisterOptionUser(); LogLevel = OpenCoverLogLevel.Info; + HideSkippedOption = OpenCoverHideSkippedOption.None; _excludeDirectories = new HashSet(); _searchDirectories = new HashSet(); } diff --git a/src/Cake.Common/Tools/OpenCover/OpenCoverSettingsExtensions.cs b/src/Cake.Common/Tools/OpenCover/OpenCoverSettingsExtensions.cs index 14e526c769..348d5aeb2b 100644 --- a/src/Cake.Common/Tools/OpenCover/OpenCoverSettingsExtensions.cs +++ b/src/Cake.Common/Tools/OpenCover/OpenCoverSettingsExtensions.cs @@ -4,6 +4,8 @@ using System; +using Cake.Core.IO; + namespace Cake.Common.Tools.OpenCover { /// @@ -59,5 +61,66 @@ public static OpenCoverSettings ExcludeByFile(this OpenCoverSettings settings, s settings.ExcludedFileFilters.Add(filter); return settings; } + + /// + /// Sets the register-option to "none". + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static OpenCoverSettings WithoutRegister(this OpenCoverSettings settings) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + settings.Register = null; + return settings; + } + + /// + /// Sets the register-option to admin-registry-access. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static OpenCoverSettings WithRegisterAdmin(this OpenCoverSettings settings) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + settings.Register = new OpenCoverRegisterOptionAdmin(); + return settings; + } + + /// + /// Sets the register-option to user-registry-access. + /// + /// The settings. + /// The same instance so that multiple calls can be chained. + public static OpenCoverSettings WithRegisterUser(this OpenCoverSettings settings) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + settings.Register = new OpenCoverRegisterOptionUser(); + return settings; + } + + /// + /// Sets the register-option to dll-registration (i.e no registry-access). + /// + /// The settings. + /// The path. + /// The same instance so that multiple calls can be chained. + public static OpenCoverSettings WithRegisterDll(this OpenCoverSettings settings, FilePath path) + { + if (settings == null) + { + throw new ArgumentNullException(nameof(settings)); + } + settings.Register = new OpenCoverRegisterOptionDll(path); + return settings; + } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorAliases.cs b/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorAliases.cs index 6160afb301..0f41f9b60b 100644 --- a/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorAliases.cs +++ b/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorAliases.cs @@ -35,7 +35,7 @@ public static class ReportGeneratorAliases /// /// [CakeMethodAlias] - public static void ReportGenerator(this ICakeContext context, string pattern, DirectoryPath targetDir) + public static void ReportGenerator(this ICakeContext context, GlobPattern pattern, DirectoryPath targetDir) { if (context == null) { @@ -60,7 +60,7 @@ public static void ReportGenerator(this ICakeContext context, string pattern, Di /// /// [CakeMethodAlias] - public static void ReportGenerator(this ICakeContext context, string pattern, DirectoryPath targetDir, ReportGeneratorSettings settings) + public static void ReportGenerator(this ICakeContext context, GlobPattern pattern, DirectoryPath targetDir, ReportGeneratorSettings settings) { if (context == null) { diff --git a/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorReportType.cs b/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorReportType.cs index 64f759009b..c809501153 100644 --- a/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorReportType.cs +++ b/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorReportType.cs @@ -98,6 +98,38 @@ public enum ReportGeneratorReportType /// /// Requires ReportGenerator 4.0.10+ /// - HtmlInline_AzurePipelines_Dark = 17 + HtmlInline_AzurePipelines_Dark = 17, + + /// + /// Creates xml report in Clover format. + /// + /// + /// Requires ReportGenerator 4.0.6+ + /// + Clover = 18, + + /// + /// Creates summary report in JSON format. + /// + /// + /// Requires ReportGenerator 4.5.2+ + /// + JsonSummary = 19, + + /// + /// Creates summary report in lcov format. + /// + /// + /// Requires ReportGenerator 4.3.0+ + /// + lcov = 20, + + /// + /// Outputs summary report as TeamCity statistics messages. + /// + /// + /// Requires ReportGenerator 4.1.3+ + /// + TeamCitySummary = 21 } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorRunner.cs b/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorRunner.cs index 83a99ed156..501b6dc4f7 100644 --- a/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorRunner.cs +++ b/src/Cake.Common/Tools/ReportGenerator/ReportGeneratorRunner.cs @@ -126,7 +126,7 @@ protected override string GetToolName() /// The tool executable name. protected override IEnumerable GetToolExecutableNames() { - return new[] { "ReportGenerator.exe" }; + return new[] { "reportgenerator", "ReportGenerator.exe" }; } private void AppendQuoted(ProcessArgumentBuilder builder, string key, string value) diff --git a/src/Cake.Common/Tools/SignTool/SignToolResolver.cs b/src/Cake.Common/Tools/SignTool/SignToolResolver.cs index c8d862f9a7..63b2e06844 100644 --- a/src/Cake.Common/Tools/SignTool/SignToolResolver.cs +++ b/src/Cake.Common/Tools/SignTool/SignToolResolver.cs @@ -37,6 +37,7 @@ public SignToolResolver(IFileSystem fileSystem, ICakeEnvironment environment, IR } } + /// public FilePath GetPath() { if (_signToolPath != null) diff --git a/src/Cake.Common/Tools/SpecFlow/SpecFlowContext.cs b/src/Cake.Common/Tools/SpecFlow/SpecFlowContext.cs index f136c378dc..c77e4467d6 100644 --- a/src/Cake.Common/Tools/SpecFlow/SpecFlowContext.cs +++ b/src/Cake.Common/Tools/SpecFlow/SpecFlowContext.cs @@ -10,38 +10,20 @@ namespace Cake.Common.Tools.SpecFlow { - internal sealed class SpecFlowContext : ICakeContext + internal sealed class SpecFlowContext : CakeContextAdapter { - private readonly ICakeContext _context; private readonly SpecFlowProcessRunner _runner; - public IFileSystem FileSystem => _context.FileSystem; + public override ICakeLog Log { get; } - public ICakeEnvironment Environment => _context.Environment; - - public IGlobber Globber => _context.Globber; - - public ICakeLog Log { get; } - - public ICakeArguments Arguments => _context.Arguments; - - public IProcessRunner ProcessRunner => _runner; - - public IRegistry Registry => _context.Registry; - - public IToolLocator Tools => _context.Tools; - - public ICakeDataResolver Data => _context.Data; + public override IProcessRunner ProcessRunner => _runner; public FilePath FilePath => _runner.FilePath; public ProcessSettings Settings => _runner.ProcessSettings; - public ICakeConfiguration Configuration => _context.Configuration; - - public SpecFlowContext(ICakeContext context) + public SpecFlowContext(ICakeContext context) : base(context) { - _context = context; Log = new NullLog(); _runner = new SpecFlowProcessRunner(); } diff --git a/src/Cake.Common/Tools/VSTest/VSTestAliases.cs b/src/Cake.Common/Tools/VSTest/VSTestAliases.cs index ea240e0125..adf46b2e28 100644 --- a/src/Cake.Common/Tools/VSTest/VSTestAliases.cs +++ b/src/Cake.Common/Tools/VSTest/VSTestAliases.cs @@ -29,7 +29,7 @@ public static class VSTestAliases /// The context. /// The pattern. [CakeMethodAlias] - public static void VSTest(this ICakeContext context, string pattern) + public static void VSTest(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -51,14 +51,14 @@ public static void VSTest(this ICakeContext context, string pattern) /// /// /// - /// VSTest("./Tests/*.UnitTests.dll", new VSTestSettings() { Logger = VSTestLogger.Trx }); + /// VSTest("./Tests/*.UnitTests.dll", new VSTestSettings() { Logger = "trx" }); /// /// /// The context. /// The pattern. /// The settings. [CakeMethodAlias] - public static void VSTest(this ICakeContext context, string pattern, VSTestSettings settings) + public static void VSTest(this ICakeContext context, GlobPattern pattern, VSTestSettings settings) { if (context == null) { @@ -120,4 +120,4 @@ public static void VSTest(this ICakeContext context, IEnumerable assem runner.Run(assemblyPaths, settings); } } -} \ No newline at end of file +} diff --git a/src/Cake.Common/Tools/VSTest/VSTestRunner.cs b/src/Cake.Common/Tools/VSTest/VSTestRunner.cs index e3c73faf87..86b99f7b7c 100644 --- a/src/Cake.Common/Tools/VSTest/VSTestRunner.cs +++ b/src/Cake.Common/Tools/VSTest/VSTestRunner.cs @@ -117,6 +117,11 @@ private ProcessArgumentBuilder GetArguments(IEnumerable assemblyPaths, builder.AppendSwitchQuoted("/Diag", ":", settings.Diag.MakeAbsolute(_environment).FullPath); } + if (settings.ResultsDirectory != null) + { + builder.AppendSwitchQuoted("/ResultsDirectory", ":", settings.ResultsDirectory.MakeAbsolute(_environment).FullPath); + } + if (!string.IsNullOrEmpty(settings.Logger)) { builder.Append("/Logger:{0}", settings.Logger.Trim()); @@ -147,37 +152,29 @@ protected override string GetToolName() /// The default tool path. protected override IEnumerable GetAlternativeToolPaths(VSTestSettings settings) { - foreach (var yearAndEdition in new[] { "2019/Enterprise", "2019/Professional", "2019/Community", "2017/Enterprise", "2017/Professional", "2017/Community" }) + var vsRootRelativeToolPath = FilePath.FromString($"Common7/IDE/CommonExtensions/Microsoft/TestWindow/{VSTestConsoleExecutableName}"); + foreach (var year in VisualStudio.Versions.TwentySeventeenAndLater) { - var path = GetYearAndEditionToolPath(yearAndEdition); - if (_fileSystem.Exist(path)) + foreach (var edition in settings.AllowPreviewVersion + ? VisualStudio.Editions.All + : VisualStudio.Editions.Stable) { - yield return path; + var path = VisualStudio.GetYearAndEditionToolPath(_environment, year, edition, vsRootRelativeToolPath); + if (_fileSystem.Exist(path)) + { + yield return path; + } } } - foreach (var version in new[] { "15.0", "14.0", "12.0", "11.0" }) + foreach (var version in VisualStudio.Versions.TenToFourteen) { - var path = GetVersionNumberToolPath(version); + var path = VisualStudio.GetVersionNumberToolPath(_environment, version, vsRootRelativeToolPath); if (_fileSystem.Exist(path)) { yield return path; } } } - - private FilePath GetYearAndEditionToolPath(string yearAndEdition) - { - var programFiles = _environment.GetSpecialPath(SpecialPath.ProgramFilesX86); - var root = programFiles.Combine(string.Concat("Microsoft Visual Studio/", yearAndEdition, "/Common7/IDE/CommonExtensions/Microsoft/TestWindow")); - return root.CombineWithFilePath(VSTestConsoleExecutableName); - } - - private FilePath GetVersionNumberToolPath(string version) - { - var programFiles = _environment.GetSpecialPath(SpecialPath.ProgramFilesX86); - var root = programFiles.Combine(string.Concat("Microsoft Visual Studio ", version, "/Common7/IDE/CommonExtensions/Microsoft/TestWindow")); - return root.CombineWithFilePath(VSTestConsoleExecutableName); - } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/VSTest/VSTestSettings.cs b/src/Cake.Common/Tools/VSTest/VSTestSettings.cs index ee6720fe09..e15a3f45bd 100644 --- a/src/Cake.Common/Tools/VSTest/VSTestSettings.cs +++ b/src/Cake.Common/Tools/VSTest/VSTestSettings.cs @@ -73,6 +73,13 @@ public sealed class VSTestSettings : ToolSettings /// public FilePath Diag { get; set; } + /// + /// Gets or sets the result directory. + /// Test results directory will be created in specified path if not exists. + /// VSTest.Console.exe flag /ResultsDirectory. + /// + public DirectoryPath ResultsDirectory { get; set; } + /// /// Gets or sets the name of your logger. Possible values: /// - A blank string (or null): no logger @@ -81,5 +88,14 @@ public sealed class VSTestSettings : ToolSettings /// - any custom value: the name of your custom logger. /// public string Logger { get; set; } + + /// + /// Gets or sets a value indicating whether tools from a preview edition of Visual Studio should be used. + /// + /// If set to true, VSTest from a Preview edition + /// (e.g. Visual Studio 2022 Preview) will be considered to be used. + /// + /// + public bool AllowPreviewVersion { get; set; } = false; } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/VisualStudio.cs b/src/Cake.Common/Tools/VisualStudio.cs new file mode 100644 index 0000000000..63fa20129b --- /dev/null +++ b/src/Cake.Common/Tools/VisualStudio.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using System.Linq; +using Cake.Core; +using Cake.Core.IO; + +namespace Cake.Common.Tools +{ + internal static class VisualStudio + { + internal static class Versions + { + internal static ICollection TenToFourteen { get; } = new[] { "14.0", "12.0", "11.0", "10.0" }; + + internal static ICollection TwentySeventeenAndLater { get; } = new[] + { + "2022", + "2019", + "2017" + }; + } + + internal static class Editions + { + internal static ICollection Preview { get; } = new[] + { + "Preview" + }; + + internal static ICollection Stable { get; } = new[] + { + "Enterprise", + "Professional", + "Community", + "BuildTools" + }; + + internal static ICollection All { get; } = Preview + .Concat(Stable) + .ToArray(); + } + + internal static FilePath GetYearAndEditionToolPath(ICakeEnvironment environment, string year, string edition, FilePath relativeFile) + { + var root = GetYearAndEditionRootPath(environment, year, edition); + return root.CombineWithFilePath(relativeFile); + } + + internal static DirectoryPath GetYearAndEditionRootPath(ICakeEnvironment environment, string year, string edition) + { + var programFiles = (year, edition) switch + { + ("2022", "BuildTools") => environment.GetSpecialPath(SpecialPath.ProgramFilesX86), + ("2022", _) => environment.GetSpecialPath(SpecialPath.ProgramFiles), + (_, _) => environment.GetSpecialPath(SpecialPath.ProgramFilesX86), + }; + + return programFiles.Combine($"Microsoft Visual Studio/{year}/{edition}"); + } + + internal static FilePath GetVersionNumberToolPath(ICakeEnvironment environment, string version, FilePath relativeFile) + { + var root = GetVersionNumberRootPath(environment, version); + return root.CombineWithFilePath(relativeFile); + } + + internal static DirectoryPath GetVersionNumberRootPath(ICakeEnvironment environment, string version) + { + var programFiles = environment.GetSpecialPath(SpecialPath.ProgramFilesX86); + return programFiles.Combine($"Microsoft Visual Studio {version}"); + } + } +} \ No newline at end of file diff --git a/src/Cake.Common/Tools/WiX/WiXAliases.cs b/src/Cake.Common/Tools/WiX/WiXAliases.cs index 4b7ed0109c..9940f548b5 100644 --- a/src/Cake.Common/Tools/WiX/WiXAliases.cs +++ b/src/Cake.Common/Tools/WiX/WiXAliases.cs @@ -43,7 +43,7 @@ public static class WiXAliases /// The settings. [CakeMethodAlias] [CakeAliasCategory("Candle")] - public static void WiXCandle(this ICakeContext context, string pattern, CandleSettings settings = null) + public static void WiXCandle(this ICakeContext context, GlobPattern pattern, CandleSettings settings = null) { if (context == null) { @@ -105,7 +105,7 @@ public static void WiXCandle(this ICakeContext context, IEnumerable so /// The settings. [CakeMethodAlias] [CakeAliasCategory("Light")] - public static void WiXLight(this ICakeContext context, string pattern, LightSettings settings = null) + public static void WiXLight(this ICakeContext context, GlobPattern pattern, LightSettings settings = null) { if (context == null) { diff --git a/src/Cake.Common/Tools/XUnit/XUnit2Aliases.cs b/src/Cake.Common/Tools/XUnit/XUnit2Aliases.cs index ff4764c234..65c540939e 100644 --- a/src/Cake.Common/Tools/XUnit/XUnit2Aliases.cs +++ b/src/Cake.Common/Tools/XUnit/XUnit2Aliases.cs @@ -36,7 +36,7 @@ public static class XUnit2Aliases /// /// [CakeMethodAlias] - public static void XUnit2(this ICakeContext context, string pattern) + public static void XUnit2(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -71,7 +71,7 @@ public static void XUnit2(this ICakeContext context, string pattern) /// /// [CakeMethodAlias] - public static void XUnit2(this ICakeContext context, string pattern, XUnit2Settings settings) + public static void XUnit2(this ICakeContext context, GlobPattern pattern, XUnit2Settings settings) { if (context == null) { diff --git a/src/Cake.Common/Tools/XUnit/XUnitAliases.cs b/src/Cake.Common/Tools/XUnit/XUnitAliases.cs index ff992ced8e..64422b84cc 100644 --- a/src/Cake.Common/Tools/XUnit/XUnitAliases.cs +++ b/src/Cake.Common/Tools/XUnit/XUnitAliases.cs @@ -35,7 +35,7 @@ public static class XUnitAliases /// /// [CakeMethodAlias] - public static void XUnit(this ICakeContext context, string pattern) + public static void XUnit(this ICakeContext context, GlobPattern pattern) { if (context == null) { @@ -62,7 +62,7 @@ public static void XUnit(this ICakeContext context, string pattern) /// /// [CakeMethodAlias] - public static void XUnit(this ICakeContext context, string pattern, XUnitSettings settings) + public static void XUnit(this ICakeContext context, GlobPattern pattern, XUnitSettings settings) { if (context == null) { diff --git a/src/Cake.Common/Xml/XmlTransformation.cs b/src/Cake.Common/Xml/XmlTransformation.cs index eaeac17c4e..be2b69dc5e 100644 --- a/src/Cake.Common/Xml/XmlTransformation.cs +++ b/src/Cake.Common/Xml/XmlTransformation.cs @@ -6,14 +6,11 @@ using System.IO; using System.Text; using System.Xml; +using System.Xml.Xsl; using Cake.Common.Polyfill; using Cake.Core; using Cake.Core.IO; -#if !NETCORE - -#endif - namespace Cake.Common.Xml { /// @@ -43,7 +40,7 @@ public static string Transform(string xsl, string xml) /// /// XML style sheet. /// XML data. - /// Settings for result file xml transformation. + /// Settings for result file XML transformation. /// Transformed XML string. public static string Transform(string xsl, string xml, XmlTransformationSettings settings) { @@ -68,7 +65,7 @@ public static string Transform(string xsl, string xml, XmlTransformationSettings { using (var result = new MemoryStream()) { - Transform(xslReader, xmlReader, result, settings.XmlWriterSettings); + Transform(xslReader, settings.XsltArgumentList, xmlReader, result, settings.XmlWriterSettings); result.Position = 0; return settings.Encoding.GetString(result.ToArray()); } @@ -79,8 +76,8 @@ public static string Transform(string xsl, string xml, XmlTransformationSettings /// Performs XML XSL transformation. /// /// The file system. - /// Path to xml style sheet. - /// Path xml data. + /// Path to XML style sheet. + /// Path XML data. /// Transformation result path. public static void Transform(IFileSystem fileSystem, FilePath xslPath, FilePath xmlPath, FilePath resultPath) { @@ -92,10 +89,10 @@ public static void Transform(IFileSystem fileSystem, FilePath xslPath, FilePath /// Performs XML XSL transformation. /// /// The file system. - /// Path to xml style sheet. - /// Path xml data. + /// Path to XML style sheet. + /// Path XML data. /// Transformation result path. - /// Settings for result file xml transformation. + /// Settings for result file XML transformation. public static void Transform(IFileSystem fileSystem, FilePath xslPath, FilePath xmlPath, FilePath resultPath, XmlTransformationSettings settings) { if (fileSystem == null) @@ -130,12 +127,12 @@ public static void Transform(IFileSystem fileSystem, FilePath xslPath, FilePath if (!xslFile.Exists) { - throw new FileNotFoundException("Xsl File not found.", xslFile.Path.FullPath); + throw new FileNotFoundException("XSL file not found.", xslFile.Path.FullPath); } if (!xmlFile.Exists) { - throw new FileNotFoundException("XML File not found.", xmlFile.Path.FullPath); + throw new FileNotFoundException("XML file not found.", xmlFile.Path.FullPath); } if (!settings.Overwrite && resultFile.Exists) @@ -153,8 +150,7 @@ public static void Transform(IFileSystem fileSystem, FilePath xslPath, FilePath xmlReader = XmlReader.Create(xmlStream); var resultWriter = XmlWriter.Create(resultStream, settings.XmlWriterSettings); - - Transform(xslReader, xmlReader, resultWriter); + Transform(xslReader, settings.XsltArgumentList, xmlReader, resultWriter); } } @@ -162,10 +158,11 @@ public static void Transform(IFileSystem fileSystem, FilePath xslPath, FilePath /// Performs XML XSL transformation. /// /// XML style sheet. + /// XSLT argument list. /// XML data. /// Transformation result. - /// Optional settings for result file xml writer. - private static void Transform(TextReader xsl, TextReader xml, Stream result, XmlWriterSettings settings = null) + /// Optional settings for result file XML writer. + private static void Transform(TextReader xsl, XsltArgumentList arguments, TextReader xml, Stream result, XmlWriterSettings settings = null) { if (xsl == null) { @@ -190,16 +187,17 @@ private static void Transform(TextReader xsl, TextReader xml, Stream result, Xml var xslXmlReader = XmlReader.Create(xsl); var xmlXmlReader = XmlReader.Create(xml); var resultXmlTextWriter = XmlWriter.Create(result, settings); - Transform(xslXmlReader, xmlXmlReader, resultXmlTextWriter); + Transform(xslXmlReader, arguments, xmlXmlReader, resultXmlTextWriter); } /// /// Performs XML XSL transformation. /// /// XML style sheet. + /// XSLT argument list. /// XML data. /// Transformation result. - private static void Transform(XmlReader xsl, XmlReader xml, XmlWriter result) + private static void Transform(XmlReader xsl, XsltArgumentList arguments, XmlReader xml, XmlWriter result) { if (xsl == null) { @@ -216,7 +214,7 @@ private static void Transform(XmlReader xsl, XmlReader xml, XmlWriter result) throw new ArgumentNullException(nameof(result), "Null result supplied."); } - XmlTransformationHelper.Transform(xsl, xml, result); + XmlTransformationHelper.Transform(xsl, arguments, xml, result); } } } \ No newline at end of file diff --git a/src/Cake.Common/Xml/XmlTransformationSettings.cs b/src/Cake.Common/Xml/XmlTransformationSettings.cs index fe1f91d0b4..aa5542d1c7 100644 --- a/src/Cake.Common/Xml/XmlTransformationSettings.cs +++ b/src/Cake.Common/Xml/XmlTransformationSettings.cs @@ -4,6 +4,7 @@ using System.Text; using System.Xml; +using System.Xml.Xsl; using Cake.Common.Polyfill; namespace Cake.Common.Xml @@ -128,6 +129,11 @@ public bool WriteEndDocumentOnClose set { XmlWriterSettings.WriteEndDocumentOnClose = value; } } + /// + /// Gets or sets an argument list for XSL transformation. + /// + public XsltArgumentList XsltArgumentList { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/src/Cake.Core.Tests/Cake.Core.Tests.csproj b/src/Cake.Core.Tests/Cake.Core.Tests.csproj index f711e4f266..2fa6fef4ba 100644 --- a/src/Cake.Core.Tests/Cake.Core.Tests.csproj +++ b/src/Cake.Core.Tests/Cake.Core.Tests.csproj @@ -1,7 +1,6 @@  Cake.Core.Tests - net461;netcoreapp2.1;netcoreapp3.1 true true @@ -15,12 +14,14 @@ - + - - + + all + runtime; build; native; contentfiles; analyzers + + - diff --git a/src/Cake.Core.Tests/Exceptions/CustomeExitCodeTests.cs b/src/Cake.Core.Tests/Exceptions/CustomeExitCodeTests.cs new file mode 100644 index 0000000000..38b37db0e7 --- /dev/null +++ b/src/Cake.Core.Tests/Exceptions/CustomeExitCodeTests.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Cake.Core.Tests.Exceptions +{ + public class CustomeExitCodeTests + { + [Fact] + public void Should_Return_Default_ExitCode() + { + var exception = new CakeException(); + Assert.Equal(1, exception.ExitCode); + } + + [Fact] + public void Should_Return_Custom_ExitCode() + { + var exception = new CakeException(5); + Assert.Equal(5, exception.ExitCode); + } + } +} diff --git a/src/Cake.Core.Tests/Fixtures/NotFormattableFixture.cs b/src/Cake.Core.Tests/Fixtures/NotFormattableFixture.cs new file mode 100644 index 0000000000..aaa5c1e977 --- /dev/null +++ b/src/Cake.Core.Tests/Fixtures/NotFormattableFixture.cs @@ -0,0 +1,6 @@ +namespace Cake.Core.Tests.Fixtures +{ + internal sealed class NotFormattableFixture + { + } +} diff --git a/src/Cake.Core.Tests/Fixtures/ScriptAnalyzerFixture.cs b/src/Cake.Core.Tests/Fixtures/ScriptAnalyzerFixture.cs index 95c70ed138..7d7c5f4f3e 100644 --- a/src/Cake.Core.Tests/Fixtures/ScriptAnalyzerFixture.cs +++ b/src/Cake.Core.Tests/Fixtures/ScriptAnalyzerFixture.cs @@ -43,7 +43,7 @@ public ScriptAnalyzer CreateAnalyzer() public ScriptAnalyzerResult Analyze(FilePath script) { - return CreateAnalyzer().Analyze(script); + return CreateAnalyzer().Analyze(script, new ScriptAnalyzerSettings()); } public void GivenScriptExist(FilePath path, string content) diff --git a/src/Cake.Core.Tests/Fixtures/ScriptRunnerFixture.cs b/src/Cake.Core.Tests/Fixtures/ScriptRunnerFixture.cs index c82a17019f..c59f1518df 100644 --- a/src/Cake.Core.Tests/Fixtures/ScriptRunnerFixture.cs +++ b/src/Cake.Core.Tests/Fixtures/ScriptRunnerFixture.cs @@ -58,9 +58,11 @@ public ScriptRunnerFixture(string fileName = "/Working/build.cake") Engine.CreateSession(Arg.Any()).Returns(Session); var runtime = new CakeRuntime(); + var referenceAssemblyResolver = Substitute.For(); + referenceAssemblyResolver.GetReferenceAssemblies().Returns(Array.Empty()); ScriptAnalyzer = new ScriptAnalyzer(FileSystem, Environment, Log, new[] { new FileLoadDirectiveProvider(Globber, Log) }); ScriptProcessor = Substitute.For(); - ScriptConventions = new ScriptConventions(FileSystem, AssemblyLoader, runtime); + ScriptConventions = new ScriptConventions(FileSystem, AssemblyLoader, runtime, referenceAssemblyResolver); var context = Substitute.For(); context.Environment.Returns(c => Environment); diff --git a/src/Cake.Core.Tests/Fixtures/ToolResolutionStrategyFixture.cs b/src/Cake.Core.Tests/Fixtures/ToolResolutionStrategyFixture.cs index 49fecc7c0b..c9dbb34326 100644 --- a/src/Cake.Core.Tests/Fixtures/ToolResolutionStrategyFixture.cs +++ b/src/Cake.Core.Tests/Fixtures/ToolResolutionStrategyFixture.cs @@ -18,9 +18,9 @@ internal sealed class ToolResolutionStrategyFixture public FakeConfiguration Configuration { get; set; } public IToolRepository Repository { get; set; } - public ToolResolutionStrategyFixture() + public ToolResolutionStrategyFixture(FakeEnvironment environment = null) { - Environment = FakeEnvironment.CreateUnixEnvironment(); + Environment = environment ?? FakeEnvironment.CreateUnixEnvironment(); FileSystem = new FakeFileSystem(Environment); Globber = new Globber(FileSystem, Environment); Configuration = new FakeConfiguration(); diff --git a/src/Cake.Core.Tests/Unit/CakeArgumentsTests.cs b/src/Cake.Core.Tests/Unit/CakeArgumentsTests.cs new file mode 100644 index 0000000000..a21ce52fea --- /dev/null +++ b/src/Cake.Core.Tests/Unit/CakeArgumentsTests.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Cake.Core.Tests.Unit +{ + public sealed class CakeArgumentsTests + { + [Fact] + public void Should_Return_Null_If_Argument_Is_Missing() + { + // Given + var arguments = new CakeArguments(new List> + { + Tuple.Create("FOO", "BAR"), + Tuple.Create("BAZ", "CORGI"), + }.ToLookup(x => x.Item1, x => x.Item2)); + + // When + var result = arguments.GetArgument("WALDO"); + + // Then + Assert.Null(result); + } + + [Fact] + public void Should_Return_Argument_If_One_With_The_Specified_Name_Exist() + { + // Given + var arguments = new CakeArguments(new List> + { + Tuple.Create("FOO", "BAR"), + Tuple.Create("BAZ", "CORGI"), + }.ToLookup(x => x.Item1, x => x.Item2)); + + // When + var result = arguments.GetArgument("BAZ"); + + // Then + Assert.Equal("CORGI", result); + } + + [Fact] + public void Should_Return_The_Last_Argument_If_Multiple_Ones_With_The_Same_Name_Exist() + { + // Given + var arguments = new CakeArguments(new List> + { + Tuple.Create("FOO", "BAR"), + Tuple.Create("FOO", "BAZ"), + }.ToLookup(x => x.Item1, x => x.Item2)); + + // When + var result = arguments.GetArgument("FOO"); + + // Then + Assert.Equal("BAZ", result); + } + } +} \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/CakeEngineTests.cs b/src/Cake.Core.Tests/Unit/CakeEngineTests.cs index 8dde7f325b..80060a4f34 100644 --- a/src/Cake.Core.Tests/Unit/CakeEngineTests.cs +++ b/src/Cake.Core.Tests/Unit/CakeEngineTests.cs @@ -1540,6 +1540,24 @@ public async Task Should_Return_Report_That_Marks_Delegated_Tasks_As_Delegated() // Then Assert.Equal(CakeTaskExecutionStatus.Delegated, report.First(e => e.TaskName == "B").ExecutionStatus); } + + [Fact] + public async Task Should_Return_Report_That_Marks_Failed_Tasks_As_Failed() + { + // Given + var fixture = new CakeEngineFixture(); + var settings = new ExecutionSettings().SetTarget("A"); + var engine = fixture.CreateEngine(); + engine.RegisterTask("A").IsDependentOn("B"); + engine.RegisterTask("B").ContinueOnError().Does(() => throw new Exception("error")); + + // When + var report = await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings); + + // Then + Assert.Equal(CakeTaskExecutionStatus.Delegated, report.First(e => e.TaskName == "A").ExecutionStatus); + Assert.Equal(CakeTaskExecutionStatus.Failed, report.First(e => e.TaskName == "B").ExecutionStatus); + } } public sealed class TheSetupEvent @@ -1554,9 +1572,30 @@ public void Should_Raise_Setup_Event() engine.RegisterTask("A"); // When - var result = Assert.Raises( - handler => engine.Setup += handler, - handler => engine.Setup -= handler, + var result = Assert.Raises( + handler => engine.BeforeSetup += handler, + handler => engine.BeforeSetup -= handler, + async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); + + // Then + Assert.NotNull(result); + Assert.Equal(engine, result.Sender); + Assert.Equal(fixture.Context, result.Arguments.Context); + } + + [Fact] + public void Should_Raise_AfterSetup_Event() + { + // Given + var fixture = new CakeEngineFixture(); + var settings = new ExecutionSettings().SetTarget("A"); + var engine = fixture.CreateEngine(); + engine.RegisterTask("A"); + + // When + var result = Assert.Raises( + handler => engine.AfterSetup += handler, + handler => engine.AfterSetup -= handler, async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); // Then @@ -1632,9 +1671,29 @@ public void Should_Raise_Task_Setup_Event() engine.RegisterTask("A"); // When - var result = Assert.Raises( - handler => engine.TaskSetup += handler, - handler => engine.TaskSetup -= handler, + var result = Assert.Raises( + handler => engine.BeforeTaskSetup += handler, + handler => engine.BeforeTaskSetup -= handler, + async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); + + // Then + Assert.NotNull(result); + Assert.Equal(engine, result.Sender); + } + + [Fact] + public void Should_Raise_Task_AfterSetup_Event() + { + // Given + var fixture = new CakeEngineFixture(); + var settings = new ExecutionSettings().SetTarget("A"); + var engine = fixture.CreateEngine(); + engine.RegisterTask("A"); + + // When + var result = Assert.Raises( + handler => engine.AfterTaskSetup += handler, + handler => engine.AfterTaskSetup -= handler, async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); // Then @@ -1652,13 +1711,13 @@ public void Should_Raise_Task_Setup_Event_With_Task_Context() engine.RegisterTask("A"); // When - var result = Assert.Raises( - handler => engine.TaskSetup += handler, - handler => engine.TaskSetup -= handler, + var result = Assert.Raises( + handler => engine.BeforeTaskSetup += handler, + handler => engine.BeforeTaskSetup -= handler, async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); // Then - Assert.IsType(result.Arguments); + Assert.IsType(result.Arguments); Assert.NotNull(result.Arguments.TaskSetupContext.Task); Assert.Equal("A", result.Arguments.TaskSetupContext.Task.Name); } @@ -1738,9 +1797,29 @@ public void Should_Raise_Task_Teardown_Event() engine.RegisterTask("A"); // When - var result = Assert.Raises( - handler => engine.TaskTeardown += handler, - handler => engine.TaskTeardown -= handler, + var result = Assert.Raises( + handler => engine.BeforeTaskTeardown += handler, + handler => engine.BeforeTaskTeardown -= handler, + async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); + + // Then + Assert.NotNull(result); + Assert.Equal(engine, result.Sender); + } + + [Fact] + public void Should_Raise_Task_AfterTeardown_Event() + { + // Given + var fixture = new CakeEngineFixture(); + var settings = new ExecutionSettings().SetTarget("A"); + var engine = fixture.CreateEngine(); + engine.RegisterTask("A"); + + // When + var result = Assert.Raises( + handler => engine.AfterTaskTeardown += handler, + handler => engine.AfterTaskTeardown -= handler, async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); // Then @@ -1758,13 +1837,13 @@ public void Should_Raise_Task_Teardown_Event_With_Task_Context() engine.RegisterTask("A"); // When - var result = Assert.Raises( - handler => engine.TaskTeardown += handler, - handler => engine.TaskTeardown -= handler, + var result = Assert.Raises( + handler => engine.BeforeTaskTeardown += handler, + handler => engine.BeforeTaskTeardown -= handler, async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); // Then - Assert.IsType(result.Arguments); + Assert.IsType(result.Arguments); Assert.NotNull(result.Arguments.TaskTeardownContext.Task); Assert.Equal("A", result.Arguments.TaskTeardownContext.Task.Name); } @@ -1782,7 +1861,7 @@ public async Task Should_Raise_Task_Teardown_Event_After_Task_Setup_Event() { list.Add("TASK_SETUP_EVENT"); }; - engine.TaskTeardown += (sender, args) => + engine.BeforeTaskTeardown += (sender, args) => { list.Add("TASK_TEARDOWN_EVENT"); }; @@ -1809,7 +1888,7 @@ public async Task Should_Raise_Task_Teardown_Event_For_All_Tasks() var engine = fixture.CreateEngine(); engine.RegisterTask("A"); engine.RegisterTask("B").IsDependentOn("A"); - engine.TaskTeardown += (sender, args) => + engine.BeforeTaskTeardown += (sender, args) => { list.Add("TASK_TEARDOWN_EVENT_" + args.TaskTeardownContext.Task.Name); }; @@ -1839,9 +1918,29 @@ public void Should_Raise_Teardown_Event() engine.RegisterTask("A"); // When - var result = Assert.Raises( - handler => engine.Teardown += handler, - handler => engine.Teardown -= handler, + var result = Assert.Raises( + handler => engine.BeforeTeardown += handler, + handler => engine.BeforeTeardown -= handler, + async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); + + // Then + Assert.NotNull(result); + Assert.Equal(engine, result.Sender); + } + + [Fact] + public void Should_Raise_AfterTeardown_Event() + { + // Given + var fixture = new CakeEngineFixture(); + var settings = new ExecutionSettings().SetTarget("A"); + var engine = fixture.CreateEngine(); + engine.RegisterTask("A"); + + // When + var result = Assert.Raises( + handler => engine.AfterTeardown += handler, + handler => engine.AfterTeardown -= handler, async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); // Then @@ -1858,9 +1957,9 @@ public void Should_Raise_Teardown_Event_With_Teardown_Context() engine.RegisterTask("A"); // When - var result = Assert.Raises( - handler => engine.Teardown += handler, - handler => engine.Teardown -= handler, + var result = Assert.Raises( + handler => engine.BeforeTeardown += handler, + handler => engine.BeforeTeardown -= handler, async () => await engine.RunTargetAsync(fixture.Context, fixture.ExecutionStrategy, settings)); // Then @@ -1878,11 +1977,11 @@ public async Task Should_Invoke_All_Handlers() var settings = new ExecutionSettings().SetTarget("A"); var engine = fixture.CreateEngine(); engine.RegisterTask("A"); - engine.Teardown += (sender, args) => + engine.BeforeTeardown += (sender, args) => { list.Add("HANDLER_1"); }; - engine.Teardown += (sender, args) => + engine.BeforeTeardown += (sender, args) => { list.Add("HANDLER_2"); }; @@ -1907,7 +2006,7 @@ public async Task Should_Raise_The_Teardown_Event_Only_Once() engine.RegisterTask("A"); engine.RegisterTask("B").IsDependentOn("A"); engine.RegisterTask("C").IsDependentOn("B"); - engine.Teardown += (sender, args) => + engine.BeforeTeardown += (sender, args) => { list.Add("TEARDOWN_EVENT"); }; @@ -1932,11 +2031,11 @@ public async Task Should_Raise_The_Teardown_Event_After_Task_Teardown_Event() var settings = new ExecutionSettings().SetTarget("A"); var engine = fixture.CreateEngine(); engine.RegisterTask("A"); - engine.TaskTeardown += (sender, args) => + engine.BeforeTaskTeardown += (sender, args) => { list.Add("TASK_TEARDOWN_EVENT"); }; - engine.Teardown += (sender, args) => + engine.BeforeTeardown += (sender, args) => { list.Add("TEARDOWN_EVENT"); }; diff --git a/src/Cake.Core.Tests/Unit/CakeReportTests.cs b/src/Cake.Core.Tests/Unit/CakeReportTests.cs index 0aff1ddb3b..b9ea8dd0a2 100644 --- a/src/Cake.Core.Tests/Unit/CakeReportTests.cs +++ b/src/Cake.Core.Tests/Unit/CakeReportTests.cs @@ -130,5 +130,46 @@ public void Should_Add_To_End_Of_Sequence() Assert.Equal(CakeTaskExecutionStatus.Delegated, lastTask.ExecutionStatus); } } + + public sealed class TheAddFailedMethod + { + [Fact] + public void Should_Add_A_New_Task() + { + // Given + var report = new CakeReport(); + var taskName = "task"; + var duration = TimeSpan.FromMilliseconds(100); + + // When + report.AddFailed(taskName, duration); + + // Then + var firstTask = report.First(); + Assert.Equal(taskName, firstTask.TaskName); + Assert.Equal(duration, firstTask.Duration); + Assert.Equal(CakeTaskExecutionStatus.Failed, firstTask.ExecutionStatus); + } + + [Fact] + public void Should_Add_To_End_Of_Sequence() + { + // Given + var report = new CakeReport(); + report.AddSkipped("task 1"); + + var taskName = "task 2"; + var duration = TimeSpan.FromMilliseconds(100); + + // When + report.AddFailed(taskName, duration); + + // Then + var lastTask = report.Last(); + Assert.Equal(taskName, lastTask.TaskName); + Assert.Equal(duration, lastTask.Duration); + Assert.Equal(CakeTaskExecutionStatus.Failed, lastTask.ExecutionStatus); + } + } } } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs b/src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs index 28beda0545..21aad8bf1e 100644 --- a/src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs +++ b/src/Cake.Core.Tests/Unit/CakeRuntimeTests.cs @@ -24,7 +24,6 @@ public TheBuiltFrameworkProperty(ITestOutputHelper testOutputHelper) TestOutputHelper = testOutputHelper; } - [RuntimeFact(TestRuntime.CoreClr)] public void Should_Return_Correct_Result_For_CoreClr() { // Given @@ -40,7 +39,11 @@ public void Should_Return_Correct_Result_For_CoreClr() Assert.Equal(".NETStandard,Version=v2.0", framework.FullName); #else var expect = string.Concat(".NETCoreApp,Version=v", -#if NETCOREAPP2_0 +#if NET6_0 + "6.0"); +#elif NET5_0 + "5.0"); +#elif NETCOREAPP2_0 "2.0"); #elif NETCOREAPP2_1 "2.1"); @@ -61,6 +64,8 @@ public void Should_Return_Correct_Result_For_CoreClr() case ".NETCoreApp,Version=v2.1": case ".NETCoreApp,Version=v3.0": case ".NETCoreApp,Version=v3.1": + case ".NETCoreApp,Version=v5.0": + case ".NETCoreApp,Version=v6.0": { TestOutputHelper.WriteLine("Expect changed from {0} to {1}.", expect, framework.FullName); expect = framework.FullName; @@ -75,6 +80,8 @@ public void Should_Return_Correct_Result_For_CoreClr() { case ".NETCoreApp,Version=v3.0": case ".NETCoreApp,Version=v3.1": + case ".NETCoreApp,Version=v5.0": + case ".NETCoreApp,Version=v6.0": { TestOutputHelper.WriteLine("Expect changed from {0} to {1}.", expect, framework.FullName); expect = framework.FullName; @@ -88,6 +95,8 @@ public void Should_Return_Correct_Result_For_CoreClr() switch (framework.FullName) { case ".NETCoreApp,Version=v3.1": + case ".NETCoreApp,Version=v5.0": + case ".NETCoreApp,Version=v6.0": { TestOutputHelper.WriteLine("Expect changed from {0} to {1}.", expect, framework.FullName); expect = framework.FullName; @@ -96,26 +105,37 @@ public void Should_Return_Correct_Result_For_CoreClr() } break; } + case ".NETCoreApp,Version=v3.1": + { + switch (framework.FullName) + { + case ".NETCoreApp,Version=v5.0": + case ".NETCoreApp,Version=v6.0": + { + TestOutputHelper.WriteLine("Expect changed from {0} to {1}.", expect, framework.FullName); + expect = framework.FullName; + break; + } + } + break; + } + case ".NETCoreApp,Version=v5.0": + { + switch (framework.FullName) + { + case ".NETCoreApp,Version=v6.0": + { + TestOutputHelper.WriteLine("Expect changed from {0} to {1}.", expect, framework.FullName); + expect = framework.FullName; + break; + } + } + break; + } } Assert.Equal(expect, framework.FullName); #endif } } - - public sealed class TheExecutingFrameworkProperty - { - [RuntimeFact(TestRuntime.Clr)] - public void Should_Return_Correct_Result_For_Clr() - { - // Given - var runtime = new CakeRuntime(); - - // When - var framework = runtime.BuiltFramework; - - // Then - Assert.Equal(".NETFramework,Version=v4.6.1", framework.FullName); - } - } } } diff --git a/src/Cake.Core.Tests/Unit/Configuration/Parser/ConfigurationParserTests.cs b/src/Cake.Core.Tests/Unit/Configuration/Parser/ConfigurationParserTests.cs index da7d631111..b9938409ef 100644 --- a/src/Cake.Core.Tests/Unit/Configuration/Parser/ConfigurationParserTests.cs +++ b/src/Cake.Core.Tests/Unit/Configuration/Parser/ConfigurationParserTests.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.IO; using Cake.Core.Configuration.Parser; using Cake.Core.Tests.Properties; @@ -114,6 +115,137 @@ public void Should_Parse_Ini_With_Sections_Correctly() Assert.True(result.ContainsKey("Section2_Baz")); Assert.Equal("Qux", result["Section2_Baz"]); } + + public sealed class EnvironmentVariableSubstitution + { + [Theory] + [MemberData(nameof(EnvironmentVariableSubstitutionTestData))] + public void Should_Substitute_Environment_Variables(EnvironmentVariableTestHarness harness) + { + // Given + var environment = harness.CreateEnvironment(); + var fileSystem = new FakeFileSystem(environment); + fileSystem.CreateFile("/Working/cake.config").SetContent(harness.IniFileContents); + var parser = new ConfigurationParser(fileSystem, environment); + + // When + var result = parser.Read("/Working/cake.config"); + + // Then + harness.Assert(result); + } + + public static IEnumerable EnvironmentVariableSubstitutionTestData() + { + yield return new object[] + { + new EnvironmentVariableTestHarness() + { + Testcase = $"Basic environment variable substitution", + CreateEnvironment = () => FakeEnvironment.CreateUnixEnvironment().AddEnvironmentVariable("VALUE", "world"), + IniFileContents = "[Section1]\nHello=%VALUE%", + Assert = result => Assert.Equal("world", result["Section1_Hello"]) + }, + }; + + yield return new object[] + { + new EnvironmentVariableTestHarness() + { + Testcase = $"Casing of substitution token should not matter", + CreateEnvironment = () => FakeEnvironment.CreateUnixEnvironment().AddEnvironmentVariable("VALUE", "world"), + IniFileContents = "[Section1]\nHello=%value%", + Assert = result => Assert.Equal("world", result["Section1_Hello"]) + }, + }; + + yield return new object[] + { + new EnvironmentVariableTestHarness() + { + Testcase = $"Should respect leading text", + CreateEnvironment = () => FakeEnvironment.CreateUnixEnvironment().AddEnvironmentVariable("VALUE", "world"), + IniFileContents = "[Section1]\nHello=it is a wonderful %VALUE%", + Assert = result => Assert.Equal("it is a wonderful world", result["Section1_Hello"]) + }, + }; + + yield return new object[] + { + new EnvironmentVariableTestHarness() + { + Testcase = $"Should respect trailing text", + CreateEnvironment = () => FakeEnvironment.CreateUnixEnvironment().AddEnvironmentVariable("VALUE", "John"), + IniFileContents = "[Section1]\nHello=%VALUE%, nice to meet you.", + Assert = result => Assert.Equal("John, nice to meet you.", result["Section1_Hello"]) + }, + }; + + yield return new object[] + { + new EnvironmentVariableTestHarness() + { + Testcase = $"No environment variable found for substitution token, should not substitute", + CreateEnvironment = () => FakeEnvironment.CreateUnixEnvironment(), + IniFileContents = "[Section1]\nHello=%VALUE%", + Assert = result => Assert.Equal("%VALUE%", result["Section1_Hello"]) + }, + }; + + yield return new object[] + { + new EnvironmentVariableTestHarness() + { + Testcase = $"Special characters should be allowed", + CreateEnvironment = () => FakeEnvironment.CreateUnixEnvironment().AddEnvironmentVariable("ProgramFiles(x86)", "PATH TO PROGRAM FILES"), + IniFileContents = "[Section1]\nSpecialPath=%ProgramFiles(x86)%", + Assert = result => Assert.Equal("PATH TO PROGRAM FILES", result["Section1_SpecialPath"]) + }, + }; + + yield return new object[] + { + new EnvironmentVariableTestHarness() + { + Testcase = $"More than one environment variable to substitute, should substitute all", + CreateEnvironment = () => FakeEnvironment.CreateUnixEnvironment() + .AddEnvironmentVariable("VARIABLE1", "Value1") + .AddEnvironmentVariable("VARIABLE2", "Value2"), + IniFileContents = "[Section1]\nValue1=%VARIABLE1%\nValue2=%VARIABLE2%", + Assert = result => + { + Assert.Equal("Value1", result["Section1_Value1"]); + Assert.Equal("Value2", result["Section1_Value2"]); + } + }, + }; + } + + public class EnvironmentVariableTestHarness + { + public string Testcase { get; set; } + + public Func CreateEnvironment { get; set; } + + public string IniFileContents { get; set; } + + public Action> Assert { get; set; } + + public override string ToString() + { + return $"Testcase={Testcase}"; + } + } + } + } + } + + internal static class FakeEnvironmentExtensions + { + internal static FakeEnvironment AddEnvironmentVariable(this FakeEnvironment environment, string variable, string value) + { + environment.SetEnvironmentVariable(variable, value); + return environment; } } } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Diagnostics/AnsiDetectorTests.cs b/src/Cake.Core.Tests/Unit/Diagnostics/AnsiDetectorTests.cs new file mode 100644 index 0000000000..42b09252bb --- /dev/null +++ b/src/Cake.Core.Tests/Unit/Diagnostics/AnsiDetectorTests.cs @@ -0,0 +1,53 @@ +using Cake.Core.Diagnostics; +using Cake.Testing; +using Xunit; + +namespace Cake.Core.Tests.Unit.Diagnostics +{ + public sealed class AnsiDetectorTests + { + public sealed class The_SupportsAnsi_Method + { + public sealed class UsingTeamCity + { + [Theory] + [InlineData("2020.2")] + [InlineData("2020.1.5")] + [InlineData("2017.1")] + [InlineData("10.0.5")] + [InlineData("10.0")] + [InlineData("9.1.7")] + public void Should_Return_True_When_Running_TeamCity_9_1_or_2017_Or_Higher(string teamCityVersion) + { + // Given + var fakeEnvironment = FakeEnvironment.CreateUnixEnvironment(); + + // When + fakeEnvironment.SetEnvironmentVariable("TEAMCITY_VERSION", teamCityVersion); + + // Then + Assert.True(AnsiDetector.SupportsAnsi(fakeEnvironment)); + } + + [Theory] + [InlineData("9.0.5")] + [InlineData("9.0.1")] + [InlineData("8.1.5")] + [InlineData("7.1.5")] + [InlineData("7.0.1")] + [InlineData("6.0")] + public void Should_Return_False_When_Running_TeamCity_9_0_Or_Lower(string teamCityVersion) + { + // Given + var fakeEnvironment = FakeEnvironment.CreateUnixEnvironment(); + + // When + fakeEnvironment.SetEnvironmentVariable("TEAMCITY_VERSION", teamCityVersion); + + // Then + Assert.False(AnsiDetector.SupportsAnsi(fakeEnvironment)); + } + } + } + } +} diff --git a/src/Cake.Core.Tests/Unit/Diagnostics/CakeBuildLogTests.cs b/src/Cake.Core.Tests/Unit/Diagnostics/CakeBuildLogTests.cs index 8f43bd43f7..90704ded20 100644 --- a/src/Cake.Core.Tests/Unit/Diagnostics/CakeBuildLogTests.cs +++ b/src/Cake.Core.Tests/Unit/Diagnostics/CakeBuildLogTests.cs @@ -102,10 +102,10 @@ public void Should_Not_Colorize_A_Log_Message_Containg_A_Single_Token() } [Theory] - [InlineData(LogLevel.Warning, "\u001b[40m\u001b[33;1mHello, \u001b[0m\u001b[40m\u001b[33;1mWorld\u001b[0m")] - [InlineData(LogLevel.Information, "\u001b[40m\u001b[37;1mHello, \u001b[0m\u001b[44m\u001b[37;1mWorld\u001b[0m")] - [InlineData(LogLevel.Verbose, "\u001b[40m\u001b[37mHello, \u001b[0m\u001b[40m\u001b[37;1mWorld\u001b[0m")] - [InlineData(LogLevel.Debug, "\u001b[40m\u001b[30;1mHello, \u001b[0m\u001b[40m\u001b[37mWorld\u001b[0m")] + [InlineData(LogLevel.Warning, "\u001b[33;1mHello, \u001b[0m\u001b[33;1mWorld\u001b[0m")] + [InlineData(LogLevel.Information, "\u001b[37;1mHello, \u001b[0m\u001b[44m\u001b[37;1mWorld\u001b[0m")] + [InlineData(LogLevel.Verbose, "\u001b[37mHello, \u001b[0m\u001b[37;1mWorld\u001b[0m")] + [InlineData(LogLevel.Debug, "\u001b[30;1mHello, \u001b[0m\u001b[37mWorld\u001b[0m")] public void Should_Colorize_Tokens_Correctly(LogLevel level, string expected) { // Given @@ -266,7 +266,7 @@ public void Should_Colorize_Error_Tokens_Correctly(LogLevel level, string expect [Theory] [InlineData(false, "#[Black|DarkGray]Executing: if ($LASTEXITCODE -gt 0) { throw \"script failed with exit code $LASTEXITCODE\" }[/]")] - [InlineData(true, "\u001b[40m\u001b[30;1mExecuting: if ($LASTEXITCODE -gt 0) { throw \"script failed with exit code $LASTEXITCODE\" }\u001b[0m")] + [InlineData(true, "\u001b[30;1mExecuting: if ($LASTEXITCODE -gt 0) { throw \"script failed with exit code $LASTEXITCODE\" }\u001b[0m")] public void Should_Output_Escaped_Tokens_Correctly(bool ansi, string expected) { // Given diff --git a/src/Cake.Core.Tests/Unit/Graph/CakeGraphTests.cs b/src/Cake.Core.Tests/Unit/Graph/CakeGraphTests.cs index 168d4c1604..b7f3f21c7f 100644 --- a/src/Cake.Core.Tests/Unit/Graph/CakeGraphTests.cs +++ b/src/Cake.Core.Tests/Unit/Graph/CakeGraphTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Linq; using Cake.Core.Graph; using Xunit; @@ -152,7 +153,7 @@ public void Should_Throw_If_Edge_Is_Unidirectional() // Then Assert.IsType(result); - Assert.Equal("Unidirectional edges in graph are not allowed.", result?.Message); + Assert.Equal($"Unidirectional edges in graph are not allowed.{Environment.NewLine}\"start\" and \"end\" cannot depend on each other.", result?.Message); } [Fact] @@ -167,7 +168,7 @@ public void Should_Throw_If_Edge_Is_Unidirectional_Regardless_Of_Casing() // Then Assert.IsType(result); - Assert.Equal("Unidirectional edges in graph are not allowed.", result?.Message); + Assert.Equal($"Unidirectional edges in graph are not allowed.{Environment.NewLine}\"start\" and \"end\" cannot depend on each other.", result?.Message); } } diff --git a/src/Cake.Core.Tests/Unit/IO/DirectoryPathConverterTests.cs b/src/Cake.Core.Tests/Unit/IO/DirectoryPathConverterTests.cs new file mode 100644 index 0000000000..fc32875fc7 --- /dev/null +++ b/src/Cake.Core.Tests/Unit/IO/DirectoryPathConverterTests.cs @@ -0,0 +1,118 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Cake.Core.IO; +using Xunit; + +namespace Cake.Core.Tests.Unit.IO +{ + public sealed class DirectoryPathConverterTests + { + public sealed class TheCanConvertFromMethod + { + [Fact] + public void Should_Return_True_When_Source_Type_Is_String() + { + var converter = new DirectoryPathConverter(); + + var result = converter.CanConvertFrom(typeof(string)); + + Assert.True(result); + } + + [Fact] + public void Should_Return_False_When_Source_Type_Is_Not_String() + { + var converter = new DirectoryPathConverter(); + + var result = converter.CanConvertFrom(typeof(DateTime)); + + Assert.False(result); + } + } + + public sealed class TheConvertFromMethod + { + [Fact] + public void Should_Convert_String_Value_To_Directory_Path() + { + var converter = new DirectoryPathConverter(); + + var result = converter.ConvertFrom("c:/data/work"); + + Assert.IsType(result); + Assert.Equal("c:/data/work", ((DirectoryPath)result).FullPath); + } + + [Fact] + public void Should_Throw_NotSupportedException_When_Value_Is_Not_A_Valid_Directory_Path() + { + var converter = new DirectoryPathConverter(); + + var result = Record.Exception(() => converter.ConvertFrom(DateTime.Now)); + + Assert.IsType(result); + } + } + + public sealed class TheCanConvertToMethod + { + [Fact] + public void Should_Return_True_When_Destination_Type_Is_String() + { + var converter = new DirectoryPathConverter(); + + var result = converter.CanConvertTo(typeof(string)); + + Assert.True(result); + } + + [Fact] + public void Should_Return_True_When_Destination_Type_Is_DirectoryPath() + { + var converter = new DirectoryPathConverter(); + + var result = converter.CanConvertTo(typeof(DirectoryPath)); + + Assert.True(result); + } + + [Fact] + public void Should_Return_False_When_Source_Type_Is_Not_DirectoryPath() + { + var converter = new DirectoryPathConverter(); + + var result = converter.CanConvertTo(typeof(DateTime)); + + Assert.False(result); + } + } + + public sealed class TheConvertToMethod + { + [Fact] + public void Should_Convert_Directory_Path_To_String_Value_Using_FullPath() + { + var converter = new DirectoryPathConverter(); + + var result = converter.ConvertTo(DirectoryPath.FromString("c:/data/work"), typeof(string)); + + Assert.IsType(result); + Assert.Equal("c:/data/work", result); + } + + [Fact] + public void Should_Throw_NotSupportedException_When_Destination_Type_Is_Not_String() + { + var converter = new DirectoryPathConverter(); + + var result = Record.Exception(() => + converter.ConvertTo(DirectoryPath.FromString("c:/data/work"), typeof(DateTime))); + + Assert.IsType(result); + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/IO/FileExtensionsTests.cs b/src/Cake.Core.Tests/Unit/IO/FileExtensionsTests.cs index f4b1974379..176c0aa200 100644 --- a/src/Cake.Core.Tests/Unit/IO/FileExtensionsTests.cs +++ b/src/Cake.Core.Tests/Unit/IO/FileExtensionsTests.cs @@ -197,5 +197,106 @@ public void Should_Read_File_With_Multiple_Lines_Correctly() Assert.Equal("3", result[2]); } } + + public sealed class TheIsClrAssemblyMethod + { + private static readonly byte[] _validPeAndClrAssemblyBytes = + { + 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x03, 0x00, 0x8a, 0x54, 0x4a, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x22, 0x20, 0x0b, 0x01, 0x30, 0x00, 0x00, 0x84, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0xa2, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x85, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2e, 0xa2, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x94, 0xa1, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x48, + }; + + private static readonly byte[] _validPeButNotClrAssemblyBytes = + { + 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xab, 0x04, 0x28, 0x30, 0xef, 0x65, 0x46, 0x63, 0xef, 0x65, 0x46, 0x63, 0xef, 0x65, 0x46, 0x63, 0x71, 0xc5, 0x81, 0x63, 0xea, 0x65, 0x46, 0x63, 0xa9, 0x34, 0xa7, 0x63, 0xc2, 0x65, 0x46, 0x63, + 0xa9, 0x34, 0xa6, 0x63, 0x71, 0x65, 0x46, 0x63, 0xa9, 0x34, 0x99, 0x63, 0xe4, 0x65, 0x46, 0x63, 0x32, 0x9a, 0x88, 0x63, 0xed, 0x65, 0x46, 0x63, 0x32, 0x9a, 0x8d, 0x63, 0xe0, 0x65, 0x46, 0x63, + 0xef, 0x65, 0x47, 0x63, 0x43, 0x65, 0x46, 0x63, 0x5a, 0xfb, 0xa2, 0x63, 0x4d, 0x65, 0x46, 0x63, 0x5a, 0xfb, 0x9a, 0x63, 0xee, 0x65, 0x46, 0x63, 0xe2, 0x37, 0x9d, 0x63, 0xee, 0x65, 0x46, 0x63, + 0xef, 0x65, 0xd1, 0x63, 0xee, 0x65, 0x46, 0x63, 0x5a, 0xfb, 0x98, 0x63, 0xee, 0x65, 0x46, 0x63, 0x52, 0x69, 0x63, 0x68, 0xef, 0x65, 0x46, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x64, 0x86, 0x06, 0x00, 0xe2, 0xac, 0x47, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x22, 0x20, + 0x0b, 0x02, 0x0c, 0x00, 0x00, 0x6e, 0x0d, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x87, 0x0c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x11, 0x00, 0x00, 0x04, 0x00, 0x00, + 0xfe, 0x24, 0x12, 0x00, 0x03, 0x00, 0x60, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x0f, 0x00, 0x8a, 0x62, 0x00, 0x00, 0x8c, 0x3b, 0x10, 0x00, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0x90, 0x11, 0x00, 0xb8, 0x05, 0x00, 0x00, 0x00, 0xb0, 0x10, 0x00, 0xb4, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x11, 0x00, 0x3c, 0x09, 0x00, 0x00, + 0xa0, 0x85, 0x0d, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x90, 0xcd, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0d, 0x00, 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + + private static readonly byte[] _invalidPeBytes = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + [Fact] + public void Should_Return_True_When_File_Is_Valid_PE_And_Is_Clr_Assembly() + { + // Given + var file = Substitute.For(); + + // When + file.Exists.Returns(true); + file.Length.Returns(_validPeAndClrAssemblyBytes.Length); + file.OpenRead().Returns(new MemoryStream(_validPeAndClrAssemblyBytes)); + + // Then + Assert.True(FileExtensions.IsClrAssembly(file)); + } + + [Fact] + public void Should_Return_False_When_File_Is_Valid_PE_But_Not_A_Clr_Assembly() + { + // Given + var file = Substitute.For(); + + // When + file.Exists.Returns(true); + file.Length.Returns(_validPeButNotClrAssemblyBytes.Length); + file.OpenRead().Returns(new MemoryStream(_validPeButNotClrAssemblyBytes)); + + // Then + Assert.False(FileExtensions.IsClrAssembly(file)); + } + + [Fact] + public void Should_Return_False_When_File_Is_Not_A_Valid_PE() + { + // Given + var file = Substitute.For(); + + // When + file.Exists.Returns(true); + file.Length.Returns(_invalidPeBytes.Length); + file.OpenRead().Returns(new MemoryStream(_invalidPeBytes)); + + // Then + Assert.False(FileExtensions.IsClrAssembly(file)); + } + } } } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/IO/FilePathConverterTests.cs b/src/Cake.Core.Tests/Unit/IO/FilePathConverterTests.cs new file mode 100644 index 0000000000..80e7cb8eac --- /dev/null +++ b/src/Cake.Core.Tests/Unit/IO/FilePathConverterTests.cs @@ -0,0 +1,118 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Cake.Core.IO; +using Xunit; + +namespace Cake.Core.Tests.Unit.IO +{ + public sealed class FilePathConverterTests + { + public sealed class TheCanConvertFromMethod + { + [Fact] + public void Should_Return_True_When_Source_Type_Is_String() + { + var converter = new FilePathConverter(); + + var result = converter.CanConvertFrom(typeof(string)); + + Assert.True(result); + } + + [Fact] + public void Should_Return_False_When_Source_Type_Is_Not_String() + { + var converter = new FilePathConverter(); + + var result = converter.CanConvertFrom(typeof(DateTime)); + + Assert.False(result); + } + } + + public sealed class TheConvertFromMethod + { + [Fact] + public void Should_Convert_String_Value_To_File_Path() + { + var converter = new FilePathConverter(); + + var result = converter.ConvertFrom("c:/data/work/file.txt"); + + Assert.IsType(result); + Assert.Equal("c:/data/work/file.txt", ((FilePath)result).FullPath); + } + + [Fact] + public void Should_Throw_NotSupportedException_When_Value_Is_Not_A_Valid_File_Path() + { + var converter = new FilePathConverter(); + + var result = Record.Exception(() => converter.ConvertFrom(DateTime.Now)); + + Assert.IsType(result); + } + } + + public sealed class TheCanConvertToMethod + { + [Fact] + public void Should_Return_True_When_Destination_Type_Is_String() + { + var converter = new FilePathConverter(); + + var result = converter.CanConvertTo(typeof(string)); + + Assert.True(result); + } + + [Fact] + public void Should_Return_True_When_Destination_Type_Is_FilePath() + { + var converter = new FilePathConverter(); + + var result = converter.CanConvertTo(typeof(FilePath)); + + Assert.True(result); + } + + [Fact] + public void Should_Return_False_When_Source_Type_Is_Not_FilePath() + { + var converter = new FilePathConverter(); + + var result = converter.CanConvertTo(typeof(DateTime)); + + Assert.False(result); + } + } + + public sealed class TheConvertToMethod + { + [Fact] + public void Should_Convert_File_Path_To_String_Value_Using_FullPath() + { + var converter = new FilePathConverter(); + + var result = converter.ConvertTo(FilePath.FromString("c:/data/work/file.txt"), typeof(string)); + + Assert.IsType(result); + Assert.Equal("c:/data/work/file.txt", result); + } + + [Fact] + public void Should_Throw_NotSupportedException_When_Destination_Type_Is_Not_String() + { + var converter = new FilePathConverter(); + + var result = Record.Exception(() => + converter.ConvertTo(FilePath.FromString("c:/data/work/file.txt"), typeof(DateTime))); + + Assert.IsType(result); + } + } + } +} \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/IO/ProcessArgumentBuilderTests.cs b/src/Cake.Core.Tests/Unit/IO/ProcessArgumentBuilderTests.cs index a8f5927b49..28401598ea 100644 --- a/src/Cake.Core.Tests/Unit/IO/ProcessArgumentBuilderTests.cs +++ b/src/Cake.Core.Tests/Unit/IO/ProcessArgumentBuilderTests.cs @@ -23,7 +23,33 @@ public void Should_Remove_All_Arguments() builder.Clear(); // Then - Assert.Empty(builder.Render()); + Assert.Empty(builder); + } + } + + public sealed class TheFromStringsMethod + { + [Fact] + public void Should_Return_Empty_Builder_When_Values_Is_Null() + { + // Given, When + var builder = ProcessArgumentBuilder.FromStrings(null); + + // Then + Assert.Empty(builder); + } + } + + public sealed class TheFromStringsQuotedMethod + { + [Fact] + public void Should_Return_Empty_Builder_When_Values_Is_Null() + { + // Given, When + var builder = ProcessArgumentBuilder.FromStringsQuoted(null); + + // Then + Assert.Empty(builder); } } diff --git a/src/Cake.Core.Tests/Unit/IO/ProcessRunnerTests.cs b/src/Cake.Core.Tests/Unit/IO/ProcessRunnerTests.cs index 25bc12d43b..500d6d6ac8 100644 --- a/src/Cake.Core.Tests/Unit/IO/ProcessRunnerTests.cs +++ b/src/Cake.Core.Tests/Unit/IO/ProcessRunnerTests.cs @@ -163,7 +163,6 @@ public void Should_Not_Log_Secret_Arguments() .Verbose(Verbosity.Diagnostic, "Executing: {0}", "\"/Program Files/Cake.exe\" [REDACTED]"); } - [RuntimeFact(TestRuntime.CoreClr)] public void Should_Coerse_Mono_On_Unix_And_CoreClr() { // Given @@ -181,7 +180,6 @@ public void Should_Coerse_Mono_On_Unix_And_CoreClr() .Write(Verbosity.Diagnostic, LogLevel.Verbose, "{0} is a .NET Framework executable, will try execute using Mono.", "/Program Files/Cake.exe"); } - [RuntimeFact(TestRuntime.CoreClr)] public void Should_Not_Coerse_Mono_On_Windows_And_CoreClr() { // Given @@ -195,7 +193,6 @@ public void Should_Not_Coerse_Mono_On_Windows_And_CoreClr() Assert.Equal("\"/Program Files/Cake.exe\"", result.FileName); } - [RuntimeFact(TestRuntime.CoreClr)] public void Should_Not_Coerse_Mono_On_Unix_And_CoreClr_With_Config_NoMonoCoersion() { // Given @@ -210,7 +207,6 @@ public void Should_Not_Coerse_Mono_On_Unix_And_CoreClr_With_Config_NoMonoCoersio Assert.Equal("/Program Files/Cake.exe", result.FileName); } - [RuntimeFact(TestRuntime.CoreClr)] public void Should_Not_Coerse_Mono_On_Unix_And_CoreClr_If_Mono_Not_Resolved() { // Given diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethod b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethod index d63e8d9166..3dc2260389 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethod +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethod @@ -1,4 +1,5 @@ -public void Generic_ExtensionMethod() +[System.Diagnostics.DebuggerStepThrough] +public void Generic_ExtensionMethod() { Cake.Core.Tests.Data.MethodAliasGeneratorData.Generic_ExtensionMethod(Context); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithGenericReturnValue b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithGenericReturnValue index 1ff0b652ca..98ad68a1b4 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithGenericReturnValue +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithGenericReturnValue @@ -1,4 +1,5 @@ -public TTest Generic_ExtensionMethodWithGenericReturnValue(TTest value) +[System.Diagnostics.DebuggerStepThrough] +public TTest Generic_ExtensionMethodWithGenericReturnValue(TTest value) { return Cake.Core.Tests.Data.MethodAliasGeneratorData.Generic_ExtensionMethodWithGenericReturnValue(Context, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithGenericReturnValueAndTypeParamConstraints b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithGenericReturnValueAndTypeParamConstraints index 4cebd2e7bc..2c686ebe56 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithGenericReturnValueAndTypeParamConstraints +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithGenericReturnValueAndTypeParamConstraints @@ -1,4 +1,5 @@ -public TOut Generic_ExtensionMethodWithGenericReturnValueAndTypeParamConstraints(TIn arg) +[System.Diagnostics.DebuggerStepThrough] +public TOut Generic_ExtensionMethodWithGenericReturnValueAndTypeParamConstraints(TIn arg) where TIn : class, new() where TOut : System.Collections.ArrayList, System.IDisposable { diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithParameter index 44b10e97a5..44046190c2 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Generic_ExtensionMethodWithParameter @@ -1,4 +1,5 @@ -public void Generic_ExtensionMethodWithParameter(TTest value) +[System.Diagnostics.DebuggerStepThrough] +public void Generic_ExtensionMethodWithParameter(TTest value) { Cake.Core.Tests.Data.MethodAliasGeneratorData.Generic_ExtensionMethodWithParameter(Context, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithArrayParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithArrayParameter index cf0128efbf..cbf59c7a7f 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithArrayParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithArrayParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithArrayParameter(System.String[] values) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithArrayParameter(System.String[] values) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithArrayParameter(Context, values); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithDynamicReturnValue b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithDynamicReturnValue index b064876b6b..4f21aed07e 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithDynamicReturnValue +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithDynamicReturnValue @@ -1,4 +1,5 @@ -public dynamic NonGeneric_ExtensionMethodWithDynamicReturnValue() +[System.Diagnostics.DebuggerStepThrough] +public dynamic NonGeneric_ExtensionMethodWithDynamicReturnValue() { return Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithDynamicReturnValue(Context); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericCollectionOfNestedType b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericCollectionOfNestedType index 3cbb762dea..63f1d940ff 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericCollectionOfNestedType +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericCollectionOfNestedType @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithGenericCollectionOfNestedType(System.Collections.Generic.ICollection items) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithGenericCollectionOfNestedType(System.Collections.Generic.ICollection items) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithGenericCollectionOfNestedType(Context, items); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionArrayParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionArrayParameter index 1fdbe09bee..4f2f20600c 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionArrayParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionArrayParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithGenericExpressionArrayParameter(System.Linq.Expressions.Expression>[] expression) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithGenericExpressionArrayParameter(System.Linq.Expressions.Expression>[] expression) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithGenericExpressionArrayParameter(Context, expression); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionParameter index 27a2f9688a..d6938025dd 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithGenericExpressionParameter(System.Linq.Expressions.Expression> expression) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithGenericExpressionParameter(System.Linq.Expressions.Expression> expression) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithGenericExpressionParameter(Context, expression); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionParamsArrayParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionParamsArrayParameter index 0ae5eac200..adef40989b 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionParamsArrayParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericExpressionParamsArrayParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithGenericExpressionParamsArrayParameter(params System.Linq.Expressions.Expression>[] expression) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithGenericExpressionParamsArrayParameter(params System.Linq.Expressions.Expression>[] expression) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithGenericExpressionParamsArrayParameter(Context, expression); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericParameter index e8e6fb042c..b0cc1889fd 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithGenericParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithGenericParameter(System.Action value) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithGenericParameter(System.Action value) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithGenericParameter(Context, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithNoParameters b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithNoParameters index b93f98b555..4377daf9c0 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithNoParameters +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithNoParameters @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithNoParameters() +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithNoParameters() { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithNoParameters(Context); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalBooleanParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalBooleanParameter index 3910643e23..0e55a933cf 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalBooleanParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalBooleanParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalBooleanParameter(System.Int32 value, System.Boolean flag = false) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalBooleanParameter(System.Int32 value, System.Boolean flag = false) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalBooleanParameter(Context, value, flag); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalCharParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalCharParameter index c9fd667b17..b4a6ae2b04 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalCharParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalCharParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalCharParameter(System.String s, System.Char c = 's') +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalCharParameter(System.String s, System.Char c = 's') { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalCharParameter(Context, s, c); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalDecimalParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalDecimalParameter index c805388202..4fee401a0b 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalDecimalParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalDecimalParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalDecimalParameter(System.String s, System.Decimal value = (System.Decimal)12.12) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalDecimalParameter(System.String s, System.Decimal value = (System.Decimal)12.12) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalDecimalParameter(Context, s, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalEnumParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalEnumParameter index 95ef9aea77..5219816d75 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalEnumParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalEnumParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalEnumParameter(System.Int32 value, System.AttributeTargets targets = (System.AttributeTargets)4) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalEnumParameter(System.Int32 value, System.AttributeTargets targets = (System.AttributeTargets)4) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalEnumParameter(Context, value, targets); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableBooleanParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableBooleanParameter index 7cf5d9d423..5fc4d9a697 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableBooleanParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableBooleanParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalNullableBooleanParameter(System.String s, System.Nullable value = (System.Boolean)false) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalNullableBooleanParameter(System.String s, System.Nullable value = (System.Boolean)false) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalNullableBooleanParameter(Context, s, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableCharParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableCharParameter index c4c55435e4..49504fb8ee 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableCharParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableCharParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalNullableCharParameter(System.String s, System.Nullable value = (System.Char)'s') +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalNullableCharParameter(System.String s, System.Nullable value = (System.Char)'s') { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalNullableCharParameter(Context, s, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableDecimalParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableDecimalParameter index ca4a920bc1..9d4cd6c2d8 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableDecimalParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableDecimalParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalNullableDecimalParameter(System.String s, System.Nullable value = (System.Decimal)123.12) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalNullableDecimalParameter(System.String s, System.Nullable value = (System.Decimal)123.12) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalNullableDecimalParameter(Context, s, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableDoubleParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableDoubleParameter index fb45cd2f91..b6ab059a48 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableDoubleParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableDoubleParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalNullableDoubleParameter(System.String s, System.Nullable value = (System.Double)1234567890.12) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalNullableDoubleParameter(System.String s, System.Nullable value = (System.Double)1234567890.12) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalNullableDoubleParameter(Context, s, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableEnumParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableEnumParameter index 61deae0c1f..1bdc60c744 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableEnumParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableEnumParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalNullableEnumParameter(System.String s, System.Nullable targets = (System.AttributeTargets)4) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalNullableEnumParameter(System.String s, System.Nullable targets = (System.AttributeTargets)4) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalNullableEnumParameter(Context, s, targets); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableLongParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableLongParameter index 1c67622077..c8b25f8cae 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableLongParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableLongParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalNullableLongParameter(System.String s, System.Nullable value = (System.Int64)1234567890) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalNullableLongParameter(System.String s, System.Nullable value = (System.Int64)1234567890) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalNullableLongParameter(Context, s, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableTParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableTParameter index 15667228cb..5df7b4ef28 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableTParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalNullableTParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalNullableTParameter(System.String s, System.Nullable value = (System.Int32)0) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalNullableTParameter(System.String s, System.Nullable value = (System.Int32)0) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalNullableTParameter(Context, s, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalObjectParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalObjectParameter index b6428571d0..82c9bac65f 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalObjectParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalObjectParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalObjectParameter(System.Int32 value, System.Object option = null) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalObjectParameter(System.Int32 value, System.Object option = null) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalObjectParameter(Context, value, option); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalStringParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalStringParameter index 79debc136f..1b8260d784 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalStringParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOptionalStringParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOptionalStringParameter(System.Int32 value, System.String s = "there is a \"string\" here and a \t tab") +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOptionalStringParameter(System.Int32 value, System.String s = "there is a \"string\" here and a \t tab") { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOptionalStringParameter(Context, value, s); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOutputParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOutputParameter index c302ce1172..800ce262a6 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOutputParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithOutputParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithOutputParameter(out System.IDisposable arg) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithOutputParameter(out System.IDisposable arg) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithOutputParameter(Context, out arg); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameter index c637d53846..196d594e5b 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithParameter(System.Int32 value) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithParameter(System.Int32 value) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithParameter(Context, value); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameterArray b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameterArray index 79998303c7..c265f0b697 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameterArray +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameterArray @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithParameterArray(params System.Int32[] values) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithParameterArray(params System.Int32[] values) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithParameterArray(Context, values); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameterAttributes b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameterAttributes index 12df00e0c3..39391cc7f4 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameterAttributes +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithParameterAttributes @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithParameterAttributes([System.Runtime.CompilerServices.CallerMemberName] System.String memberName = "", [System.Runtime.CompilerServices.CallerFilePath] System.String sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] System.Int32 sourceLineNumber = (System.Int32)0) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithParameterAttributes([System.Runtime.CompilerServices.CallerMemberName] System.String memberName = "", [System.Runtime.CompilerServices.CallerFilePath] System.String sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] System.Int32 sourceLineNumber = (System.Int32)0) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithParameterAttributes(Context, memberName, sourceFilePath, sourceLineNumber); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithReservedKeywordParameter b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithReservedKeywordParameter index 83eda2be92..c16ac53884 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithReservedKeywordParameter +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithReservedKeywordParameter @@ -1,4 +1,5 @@ -public void NonGeneric_ExtensionMethodWithReservedKeywordParameter(System.Int32 @new) +[System.Diagnostics.DebuggerStepThrough] +public void NonGeneric_ExtensionMethodWithReservedKeywordParameter(System.Int32 @new) { Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithReservedKeywordParameter(Context, @new); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithReturnValue b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithReturnValue index 06b202e16d..8075bdc12d 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithReturnValue +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/NonGeneric_ExtensionMethodWithReturnValue @@ -1,4 +1,5 @@ -public System.String NonGeneric_ExtensionMethodWithReturnValue() +[System.Diagnostics.DebuggerStepThrough] +public System.String NonGeneric_ExtensionMethodWithReturnValue() { return Cake.Core.Tests.Data.MethodAliasGeneratorData.NonGeneric_ExtensionMethodWithReturnValue(Context); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ExplicitError_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ExplicitError_WithMessage index 69ad78324c..d180837ad1 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ExplicitError_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ExplicitError_WithMessage @@ -1,4 +1,5 @@ -public void Obsolete_ExplicitError_WithMessage() +[System.Diagnostics.DebuggerStepThrough] +public void Obsolete_ExplicitError_WithMessage() { throw new Cake.Core.CakeException("The alias Obsolete_ExplicitError_WithMessage has been made obsolete. Please use Foo.Bar instead."); } \ No newline at end of file diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ExplicitWarning_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ExplicitWarning_WithMessage index c19c4bcaa5..e436ddede9 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ExplicitWarning_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ExplicitWarning_WithMessage @@ -1,4 +1,5 @@ -public void Obsolete_ExplicitWarning_WithMessage() +[System.Diagnostics.DebuggerStepThrough] +public void Obsolete_ExplicitWarning_WithMessage() { Context.Log.Warning("Warning: The alias Obsolete_ExplicitWarning_WithMessage has been made obsolete. Please use Foo.Bar instead."); #pragma warning disable 0618 diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ImplicitWarning_NoMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ImplicitWarning_NoMessage index 6ef94e1ccf..1523fa310d 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ImplicitWarning_NoMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ImplicitWarning_NoMessage @@ -1,4 +1,5 @@ -public void Obsolete_ImplicitWarning_NoMessage() +[System.Diagnostics.DebuggerStepThrough] +public void Obsolete_ImplicitWarning_NoMessage() { Context.Log.Warning("Warning: The alias Obsolete_ImplicitWarning_NoMessage has been made obsolete."); #pragma warning disable 0618 diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ImplicitWarning_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ImplicitWarning_WithMessage index d50f79f1c5..4ab4b9ea47 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ImplicitWarning_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Methods/Obsolete_ImplicitWarning_WithMessage @@ -1,4 +1,5 @@ -public void Obsolete_ImplicitWarning_WithMessage() +[System.Diagnostics.DebuggerStepThrough] +public void Obsolete_ImplicitWarning_WithMessage() { Context.Log.Warning("Warning: The alias Obsolete_ImplicitWarning_WithMessage has been made obsolete. Please use Foo.Bar instead."); #pragma warning disable 0618 diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Dynamic_Type b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Dynamic_Type index 96dfcefd11..b57a1679d3 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Dynamic_Type +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Dynamic_Type @@ -1,6 +1,7 @@ private dynamic _Cached_Dynamic_Type; public dynamic Cached_Dynamic_Type { + [System.Diagnostics.DebuggerStepThrough] get { if (_Cached_Dynamic_Type==null) diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ExplicitError_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ExplicitError_WithMessage index 57c6caf94f..0d109964de 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ExplicitError_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ExplicitError_WithMessage @@ -1,5 +1,6 @@ public System.Int32 Cached_Obsolete_ExplicitError_WithMessage { + [System.Diagnostics.DebuggerStepThrough] get { throw new Cake.Core.CakeException("The alias Cached_Obsolete_ExplicitError_WithMessage has been made obsolete. Please use Foo.Bar instead."); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ExplicitWarning_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ExplicitWarning_WithMessage index 6bca364694..a54cb38ce5 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ExplicitWarning_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ExplicitWarning_WithMessage @@ -2,6 +2,7 @@ [Obsolete("Please use Foo.Bar instead.")] public System.Int32 Cached_Obsolete_ExplicitWarning_WithMessage { + [System.Diagnostics.DebuggerStepThrough] get { Context.Log.Warning("Warning: The alias Cached_Obsolete_ExplicitWarning_WithMessage has been made obsolete. Please use Foo.Bar instead."); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ImplicitWarning_NoMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ImplicitWarning_NoMessage index 65364704a2..0b5db4d12e 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ImplicitWarning_NoMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ImplicitWarning_NoMessage @@ -2,6 +2,7 @@ [Obsolete] public System.Int32 Cached_Obsolete_ImplicitWarning_NoMessage { + [System.Diagnostics.DebuggerStepThrough] get { Context.Log.Warning("Warning: The alias Cached_Obsolete_ImplicitWarning_NoMessage has been made obsolete."); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ImplicitWarning_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ImplicitWarning_WithMessage index 89f6e79c79..ffb6c8c272 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ImplicitWarning_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Obsolete_ImplicitWarning_WithMessage @@ -2,6 +2,7 @@ [Obsolete("Please use Foo.Bar instead.")] public System.Int32 Cached_Obsolete_ImplicitWarning_WithMessage { + [System.Diagnostics.DebuggerStepThrough] get { Context.Log.Warning("Warning: The alias Cached_Obsolete_ImplicitWarning_WithMessage has been made obsolete. Please use Foo.Bar instead."); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Reference_Type b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Reference_Type index 1df2421f9f..203e42b432 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Reference_Type +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Reference_Type @@ -1,6 +1,7 @@ private System.String _Cached_Reference_Type; public System.String Cached_Reference_Type { + [System.Diagnostics.DebuggerStepThrough] get { if (_Cached_Reference_Type==null) diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Value_Type b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Value_Type index 68bb776893..159ad45343 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Value_Type +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/Cached_Value_Type @@ -1,6 +1,7 @@ private System.Boolean? _Cached_Value_Type; public System.Boolean Cached_Value_Type { + [System.Diagnostics.DebuggerStepThrough] get { if (_Cached_Value_Type==null) diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Dynamic_Type b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Dynamic_Type index e1225c3e74..8afeee8917 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Dynamic_Type +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Dynamic_Type @@ -1,5 +1,6 @@ public dynamic NonCached_Dynamic_Type { + [System.Diagnostics.DebuggerStepThrough] get { return Cake.Core.Tests.Data.PropertyAliasGeneratorData.NonCached_Dynamic_Type(Context); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ExplicitError_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ExplicitError_WithMessage index 4eed195dcc..981d8ef161 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ExplicitError_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ExplicitError_WithMessage @@ -1,5 +1,6 @@ public System.Int32 NonCached_Obsolete_ExplicitError_WithMessage { + [System.Diagnostics.DebuggerStepThrough] get { throw new Cake.Core.CakeException("The alias NonCached_Obsolete_ExplicitError_WithMessage has been made obsolete. Please use Foo.Bar instead."); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ExplicitWarning_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ExplicitWarning_WithMessage index 102bc209f0..4fc0eb5f89 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ExplicitWarning_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ExplicitWarning_WithMessage @@ -1,5 +1,6 @@ public System.Int32 NonCached_Obsolete_ExplicitWarning_WithMessage { + [System.Diagnostics.DebuggerStepThrough] get { Context.Log.Warning("Warning: The alias NonCached_Obsolete_ExplicitWarning_WithMessage has been made obsolete. Please use Foo.Bar instead."); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ImplicitWarning_NoMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ImplicitWarning_NoMessage index be258ce45a..93e9bb7369 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ImplicitWarning_NoMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ImplicitWarning_NoMessage @@ -1,5 +1,6 @@ public System.Int32 NonCached_Obsolete_ImplicitWarning_NoMessage { + [System.Diagnostics.DebuggerStepThrough] get { Context.Log.Warning("Warning: The alias NonCached_Obsolete_ImplicitWarning_NoMessage has been made obsolete."); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ImplicitWarning_WithMessage b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ImplicitWarning_WithMessage index d82977bc0d..f6def61039 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ImplicitWarning_WithMessage +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Obsolete_ImplicitWarning_WithMessage @@ -1,5 +1,6 @@ public System.Int32 NonCached_Obsolete_ImplicitWarning_WithMessage { + [System.Diagnostics.DebuggerStepThrough] get { Context.Log.Warning("Warning: The alias NonCached_Obsolete_ImplicitWarning_WithMessage has been made obsolete. Please use Foo.Bar instead."); diff --git a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Value_Type b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Value_Type index cdfe390809..877caa66bf 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Value_Type +++ b/src/Cake.Core.Tests/Unit/Scripting/CodeGen/Expected/Properties/NonCached_Value_Type @@ -1,5 +1,6 @@ public System.Int32 NonCached_Value_Type { + [System.Diagnostics.DebuggerStepThrough] get { return Cake.Core.Tests.Data.PropertyAliasGeneratorData.NonCached_Value_Type(Context); diff --git a/src/Cake.Core.Tests/Unit/Scripting/ScriptRunnerTests.cs b/src/Cake.Core.Tests/Unit/Scripting/ScriptRunnerTests.cs index 799ed252e4..6918745332 100644 --- a/src/Cake.Core.Tests/Unit/Scripting/ScriptRunnerTests.cs +++ b/src/Cake.Core.Tests/Unit/Scripting/ScriptRunnerTests.cs @@ -117,7 +117,7 @@ public void Should_Throw_If_Script_Host_Is_Null() var runner = fixture.CreateScriptRunner(); // When - var result = Record.Exception(() => runner.Run(null, fixture.Script, fixture.ArgumentDictionary)); + var result = Record.Exception(() => runner.Run(null, fixture.Script)); // Then AssertEx.IsArgumentNullException(result, "host"); @@ -131,26 +131,12 @@ public void Should_Throw_If_Script_Is_Null() var runner = fixture.CreateScriptRunner(); // When - var result = Record.Exception(() => runner.Run(fixture.Host, null, fixture.ArgumentDictionary)); + var result = Record.Exception(() => runner.Run(fixture.Host, null)); // Then AssertEx.IsArgumentNullException(result, "scriptPath"); } - [Fact] - public void Should_Throw_If_Arguments_Are_Null() - { - // Given - var fixture = new ScriptRunnerFixture(); - var runner = fixture.CreateScriptRunner(); - - // When - var result = Record.Exception(() => runner.Run(fixture.Host, fixture.Script, null)); - - // Then - AssertEx.IsArgumentNullException(result, "arguments"); - } - [Fact] public void Should_Create_Session_Via_Session_Factory() { @@ -159,7 +145,7 @@ public void Should_Create_Session_Via_Session_Factory() var runner = fixture.CreateScriptRunner(); // When - runner.Run(fixture.Host, fixture.Script, fixture.ArgumentDictionary); + runner.Run(fixture.Host, fixture.Script); // Then fixture.Engine.Received(1).CreateSession(fixture.Host); @@ -173,35 +159,12 @@ public void Should_Set_Working_Directory_To_Script_Directory() var runner = fixture.CreateScriptRunner(); // When - runner.Run(fixture.Host, fixture.Script, fixture.ArgumentDictionary); + runner.Run(fixture.Host, fixture.Script); // Then Assert.Equal("/build", fixture.Environment.WorkingDirectory.FullPath); } -#if !NETCORE - [Theory] - [InlineData("mscorlib")] - [InlineData("System")] - [InlineData("System.Core")] - [InlineData("System.Data")] - [InlineData("System.Xml")] - [InlineData("System.Xml.Linq")] - public void Should_Add_References_To_Session(string assemblyName) - { - // Given - var fixture = new ScriptRunnerFixture(); - var runner = fixture.CreateScriptRunner(); - - // When - runner.Run(fixture.Host, fixture.Script, fixture.ArgumentDictionary); - - // Then - fixture.Session.Received(1).AddReference( - Arg.Is(a => a.FullName.StartsWith(assemblyName + ", ", StringComparison.OrdinalIgnoreCase))); - } -#endif - [Theory] [InlineData("System")] [InlineData("System.Collections.Generic")] @@ -220,7 +183,7 @@ public void Should_Add_Namespaces_To_Session(string @namespace) var runner = fixture.CreateScriptRunner(); // When - runner.Run(fixture.Host, fixture.Script, fixture.ArgumentDictionary); + runner.Run(fixture.Host, fixture.Script); // Then fixture.Session.Received(1).ImportNamespace(@namespace); @@ -234,7 +197,7 @@ public void Should_Generate_Script_Aliases() var runner = fixture.CreateScriptRunner(); // When - runner.Run(fixture.Host, fixture.Script, fixture.ArgumentDictionary); + runner.Run(fixture.Host, fixture.Script); // Then fixture.AliasFinder.Received(1).FindAliases( @@ -249,7 +212,7 @@ public void Should_Execute_Script_Code() var runner = fixture.CreateScriptRunner(); // When - runner.Run(fixture.Host, fixture.Script, fixture.ArgumentDictionary); + runner.Run(fixture.Host, fixture.Script); // Then fixture.Session.Received(1).Execute(Arg.Any