build/scripts/Versioning.fs (144 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
open System.IO
open Fake.Core
open Fake.IO
open Fake.IO.Globbing.Operators
open Fake.Tools.Git
open Newtonsoft.Json
module Versioning =
// We used to rely on AssemblyInfo.cs from NEST to read and write the current version.
// Since that file is now generated by the dotnet tooling and GitVersion and similar tooling all still have
// active issues related to dotnet core, we now just burn this info in global.json
let parse (v: string) = SemVer.parse(if String.IsNullOrEmpty(v) then "1.0.0" else v)
//Versions in form of e.g 6.1.0 is inferred as datetime so we bake the json shape into the provider like this
type SdkVersion = { version:string; rollForward:string; allowPrerelease:bool }
type GlobalJson = { sdk: SdkVersion; version:string; doc_current:string; doc_branch: string; }
let private globalJson () =
let jsonString = File.ReadAllText "global.json"
JsonConvert.DeserializeObject<GlobalJson>(jsonString)
let writeVersionIntoAutoLabel oldVersion newVersion =
let path = Path.Join(".github","auto-label.json")
let text = File.ReadAllText(path)
let oldV = sprintf "v%s" oldVersion
let newV = sprintf "v%s" newVersion
if not(text.Contains(oldV)) then
failwithf "auto-label.json does not contain %s" oldV
let replaced = String.replace oldV newV text
File.WriteAllText(path, replaced)
let writeVersionIntoGlobalJson version =
let globalJson = globalJson ()
let doc_current =
match globalJson.doc_current with
| "main" -> "main"
| s when s.EndsWith(".x") -> sprintf "%i.x" version.Major
| _ -> sprintf "%i.%i" version.Major version.Minor
let doc_branch =
match globalJson.doc_current with
| "main" -> "main"
| _ -> sprintf "%i.x" version.Major
let newGlobalJson = {
globalJson with
version = version.ToString()
doc_current = doc_current
doc_branch = doc_branch
}
File.WriteAllText("global.json", JsonConvert.SerializeObject(newGlobalJson, Formatting.Indented))
printfn "Written (%s) to global.json as the current version will use this version from now on as current in the build" (version.ToString())
let GlobalJsonVersion = parse <| globalJson().version
let private getVersion (args:Commandline.PassedArguments) =
match (args.Target, args.CommandArguments) with
| (_, Commandline.SetVersion v) ->
match v.Version with
| v when String.IsNullOrEmpty v -> None
| v -> Some <| parse v
| ("canary", _) ->
let v = GlobalJsonVersion
let timestampedVersion = (sprintf "ci%s" (DateTime.UtcNow.ToString("yyyyMMddTHHmmss")))
let canaryVersion =
match v.PreRelease with
| Some _ -> parse ((sprintf "%d.%d.%d-%s" v.Major v.Minor v.Patch timestampedVersion).Trim())
| None -> parse ((sprintf "%d.%d.%d-%s" v.Major v.Minor (v.Patch + 1u) timestampedVersion).Trim())
Some canaryVersion
| _ -> None
type AnchoredVersion = { Full: SemVerInfo; Assembly:SemVerInfo; AssemblyFile:SemVerInfo }
type BuildVersions =
| Update of New: AnchoredVersion * Old: AnchoredVersion
| NoChange of Current: AnchoredVersion
let AnchoredVersion version =
let av v = parse (sprintf "%s.0.0" (v.Major.ToString()))
let fv v = parse (sprintf "%s.%s.%s.0" (v.Major.ToString()) (v.Minor.ToString()) (v.Patch.ToString()))
{ Full = version; Assembly = av version; AssemblyFile = fv version }
let BuildVersioning args =
let currentVersion = GlobalJsonVersion
let buildVersion = getVersion args
match buildVersion with
| None -> NoChange(Current = AnchoredVersion currentVersion)
| Some v -> Update(New = AnchoredVersion v, Old = AnchoredVersion currentVersion)
let WriteVersion version =
match version with
| NoChange _ -> failwithf "cannot run update versions because no explicit version number was passed on the command line"
| Update (newVersion, currentVersion) ->
match newVersion.Full.PreRelease with
| Some v when v.Name.StartsWith("SNAPSHOT", StringComparison.OrdinalIgnoreCase) ->
printfn "Building snapshot, foregoing persisting version information"
| _ ->
// fail if current is greater than the new version
if (currentVersion > newVersion) then
failwithf "Can not release %O as it's lower then current %O" newVersion.Full currentVersion.Full
writeVersionIntoGlobalJson newVersion.Full
writeVersionIntoAutoLabel (currentVersion.Full.ToString()) (newVersion.Full.ToString())
let Validate target version =
match (target, version) with
| ("release", version) ->
WriteVersion version
| _ -> ignore()
let ArtifactsVersion buildVersions =
match buildVersions with
| NoChange n -> n
| Update (newVersion, _) -> newVersion
let private officialToken = "96c599bbe3e70f5d"
let BuiltArtifacts (version: AnchoredVersion) =
let packages =
let allPackages = !! "build/output/*.nupkg" |> Seq.toList
let toProject (package: string) =
let id = Path.GetFileName(package) |> String.replace (version.Full.ToString()) "" |> String.replace "..nupkg" ""
let assembly = id
{| Package = package; NugetId = id; AssemblyName = assembly |}
allPackages |> List.map toProject
packages
let ValidateArtifacts version =
let tmp = "build/output/tmp"
let packages = BuiltArtifacts version
printf "%O" packages
packages
// do not validate versioned packages for now
|> Seq.filter(fun f -> not <| f.NugetId.EndsWith(sprintf ".v%i" version.Assembly.Major))
|> Seq.iter(fun p ->
let v = sprintf "%O+%s" version.Full (Information.getCurrentSHA1("."))
// loading dlls is locked down on APPVEYOR so we can not assert release mode
let ciArgs =
let appVeyor = Environment.hasEnvironVar "APPVEYOR"
let azDevops = Environment.hasEnvironVar "TF_BUILD"
if appVeyor || azDevops then ["-r"; "true"] else []
ReposTooling.PackageValidator
<| [p.Package; "-v"; v; "-a"; p.AssemblyName; "-k"; officialToken] @ ciArgs
|> ignore
Zip.unzip tmp p.Package
let nugetId = p.NugetId
let directories = Directory.GetDirectories <| sprintf "%s/lib" tmp
directories
|> Seq.iter(fun d ->
let info = DirectoryInfo d
let tfm = info.Name
let fullPath = Path.GetFullPath d
let command = [ sprintf "previous-nuget|%s|%s|%s" nugetId (version.Full.ToString()) tfm;
sprintf "directory|%s" fullPath
"-a"; "-f"; "github-comment"; "--output"; Paths.BuildOutput]
ReposTooling.Differ command
)
Directory.delete tmp
)