Skip to content

Instantly share code, notes, and snippets.

@vbfox
Last active January 29, 2018 13:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vbfox/2eee346524d688af55ccc467e154e1b4 to your computer and use it in GitHub Desktop.
Save vbfox/2eee346524d688af55ccc467e154e1b4 to your computer and use it in GitHub Desktop.
Allow to define FAKE targets with a syntax similar to Gulp tasks and typed !
let clean = task "Clean" [] {
CleanDir "out"
}
let assemblyInfo = task "AssemblyInfo" [ clean.IfNeeded ] {
// ...
}
let build = task "Build" [ assemblyInfo ] {
!! "**/*.fsproj" |> MSBuildRelease "" "Rebuild" |> ignore
}
let runTests = task "RunTests" [ build ] {
!! "**/*Test.exe" |> Expecto id
}
let default = Task "Default" [ build; test.If(buildServer = AppVeyor) ] DoNothing
RunTaskOrDefault default
/// Allow to define FAKE tasks with a syntax similar to Gulp tasks and using instances instead of strings
/// https://gist.github.com/vbfox/2eee346524d688af55ccc467e154e1b4
module BlackFox.TypedTaskDefinitionHelper
open Fake
open System
type TaskMetadata = {
name: string
dependencies: TaskInfo list
}
and TaskInfo = {
metadata: TaskMetadata option
isSoft: bool
}
with
static member NoTask =
{ metadata = None; isSoft = false }
member this.Always
with get() = { this with isSoft = false }
member this.IfNeeded
with get() = { this with isSoft = true }
member this.If(condition: bool) =
if condition then this else TaskInfo.NoTask
let inline private applyTaskDependecies meta =
for dependency in meta.dependencies do
match dependency.metadata with
| Some dependencyMetadata ->
if dependency.isSoft then
dependencyMetadata.name ?=> meta.name |> ignore
else
dependencyMetadata.name ==> meta.name |> ignore
| None -> ()
let inline private registerTask meta body =
Target meta.name body
applyTaskDependecies meta
let inline private infoFromMeta meta =
{ metadata = Some meta; isSoft = false }
type TaskBuilder(metadata: TaskMetadata) =
member __.TryFinally(f, compensation) =
try
f()
finally
compensation()
member __.TryWith(f, catchHandler) =
try
f()
with e -> catchHandler e
member __.Using(disposable: #IDisposable, f) =
try
f disposable
finally
match disposable with
| null -> ()
| disp -> disp.Dispose()
member __.For(sequence, f) =
for i in sequence do f i
member __.Combine(f1, f2) = f2(); f1
member __.Zero() = ()
member __.Delay f = f
member __.Run f =
registerTask metadata f
infoFromMeta metadata
/// Define a task with it's dependencies
let Task name dependencies body =
let metadata = {name = name; dependencies = dependencies }
registerTask metadata body
infoFromMeta metadata
/// Define a task with it's dependencies
let task name dependencies =
let metadata = {name = name; dependencies = dependencies }
TaskBuilder(metadata)
/// Define a task without any body, only dependencies
let EmptyTask name dependencies =
let metadata = {name = name; dependencies = dependencies }
registerTask metadata (fun () -> ())
infoFromMeta metadata
/// Run the task specified on the command line if there was one or the
/// default one otherwise.
let RunTaskOrDefault (taskInfo: TaskInfo) =
match taskInfo.metadata with
| Some metadata -> RunTargetOrDefault metadata.name
| None -> RunTarget ()
let RunTask () =
RunTarget ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment