2017-01-24 08:46:20 +03:00
#I @"tools/FAKE/tools"
2016-11-24 13:52:29 +03:00
#r "FakeLib.dll"
open System
open System.IO
open System.Text
2017-01-24 08:46:20 +03:00
open Fake
open Fake.DotNetCli
2018-01-18 09:58:03 +03:00
open Fake.DocFxHelper
2016-11-24 13:52:29 +03:00
2018-01-18 09:58:03 +03:00
// Information about the project for Nuget and Assembly info files
2019-10-03 17:22:28 +03:00
let product = "Hyperion"
2016-11-24 13:52:29 +03:00
let configuration = "Release"
2019-10-03 17:22:28 +03:00
// Metadata used when signing packages and DLLs
let signingName = "Hyperion"
let signingDescription = "A high performance polymorphic serializer for the .NET framework"
let signingUrl = ""
2018-01-18 09:58:03 +03:00
// Read release notes and version
let solutionFile = FindFirstMatchingFile "*.sln" __SOURCE_DIRECTORY__ // dynamically look up the solution
2017-07-24 18:28:57 +03:00
let buildNumber = environVarOrDefault "BUILD_NUMBER" "0"
2019-10-03 17:22:28 +03:00
let hasTeamCity = (not (buildNumber = "0")) // check if we have the TeamCity environment variable for build # set
let preReleaseVersionSuffix = "beta" + (if (not (buildNumber = "0")) then (buildNumber) else DateTime.UtcNow.Ticks.ToString())
2017-07-24 18:28:57 +03:00
let versionSuffix =
match (getBuildParam "nugetprerelease") with
2018-01-18 09:58:03 +03:00
| "dev" -> preReleaseVersionSuffix
2017-07-24 18:28:57 +03:00
| _ -> ""
2018-01-18 09:58:03 +03:00
let releaseNotes =
File.ReadLines "./RELEASE_NOTES.md"
|> ReleaseNotesHelper.parseReleaseNotes
// Directories
let toolsDir = __SOURCE_DIRECTORY__ @@ "tools"
let output = __SOURCE_DIRECTORY__ @@ "bin"
let outputTests = __SOURCE_DIRECTORY__ @@ "TestResults"
let outputPerfTests = __SOURCE_DIRECTORY__ @@ "PerfResults"
let outputNuGet = output @@ "nuget"
2017-01-24 08:46:20 +03:00
Target "Clean" (fun _ ->
2019-10-03 17:22:28 +03:00
ActivateFinalTarget "KillCreatedProcesses"
2017-01-24 08:46:20 +03:00
CleanDir output
CleanDir outputTests
CleanDir outputPerfTests
CleanDir outputNuGet
2018-01-18 09:58:03 +03:00
CleanDir "docs/_site"
2017-01-24 08:46:20 +03:00
)
2016-11-24 13:52:29 +03:00
2018-01-18 09:58:03 +03:00
Target "AssemblyInfo" (fun _ ->
XmlPokeInnerText "./src/common.props" "//Project/PropertyGroup/VersionPrefix" releaseNotes.AssemblyVersion
XmlPokeInnerText "./src/common.props" "//Project/PropertyGroup/PackageReleaseNotes" (releaseNotes.Notes |> String.concat "\n")
)
2017-07-24 18:28:57 +03:00
2019-10-03 17:22:28 +03:00
Target "Build" (fun _ ->
DotNetCli.Build
2017-01-24 08:46:20 +03:00
(fun p ->
{ p with
2018-01-18 09:58:03 +03:00
Project = solutionFile
2019-10-03 17:22:28 +03:00
Configuration = configuration }) // "Rebuild"
2016-11-24 13:52:29 +03:00
)
2018-01-18 09:58:03 +03:00
//--------------------------------------------------------------------------------
// Tests targets
//--------------------------------------------------------------------------------
module internal ResultHandling =
let (|OK|Failure|) = function
| 0 -> OK
| x -> Failure x
2016-11-24 13:52:29 +03:00
2018-01-18 09:58:03 +03:00
let buildErrorMessage = function
| OK -> None
| Failure errorCode ->
Some (sprintf "xUnit2 reported an error (Error Code %d)" errorCode)
2016-11-24 13:52:29 +03:00
2018-01-18 09:58:03 +03:00
let failBuildWithMessage = function
| DontFailBuild -> traceError
| _ -> (fun m -> raise(FailedTestsException m))
2016-11-24 22:27:14 +03:00
2018-01-18 09:58:03 +03:00
let failBuildIfXUnitReportedError errorLevel =
buildErrorMessage
>> Option.iter (failBuildWithMessage errorLevel)
2017-01-24 08:46:20 +03:00
2018-01-18 09:58:03 +03:00
Target "RunTests" (fun _ ->
let projects =
match (isWindows) with
| true -> !! "./src/**/*.Tests.csproj"
| _ -> !! "./src/**/*.Tests.csproj" // if you need to filter specs for Linux vs. Windows, do it here
let runSingleProject project =
2019-10-03 17:22:28 +03:00
let arguments =
match (hasTeamCity) with
| true -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --results-directory %s -- -parallel none -teamcity" (outputTests))
| false -> (sprintf "test -c Release --no-build --logger:trx --logger:\"console;verbosity=normal\" --results-directory %s -- -parallel none" (outputTests))
2018-01-18 09:58:03 +03:00
let result = ExecProcess(fun info ->
info.FileName <- "dotnet"
info.WorkingDirectory <- (Directory.GetParent project).FullName
2019-10-03 17:22:28 +03:00
info.Arguments <- arguments) (TimeSpan.FromMinutes 30.0)
2018-01-18 09:58:03 +03:00
2019-10-03 17:22:28 +03:00
ResultHandling.failBuildIfXUnitReportedError TestRunnerErrorLevel.Error result
2018-01-18 09:58:03 +03:00
projects |> Seq.iter (log)
projects |> Seq.iter (runSingleProject)
2017-01-24 08:46:20 +03:00
)
2016-11-24 22:27:14 +03:00
2018-01-18 09:58:03 +03:00
Target "NBench" <| fun _ ->
let nbenchTestPath = findToolInSubPath "NBench.Runner.exe" (toolsDir @@ "NBench.Runner*")
printfn "Using NBench.Runner: %s" nbenchTestPath
2017-01-31 11:47:19 +03:00
2019-10-03 17:22:28 +03:00
let nbenchTestAssemblies = !! "./src/**/bin/**/*Tests.Performance.dll" // doesn't support .NET Core at the moment
2018-01-18 09:58:03 +03:00
let runNBench assembly =
let includes = getBuildParam "include"
let excludes = getBuildParam "exclude"
let teamcityStr = (getBuildParam "teamcity")
let enableTeamCity =
match teamcityStr with
| null -> false
| "" -> false
| _ -> bool.Parse teamcityStr
2016-11-24 22:27:14 +03:00
2018-01-18 09:58:03 +03:00
let args = StringBuilder()
2016-11-24 22:27:14 +03:00
|> append assembly
2017-01-24 08:46:20 +03:00
|> append (sprintf "output-directory=\"%s\"" outputPerfTests)
|> append (sprintf "concurrent=\"%b\"" true)
2016-11-24 22:27:14 +03:00
|> append (sprintf "trace=\"%b\"" true)
2018-01-18 09:58:03 +03:00
|> append (sprintf "teamcity=\"%b\"" enableTeamCity)
|> appendIfNotNullOrEmpty includes "include="
|> appendIfNotNullOrEmpty excludes "include="
2016-11-24 22:27:14 +03:00
|> toText
let result = ExecProcess(fun info ->
info.FileName <- nbenchTestPath
info.WorkingDirectory <- (Path.GetDirectoryName (FullName nbenchTestPath))
2018-01-18 09:58:03 +03:00
info.Arguments <- args) (System.TimeSpan.FromMinutes 45.0) (* Reasonably long-running task. *)
2019-10-03 17:22:28 +03:00
2016-11-24 22:27:14 +03:00
if result <> 0 then failwithf "NBench.Runner failed. %s %s" nbenchTestPath args
2018-01-18 09:58:03 +03:00
nbenchTestAssemblies |> Seq.iter runNBench
2016-11-24 13:52:29 +03:00
2019-10-03 17:22:28 +03:00
//--------------------------------------------------------------------------------
// Code signing targets
//--------------------------------------------------------------------------------
Target "SignPackages" (fun _ ->
let canSign = hasBuildParam "SignClientSecret" && hasBuildParam "SignClientUser"
if(false) then
log "Signing information is available."
let assemblies = !! (outputNuGet @@ "*.nupkg")
let signPath =
let globalTool = tryFindFileOnPath "SignClient.exe"
match globalTool with
| Some t -> t
| None -> if isWindows then findToolInSubPath "SignClient.exe" "tools/signclient"
elif isMacOS then findToolInSubPath "SignClient" "tools/signclient"
else findToolInSubPath "SignClient" "tools/signclient"
let signAssembly assembly =
let args = StringBuilder()
|> append "sign"
|> append "--config"
|> append (__SOURCE_DIRECTORY__ @@ "appsettings.json")
|> append "-i"
|> append assembly
|> append "-r"
|> append (getBuildParam "SignClientUser")
|> append "-s"
|> append (getBuildParam "SignClientSecret")
|> append "-n"
|> append signingName
|> append "-d"
|> append signingDescription
|> append "-u"
|> append signingUrl
|> toText
let result = ExecProcess(fun info ->
info.FileName <- signPath
info.WorkingDirectory <- __SOURCE_DIRECTORY__
info.Arguments <- args) (System.TimeSpan.FromMinutes 5.0) (* Reasonably long-running task. *)
if result <> 0 then failwithf "SignClient failed.%s" args
assemblies |> Seq.iter (signAssembly)
else
log "SignClientSecret not available. Skipping signing"
)
2017-01-31 11:47:19 +03:00
//--------------------------------------------------------------------------------
// Nuget targets
//--------------------------------------------------------------------------------
2018-01-18 09:58:03 +03:00
let overrideVersionSuffix (project:string) =
match project with
| _ -> versionSuffix // add additional matches to publish different versions for different projects in solution
Target "CreateNuget" (fun _ ->
let projects = !! "src/**/*.csproj"
-- "src/**/*Tests.csproj" // Don't publish unit tests
-- "src/**/*Tests*.csproj"
let runSingleProject project =
DotNetCli.Pack
(fun p ->
{ p with
Project = project
Configuration = configuration
2019-10-03 17:22:28 +03:00
AdditionalArgs = ["--include-symbols --no-build"]
2018-01-18 09:58:03 +03:00
VersionSuffix = overrideVersionSuffix project
OutputPath = outputNuGet })
projects |> Seq.iter (runSingleProject)
2017-01-24 08:46:20 +03:00
)
2016-11-24 13:52:29 +03:00
2017-01-30 19:55:29 +03:00
Target "PublishNuget" (fun _ ->
2018-01-18 09:58:03 +03:00
let projects = !! "./bin/nuget/*.nupkg" -- "./bin/nuget/*.symbols.nupkg"
2017-01-30 19:55:29 +03:00
let apiKey = getBuildParamOrDefault "nugetkey" ""
let source = getBuildParamOrDefault "nugetpublishurl" ""
let symbolSource = getBuildParamOrDefault "symbolspublishurl" ""
2017-08-11 20:30:24 +03:00
let shouldPublishSymbolsPackages = not (symbolSource = "")
2017-01-30 19:55:29 +03:00
2017-08-11 20:30:24 +03:00
if (not (source = "") && not (apiKey = "") && shouldPublishSymbolsPackages) then
let runSingleProject project =
DotNetCli.RunCommand
(fun p ->
{ p with
TimeOut = TimeSpan.FromMinutes 10. })
(sprintf "nuget push %s --api-key %s --source %s --symbol-source %s" project apiKey source symbolSource)
projects |> Seq.iter (runSingleProject)
else if (not (source = "") && not (apiKey = "") && not shouldPublishSymbolsPackages) then
let runSingleProject project =
DotNetCli.RunCommand
(fun p ->
{ p with
TimeOut = TimeSpan.FromMinutes 10. })
(sprintf "nuget push %s --api-key %s --source %s" project apiKey source)
2017-01-30 19:55:29 +03:00
2017-08-11 20:30:24 +03:00
projects |> Seq.iter (runSingleProject)
2017-01-30 19:55:29 +03:00
)
2018-01-18 09:58:03 +03:00
//--------------------------------------------------------------------------------
// Documentation
//--------------------------------------------------------------------------------
Target "DocFx" (fun _ ->
DotNetCli.Restore (fun p -> { p with Project = solutionFile })
DotNetCli.Build (fun p -> { p with Project = solutionFile; Configuration = configuration })
let docsPath = "./docs"
DocFx (fun p ->
{ p with
Timeout = TimeSpan.FromMinutes 30.0;
WorkingDirectory = docsPath;
DocFxJson = docsPath @@ "docfx.json" })
)
2019-10-03 17:22:28 +03:00
//--------------------------------------------------------------------------------
// Cleanup
//--------------------------------------------------------------------------------
FinalTarget "KillCreatedProcesses" (fun _ ->
log "Shutting down dotnet build-server"
let result = ExecProcess(fun info ->
info.FileName <- "dotnet"
info.WorkingDirectory <- __SOURCE_DIRECTORY__
info.Arguments <- "build-server shutdown") (System.TimeSpan.FromMinutes 2.0)
if result <> 0 then failwithf "dotnet build-server shutdown failed"
)
2016-11-24 13:52:29 +03:00
//--------------------------------------------------------------------------------
// Help
//--------------------------------------------------------------------------------
Target "Help" <| fun _ ->
List.iter printfn [
"usage:"
2018-01-18 09:58:03 +03:00
"./build.ps1 [target]"
2016-11-24 13:52:29 +03:00
""
" Targets for building:"
2019-10-03 17:22:28 +03:00
" * Build Builds"
" * Nuget Create and optionally publish nugets packages"
" * SignPackages Signs all NuGet packages, provided that the following arguments are passed into the script: SignClientSecret={secret} and SignClientUser={username}"
" * RunTests Runs tests"
" * All Builds, run tests, creates and optionally publish nuget packages"
" * DocFx Creates a DocFx-based website for this solution"
2016-11-24 13:52:29 +03:00
""
" Other Targets"
" * Help Display this help"
""]
//--------------------------------------------------------------------------------
// Target dependencies
//--------------------------------------------------------------------------------
2017-01-24 08:46:20 +03:00
Target "BuildRelease" DoNothing
Target "All" DoNothing
2017-01-31 11:47:19 +03:00
Target "Nuget" DoNothing
2017-01-24 08:46:20 +03:00
2016-11-24 13:52:29 +03:00
// build dependencies
2019-10-03 17:22:28 +03:00
"Clean" ==> "AssemblyInfo" ==> "Build" ==> "BuildRelease"
2016-11-24 13:52:29 +03:00
// tests dependencies
2019-10-03 17:22:28 +03:00
"Build" ==> "RunTests"
2016-11-24 22:27:14 +03:00
2016-11-24 13:52:29 +03:00
// nuget dependencies
2019-10-03 17:22:28 +03:00
"Clean" ==> "Build" ==> "CreateNuget"
"CreateNuget" ==> "SignPackages" ==> "PublishNuget" ==> "Nuget"
2018-01-18 09:58:03 +03:00
// docs
2019-10-03 17:22:28 +03:00
"Clean" ==> "BuildRelease" ==> "Docfx"
2016-11-24 13:52:29 +03:00
2017-01-24 08:46:20 +03:00
// all
2016-11-24 13:52:29 +03:00
"BuildRelease" ==> "All"
"RunTests" ==> "All"
2019-10-03 17:22:28 +03:00
"NBench" ==> "All"
2017-08-17 23:18:27 +03:00
"Nuget" ==> "All"
2016-11-24 13:52:29 +03:00
RunTargetOrDefault "Help"