Created
January 5, 2017 15:46
-
-
Save ImaginaryDevelopment/4a735576a7f7349b4bdf7ba345e5bbb7 to your computer and use it in GitHub Desktop.
VsCode Fake build system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Fake] | |
linuxPrefix = "mono" | |
command = "build.cmd" | |
build = "build.fsx" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// include Fake lib | |
#r @"../packages/FAKE/tools/FakeLib.dll" | |
open System | |
open System.Diagnostics | |
open System.IO | |
open Fake | |
// Properties | |
let buildDir = "./bin/" | |
let targetScript = | |
let linqPadQueriesFolder = @"C:\projects\LinqPad\LinqPad\LINQPad Queries\" | |
Path.Combine(linqPadQueriesFolder,@"WIP\runPmWeb.linq") | |
let lprunPath = @"C:\ProgramData\LINQPad\Updates50\510\lprun.exe" | |
let configLpRun (pi: ProcessStartInfo) = | |
trace (sprintf "Target script:%s" targetScript) | |
pi.FileName <- lprunPath | |
pi.Arguments <- sprintf "\"%s\"" targetScript | |
// Helpers | |
let flip f y x = f x y | |
let warn msg = trace (sprintf "WARNING: %s" msg) | |
type System.String with | |
static member Delimit delimiter (items:string seq) = | |
String.Join(delimiter,items |> Array.ofSeq) | |
module Sec = | |
open System.Security.Principal | |
let getIsAdmin() = | |
WindowsIdentity.GetCurrent() | |
|> WindowsPrincipal | |
|> fun wp -> wp.IsInRole(WindowsBuiltInRole.Administrator) | |
let requireAdmin () = | |
let runningAsAdmin = getIsAdmin() | |
if not runningAsAdmin then | |
failwithf "Requested feature is not known to work without administrator permissions" | |
module Proc = | |
//let execCmd prog args timeout = | |
let findCmd cmd = | |
let processResult = | |
ExecProcessAndReturnMessages (fun psi -> | |
psi.FileName <- "where" | |
psi.Arguments <- quoteIfNeeded cmd | |
) (TimeSpan.FromSeconds 2.) | |
if processResult.OK then | |
// require the result not be a directory | |
let cmdPath = | |
processResult.Messages | |
|> Seq.filter (Directory.Exists >> not) | |
|> Seq.filter (File.Exists) | |
|> Seq.filter (fun x -> x.EndsWith ".bat" || x.EndsWith ".exe" || x.EndsWith ".cmd") | |
|> Seq.tryHead | |
if processResult.Messages.Count > 1 then | |
warn (sprintf "found multiple items matching '%s'" cmd) | |
trace (processResult.Messages |> String.Delimit ";") | |
match cmdPath with | |
| Some path -> | |
trace (sprintf "found %s at %s" cmd path) | |
Some path | |
| None -> | |
warn "where didn't return a valid file" | |
None | |
else None | |
let runWithOutput cmd args timeOut = | |
let cmd = | |
// consider: what if the cmd is in the current dir? where may find one elsewhere first? | |
if Path.IsPathRooted cmd then | |
cmd | |
else | |
match findCmd cmd with | |
| Some x -> x | |
| None -> | |
warn (sprintf "findCmd didn't find %s" cmd) | |
cmd | |
let result = | |
ExecProcessAndReturnMessages (fun f -> | |
//ExecProcessRedirected (fun f -> | |
//f.FileName <- @"gulp" | |
//f. Arguments <- "sass" | |
// why did 'where' with no full path work, but this fails? | |
f.FileName <- cmd | |
f.Arguments <- args | |
) (TimeSpan.FromMinutes 1.0) | |
result,cmd | |
let showInExplorer path = | |
Process.Start("explorer.exe",sprintf "/select, \"%s\"" path) | |
// wrapper for fake built-in in case we want the entire process results, not just the exitcode | |
let runElevated cmd args timeOut = | |
let tempFilePath = System.IO.Path.GetTempFileName() | |
// could also redirect error stream with 2> tempErrorFilePath | |
// see also http://www.robvanderwoude.com/battech_redirection.php | |
let resultCode = ExecProcessElevated "cmd" (sprintf "/c %s %s > %s" cmd args tempFilePath) timeOut | |
trace "reading output results of runElevated" | |
let outputResults = File.ReadAllLines tempFilePath | |
File.Delete tempFilePath | |
let processResult = ProcessResult.New resultCode (ResizeArray<_> outputResults) (ResizeArray<_>()) | |
(String.Delimit "\r\n" outputResults) | |
|> trace | |
processResult | |
type FindOrInstallResult = | |
|Found | |
|InstalledThenFound | |
let findOrInstall cmd fInstall = | |
match findCmd cmd with | |
| Some x -> Some (x,Found) | |
| None -> | |
fInstall() | |
findCmd cmd | |
|> Option.map (fun x -> (x,InstalledThenFound)) | |
module Node = | |
let npmPath = lazy(Proc.findCmd "npm") | |
// assumes the output is unimportant, just the result code | |
let npmInstall args = | |
let resultCode = | |
let filename, useShell = | |
match npmPath.Value with | |
| Some x -> x, false | |
// can't capture output with true | |
| None -> "npm", true | |
trace (sprintf "npm filename is %s" filename) | |
ExecProcess (fun psi -> | |
psi.FileName <- filename | |
psi.Arguments <- "install" | |
psi.UseShellExecute <- useShell | |
) (TimeSpan.FromMinutes 1.) | |
resultCode | |
// Targets | |
Target "SetupNode" (fun _ -> | |
// goal: install and setup everything required for any node dependencies this project has | |
// including nodejs, gulp, node-sass | |
// install Choco | |
let chocoPath = | |
let fInstall () = | |
let resultCode = | |
ExecProcessElevated | |
"@powershell" | |
"""-NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" """ | |
(TimeSpan.FromMinutes 3.) | |
resultCode | |
|> sprintf "choco install script returned %i" | |
|> trace | |
if resultCode <> 0 then | |
failwithf "Task failed" | |
// choco is installled, we think | |
// probably won't work if it was just installed, the %path% variable given to/used by a process is immutable | |
match Proc.findOrInstall "choco" fInstall with | |
//| Some (x,Proc.FindOrInstallResult.Found) -> x | |
| Some (x,_) -> x | |
| None -> failwithf "choco was installed, in order for choco to be found or used, this has process has to be restarted" | |
// choco install nodeJs | |
let nodePath = | |
let fInstall () = | |
let results = Proc.runElevated "choco" "install nodejs -y" (TimeSpan.FromSeconds 3.) | |
trace (sprintf "%A" results) | |
match Proc.findOrInstall "node" fInstall with | |
| Some (x,_) -> x | |
| None -> failwithf "nodejs was installed, in order for node to be found or used, this process has to be restarted" | |
// node should have installed npm | |
// npm | |
let npmPath = Proc.findCmd "npm" | |
// install all packages that packages.json says this project needs | |
let resultCode = | |
let filename, useShell = | |
match npmPath with | |
| Some x -> x, false | |
// can't capture output with true | |
| None -> "npm", true | |
trace (sprintf "npm filename is %s" filename) | |
ExecProcess (fun psi -> | |
psi.FileName <- filename | |
psi.Arguments <- "install" | |
psi.UseShellExecute <- useShell | |
) (TimeSpan.FromMinutes 1.) | |
() | |
) | |
// run node tests and whatever else | |
Target "Test" (fun _ -> | |
let result, _ = Proc.runWithOutput "npm" "test" (TimeSpan.FromSeconds 4.) | |
result.Messages | |
|> Seq.iter (printfn "test-msg:%s") | |
if result.ExitCode <> 0 then | |
result.Errors | |
|> Seq.iter(printfn "test-err:%s") | |
failwithf "Task failed: %i" result.ExitCode | |
) | |
Target "Coffee" (fun _ -> | |
let coffees = [ | |
"test/test.coffee" | |
] | |
let compileCoffee relPath = | |
let result,_ = Proc.runWithOutput "node" (sprintf "node_modules/coffee-script/bin/coffee -b -m --no-header -c %s" relPath) (TimeSpan.FromSeconds 2.) | |
if result.ExitCode <> 0 then | |
failwithf "Task failed: %A" result | |
coffees | |
|> Seq.iter compileCoffee | |
) | |
Target "Babel" (fun _ -> | |
// run jsx compilation | |
let babels = [ | |
"Scripts/pm-era.jsx" | |
"Scripts/pm-era-remitdetail.jsx" | |
] | |
let babel relPath = | |
let targetPath = | |
let fullPath = Path.GetFullPath relPath | |
Path.Combine(fullPath |> Path.GetDirectoryName, fullPath |> Path.GetFileNameWithoutExtension |> flip (+) ".react.js") | |
let result,_ = Proc.runWithOutput "node" (sprintf "node_modules/babel-cli/bin/babel %s -o %s -s --presets react" relPath targetPath) (TimeSpan.FromSeconds 2.) | |
if result.ExitCode <> 0 then | |
result.Messages | |
|> Seq.iter (printfn "babel-msg:%s") | |
result.Errors | |
|> Seq.iter(printfn "babel-err:%s") | |
failwithf "Task failed: %i" result.ExitCode | |
else | |
result.Messages | |
|> Seq.iter (printfn "babel-msg:%s") | |
babels | |
|> Seq.iter babel | |
) | |
//node node_modules\coffee-script\bin\coffee -b -c test/test.coffee | |
Target "Clean" (fun _ -> | |
CleanDir buildDir | |
let files = Directory.GetFiles buildDir |> Seq.length | |
let directories = Directory.GetDirectories buildDir |> Seq.length | |
printfn "cleaned directory had %i item(s) remaining after clean" (files + directories) | |
) | |
Target "BuildApp" (fun _ -> | |
let output = | |
if isNullOrEmpty buildDir then "" | |
else | |
buildDir | |
|> FullName | |
|> trimSeparator | |
let setParams defaults = | |
{ defaults with | |
MSBuildParams.Targets= ["Build"] | |
//Verbosity = Some(MSBuildVerbosity.Diagnostic) | |
Properties = | |
[ | |
"Configuration", "Debug" | |
"Platform", "AnyCPU" | |
"DebugSymbols", "True" | |
"OutputPath", buildDir | |
"SolutionDir", ".." |> FullName | |
] | |
} | |
//https://github.com/fsharp/FAKE/blob/master/src/app/FakeLib/MSBuildHelper.fs | |
build setParams "Pm.Web.fsproj" | |
if isNotNullOrEmpty output then !!(buildDir @@ "/**/*.*") |> Seq.toList | |
else [] | |
|> Log "AppBuild-Output: " | |
) | |
Target "StartApp" (fun _ -> | |
let proc = new Process() | |
configLpRun proc.StartInfo | |
//proc.StartInfo.UseShellExecute <- false | |
// not using ProcessHelper.Start we don't want fake killing it | |
proc.Start() |> ignore | |
trace (sprintf "started app with pid:%i" proc.Id) | |
) | |
Target "Fire" (fun _ -> | |
ProcessHelper.fireAndForget configLpRun | |
) | |
Target "Run" (fun _ -> | |
//C:\projects\LinqPad\LinqPad\LINQPad Queries\WIP\runPmWeb.linq | |
//https://github.com/fsharp/FAKE/blob/master/src/app/FakeLib/ProcessHelper.fs | |
asyncShellExec { | |
Program = lprunPath | |
WorkingDirectory = null | |
CommandLine = sprintf "\"%s\"" targetScript | |
Args = list.Empty | |
} | |
|> Async.RunSynchronously | |
//Shell.Exec (,@"C:\projects\LinqPad\LinqPad\LINQPad Queries\",@"C:\projects\LinqPad\LinqPad\LINQPad Queries\WIP\") | |
|> sprintf "script returned %i" | |
|> trace | |
) | |
Target "Stop" (fun _ -> | |
killProcess "lprun" | |
) | |
Target "NodeTasks" (fun _ -> | |
trace "Node Tasks completed" | |
) | |
Target "Sass" (fun _ -> | |
let result,_ = Proc.runWithOutput "node-sass" "content/site.scss content/site.css" (TimeSpan.FromSeconds 4.) | |
trace "finished attempting sass" | |
printfn "sass:%A" result | |
//result.Messages | |
//|> Seq.iter (printfn "sass:%A") | |
if result.ExitCode <> 0 then | |
failwithf "Task failed" | |
) | |
Target "NodeList" (fun _ -> | |
let result = Proc.runWithOutput "npm" "list --depth=0" (TimeSpan.FromSeconds 2.0) | |
printfn "npm list -g --depth=0:\r\n%A" result | |
) | |
Target "Default" (fun _ -> | |
trace "Hello World from FAKE" | |
) | |
Target "AfterAll" (fun _ -> | |
trace (sprintf "%A" DateTime.Now) | |
) | |
// Dependencies | |
// this should be NodeTasks depends on Sass, Coffee, and jsx compilation | |
// ==> "Coffee" | |
"Sass" | |
==> "NodeTasks" | |
"Coffee" | |
==> "NodeTasks" | |
"Stop" ==> "Run" | |
For "NodeTasks" ["Sass";"Coffee";"Babel";"Test"] | |
// "Stop" ==> "Fire" | |
For "Fire" [ "Stop" ] | |
For "StartApp" [ "Stop" ] | |
For "StartApp" [ "Stop" ] | |
For "Test" [ "Coffee" ] | |
// default doesn't include starting the app | |
"Stop" | |
==> "Clean" | |
==> "BuildApp" | |
==> "StartApp" | |
==> "Default" | |
==> "AfterAll" | |
// make sure nodetasks happens before buildapp if nodetasks is executed | |
"NodeTasks" ?=> "BuildApp" | |
"Coffee" ?=> "Test" | |
RunTargetOrDefault "Default" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "pm.web", | |
"version": "1.0.0", | |
"description": "Registry additions have been made in order to provide you the best web development experience. See http://bloggemdano.blogspot.com/2013/11/adding-new-items-to-pure-f-aspnet.html for more information.", | |
"main": "index.js", | |
"dependencies": { | |
"requirejs": "^2.3.2" | |
}, | |
"devDependencies": { | |
"babel-cli": "^6.18.0", | |
"babel-preset-react": "^6.16.0", | |
"coffee-script": "github:jashkenas/coffeescript", | |
"mocha": "^3.2.0" | |
}, | |
"scripts": { | |
"wastest": "echo \"Error: no test specified\" && exit 1", | |
"test": "mocha" | |
}, | |
"author": "", | |
"license": "ISC" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment