Stacktape
Stacktape


Directives



Directives are functions that add dynamic behavior to your stacktape.yml file. They allow you to go beyond the declarative nature of YAML and introduce logic into your configurations.

Stacktape supports two types of directives:

  • Built-in directives are provided by Stacktape for common tasks, such as accessing command-line arguments or formatting strings.
  • Custom directives are user-defined functions that allow you to add your own logic, such as setting a database instance size based on the deployment stage or fetching data required for your configuration. Custom directives can be written in Javascript, Typescript, or Python.

How to use directives

Directives always start with a $ and can be used to configure any property in your stacktape.yml file.

myProperty: $MyDirective()

A directive can return primitive values (strings, numbers, booleans), objects, or arrays. You can access properties of a returned object using dot notation (e.g., $Directive().propertyName).

Directives can accept any number of arguments. If you pass arguments inline, they must be primitive values. If you pass arguments as the result of another directive, they can be primitive values, objects, or arrays.

myProperty: $MyDirective('myParameter', 3, true)

Directives can be nested up to two levels deep (e.g., $MyDirective1($MyDirective2())). To overcome this limitation, you can use variables to store the output of a directive and then reference it in another.

myProperty: $MyDirective1($MyDirective2())

Built-in directives

Built-in directives are resolved either locally (when the configuration is loaded) or at runtime (during deployment).

Local directives

Local directives are resolved when the configuration is loaded, and their values are substituted directly into the configuration.

$CliArgs()

Returns a command-line argument passed to a Stacktape command. You can pass custom arguments to a Stacktape command after the -- separator. You can also specify a default value as the second argument to the directive (e.g., $CliArgs('myArg', 'myDefaultValue')).

stacktape deploy --stage test --region eu-west-1 -- --myCustomArg myValue
scripts:
build:
type: local-script
properties:
executeCommand: $Format('npm run build --stage {}', $CliArgs('stage'))
resources:
webService:
type: web-service
properties:
packaging:
type: stacktape-image-buildpack
properties:
entryfilePath: src/main.ts
environment:
- name: STAGE
value: $CliArgs('stage')
- name: CUSTOM_ARG
value: $CliArgs('myCustomArg', 'myDefaultValue')
resources:
cpu: 2
memory: 2048

$File()

Reads and parses the content of a file. Supported file types are .env, .ini, .json, and .yml.

If you need to read the raw content of a file as a string, use the $FileRaw() directive instead.

Dotenv files

Parses the contents of a .env file.

myvar1=value1
resources:
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my-lambda.ts
environment:
- name: MY_DIRECTIVE_VARIABLE
value: $File('.env.staging').myvar1
INI files

Parses the contents of an .ini file.

myvar1=value1
resources:
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my-lambda.ts
environment:
- name: MY_DIRECTIVE_VARIABLE
value: $File('file.ini').myvar1
JSON files

Parses the contents of a .json file.

{ "myvar1": "value1" }
resources:
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my-lambda.ts
environment:
- name: MY_DIRECTIVE_VARIABLE
value: $File('file.json').myvar1
YML files

Parses the contents of a .yml file.

myvar1: value1
resources:
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my-lambda.ts
environment:
- name: MY_DIRECTIVE_VARIABLE
value: $File('file.yml').myvar1

$FileRaw()

Loads the content of a file and returns it as a string (UTF-8 encoded).

resources:
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my-lambda.ts
environment:
- name: MY_KEY
value: $FileRaw('my-key.txt')

$Format()

Returns an interpolated string. The first argument is the string to be interpolated, and subsequent arguments are the values to be substituted for each {} placeholder. The number of placeholders must match the number of subsequent arguments.

The $Format() directive cannot contain runtime-resolved directives as arguments. For those use cases, use the $CfFormat() directive.

  • $Format('{}-{}', 'foo', 'bar') results in foo-bar.
  • $Format('{}-mydomain.com', 'foo') results in foo-mydomain.com.
  • $Format('{}.{}', $Stage(), 'mydomain.com') results in staging.mydomain.com if the stage is staging.

$Var()

Returns a variable defined in the variables section of your stacktape.yml file. Variables are useful for:

  • Reusing values throughout your template.
  • Organizing your template files.
  • Storing intermediate return values of other directives to allow for multi-level nesting.
