loading...

FAKE 5 Migration Cheat Sheet

jeremyabbott profile image Jeremy Abbott ・3 min read

FAKE 5 Migration Cheat Sheet

Happy holidays everyone!

Pikachu in a Santa hat

When you start migrating from FAKE 4 and FAKE 5, you'll find that a simply opening the FAKE namespace isn't enough. Also, if like me, deprecation warnings drive you mad, you'll want to get rid of them as quickly as possible. I made the following cheat sheet to expedite your FAKE migration (and to help me update the other scripts I still need to update.)

Function/Module changes

Below are the functions I've had to update more than once. Most of them at least require referencing a nuget package and/or opening a module that you didn't have to open before.

Each of the following headers is the name of a FAKE 4 function. The snippet that follows shows how it is used in FAKE 4 followed by how to accomplish the same task in FAKE 5.

Target

// =======================================
// Before
// =======================================

Target "Foo" (fun _ -> 
    printfn "Foo to the Bar"
)

// =======================================
// After
// =======================================

open Fake.Core // From the Fake.Core.Target nuget package

Target.create "Foo" (fun _ ->
    printfn "Foo to the Bar"
)

Target Operators

All of the FAKE custom operators are in their own modules now.

open Fake.Core.TargetOperators // From the Fake.Core.Target nuget package
"Clean"
    ==> "Restore"
    ==> "Build"

Important: FAKE 4 Target operators (from FakeLib) do not work with FAKE 5 targets (and vice versa). That means converting Targets to FAKE 5 means using the operators from FAKE 5.

FullName

// =======================================
// Before
// =======================================

let path = "./foo" |> FullName // Auto-opened from Fake.FileSystemHelper

// =======================================
// After
// =======================================

open Fake.IO 

let path = "./foo" |> Path.getFullName // From the Fake.IO.FileSystem the nuget package 

getBuildParam

// =======================================
// Before
// =======================================

// In FAKE 4 getBuildParam implicitly called getBuildParamOrDefault with empty string as the default

let userName = getBuildParam "userName" // Auto-opened from Fake.EnvironmentHelper

// =======================================
// After
// =======================================

open Fake.Core

let userName = 
    // From nuget package Fake.Core.Environment
    Environment.environVarOrDefault "UserName" ""

Some Extra Notes

Passing arguments to your FAKE script is a little different in FAKE 5. In FAKE 4 you may have had something like

./build.sh <targetName> <buildParam>=foo, you now have a couple of different options, depending on your use case:

# create an environment variable that's scoped to the current shell session.
export myKey="my value"
./build.sh build
let myKey = Environment.environVarOrDefault "myKey" ""

If you want to pass arguments on the command line, you have to pass them with the following syntax:

# using the FAKE dotnet CLI tool
fake run build.fsx -t build --arg

And then in build.fsx:

Target.create "Foo" (fun p ->
    printfn "args: %A" p.Context.Arguments

    printfn "%A " p
)

Target.runOrDefaultWithArguments "Foo"

You need to use Target.runOrDefaultWithArguments instead of Target.runOrDefault to access arguments this way. Additionally, the target function signature is now string -> TargetParameter -> unit -> unit. You have to use the TargetParameter (p in the example above) to get access to it. Context.Arguments is a string list. You can use the module Fake.Core.CommandLineParsing to parse the target arguments.

parseAllReleaseNotes

// =======================================
// Before
// =======================================
open Fake.ReleaseNotesHelper

let releaseNotes = File.ReadAllLines "RELEASE_NOTES.md"

let releaseNotesData =
     releaseNotes
     |> parseAllReleaseNotes

let release = List.head releaseNotesData

// =======================================
// After
// =======================================

open Fake.Core

let release = 
    // From Fake.Core.ReleaseNotes nuget package
    ReleaseNotes.load "RELEASE_NOTES.md"

SemVerHelper.parse

// =======================================
// Before
// =======================================

let packageVersion = SemVerHelper.parse release.NugetVersion // From Fake.SemVerHelper

// =======================================
// After
// =======================================

open Fake.Core
let semVer =
    // From Fake.Core.SemVer nuget package
    SemVer.parse release.NugetVersion
printfn "semver.Parse: %s" <| semVer.ToString()


isUnix

// =======================================
// Before
// =======================================

let pathSep = if isUnix then """\""" else "/" // From Fake.EnvironmentHelper

// =======================================
// After
// =======================================
open Fake.Core

let pathSep = 
    // From the nuget package Fake.Core.Environment
    if Environment.isUnix then """\""" else "/"

ProcessHelper.tryFindFileOnPath

// =======================================
// Before
// =======================================

let fooExe = ProcessHelper.tryFindFileOnPath "foo"

// =======================================
// After
// =======================================

open Fake.Core

let fooExe =
    // From the nuget package Fake.Core.Process
    ProcessUtils.tryFindFileOnPath "foo" 

DotNetCli.GetDotNetSDKVersionFromGlobalJson()

// =======================================
// Before
// =======================================

let dotnetcliVersion = DotNetCli.GetDotNetSDKVersionFromGlobalJson()

// =======================================
// After
// =======================================

open Fake.DotNet

// After
// From the nuget package Fake.DotNet.Cli
// In the namespace Fake.DotNet and module DotNet
let dotnetcliVersion = DotNet.CliVersion.GlobalJson

CleanDirs

// =======================================
// Before
// =======================================

// Auto-opened from Fake.FileHelper
CleanDirs [exampleDir]

// =======================================
// After
// =======================================

open Fake.IO

//From the nuget package Fake.IO.FileSystem
Shell.cleanDirs [deployDir] 

ExecProcess / Shell.Exec

// =======================================
// Before
// =======================================

let result = Shell.Exec("foo", "--version")
if result <> 0 failwith "boom"

// =======================================
// After
// =======================================

open Fake.Core

let result =
    // From the NuGet Package Fake.Core.Process
    CreateProcess.fromRawCommand "dotnet" ["--info"]
    |> Proc.run
if result.ExitCode <> 0 then failwith "boom"

build

// =======================================
// Before
// =======================================
open Fake

Target "MSBuild" (fun _ ->
    let setMsBuildParams defaultParams =
        { defaultParams with
            Targets=["Build"]
            Properties = ["Configuration", "Debug"]
        }
    // Auto-opened from Fake.MSBuildHelper
    build setMsBuildParams "Foo.sln"
)

// =======================================
// After
// =======================================

open Fake.DotNet

Target.create "MSBuild" (fun _ ->
    let setMsBuildParams defaultParams =
        { defaultParams with
            Targets=["Build"]
            Properties = ["Configuration", "Debug"]
        }
    MSBuild.build setMsBuildParams "Foo.sln"
)

Posted on by:

jeremyabbott profile

Jeremy Abbott

@jeremyabbott

Software engineer, Poké Master, functional programming enthusiast, LGBT Activist

Discussion

pic
Editor guide
 

Thanks great article. The only minor typo was in wrong pathSep, but you can get the correct one from Path.DirectorySeparatorChar (off-topic anyway). Is Fake5 focused for .NET Core, or should you consider migrating an old .NET Framework full application also?

 

Thank you for the feedback! I didn't know about Path.DirectorySeparatorChar

I would consider migrating regardless of which flavor of .NET you're using. FAKE 5 includes MSBuild and NuGet APIs. The FAKE runner is a dotnet SDK global tool, but that doesn't mean it can't be used with scripts written for .NET Framework applications.

 

Thanks, great article... It saved me hundreds of hours searching for the right migration

Patricia