-
Notifications
You must be signed in to change notification settings - Fork 8
Writing Tasks
A Whiskey task is a PowerShell function that has a Whiskey.Task
attribute:
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
)
Set-StrictMode -Version 'Latest'
}
To allow users to pass values to your task, create parameters on your function. Whiskey will map the parameter names to the property names from the build YAML.
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
[string]$Property
)
Set-StrictMode -Version 'Latest'
}
With the above task, your task would be used in the YAML like this:
- TASK_NAME:
Property: Value
With this YAML, Whiskey will pass Value
to your function's Property
parameter.
You can get the raw, parsed YAML as a hashtable by having a TaskParameter
parameter on your function:
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
[hasthable]$TaskParameter
)
Set-StrictMode -Version 'Latest'
}
Named parameters are never passed in the TaskParameter
hashtable.
All values from YAML files are strings and are passed to your function as strings. If a named parameter has a specific type, PowerShell must be able to implicity convert strings to that type. Additionally, Whiskey will convert YAML booleans (yes
, no
, true
, false
, 1
, or 0
) to PowerShell booleans for any parameters whose types are [Switch]
or [bool]
.
If you want the value of a parameter to come from a Whiskey variable, decorate the parameter with Whiskey's Whiskey.Tasks.ParameterValueFromVariable
attribute, passing the variable expression (method/property names allowed):
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
[Whiskey.Tasks.ParameterValueFromVariable('WHISKEY_ENVIRONMENT')]
$Environment,
[Whiskey.Tasks.ParameterValueFromVariable('WHISKEY_ENVIRONMENT.Length')]
$Length
)
Set-StrictMode -Version 'Latest'
}
See Variables for a list of variables available.
All Whiskey tasks have these global, reserved parameters, which you should not define on your task:
OnlyDuring
ExceptDuring
OnlyOnBranch
ExceptOnBranch
OnlyBy
ExceptBy
WorkingDirectory
IfExists
UnlessExists
Reserved properties are never passed to your function, either as a parameter or in the TaskParameter
hashtable.
If you have a parameter that is a path to a file or directory, Whiskey can validate the path exists and convert it to a literal path for you, converting directory separators to the preferred separator for the build's current platform. This allows users to use either forward or backward slashes and your task doesn't have to worry about converting them.
Whiskey resolves all paths relative to the current task's working directory (which by default is the directory of the build's whiskey.yml file, or the directory chosen by the user via the WorkingDirectory
common task properth). It passes relative paths to your task. To enable this, add the Whiskey.Tasks.ValidatePath
attribute to the function parameter (or parameters) that should be resolved as paths.
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
[Whiskey.Tasks.ValidatePath()]
[string]$Path
)
Set-StrictMode -Version 'Latest'
}
By default, the property can be empty and any paths that are given in YAML must exist. If you want to require that the user give at least one path (and fail the build if they don't), use the Mandatory
property:
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
# The user must supply a path to a single file/directory that exists.
[Whiskey.Tasks.ValidatePath(Mandatory)]
[string]$Path
)
Set-StrictMode -Version 'Latest'
}
To support multiple paths, set the type of the parameter to [string[]]
:
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
# The user can use wildcards that point to multiple items.
[Whiskey.Tasks.ValidatePath(Mandatory)]
[string[]]$Path
)
Set-StrictMode -Version 'Latest'
}
If the path must be to a file or directory, use the PathType
property to specify which. The build will fail if any path in the YAML isn't of the given type.
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
# Must be paths to files only.
[Whiskey.Tasks.ValidatePath(PathType='File')]
[string[]]$FilePath,
# Must be paths to directories only.
[Whiskey.Tasks.ValidatePath(PathType='Directory')]
[string[]]$DirectoryPath
)
Set-StrictMode -Version 'Latest'
}
By default, the path must point to a file or directory that exists. If you'd like to allow the user to supply a path to a file or directory your task will create, use the AllowNonexistent
property:
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
# Must be paths to files only.
[Whiskey.Tasks.ValidatePath(AllowNonexistent)]
[string]$Path
)
Set-StrictMode -Version 'Latest'
if( -not (Test-Path -Path $Path -PathType Leaf) )
{
New-Item -Path $Path -ItemType 'File'
}
}
By default, paths must be under the build root (i.e. the directory where a build's whiskey.yml file is). If you want your task to access items outside this directory, use the AllowOutsideBuildRoot
property:
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[CmdletBinding()]
param(
# Must be paths to files only.
[Whiskey.Tasks.ValidatePath(AllowOutsideBuildRoot)]
[string]$Path
)
Set-StrictMode -Version 'Latest'
}
If your task should only run on certain platforms/operating systems, set the Platform
property on your task's TaskAttribute
to the platform(s) it is restricted to. If the task runs on an unsupported platform, the build will fail. By default, tasks can run on all platforms. Supported platforms are Windows
, Linux
, and MacOS
. For example, a task with this task attribute will only run on Windows:
[Whiskey.Task('TASK_NAME',Platform=[Whiskey.Platform]::Windows)]
To run on multiple platforms, use PowerShell's -bor
operator:
[Whiskey.Task('TASK_NAME',Platform=[Whiskey.Platform]::Windows -bor [Whiskey.Platform]::Linux)]
You can define aliases for your task name. This is useful for making your tasks more discoverable or for re-naming tasks without requiring people to update their build scripts when they upgrade. Use the Aliases
property to define a list of aliases.
[Whiskey.Task('TASK_NAME',Aliases=('OldName','AnotherOldName'))]
If you want to warn when someone uses your task using an aliased name, use the WarnWhenUsingAlias
property.
[Whiskey.Task('TASK_NAME',Aliases=('DeprecatedName'),WarnWhenUsingAlias)]
To deprecate a task, set the Obsolete
property on its Whiskey.Task
attribute:
[Whiskey.Task('TASK_NAME',Obsolete)]
When someone uses your task, Whiskey will write a warning that the task is obsolete and shouldn't be used. You can customize the message shown to users with the ObsoleteMessage
property:
[Whiskey.Task('TASK_NAME',Obsolete,ObsoleteMessage='The "TASK_NAME" task is obsolete. Please use the "NonObsoleteTask" instead.')]
To use your task in a whiskey.yml file, use the LoadTask task to load it, then its name from the Whiskey.Task
attribute in your whiskey.yml file, e.g.
Build:
- LoadTask:
Path: path\to\task\file.ps1
- TASK_NAME:
Property: Value
Property2:
- One
- Two
Whiskey can automatically install some tools for your task. The path to that tool is passed to your task as a parameter.
To tell Whiskey what tools you depend on, add a Whiskey.RequiresTool
attribute. It has two parameters: the name of the tool, and the name of the parameter to which the path to that tool should be passed to your task.
For example, given this task:
function FUNCTION_NAME
{
[Whiskey.Task('TASK_NAME')]
[Whiskey.RequiresTool('Node','NodePath')]
[CmdletBinding()]
param(
[string]$NodePath
)
& $NodePath --version
}
Whiskey will install the latest version of Node.js, and pass the path Node executable to the NodePath
parameter.
We recommend that you always pin your task to a specific version. Use the Whiskey.RequiresTool
attribute's Version
property:
[Whiskey.RequiresTool('NodeModule::nsp', 'NspPath', Version='2.7.0')]
Wildcards are supported (except for NuGet packages due to a bug in nuget.org), so you can pin to major and minor versions of a tool.
We recommend allowing users to control what version of a tool they want. Use the Whiskey.RequiresTool
attribute's VersionParameterName
property. Set this to the name of a parameter the user can specify in their whiskey.yml file to control what version to use. The default name is Version
. For example, if your Whiskey.RequiresTool
attribute looks like this:
[Whiskey.RequiresTool('PowerShell::Zip', 'ZipPath', Version='0.3.*', VersionParameterName='ZipVersion')]
A user could use the ZipVersion
property to control the version of the Zip
module to use.
Build:
- TASK_NAME:
ZipVersion: "0.*"
Whiskey supports installing:
- Node.js
-
Node.js Modules, into the global
packages
directory of the instance of Node.js a build is using. -
.NET Core SDK, into a
.dotnet
directory in the build root. -
PowerShell Modules, into a
PSModules
directory in the build root. -
NuGet Packages, into a
packages
directory into the build root.
To install Node, add this to your task:
[Whiskey.RequiresTool('Node','NodePath')]
The NodePath
string is the name of your task's parameter to which Whiskey should pass the path to the Node.js executable when running your task.
If the user doesn't use the Version
parameter in their whiskey.yml file to specify what version of Node to use, Whiskey also looks in the user's package.json file at the engines.node
property, e.g.
{
"engines": {
"node": "^8.9.4"
}
}
Node is installed to a .node
directory in the build root. This gives every project its own version of Node to use.
If you or the user doesn't specify a version of Node.js to use, Whiskey uses the latest LTS version.
To install a Node module, pass the name of the module (case-sensitive) to the Whiskey.RequiresTool
attribute, prefixed with NodeModule::
. For example,
[Whiskey.RequiresTool('NodeModule::nsp', 'NspPath')]
would cause Whiskey to install the NSP module and passthe path to its directory to the NspPath
parameter of your task. The path will always be to the Node module's directory in the node_modules
directory.
Node modules are installed in the global packages
directory of the instance of Node.js you're using.
To install the .NET Core SDK, add this to your task:
[Whiskey.RequiresTool('DotNet','DotNetPath')]
Replace the DotNetPath
string with the name of the parameter to which Whiskey should pass the path to the dotnet
executable to your task.
If the SDK version to install is not defined in the whiskey.yml
file, then Whiskey will look for a .NET Core global.json
file first in the task's working directory and then in the same directory as the whiskey.yml
file. The global.json
file defines the SDK version with the sdk.version
property, e.g.
{
"sdk": {
"version": "2.1.4"
}
}
If no SDK version is found in the whiskey.yml
or global.json
, Whiskey will use the latest LTS release of the .NET Core SDK.
Before installing the .NET Core SDK to the build root, Whiskey will first search for global .NET Core installs containing the desired version. If a global install is found with the correct version, that path is used and the install to the local build root is skipped.
Whiskey will always update the sdk.version
property within the global.json
file found in the task working directory or the Whiskey build root with the version of the SDK that task is using. If a global.json
file does not exist in either the working directory or build root, one is created in the build root.
To use a PowerShell module, add this to your task:
[Whiskey.RequiresPowerShellModule('Whiskey','WhiskeyPath')]
Whiskey will install and import the module for you.
Replace the WhiskeyPath
string with the name of the parameter to which Whiskey should pass the path to the directory where PowerShell's Save-Module
cmdlet saved the module (e.g. if it was saved to PSModules\MODULE_NAME\1.2.3
, the path will be set to PSModules\MODULE_NAME
).
Modules are saved to a PSModules
directory in the working directory of the task that requires it. The exact directory is an implementation detail, and is subject to change. Use the path as passed to your task.
Support for NuGet packages was added in Whiskey 0.42.0.
To install a NuGet package, pass the name of the NuGet package to the Whiskey.RequiresTool
attribute, prefixed with NuGet::
. For example, to install NUnit.Console
, your attribute would look like this:
[Whiskey.RequiresTool('NuGet::NUnit.Console', 'ConsolePath',)]
The second parameter is the name of the parameter to which the path to the NuGet package should be passed. In the above example, the task should have a ConsolePath
parameter. The path to the tool is the root of the package. The layout of NuGet packages can vary, so your task is responsible for finding the right files inside that package.
Packages are installed into a packages
directory in the build root.
A note on versioning: there is bug in nuget.org that prevents all versions of a package from being returned. When requesting all versions, only the latest is returned. If you pin to a version of a NuGet package that contains wildcards, and the user's download packages from nuget.org, they'll always get the latest version. So, until this bug if fixed, we recommend pinning the version of the package to a specific version, and exposing a parameter that allows users to use a newer version.
Whiskey also exposes many of its internal functions for you to use in your tasks. Documentation for these functions are available in PowerShell. Import Whiskey and run Get-Command -Module Whiskey
to see the list. Run help COMMAND_NAME
for detailed information.
- Common Task Properties
- AppVeyorWaitForBuildJob
- CopyFile
- Delete
- DotNet
- Exec
- File
- GetPowerShellModule
- GitHubRelease
- InstallNodeJs
- LoadTask
- Log
- MergeFile
- MSBuild
- NuGetPack
- NuGetPush
- NuGetRestore
- NUnit2
- NUnit3
- Parallel
- Pester
- Pipeline
- PowerShell
- ProGetUniversalPackage
- PublishBitbucketServerTag
- PublishBuildMasterPackage
- PublishNodeModule
- PublishPowerShellModule
- PublishProGetAsset
- PublishProGetUniversalPackage
- SetVariable
- SetVariableFromPowerShellDataFile
- SetVariableFromXml
- TaskDefaults
- Version
- Zip