build/scripts/Targets.fs (178 lines of code) (raw):
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information
module Targets
open Argu
open System.IO
open CommandLine
open Fake.Core
open Fake.IO
open Fake.Tools.Git
open Proc.Fs
open BuildInformation
let private clean _ =
exec { run "dotnet" "clean" "-c" "release" }
let removeArtifacts folder = Shell.cleanDir (Paths.ArtifactPath folder).FullName
removeArtifacts "package"
removeArtifacts "release-notes"
removeArtifacts "tests"
let private compile _ = exec { run "dotnet" "build" "-c" "release" }
let private build _ = printfn "build"
let private release _ = printfn "release"
let private version _ =
let version = Software.Version
printfn $"Informational version: %s{version.AsString}"
printfn $"Semantic version: %s{version.NormalizeToShorter()}"
let otelVersion = Software.OpenTelemetryVersion;
printfn $"OpenTelemetry version: %s{otelVersion.AsString}"
let otelAutoVersion = Software.OpenTelemetryAutoInstrumentationVersion;
printfn $"OpenTelemetry Auto Instrumentation version: %s{otelAutoVersion.AsString}"
let private generatePackages _ = exec { run "dotnet" "pack" }
let private format _ = exec { run "dotnet" "format" "--verbosity" "quiet" }
let private checkFormat _ =
match exec { exit_code_of "dotnet" "format" "--verify-no-changes" } with
| 0 -> printfn "There are no dotnet formatting violations, continuing the build."
| _ -> failwithf "There are dotnet formatting violations. Call `dotnet format` to fix or specify -c to ./build.sh to skip this check"
let private pristineCheck (arguments:ParseResults<Build>) =
let skipCheck = arguments.TryGetResult Skip_Dirty_Check |> Option.isSome
match skipCheck, Information.isCleanWorkingCopy "." with
| true, _ -> printfn "Skip checking for clean working copy since -c is specified"
| _, true -> printfn "The checkout folder does not have pending changes, proceeding"
| _ -> failwithf "The checkout folder has pending changes, aborting. Specify -c to ./build.sh to skip this check"
match skipCheck, (exec { exit_code_of "dotnet" "format" "--verify-no-changes" }) with
| true, _ -> printfn "Skip formatting checks since -c is specified"
| _, 0 -> printfn "There are no dotnet formatting violations, continuing the build."
| _ -> failwithf "There are dotnet formatting violations. Call `dotnet format` to fix or specify -c to ./build.sh to skip this check"
let private runTests suite _ =
let logger =
// use junit xml logging locally, github actions logs using console out formats
match BuildServer.isGitHubActionsBuild with
| true -> "--logger:\"GitHubActions;summary.includePassedTests=false;summary.includeNotFoundTests=false\""
| false ->
let testOutputPath = Paths.ArtifactPath "tests"
let junitOutput = Path.Combine(testOutputPath.FullName, "junit-{assembly}-{framework}-test-results.xml")
let loggerPathArgs = $"LogFilePath=%s{junitOutput}"
$"--logger:\"junit;%s{loggerPathArgs}\""
let filterArgs =
match suite with
| All -> []
| Skip_All -> ["--filter"; "FullyQualifiedName~.SKIPPING.ALL.TESTS"]
| Unit -> [ "--filter"; "FullyQualifiedName~.Tests" ]
| Integration -> [ "--filter"; "FullyQualifiedName~.IntegrationTests" ]
| E2E -> [ "--filter"; "FullyQualifiedName~.EndToEndTests" ]
| Skip_E2E -> [ "--filter"; "FullyQualifiedName!~.EndToEndTests" ]
let settingsArg = ["-s"; "tests/.runsettings"]
let tfmArgs =
if OS.Current = Windows then []
elif suite.Equals(E2E) then ["-f"; "net8.0"]
else ["-f"; "net9.0"]
exec {
env (Map ["TEST_SUITE", suite.SuitName])
run "dotnet" (
["test"; "-c"; "release"; "--no-restore"; "--no-build"; logger]
@ settingsArg
@ filterArgs
@ tfmArgs
@ ["--"; "RunConfiguration.CollectSourceInformation=true"]
)
}
let private test (arguments:ParseResults<Build>) =
let arg = arguments.TryGetResult Test_Suite
match arg with
| None -> runTests TestSuite.All arguments
| Some suite ->
match suite with
| Skip_All -> printfn "Skipping tests because --test-suite skip was provided"
| _ -> runTests suite arguments
let private validateLicenses _ =
let args = ["-u"; "-t"; "-i"; "Elastic.OpenTelemetry.sln"; "--use-project-assets-json"
"--forbidden-license-types"; "build/forbidden-license-types.json"
"--packages-filter"; "#System\..*#";]
exec { run "dotnet" (["dotnet-project-licenses"] @ args) }
let private validatePackages _ =
let packagesPath = Paths.ArtifactPath "package"
let output = Paths.RelativePathToRoot <| packagesPath.FullName
let nugetPackages =
packagesPath.GetFiles("*.nupkg", SearchOption.AllDirectories)
|> Seq.sortByDescending(fun f -> f.CreationTimeUtc)
|> Seq.map (fun p -> Paths.RelativePathToRoot p.FullName)
let args = ["-v"; Software.Version.AsString; "-k"; Software.SignKey; "-t"; output]
nugetPackages
|> Seq.iter (fun p ->
exec { run "dotnet" (["nupkg-validator"; p] @ args) }
)
let private generateApiChanges _ =
let packagesPath = Paths.ArtifactPath "package"
let output = Paths.RelativePathToRoot <| packagesPath.FullName
let currentVersion = Software.Version.NormalizeToShorter()
let nugetPackages =
packagesPath.GetFiles("*.nupkg", SearchOption.AllDirectories)
|> Seq.sortByDescending(fun f -> f.CreationTimeUtc)
|> Seq.map (fun p -> Path.GetFileNameWithoutExtension(Paths.RelativePathToRoot p.FullName).Replace("." + currentVersion, ""))
nugetPackages
|> Seq.iter(fun p ->
let outputFile = Path.Combine(output, $"breaking-changes-%s{p}.md")
let tfm = "net8.0" // We use net8.0 as AutoInstrumentation doesn't have a net9.0 target
let args =
[
"assembly-differ"
$"previous-nuget|%s{p}|%s{currentVersion}|%s{tfm}";
$"directory|.artifacts/bin/%s{p}/release_%s{tfm}";
"-a"; "true"; "--target"; p; "-f"; "github-comment"; "--output"; outputFile
]
exec { run "dotnet" args }
)
let private generateReleaseNotes (arguments:ParseResults<Build>) =
let currentVersion = Software.Version.NormalizeToShorter()
let releaseNotesPath = Paths.ArtifactPath "release-notes"
let output =
Paths.RelativePathToRoot <| Path.Combine(releaseNotesPath.FullName, $"release-notes-%s{currentVersion}.md")
let tokenArgs =
match arguments.TryGetResult Token with
| None -> []
| Some token -> ["--token"; token;]
let releaseNotesArgs =
(Software.GithubMoniker.Split("/") |> Seq.toList)
@ ["--version"; currentVersion
"--label"; "enhancement"; "Features"
"--label"; "bug"; "Fixes"
"--label"; "documentation"; "Documentation"
] @ tokenArgs
@ ["--output"; output]
let args = ["release-notes"] @ releaseNotesArgs
exec { run "dotnet" args }
let Setup (parsed:ParseResults<Build>) =
let wireCommandLine (t: Build) =
match t with
// commands
| Version -> Build.Step version
| Clean -> Build.Cmd [Version] [] clean
| Compile -> Build.Step compile
| Build -> Build.Cmd [Clean; CheckFormat; Compile] [] build
| End_To_End -> Build.Cmd [] [Build] <| runTests E2E
| Integrate -> Build.Cmd [] [Build] <| runTests Integration
| Unit_Test -> Build.Cmd [] [Build] <| runTests Unit
| Test -> Build.Cmd [] [Build] test
| Redistribute -> Build.Cmd [] [] Packaging.redistribute
| Release ->
Build.Cmd
[PristineCheck; Build; Redistribute]
[ValidateLicenses; GeneratePackages; ValidatePackages; GenerateReleaseNotes]
release
| Format -> Build.Step format
// steps
| CheckFormat -> Build.Step checkFormat
| PristineCheck -> Build.Step pristineCheck
| GeneratePackages -> Build.Step generatePackages
| ValidateLicenses -> Build.Step validateLicenses
| ValidatePackages -> Build.Step validatePackages
| GenerateReleaseNotes -> Build.Step generateReleaseNotes
| GenerateApiChanges -> Build.Step generateApiChanges
// flags
| Single_Target
| Test_Suite _
| Token _
| Skip_Dirty_Check -> Build.Ignore
for target in Build.Targets do
let setup = wireCommandLine target
setup target parsed