Hooks

Hooks are used to perform actions in different stages of stack operations. You can use them, for example, to compile and package lambda functions or notify whenever a deployment completes.

There can be different types of hooks. When configuring a hook, you give it a name and specify which hook type it is.

Hook Execution

Hooks are executed in the order they are defined. If one hook fails, the whole stack operation with any remaining hooks is aborted and deemed as a failure. Hook configuration is used to determine when the hook should be executed. For example, you can configure the hook to be executed before an existing stack is updated.

Hook Configuration

You configure hooks in stack configuration using following properties.

KeyRequiredTypeDescription
nameyesstringName of the hook.
typeyesstringType of the hook.
operationnostring or string[]Stack operations during which the hook is executed. Supported values are:

  • create - The hook is executed when a new stack is created
  • update - The hook is executed when an existing stack is updated
  • delete - The hook is executed when an existing stack is deleted
By default, the hook is executed in every stack operation.
stagenostring or string[]Stack operation stages during which the hook is executed.

  • before - The hook is executed before the stack operation
  • after - The hook is executed after the stack operation
By default, the hook is executed in every stage.
statusnostring or string[]Stack operation results during which the hook is executed.

  • success - The hook is executed when the stack operation succeeded
  • failed - The hook is executed when the stack operation failed
  • skipped - The hook is executed when the stack operation was skipped
  • cancelled - The hook is executed when the stack operation was cancelled
By default, the hook is executed in every status. Status is available only when stage is after.

In addition to the properties mentioned above, different hook types can have properties of their own.

Sharing Data Between Hooks

Hooks can expose values to other hooks by returning a detailed hook output object. The returned value is stored with a hook's name in a mutable variables object that is then passed to the subsequent hooks. The mutable variables object is discarded after the current stack operation is completed. The exposed data is not visible to hooks executed in other stacks.

Built-in Hooks

There is one built-in hook:

Command Hook

Executes a shell command given in command property. Exposes the following environment variables to the shell command:

NameDescription
TKM_COMMAND_STAGEThe current stack operation stage.
TKM_COMMAND_OPERATIONThe current stack operation.
TKM_COMMAND_STATUSThe current stack operation status, not present in before stage

Any output the hook prints to the stdout is captured and exposed for other hooks.

Properties

Here are the properties available for Command hook:

KeyRequiredTypeDescription
typeyesstringType of the hook, this must be cmd.
nameyesstringName of the hook.
commandyesstringShell command to execute.
cwdyesstringThe working directory from where the shell command is executed.

Implementing Custom Hooks

You can provide custom hooks by placing plain JavaScript files, with .js file extension, into the hooks directory. Each file must export a hook provider object that is used to initialize the actual hook. You can use all language features available in Node 14.4.0.

Hook Provider

Hook provider has the following properties:

KeyRequiredTypeDescription
typeyesstringType of the hook
inityesfunctionA function that initializes the hook with properties given in a stack group or stack configuration file. The function can be either synchronous or asynchronous, and must return an instantiated hook object.

Hook

Hook has the following properties:

KeyRequiredTypeDescription
executeyesfunctionA function that is invoked with an hook input object when the hook is executed. The function can be synchronous or asynchronous and must return a hook output.

Hook Input

Hook input has the following properties:

KeyRequiredTypeDescription
stageyesstringCurrent stack operation stage. Possible values are:

  • before - The hook is being executed before the stack operation
  • after - The hook is being executed after the stack operation
operationyesstringCurrent stack operation. Possible values are:

  • create - The hook is being executed when a new stack is being created
  • update - The hook is being executed when an existing stack is being updated
  • delete - The hook is being executed when an existing stack is being deleted
statusyesstringCurrent stack operation status. Possible values are:

  • success - The hook is being executed after a successful stack operation
  • failure - The hook is being executed after a failed stack operation
  • skipped - The hook is being executed after a skipped stack operation
  • cancelled - The hook is being executed after a cancelled stack operation
This is defined only when the stage is after.
variablesyesobjectMutable variables object containing command line and environment variables. The hook can modify existing variables and add new ones. After the hook is completed, the same variables object is passed to the subsequent hooks which can then access its contents. If the stack's template is .hbs file, the same variables are also usable there.
ctxyesstringCommand context object

Hook Output

Hook output is used to determine if the hook execution was successful and to share data between hooks. It can be either a boolean, an Error which is always considered as failure, or a detailed object with the following properties:

KeyRequiredTypeDescription
successyesbooleanA boolean determining if the hook execution was successful.
messagenostringAn informative message about the hook execution outcome.
valuenoanyA value to be exposed to other hooks.

Example

This example hook prints some debug information to the console.

Our file structure looks like this:

.
โ”œโ”€ stacks
| โ””โ”€ my-stack.yml
โ”œโ”€ hooks
| โ””โ”€ debug.js
โ””โ”€ templates
โ””โ”€ my-stack.yml

The hook provider defined in hooks/debug.js looks like this:

hooks/debug.js
module.exports = {
type: "debug",
init: (props) => {
console.log("Initialize debug hook");
return {
execute: (input) => {
console.log("Execute debug hook!");
console.log(`Stage: ${input.stage}`);
console.log(`Operation: ${input.operation}`);
console.log(`Status: ${input.status}`);
console.log(JSON.stringify(props, null, 2));
return {
message: "OK",
success: true,
value: "Did some debugging"
};
}
}
}
};

Our custom hook is used in the stack configuration like so:

stacks/my-stack.yml
hooks:
- name: my-hook
type: debug

When executed, the hook exposes string "Did some debugging" in the mutable variables object.

See Also