Script
Extensions can provide actions to help performing a specific step. An extension can be implemented using an F# script:
extension say {
script = "say.fsx"
}
target build {
sayHello { who = "world" }
}#if !TERRABUILD_SCRIPT
#r "<path-to>/Terrabuild.Extensibility.dll"
#endif
open Terrabuild.Extensibility
let sayHello (context: ActionContext) (who: string) =
let ops = [ shellOp "echo" $"Hello {who}" ]
ops |> execRequest Cacheability.AlwaysIn this example, who argument is used to invoke the sayHello action (that’s just the name of the function).
When the script is runned in Terrabuild, TERRABUILD_SCRIPT is defined as well a reference to Terrabuild.Extensibility.dll assembly. Script is always compiled with this dependency.
If TERRABUILD_SCRIPT is not defined, you have to reference the assembly. This can also be used to test script without running in Terrabuild.
Arguments
Functions accept arguments. Supported types are:
stringandstring optionboolandbool optionList<string>andList<string> optionMap<string, string>andMap<string, string> optionActionContextfor action functions (must be namedcontext)InitContextfor action function (must be namedcontext)
Dispatch
If you want to let the user define the verb, you can use the special function name __dispatch__. If this function is defined, Terrabuild will used it to dispatch the command if the named one is not found. An action function must return an ActionExecutionRequest record.
extension hello {
script = "hello.fsx"
}
target build {
hello { who = "world" }
}#if !TERRABUILD_SCRIPT
#r "<path-to>/Terrabuild.Extensibility.dll"
#endif
open Terrabuild.Extensibility
let __dispatch__ (context: ActionContext) (who: string) =
let ops = [ shellOp "echo" $"{context.Command} {who}" ]
execRequest Cacheability.Always opscontext argument name is required to pass the ActionContext.Defaults
An extension can also provide a default configuration for a project by implementing __defaults__ function. This function must return a ProjectInfo instance.
Here is a sample extension extracting projects from an sln project file (Visual Studio Solution file):
extension {
script = "sln.fsx"
}#if !TERRABUILD_SCRIPT
#r "<path-to>/Terrabuild.Extensibility.dll"
#endif
open Terrabuild.Extensibility
open System.IO
open System.Text.RegularExpressions
let private (|Regex|_|) pattern input =
let m = Regex.Match(input, pattern)
if m.Success then
List.tail [ for g in m.Groups -> g.Value ] |> Some
else
None
let private findProject = function
| Regex "^Project\(.*\) = \".*\", \"(.*)\", .*$" [projectFile] ->
Some projectFile
| _ ->
None
let __defaults__ (context: InitContext) =
let dependencies =
Directory.EnumerateFiles(context.Directory, "*.sln") |> Seq.head
|> File.ReadLines
|> Seq.choose findProject
{ ProjectInfo.Default
with Ignores = Set.empty
Outputs = Set.empty
Dependencies = Set dependencies }context argument name is required to pass the InitContext.