anchor.diff:  
       serverProcess.Kill()
   )
  +
  +
  +// --------------------------------------------------------------------------------------
  +// Development mode
  +
  +let host = "localhost"
  +let port = 8080
  +let serverPort = 8085
  +
  +
  +Target "Run" (fun _ ->
  +    runDotnet serverTestsPath "restore"
  +    runDotnet clientPath "restore"
  +
  +    let unitTestsWatch = async {
  +        let result =
  +            ExecProcess (fun info ->
  +                info.FileName <- dotnetExePath
  +                info.WorkingDirectory <- serverTestsPath
  +                info.Arguments <- sprintf "watch msbuild /t:TestAndRun /p:DotNetHost=%s" dotnetExePath) TimeSpan.MaxValue
  +
  +        if result <> 0 then failwith "Website shut down."
  +    }
  +
  +    let fablewatch = async { 
  +        runDotnet clientPath "fable webpack-dev-server -- --config src/Client/webpack.config.js"
  +    }
  +
  +    let openBrowser = async {
  +        System.Threading.Thread.Sleep(5000)
  +        Diagnostics.Process.Start("http://"+ host + sprintf ":%d" port) |> ignore
  +    }
  +
  +    Async.Parallel [| unitTestsWatch; fablewatch; openBrowser |]
  +    |> Async.RunSynchronously
  +    |> ignore
  +)
  +
  +
  +Target "RunSSR" (fun _ ->
  +    runDotnet serverTestsPath "restore"
  +    runDotnet clientPath "restore"
  +
  +    let unitTestsWatch = async {
  +        let result =
  +            ExecProcess (fun info ->
  +                info.FileName <- dotnetExePath
  +                info.WorkingDirectory <- serverTestsPath
  +                info.Arguments <- sprintf "watch msbuild /t:TestAndRun /p:DotNetHost=%s /p:DebugSSR=true" dotnetExePath) TimeSpan.MaxValue
  +
  +        if result <> 0 then failwith "Website shut down."
  +    }
  +
  +    let fablewatch = async { 
  +        runDotnet clientPath "fable webpack-cli -- --config src/Client/webpack.config.js -w"
  +    }
  +
  +    let openBrowser = async {
  +        System.Threading.Thread.Sleep(10000)
  +        Diagnostics.Process.Start("http://"+ host + sprintf ":%d" serverPort) |> ignore
  +    }
  +
  +    Async.Parallel [| unitTestsWatch; fablewatch; openBrowser |]
  +    |> Async.RunSynchronously
  +    |> ignore
  +)
  +
  +
  +// --------------------------------------------------------------------------------------
  +// Release Scripts
  +
  +
  +Target "SetReleaseNotes" (fun _ ->
  +    let lines = [
  +            "module internal ReleaseNotes"
  +            ""
  +            (sprintf "let Version = \"%s\"" release.NugetVersion)
  +            ""
  +            (sprintf "let IsPrerelease = %b" (release.SemVer.PreRelease <> None))
  +            ""
  +            "let Notes = \"\"\""] @ Array.toList releaseNotes @ ["\"\"\""]
  +    File.WriteAllLines("src/Client/ReleaseNotes.fs",lines)
  +)
  +
  +Target "PrepareRelease" (fun _ ->
  +    Git.Branches.checkout "" false "master"
  +    Git.CommandHelper.directRunGitCommand "" "fetch origin" |> ignore
  +    Git.CommandHelper.directRunGitCommand "" "fetch origin --tags" |> ignore
  +
  +    StageAll ""
  +    Git.Commit.Commit "" (sprintf "Bumping version to %O" release.NugetVersion)
  +    Git.Branches.pushBranch "" "origin" "master"
  +
  +    let tagName = string release.NugetVersion
  +    Git.Branches.tag "" tagName
  +    Git.Branches.pushTag "" "origin" tagName
  +
  +    let result =
  +        ExecProcess (fun info ->
  +            info.FileName <- "docker"
  +            info.Arguments <- sprintf "tag %s/%s %s/%s:%s" dockerUser dockerImageName dockerUser dockerImageName release.NugetVersion) TimeSpan.MaxValue
  +    if result <> 0 then failwith "Docker tag failed"
  +)
  +
  +Target "BundleClient" (fun _ ->
  +    let result =
  +        ExecProcess (fun info ->
  +            info.FileName <- dotnetExePath
  +            info.WorkingDirectory <- serverPath
  +            info.Arguments <- "publish -c Release -o \"" + FullName deployDir + "\"") TimeSpan.MaxValue
  +    if result <> 0 then failwith "Publish failed"
  +
  +    let clientDir = deployDir </> "client"
  +    let publicDir = clientDir </> "public"
  +    let jsDir = clientDir </> "js"
  +    let cssDir = clientDir </> "css"
  +    let imageDir = clientDir </> "Images"
  +
  +    !! "src/Client/public/**/*.*" |> CopyFiles publicDir
  +    !! "src/Client/js/**/*.*" |> CopyFiles jsDir
  +    !! "src/Client/css/**/*.*" |> CopyFiles cssDir
  +    !! "src/Client/Images/**/*.*" |> CopyFiles imageDir
  +
  +    "src/Client/index.html" |> CopyFile clientDir
  +)
  +
  +Target "CreateDockerImage" (fun _ ->
  +    if String.IsNullOrEmpty dockerUser then
  +        failwithf "docker username not given."
  +    if String.IsNullOrEmpty dockerImageName then
  +        failwithf "docker image Name not given."
  +    let result =
  +        ExecProcess (fun info ->
  +            info.FileName <- "docker"
  +            info.UseShellExecute <- false
  +            info.Arguments <- sprintf "build -t %s/%s ." dockerUser dockerImageName) TimeSpan.MaxValue
  +    if result <> 0 then failwith "Docker build failed"
  +)
  +
  +Target "TestDockerImage" (fun _ ->
  +    ActivateFinalTarget "KillProcess"
  +    let testImageName = "test"
  +
  +    let result =
  +        ExecProcess (fun info ->
  +            info.FileName <- "docker"
  +            info.Arguments <- sprintf "run -d -p 127.0.0.1:8086:8085 --rm --name %s -it %s/%s" testImageName dockerUser dockerImageName) TimeSpan.MaxValue
  +    if result <> 0 then failwith "Docker run failed"
  +
  +    System.Threading.Thread.Sleep 5000 |> ignore  // give server some time to start
  +
  +    !! clientTestExecutables
  +    |> Expecto (fun p -> { p with Parallel = false } )
  +    |> ignore
  +
  +    let result =
  +        ExecProcess (fun info ->
  +            info.FileName <- "docker"
  +            info.Arguments <- sprintf "stop %s" testImageName) TimeSpan.MaxValue
  +    if result <> 0 then failwith "Docker stop failed"
  +)
  +
  +Target "Deploy" (fun _ ->
  +    let result =
  +        ExecProcess (fun info ->
  +            info.FileName <- "docker"
  +            info.WorkingDirectory <- deployDir
  +            info.Arguments <- sprintf "login %s --username \"%s\" --password \"%s\"" dockerLoginServer dockerUser dockerPassword) TimeSpan.MaxValue
  +    if result <> 0 then failwith "Docker login failed"
  +
  +    let result =
  +        ExecProcess (fun info ->
  +            info.FileName <- "docker"
  +            info.WorkingDirectory <- deployDir
  +            info.Arguments <- sprintf "push %s/%s" dockerUser dockerImageName) TimeSpan.MaxValue
  +    if result <> 0 then failwith "Docker push failed"
  +)
  +
  +// -------------------------------------------------------------------------------------
  +
   
   let getFunctionApp projectName =
       match projectName with 
  
positive.code:             info.FileName <- dotnetExePath
              info.WorkingDirectory <- workingDir
              info.Arguments <- args) TimeSpan.MaxValue
      if result <> 0 then failwithf "dotnet %s failed" args
  
  let platformTool tool winTool =
      let tool = if isUnix then tool else winTool
  
negative.code:     runDotnet serverPath "build"
  )
  
  Target "BuildTests" (fun _ ->
      runDotnet clientTestsPath "build"
      runDotnet serverTestsPath "build"
  )
  
  Target "NPMInstall" (fun _ ->
      printfn "Node version:"
      run nodeTool "--version" __SOURCE_DIRECTORY__
      printfn "Yarn version:"
  