Skip to content

Commit

Permalink
Merge pull request #2438 from vilinski/sonarscanner
Browse files Browse the repository at this point in the history
Sonarscanner
  • Loading branch information
matthid authored Dec 17, 2019
2 parents 56b3f7e + 06d7e74 commit 1aac550
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 113 deletions.
3 changes: 2 additions & 1 deletion src/app/Fake.Testing.SonarQube/Fake.Testing.SonarQube.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk" >
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
<DefineConstants>$(DefineConstants);NO_DOTNETCORE_BOOTSTRAP</DefineConstants>
Expand All @@ -19,6 +19,7 @@
<ItemGroup>
<ProjectReference Include="..\Fake.Core.Trace\Fake.Core.Trace.fsproj" />
<ProjectReference Include="..\Fake.Core.Process\Fake.Core.Process.fsproj" />
<ProjectReference Include="..\Fake.DotNet.Cli\Fake.DotNet.Cli.fsproj" />
<ProjectReference Include="..\Fake.IO.FileSystem\Fake.IO.FileSystem.fsproj" />
</ItemGroup>
<Import Project="..\..\..\.paket\Paket.Restore.targets" />
Expand Down
270 changes: 159 additions & 111 deletions src/app/Fake.Testing.SonarQube/SonarQube.fs
Original file line number Diff line number Diff line change
@@ -1,121 +1,169 @@
/// Contains a task to run the msbuild runner of [SonarQube analyzer](http://sonarqube.org).
/// Contains a task to run the [SonarQube](http://sonarqube.org) static code analyzer.
/// It uses the [SonarScanner for MSBuild](https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-msbuild/)
module Fake.Testing.SonarQube

open System.IO
open Fake.Core
open Fake.IO.Globbing
open Fake.IO.FileSystemOperators
open System.IO
open Fake.Core
open Fake.DotNet

/// [omit]
/// The supported commands of SonarQube. It is called with Begin before compilation, and End after compilation.
type internal SonarQubeCall = Begin | End
/// [omit]
/// The supported commands of SonarQube. It is called with Begin before compilation, and End after compilation.
type internal SonarQubeCall =
| Begin
| End

/// Parameter type to configure the SonarQube runner.
type SonarQubeParams = {
/// FileName of the SonarQube runner exe.
ToolsPath : string
/// Organization which owns the SonarQube project
Organization : string option
/// Key to identify the SonarQube project
Key : string
/// Name of the project
Name : string
/// Version number of the project
Version : string
/// Individual global settings for SonarQube
Settings : string list
/// Read settings from configuration file
Config : string option
}
/// Parameter type to configure the SonarQube runner.
type SonarQubeParams =
{ /// The directory where the SonarQube scanner process will be started.
WorkingDirectory: string
/// Tool type
ToolType: ToolType
/// FileName of the SonarQube runner exe.
ToolsPath: string
/// Organization which owns the SonarQube project
Organization: string option
/// Key to identify the SonarQube project
Key: string
/// Name of the project
Name: string
/// Version number of the project
Version: string
/// Individual global settings for SonarQube
Settings: string list
/// Read settings from configuration file
Config: string option }

/// SonarQube default parameters - tries to locate MSBuild.SonarQube.exe in any subfolder.
let internal SonarQubeDefaults =
{ ToolsPath = Tools.findToolInSubPath "MSBuild.SonarQube.Runner.exe" (Directory.GetCurrentDirectory() @@ "tools" @@ "SonarQube")
Organization = None
Key = null
Name = null
Version = "1.0"
Settings = []
Config = None }
/// SonarQube default parameters
let internal SonarQubeDefaults =
{ WorkingDirectory = Directory.GetCurrentDirectory()
ToolType = ToolType.Create()
ToolsPath = ProcessUtils.findLocalTool "TOOL" "MSBuild.SonarQube.Runner.exe" [ "." ]
Organization = None
Key = null
Name = null
Version = "1.0"
Settings = []
Config = None }

