Script

Extensions can provide actions to help performing a specific step. An extension can be implemented using an F# script:

PROJECT
extension say {
  script = "say.fsx"
}

target build {
  say verb { who: "world" }
}
say.fsx
#if !TERRABUILD_SCRIPT
#r "<path-to>/Terrabuild.Extensibility.dll"
#endif

open Terrabuild.Extensibility

let verb (who: string) =
  scope Cacheability.Always
  |> andThen "echo" $"Hello {who}!"

In this example, who argument is used to invoke the verb 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:

  • string and string option
  • bool and bool option
  • List<string> and List<string> option
  • Map<string, string> and Map<string, string> option
  • ActionContext for action functions (must be named context)
  • InitContext for action function (must be named context)

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 ActionBatch record.

PROJECT
extension hello {
  script = "hello.fsx"
}

target build {
  hello world
}
hello.fsx
#if !TERRABUILD_SCRIPT
#r "<path-to>/Terrabuild.Extensibility.dll"
#endif

open Terrabuild.Extensibility

let __dispatch__ (context: ActionContext) =
  scope Cacheability.Always
  |> andThen "echo" $"Hello {context.Command}!"
ℹ️
context 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):

PROJECT
extension  {
  script = "sln.fsx"
}
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.
Last updated on