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-scriptproperties:executeCommand: $Format('npm run build --stage {}', $CliArgs('stage'))resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsenvironment:- name: STAGEvalue: $CliArgs('stage')- name: CUSTOM_ARGvalue: $CliArgs('myCustomArg', 'myDefaultValue')resources:cpu: 2memory: 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: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my-lambda.tsenvironment:- name: MY_DIRECTIVE_VARIABLEvalue: $File('.env.staging').myvar1
INI files
Parses the contents of an .ini
file.
myvar1=value1
resources:myFunction:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my-lambda.tsenvironment:- name: MY_DIRECTIVE_VARIABLEvalue: $File('file.ini').myvar1
JSON files
Parses the contents of a .json
file.
{ "myvar1": "value1" }
resources:myFunction:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my-lambda.tsenvironment:- name: MY_DIRECTIVE_VARIABLEvalue: $File('file.json').myvar1
YML files
Parses the contents of a .yml
file.
myvar1: value1
resources:myFunction:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my-lambda.tsenvironment:- name: MY_DIRECTIVE_VARIABLEvalue: $File('file.yml').myvar1
$FileRaw()
Loads the content of a file and returns it as a string (UTF-8 encoded).
resources:myFunction:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my-lambda.tsenvironment:- name: MY_KEYvalue: $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 infoo-bar
.$Format('{}-mydomain.com', 'foo')
results infoo-mydomain.com
.$Format('{}.{}', $Stage(), 'mydomain.com')
results instaging.mydomain.com
if the stage isstaging
.
$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: myCustomEventNameresources:myEventBus:type: 'event-bus'# publishes events with EventName set to $Var().eventName into myEventBusmyPublisherFunction:type: 'function'properties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: 'lambdas/event-bus-publisher.ts'environment:- name: EVENT_NAMEvalue: $Var().eventNameconnectTo:- myEventBus# listens for events with EventName set to $Var().eventName published into myEventBusmyConsumerFunction:type: 'function'properties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: 'lambdas/consumer.ts'events:- type: event-busproperties:eventBusName: myEventBuseventPattern: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.
Directive | Description |
---|---|
$GitInfo().sha1 | SHA-1 of the latest commit |
$GitInfo().commit | The latest commit ID |
$GitInfo().branch | The name of the current branch |
$GitInfo().message | The message of the last commit |
$GitInfo().user | Git user's name |
$GitInfo().email | Git user's email |
$GitInfo().repository | The name of the git repository |
$GitInfo().tags | The tags pointing to the current commit |
$GitInfo().describe | The most recent tag that is reachable from a commit |
stackConfig:tags:- name: stagevalue: $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: bucketNamevalue: $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.tsenvironment:- name: BUCKET_NAMEvalue: $StackOutput($Var().baseStackName, 'baseBucketName')hooks:beforeDeploy:- executeNamedScript: validateBucketresources: ...
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:
- stacktape resource name: The name of the Stacktape resource as defined in your configuration.
- parameter name: The parameter to reference. You can find a list of all referenceable parameters in the documentation for each resource:
For more information, see Referencing parameters.
resources:myDatabase:type: relational-databaseproperties: ...myFunction:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my/lambda.tsenvironment:- name: DB_CONNECTION_STRINGvalue: $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 thestacktape 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::Topicresources:myBucket:type: bucketprocessData:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my/lambda.tsdestinations:onFailure: $CfResourceParam('MySnsTopic', 'Arn')environment:- name: BUCKET_NAMEvalue: $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-databaseproperties:credentials:masterUserPassword: $Secret('my-database-password')
Alternatively:
resources:myDatabase:type: relational-databaseproperties: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 infoo-bar
. -
$CfFormat('{}-mydomain.com', 'foo')
results infoo-mydomain.com
. -
$CfFormat('{}.mydomain.com', $Stage())
results instaging.mydomain.com
if the stage isstaging
.
$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: bucketNamevalue: $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: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: path/to/my/lambda.tsenvironment:- name: OTHER_STACK_BUCKET_NAMEvalue: $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: myDirectivefilePath: path/to/my/directive.ts:functionName
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: getDbInstanceSizefilePath: my-directive.ts:getDbInstanceSizeresources:myDatabase:type: relational-databaseproperties:credentials:masterUserPassword: $Secret('database.password')engine:type: postgresproperties:version: '16.2'port: 5432primaryInstance:instanceSize: $getDbInstanceSize($Stage())
Python
def get_db_instance_size(stage):if (stage == 'production'):return 'M5'return 'M2'
directives:- name: get_db_instance_sizefilePath: my-directive.py:get_db_instance_sizeresources:myDatabase:type: relational-databaseproperties:credentials:masterUserPassword: $Secret('database.password')engine:type: postgresproperties:version: '16.2'port: 5432primaryInstance:instanceSize: $get_db_instance_size($Stage())