Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/Terrabuild.Extensions/Cargo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ type Cargo() =
/// <param name="arguments" example="&quot;check&quot;">Arguments for command.</param>
static member __dispatch__ (context: ActionContext) (arguments: string option) =
let arguments = arguments |> Option.defaultValue ""

let ops = [ shellOp context.Command arguments ]
let arguments = $"{context.Command} {arguments}"

let ops = [ shellOp "cargo" arguments ]
execRequest Cacheability.Always ops


Expand Down
13 changes: 13 additions & 0 deletions src/Terrabuild.Extensions/Docker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ open Terrabuild.Extensibility
/// </summary>
type Docker() =

/// <summary>
/// Run a docker `command`.
/// </summary>
/// <param name="__dispatch__" example="image">Example.</param>
/// <param name="arguments" example="prune -f">Arguments for command.</param>
static member __dispatch__ (context: ActionContext) (arguments: string option) =
let arguments = arguments |> Option.defaultValue ""
let arguments = $"{context.Command} {arguments}"

let ops = [ shellOp "docker" arguments ]
execRequest Cacheability.Always ops


/// <summary>
/// Build a Dockerfile.
/// </summary>
Expand Down
24 changes: 13 additions & 11 deletions src/Terrabuild.Extensions/Dotnet.fs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ type Dotnet() =
projectInfo


/// <summary>
/// Run a dotnet `command`.
/// </summary>
/// <param name="__dispatch__" example="run">Example.</param>
/// <param name="arguments" example="-v">Arguments for command.</param>
static member __dispatch__ (context: ActionContext) (arguments: string option) =
let arguments = arguments |> Option.defaultValue ""
let arguments = $"{context.Command} {arguments}"

let ops = [ shellOp "dotnet" arguments ]
execRequest Cacheability.Always ops


/// <summary title="Build project.">
/// Build project and ensure packages are available first.
/// </summary>
Expand Down Expand Up @@ -110,17 +123,6 @@ type Dotnet() =

buildRequest context buildOps

/// <summary>
/// Run a dotnet `command`.
/// </summary>
/// <param name="__dispatch__" example="format">Example.</param>
/// <param name="arguments" example="&quot;--verify-no-changes&quot;">Arguments for command.</param>
static member __dispatch__ (context: ActionContext) (arguments: string option) =
let arguments = arguments |> Option.defaultValue ""

let ops = [ shellOp context.Command arguments ]
execRequest Cacheability.Always ops


/// <summary>
/// Pack a project.
Expand Down
13 changes: 13 additions & 0 deletions src/Terrabuild.Extensions/Gradle.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ type Gradle() =
with Outputs = Set [ "build/classes/" ] }
projectInfo

/// <summary>
/// Run a gradle `command`.
/// </summary>
/// <param name="__dispatch__" example="clean">Example.</param>
/// <param name="arguments" example="">Arguments for command.</param>
static member __dispatch__ (context: ActionContext) (arguments: string option) =
let arguments = arguments |> Option.defaultValue ""
let arguments = $"{context.Command} {arguments}"

let ops = [ shellOp "gradle" arguments ]
execRequest Cacheability.Always ops


/// <summary>
/// Invoke build task `assemble` for `configuration`.
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions src/Terrabuild.Extensions/Npm.fs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ type Npm() =
projectInfo


/// <summary>
/// Run npm command.
/// </summary>
/// <param name="arguments" example="&quot;--port=1337&quot;">Arguments to pass to target.</param>
static member __dispatch__ (context: ActionContext) (arguments: string option) =
let cmd = context.Command
let arguments = arguments |> Option.defaultValue ""

let ops = [
shellOp "npm" "ci"
shellOp "npm" $"run {cmd} -- {arguments}"
]
execRequest Cacheability.Always ops


/// <summary>
/// Install packages using lock file.
/// </summary>
Expand Down
14 changes: 14 additions & 0 deletions src/Terrabuild.Extensions/Terraform.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ type Terraform() =
Outputs = Set [ "*.planfile" ] }
projectInfo


/// <summary>
/// Run a terraform `command`.
/// </summary>
/// <param name="__dispatch__" example="fmt">Example.</param>
/// <param name="arguments" example="-write=false">Arguments for command.</param>
static member __dispatch__ (context: ActionContext) (arguments: string option) =
let arguments = arguments |> Option.defaultValue ""
let arguments = $"{context.Command} {arguments}"

let ops = [ shellOp "terraform" arguments ]
execRequest Cacheability.Always ops


/// <summary weight="1">
/// Init Terraform.
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions src/Terrabuild.Extensions/Yarn.fs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ type Yarn() =
projectInfo


/// <summary>
/// Run yarn `command`.
/// </summary>
/// <param name="arguments" example="&quot;--port=1337&quot;">Arguments to pass to target.</param>
static member __dispatch__ (context: ActionContext) (arguments: string option) =
let arguments = arguments |> Option.defaultValue ""
let cmd = context.Command

let ops = [
shellOp "yarn" "install --frozen-lockfile"
shellOp "yarn" $"{cmd} -- {arguments}"
]
execRequest Cacheability.Always ops


/// <summary>
/// Install packages using lock file.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions src/Terrabuild/CLI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ with
| Container_Tool _ -> "Container Tool to use (docker or podman)."
| WhatIf -> "Prepare the action but do not apply."

[<RequireQualifiedAccess>]
type ServeArgs =
| [<Unique; AltCommandLine("-w")>] Workspace of path:string
| [<Unique; AltCommandLine("-c")>] Configuration of name:string
| [<EqualsAssignment; AltCommandLine("-v")>] Variable of variable:string * value:string
| [<Unique; AltCommandLine("-l")>] Label of labels:string list
| [<Unique>] Logs
with
interface IArgParserTemplate with
member this.Usage =
match this with
| Workspace _ -> "Root of workspace. If not specified, current directory is used."
| Configuration _ -> "Configuration to use."
| Variable _ -> "Set variable."
| Label _-> "Select projects based on labels."
| Logs -> "Output logs for impacted projects."


[<RequireQualifiedAccess>]
type ClearArgs =
| [<Unique>] Cache
Expand Down Expand Up @@ -110,6 +128,7 @@ type TerrabuildArgs =
| [<CliPrefix(CliPrefix.None)>] Scaffold of ParseResults<ScaffoldArgs>
| [<CliPrefix(CliPrefix.None)>] Logs of ParseResults<LogsArgs>
| [<CliPrefix(CliPrefix.None)>] Run of ParseResults<RunArgs>
| [<CliPrefix(CliPrefix.None)>] Serve of ParseResults<ServeArgs>
| [<CliPrefix(CliPrefix.None)>] Clear of ParseResults<ClearArgs>
| [<CliPrefix(CliPrefix.None)>] Login of ParseResults<LoginArgs>
| [<CliPrefix(CliPrefix.None)>] Logout of ParseResults<LogoutArgs>
Expand All @@ -122,6 +141,7 @@ with
| Scaffold _ -> "Scaffold workspace."
| Logs _ -> "dump logs."
| Run _ -> "Run specified targets."
| Serve _ -> "Serve specified targets."
| Clear _ -> "Clear specified caches."
| Login _ -> "Connect to backend."
| Logout _ -> "Disconnect from backend."
Expand Down
6 changes: 5 additions & 1 deletion src/Terrabuild/Core/Build.fs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,11 @@ let execCommands (node: GraphDef.Node) (cacheEntry: Cache.IEntry) (options: Conf

Log.Debug("{Hash}: Running '{Command}' with '{Arguments}'", node.TargetHash, cmd, args)
let logFile = cacheEntry.NextLogFile()
let exitCode = Exec.execCaptureTimestampedOutput workDir cmd args logFile
let exitCode =
if options.Targets |> Set.contains "serve" then
Exec.execConsole workDir cmd args
else
Exec.execCaptureTimestampedOutput workDir cmd args logFile
cmdLastEndedAt <- DateTime.UtcNow
let endedAt = cmdLastEndedAt
let duration = endedAt - startedAt
Expand Down
20 changes: 14 additions & 6 deletions src/Terrabuild/Helpers/Exec.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,33 @@ type CaptureResult =
| Success of string*int
| Error of string*int

let private createProcess workingDir command args =
let private createProcess workingDir command args redirect =
let psi = ProcessStartInfo (FileName = command,
Arguments = args,
UseShellExecute = false,
WorkingDirectory = workingDir,
RedirectStandardOutput = true,
RedirectStandardError = true)
RedirectStandardOutput = redirect,
RedirectStandardError = redirect)
new Process(StartInfo = psi)

let execCaptureOutput (workingDir: string) (command: string) (args: string) =
use proc = createProcess workingDir command args
use proc = createProcess workingDir command args true
proc.Start() |> ignore
proc.WaitForExit()

match proc.ExitCode with
| 0 -> Success (proc.StandardOutput.ReadToEnd(), proc.ExitCode)
| _ -> Error (proc.StandardError.ReadToEnd(), proc.ExitCode)

let execConsole (workingDir: string) (command: string) (args: string) =
try
use proc = createProcess workingDir command args false
proc.Start() |> ignore
proc.WaitForExit()
proc.ExitCode
with
| exn -> TerrabuildException.Raise($"Process '{command} {args} in directory '{workingDir}' failed", exn)

let execCaptureTimestampedOutput (workingDir: string) (command: string) (args: string) (logFile: string) =
try
use logWriter = new StreamWriter(logFile)
Expand All @@ -35,14 +44,13 @@ let execCaptureTimestampedOutput (workingDir: string) (command: string) (args: s
let inline lockWrite (from: string) (msg: string) =
lock writeLock (fun () -> logWriter.WriteLine($"{DateTime.UtcNow} {from} {msg}"))

use proc = createProcess workingDir command args
use proc = createProcess workingDir command args true
proc.OutputDataReceived.Add(fun e -> lockWrite "OUT" e.Data)
proc.ErrorDataReceived.Add(fun e -> lockWrite "ERR" e.Data)
proc.Start() |> ignore
proc.BeginOutputReadLine()
proc.BeginErrorReadLine()
proc.WaitForExit()

proc.ExitCode
with
| exn -> TerrabuildException.Raise($"Process '{command} {args} in directory '{workingDir}' failed", exn)
Expand Down
33 changes: 32 additions & 1 deletion src/Terrabuild/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,14 @@ let processCommandLine (parser: ArgumentParser<TerrabuildArgs>) (result: ParseRe
0

let run (runArgs: ParseResults<RunArgs>) =
let targets = runArgs.GetResult(RunArgs.Target) |> Seq.map String.toLower
let wsDir =
match runArgs.TryGetResult(RunArgs.Workspace) with
| Some ws -> ws
| _ ->
match Environment.CurrentDirectory |> findWorkspace with
| Some ws -> ws
| _ -> TerrabuildException.Raise("Can't find workspace root directory. Check you are in a workspace.")
let targets = runArgs.GetResult(RunArgs.Target) |> Seq.map String.toLower
let configuration = runArgs.TryGetResult(RunArgs.Configuration) |> Option.defaultValue "default" |> String.toLower
let note = runArgs.TryGetResult(RunArgs.Note)
let labels = runArgs.TryGetResult(RunArgs.Label) |> Option.map (fun labels -> labels |> Seq.map String.toLower |> Set)
Expand Down Expand Up @@ -218,6 +218,36 @@ let processCommandLine (parser: ArgumentParser<TerrabuildArgs>) (result: ParseRe
RunTargetOptions.ContainerTool = containerTool }
runTarget logs options

let serve (serveArgs: ParseResults<ServeArgs>) =
let wsDir =
match serveArgs.TryGetResult(ServeArgs.Workspace) with
| Some ws -> ws
| _ ->
match Environment.CurrentDirectory |> findWorkspace with
| Some ws -> ws
| _ -> TerrabuildException.Raise("Can't find workspace root directory. Check you are in a workspace.")
let configuration = serveArgs.TryGetResult(ServeArgs.Configuration) |> Option.defaultValue "default" |> String.toLower
let labels = serveArgs.TryGetResult(ServeArgs.Label) |> Option.map (fun labels -> labels |> Seq.map String.toLower |> Set)
let variables = serveArgs.GetResults(ServeArgs.Variable) |> Map
let options = { RunTargetOptions.Workspace = wsDir |> FS.fullPath
RunTargetOptions.WhatIf = false
RunTargetOptions.Debug = debug
RunTargetOptions.Force = false
RunTargetOptions.MaxConcurrency = Int32.MaxValue
RunTargetOptions.Retry = true
RunTargetOptions.StartedAt = DateTime.UtcNow
RunTargetOptions.IsLog = false
RunTargetOptions.Targets = Set [ "serve" ]
RunTargetOptions.LocalOnly = true
RunTargetOptions.CheckState = false
RunTargetOptions.Configuration = configuration
RunTargetOptions.Note = None
RunTargetOptions.Tag = None
RunTargetOptions.Labels = labels
RunTargetOptions.Variables = variables
RunTargetOptions.ContainerTool = None }
runTarget true options

let logs (logsArgs: ParseResults<LogsArgs>) =
let targets = logsArgs.GetResult(LogsArgs.Target) |> Seq.map String.toLower
let wsDir =
Expand Down Expand Up @@ -279,6 +309,7 @@ let processCommandLine (parser: ArgumentParser<TerrabuildArgs>) (result: ParseRe
| p when p.Contains(TerrabuildArgs.Scaffold) -> p.GetResult(TerrabuildArgs.Scaffold) |> scaffold
| p when p.Contains(TerrabuildArgs.Logs) -> p.GetResult(TerrabuildArgs.Logs) |> logs
| p when p.Contains(TerrabuildArgs.Run) -> p.GetResult(TerrabuildArgs.Run) |> run
| p when p.Contains(TerrabuildArgs.Serve) -> p.GetResult(TerrabuildArgs.Serve) |> serve
| p when p.Contains(TerrabuildArgs.Clear) -> p.GetResult(TerrabuildArgs.Clear) |> clear
| p when p.Contains(TerrabuildArgs.Login) -> p.GetResult(TerrabuildArgs.Login) |> login
| p when p.Contains(TerrabuildArgs.Logout) -> p.GetResult(TerrabuildArgs.Logout) |> logout
Expand Down
Loading