variables:
eventName: myCustomEventName
resources:
myEventBus:
type: 'event-bus'
# publishes events with EventName set to $Var().eventName into myEventBus
myPublisherFunction:
type: 'function'
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: 'lambdas/event-bus-publisher.ts'
environment:
- name: EVENT_NAME
value: $Var().eventName
connectTo:
- myEventBus
# listens for events with EventName set to $Var().eventName published into myEventBus
myConsumerFunction:
type: 'function'
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: 'lambdas/consumer.ts'
events:
- type: event-bus
properties:
eventBusName: myEventBus
eventPattern:
detail:
EventName:
- $Var().eventName

$Stage()

Returns the current stage. Unlike $CliArgs().stage, this directive also resolves default values configured with the stacktape defaults:configure command.

$Region()

Returns the current region. Unlike $CliArgs().region, this directive also resolves default values configured with the stacktape defaults:configure command.

$Profile()

Returns the current profile. Unlike $CliArgs().profile, this directive also resolves default values configured with the stacktape defaults:configure command.

$This()

Returns the current Stacktape template as an object.

resources:
myHttpApi:
type: 'http-api-gateway'
properties:
customDomains:
# we are interpolating serviceName using This directive
- domainName: $Format('{}-{}', $This().serviceName, 'mydomain.com')

$GitInfo()

Returns information about the current Git repository.

DirectiveDescription
$GitInfo().sha1SHA-1 of the latest commit
$GitInfo().commitThe latest commit ID
$GitInfo().branchThe name of the current branch
$GitInfo().messageThe message of the last commit
$GitInfo().userGit user's name
$GitInfo().emailGit user's email
$GitInfo().repositoryThe name of the git repository
$GitInfo().tagsThe tags pointing to the current commit
$GitInfo().describeThe most recent tag that is reachable from a commit
stackConfig:
tags:
- name: stage
value: $GitInfo().repository

$StackOutput()

Returns the specified output of another stack, allowing you to reference resources deployed in a different stack.

The arguments are:

  • stack name: The name of the stack that contains the output. If the stack was deployed with Stacktape, the name has the format <<projectName>>-<<stage>>.
  • output name: The name of the output to return.

The $StackOutput() directive returns the output value of another stack at the time the current stack is deployed. To ensure that the value does not change or that the other stack is not deleted, use the $CfStackOutput() directive instead.

Consider a stack named base-stack deployed to a dev stage with the following configuration:

stackConfig:
outputs:
- name: bucketName
value: $ResourceParam('baseBucket', 'arn')
resources:
baseBucket:
type: bucket

You can reference the output of base-stack in another stack:

variables:
baseStackName: $Format('{}-{}', 'base-stack', $Stage())
scripts:
validateBucket:
executeScript: hooks/validate-bucket-in-base-stack.ts
environment:
- name: BUCKET_NAME
value: $StackOutput($Var().baseStackName, 'baseBucketName')
hooks:
beforeDeploy:
- executeNamedScript: validateBucket
resources: ...

Runtime directives

Some directives are resolved at runtime by Cloudformation during deployment. This is necessary when the value of a directive is not known until a resource is created. For example, the connection string of a database is only available after the database has been deployed.

Under the hood, runtime directives are transformed into CloudFormation intrinsic functions.

Runtime directives can only be used in the resources and scripts sections of your stacktape.yml file.

For convenience, Stacktape resolves runtime directives locally (by automatically downloading the value) when they are used inside a script or with development commands (stacktape cw:run-local and stacktape fn:develop).

$ResourceParam()

Returns a specified parameter of a Stacktape resource, such as the name or port of a database, or the URL of an HTTP API Gateway.

The arguments are:

For more information, see Referencing parameters.

resources:
myDatabase:
type: relational-database
properties: ...
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my/lambda.ts
environment:
- name: DB_CONNECTION_STRING
value: $ResourceParam('myDatabase', 'connectionString')

$CfResourceParam()

Returns a specified parameter of a Cloudformation resource.

The arguments are:

  • cloudformation logical name: The logical name of the Cloudformation resource. If you are referencing a resource defined in the cloudformationResources section, use its name. To reference a child resource of a Stacktape resource, you can get a list of child resources with the stacktape stack-info command.
  • parameter name: The parameter of the Cloudformation resource to reference. For a list of all referenceable parameters, see Referencing parameters.

