build/scripts/Building.fs (132 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.
namespace Scripts
open System.IO
open Scripts.Commandline
open Tooling
open Versioning
open Fake.Core
open Fake.IO
open Fake.IO.Globbing.Operators
open System.Xml
open System.Xml.Linq
open System.Xml.XPath
open System.IO.Compression
module Build =
let Restore () = DotNet.Exec ["restore"; Paths.Solution; ] |> ignore
let Compile _ version =
let props =
[
"CurrentVersion", (version.Full.ToString());
"CurrentAssemblyVersion", (version.Assembly.ToString());
"CurrentAssemblyFileVersion", (version.AssemblyFile.ToString());
]
|> List.map (fun (p,v) -> sprintf "%s=%s" p v)
|> String.concat ";"
|> sprintf "/property:%s"
DotNet.Exec ["build"; Paths.Solution; "-c"; "Release"; props] |> ignore
let Pack version =
let props =
[
"CurrentVersion", (version.Full.ToString());
"CurrentAssemblyVersion", (version.Assembly.ToString());
"CurrentAssemblyFileVersion", (version.AssemblyFile.ToString());
]
|> List.map (fun (p,v) -> sprintf "%s=%s" p v)
|> String.concat ";"
|> sprintf "/p:%s"
DotNet.Exec ["pack"; Paths.Solution; "-c"; "Release"; "-o"; Paths.NugetOutput ; props] |> ignore
let Clean (parsed:PassedArguments) =
let outputPath = match parsed.CommandArguments with | SetVersion c -> c.OutputLocation | _ -> None
printfn "Cleaning known output folders"
if (Option.isSome outputPath) then Shell.cleanDir outputPath.Value
Shell.cleanDir Paths.BuildOutput
DotNet.Exec ["clean"; Paths.Solution; "-c"; "Release"; "-v"; "q"]
let private keyFile = Paths.Keys "keypair.snk"
let private tmp = "build/output/tmp"
let VersionedPack version =
let packages = BuiltArtifacts version
let currentMajorVersion = version.Full.Major
let newId nugetId = sprintf "%s.v%i" nugetId currentMajorVersion
let replaceId nugetId str = str |> String.replace nugetId (newId nugetId)
let updatePackage package nugetId =
let nuspec = !! (sprintf "%s/*.nuspec" tmp) |> Seq.head
printfn "Validating: %s => %s" package nuspec
let xName n = XName.op_Implicit n
use stream = File.OpenRead <| nuspec
let doc = XDocument.Load(stream)
let nsManager = XmlNamespaceManager(doc.CreateNavigator().NameTable);
nsManager.AddNamespace("x", "http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd")
doc.XPathSelectElement("/x:package/x:metadata/x:id", nsManager).Value <- newId nugetId
let titleNode = doc.XPathSelectElement("/x:package/x:metadata/x:title", nsManager)
titleNode.Value <- sprintf "%i.x namespaced package, can be installed alongside %s" currentMajorVersion nugetId
let descriptionNode = doc.XPathSelectElement("/x:package/x:metadata/x:description", nsManager)
descriptionNode.Value <- sprintf "%i.x namespaced package, can be installed alongside %s" currentMajorVersion nugetId
let iconNode = doc.XPathSelectElement("/x:package/x:metadata/x:iconUrl", nsManager)
iconNode.Value <- iconNode.Value.Replace("icon", "icon-aux")
let iconNode = doc.XPathSelectElement("/x:package/x:metadata/x:icon", nsManager)
iconNode.Value <- iconNode.Value.Replace("icon", "icon-aux")
let deps =
doc.XPathSelectElements("/x:package//x:dependency", nsManager)
|> Seq.map (fun e -> e.Attribute(xName "id").Value)
|> Seq.filter (fun id -> packages |> Seq.exists (fun p -> p.NugetId = id))
|> Seq.toList
// update dependencies we've built to their versioned counterparts
doc.XPathSelectElements("/x:package//x:dependency", nsManager)
|> Seq.map (fun e -> (e, e.Attribute(xName "id").Value))
// filter packages that exist in the build output folder `tmp`
|> Seq.filter (fun (_, id) -> packages |> Seq.exists (fun p -> p.NugetId = id))
|> Seq.iter (fun (e, id) -> e.Attribute(xName "id").Value <- newId id)
doc.Save(nuspec |> replaceId nugetId)
stream.Dispose()
Shell.rm nuspec
deps
let rewriteLibFolder libFolder project nugetId dependencies =
let info = DirectoryInfo libFolder
let tfm = info.Name
let fullPath = Path.GetFullPath libFolder
let mainDll = sprintf "%s.dll" (Path.Combine(fullPath, project))
let renamedDll dll = dll |> String.replace ".dll" (sprintf "%i.dll" version.Full.Major)
printfn "dll: %s Nuget id: %s dependencies: %A" mainDll nugetId dependencies
let depAssemblies =
dependencies
|> Seq.map (fun d -> sprintf "%s.dll" (Path.Combine(Paths.InplaceBuildOutput project tfm, d)))
let dlls =
[mainDll]
|> Seq.append depAssemblies
|> Seq.map (fun dll ->
sprintf @"-i ""%s"" -o ""%s"" -k ""%s""" dll (renamedDll dll) keyFile
)
ReposTooling.Rewriter dlls
Shell.rm mainDll
let mainPdb = sprintf "%s.pdb" (Path.Combine(fullPath, project))
if File.exists mainPdb then Shell.rm mainPdb
packages
|> Seq.iter(fun p ->
Zip.unzip tmp p.Package
let nugetId = p.NugetId
let project = p.AssemblyName
//update nuget metadata
let deps = updatePackage p.Package nugetId
//rewrite assemblies to versioned counterparts
let dependentAssemblies =
let injectEsNet =
match deps |> Seq.contains "NEST" with
| true -> List.append deps ["Elasticsearch.Net"]
| false -> deps
injectEsNet
|> Seq.map (fun id ->
let p = packages |> Seq.find (fun p -> p.NugetId = id)
p.AssemblyName
)
|> Seq.distinct
let directories = Directory.GetDirectories <| sprintf "%s/lib" tmp
directories
|> Seq.iter (fun libFolder -> rewriteLibFolder libFolder project nugetId dependentAssemblies)
//Repackage
let versionedPackage = p.Package |> replaceId nugetId
ZipFile.CreateFromDirectory(tmp, versionedPackage)
printfn "Created %s" versionedPackage
Directory.delete tmp
)