/// [omit]
/// Execute the external msbuild runner of SonarQube. Parameters are given to the command line tool as required.
let internal getSonarQubeCallParams (call: SonarQubeCall) (parameters : SonarQubeParams) =
let beginInitialArguments =
Arguments.Empty
|> Arguments.appendRaw "begin"
|> Arguments.appendRawEscapedNotEmpty "/k:" parameters.Key
|> Arguments.appendRawEscapedNotEmpty "/n:" parameters.Name
|> Arguments.appendRawEscapedNotEmpty "/v:" parameters.Version
|> Arguments.appendRawEscapedOption "/o:" parameters.Organization
|> Arguments.appendRawEscapedOption "/s:" parameters.Config

let beginCall =
parameters.Settings
|> List.fold (fun arguments x -> arguments |> Arguments.appendRawEscaped "/d:" x) beginInitialArguments

let endInitialArguments =
Arguments.Empty
|> Arguments.appendRaw "end"
|> Arguments.appendRawEscapedOption "/s:" parameters.Config
let endCall =
parameters.Settings
|> List.fold (fun arguments x -> arguments |> Arguments.appendRawEscaped "/d:" x) endInitialArguments

match call with
| Begin -> beginCall
| End -> endCall
/// [omit]
/// Execute the external msbuild runner of SonarQube. Parameters are given to the command line tool as required.
let internal getSonarQubeCallParams (call: SonarQubeCall) (parameters: SonarQubeParams) =
let beginInitialArguments =
Arguments.Empty
|> Arguments.appendRaw "begin"
|> Arguments.appendRawEscapedNotEmpty "/k:" parameters.Key
|> Arguments.appendRawEscapedNotEmpty "/n:" parameters.Name
|> Arguments.appendRawEscapedNotEmpty "/v:" parameters.Version
|> Arguments.appendRawEscapedOption "/o:" parameters.Organization
|> Arguments.appendRawEscapedOption "/s:" parameters.Config

let private sonarQubeCall (call: SonarQubeCall) (parameters : SonarQubeParams) =
let sonarPath = parameters.ToolsPath
let result =
getSonarQubeCallParams call parameters
|> Arguments.toStartInfo
|> CreateProcess.fromRawCommandLine sonarPath
|> CreateProcess.withFramework
|> Proc.run
if result.ExitCode <> 0 then failwithf "Error during sonar qube call %s" (call.ToString())
let beginCall =
parameters.Settings
|> List.fold (fun arguments x -> arguments |> Arguments.appendRawEscaped "/d:" x) beginInitialArguments

/// This task to can be used to run the begin command of [Sonar Qube](http://sonarqube.org/) on a project.
/// ## Parameters
///
/// - `setParams` - Function used to overwrite the SonarQube default parameters.
///
/// ## Sample
let endInitialArguments =
Arguments.Empty
|> Arguments.appendRaw "end"
|> Arguments.appendRawEscapedOption "/s:" parameters.Config

/// open Fake.Testing
///
/// SonarQube.start (fun p ->
/// {p with
/// Key = "MyProject"
/// Name = "MainTool"
/// Version = "1.0 })
///
let start setParams =
use __ = Trace.traceTask "SonarQube" "Begin"
let parameters = setParams SonarQubeDefaults
sonarQubeCall Begin parameters
__.MarkSuccess()
let endCall =
parameters.Settings
|> List.fold (fun arguments x -> arguments |> Arguments.appendRawEscaped "/d:" x) endInitialArguments

/// This task to can be used to run the end command of [Sonar Qube](http://sonarqube.org/) on a project.
/// ## Parameters
///
/// - `setParams` - Function used to overwrite the SonarQube default parameters.
///
/// ## Sample
/// open Fake.Testing
///
/// SonarQube.finish None
///
/// SonarQube.finish (Some (fun p ->
/// {p with
/// Settings = ["sonar.login=login"; "sonar.password=password"] }))
///
let finish setParams =
use __ = Trace.traceTask "SonarQube" "End"
let parameters = match setParams with
| Some setParams -> setParams SonarQubeDefaults
| None -> (fun p -> { p with Settings = [] }) SonarQubeDefaults
sonarQubeCall End parameters
__.MarkSuccess()
match call with
| Begin -> beginCall
| End -> endCall