For more information, see Referencing parameters.

cloudformationResources:
MySnsTopic:
Type: AWS::SNS::Topic
resources:
myBucket:
type: bucket
processData:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my/lambda.ts
destinations:
onFailure: $CfResourceParam('MySnsTopic', 'Arn')
environment:
- name: BUCKET_NAME
value: $CfResourceParam('MyBucketBucket', 'Name')

$Secret()

Returns the value of a secret. For more information, see the secrets documentation.

The argument is the name of the secret. If the secret is in JSON format, you can extract nested properties using dot notation.

resources:
myDatabase:
type: relational-database
properties:
credentials:
masterUserPassword: $Secret('my-database-password')

Alternatively:

resources:
myDatabase:
type: relational-database
properties:
credentials:
masterUserPassword: $Secret('my-database-credentials.password')

$CfFormat()

Returns an interpolated string. Unlike the $Format() directive, the $CfFormat() directive can contain runtime-resolved directives as arguments.

The arguments are:

  • string to interpolate: Occurrences of {} are replaced by the subsequent arguments.

  • values to use in the interpolation: The number of values must be equal to the number of {} placeholders in the first argument.

  • $CfFormat('{}-{}', 'foo', 'bar') results in foo-bar.

  • $CfFormat('{}-mydomain.com', 'foo') results in foo-mydomain.com.

  • $CfFormat('{}.mydomain.com', $Stage()) results in staging.mydomain.com if the stage is staging.

$CfStackOutput()

Returns the output of another stack, allowing you to reference resources deployed in another stack. The referenced stack must already be deployed. If you try to delete a stack that is referenced by another stack, you will get an error.

To get the output locally (i.e., download the value and pass it to the configuration), use the $StackOutput() directive.

The arguments are:

  • stack name: The name of the stack that contains the output. If the stack was deployed using Stacktape, the name has the format <<projectName>>-<<stage>>.
  • output name: The name of the output to reference.

Consider a stack named base-stack deployed to a dev stage with the following configuration:

stackConfig:
outputs:
- name: bucketName
value: $ResourceParam('baseBucket', 'arn')
resources:
baseBucket:
type: bucket

You can reference the output of base-stack in another stack:

variables:
baseStackName: $Format('{}-{}', 'base-stack', $Stage())
resources:
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my/lambda.ts
environment:
- name: OTHER_STACK_BUCKET_NAME
value: $CfStackOutput($Var().baseStackName, 'bucketName')

Custom directives

Custom directives are user-defined functions that allow you to add your own logic to your configurations, such as setting a database instance size based on the deployment stage or fetching data required for your configuration.

Registering directives

To use a custom directive, you must first register it in the directives section of your stacktape.yml file.

directives:
- name: myDirective
filePath: path/to/my/directive.ts:functionName
DirectiveDefinition  API reference
name
Required
filePath
Required

Writing directives

You can write custom directives in Javascript, Typescript, or Python. They can return primitive values, objects, or arrays. If a directive returns an object, you can access its properties using dot notation (e.g., $GetBooks().books.Dune).

Any code outside the function handler will be executed only once, when the configuration is first parsed.

Javascript and Typescript

You can write directives in Javascript (ES2020) and Typescript. The code is automatically transpiled. Your directive can return a promise, which will be automatically awaited.

export const getDbInstanceSize = (stage: string) => {
if (stage === "production") {
return "db.m5.xlarge";
}
return "db.t2.micro";
};
directives:
- name: getDbInstanceSize
filePath: my-directive.ts:getDbInstanceSize
resources:
myDatabase:
type: relational-database
properties:
credentials:
masterUserPassword: $Secret('database.password')
engine:
type: postgres
properties:
version: '16.2'
port: 5432
primaryInstance:
instanceSize: $getDbInstanceSize($Stage())

Python

def get_db_instance_size(stage):
if (stage == 'production'):
return 'M5'
return 'M2'
directives:
- name: get_db_instance_size
filePath: my-directive.py:get_db_instance_size
resources:
myDatabase:
type: relational-database
properties:
credentials:
masterUserPassword: $Secret('database.password')
engine:
type: postgres
properties:
version: '16.2'
port: 5432
primaryInstance:
instanceSize: $get_db_instance_size($Stage())

Contents