let private sonarQubeCall (call: SonarQubeCall) (parameters: SonarQubeParams) =
let args = getSonarQubeCallParams call parameters
CreateProcess.fromCommand (RawCommand(parameters.ToolsPath, args))
|> CreateProcess.withToolType (parameters.ToolType.WithDefaultToolCommandName "sonarscanner")
|> CreateProcess.withWorkingDirectory parameters.WorkingDirectory
|> CreateProcess.ensureExitCode
|> Proc.run
|> ignore

/// This task can be used to run the begin command of [Sonar Qube](http://sonarqube.org/) on a project.
/// ## Parameters
///
/// - `setParams` - Function used to overwrite the SonarQube default parameters.
///
/// ## Sample
///
/// open Fake.Testing
///
/// SonarQube.start (fun p ->
/// { p with
/// Key = "MyProject"
/// Name = "MainTool"
/// Version = "1.0 })
///
let start setParams =
use __ = Trace.traceTask "SonarQube" "Begin"
let parameters = setParams SonarQubeDefaults
sonarQubeCall Begin parameters
__.MarkSuccess()

/// This task can be used to run the end command of [Sonar Qube](http://sonarqube.org/) on a project.
/// ## Parameters
///
/// - `setParams` - Function used to overwrite the SonarQube default parameters.
///
/// ## Sample
///
/// open Fake.Testing
///
/// SonarQube.finish None
///
/// SonarQube.finish (Some (fun p ->
/// { p with
/// Settings = ["sonar.login=login"; "sonar.password=password"] }))
///
let finish setParams =
use __ = Trace.traceTask "SonarQube" "End"

let parameters =
match setParams with
| Some setParams -> setParams SonarQubeDefaults
| None -> (fun p -> { p with Settings = [] }) SonarQubeDefaults
sonarQubeCall End parameters
__.MarkSuccess()

/// This task can be used to execute some code between
/// the `begin` and `end` [Sonar Qube](http://sonarqube.org/) on a project.
///
/// ## Parameters
///
/// - `setParams` - Function used to overwrite the SonarQube default parameters.
/// - `doBetween` - Function executed between `begin` and `end` [Sonar Qube](http://sonarqube.org/) commands.
///
/// ## Sample
///
/// ```
/// open Fake.Testing
///
/// Target.create "StaticAnalysis" (fun _ ->
/// let setParams p =
/// { p with Key = "ProjectKey"
/// Name = "ProjectName"
/// Version = "3.2.1"
/// Settings =
/// [ "sonar.host.url=" + SONAR_HOST_URL
/// "sonar.login=" + SONAR_TOKEN
/// "sonar.cs.opencover.reportsPaths=opencovercoverage.xml"
/// ]
/// // choose what you need
/// // https://fake.build/dotnet-cli.html#SDK-tools-local-global-clireference
/// ToolType = ToolType.CreateGlobalTool() // Start as dotnet global tool (`sonarscanner`)
/// ToolType = ToolType.CreateLocalTool() // Start as dotnet local tool (`dotnet sonarscanner`)
/// }
/// SonarQube.scan setParams (fun () ->
/// DotNet.build id
/// DotNet.test id
/// )
/// )
/// ```
let scan setParams doBetween =
start setParams
doBetween()
finish (Some setParams)
1 change: 0 additions & 1 deletion src/test/Fake.Core.UnitTests/Fake.Testing.SonarQube.fs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module Fake.Testing.SonarQubeTests

open System.IO
open Fake.Core
open Fake.Testing
open Expecto
Expand Down

0 comments on commit 1aac550

Please sign in to comment.