Runtime configuration

Runtime configuration is an optional piece of setup that is applied to individual runs instead of being global to the stack. It's defined in .spacelift/config.yml YAML file at the root of your repository. A single file is used to define settings for all stacks associated with its host Git repository, so the file structure looks like this:

version: "1"
runner_image: your/first:runner
# Note that tflint is not installed by
# default - this example assumes that your
# runner image has this available.
- terraform fmt -check
- tflint
# Note that every field in the configuration is
# optional, and has a reasonable default. This file
# allows you to override those defaults, and you can
# merely override individual fields.
# The key of is the immutable slug of your stack
# which you will find in the URL.
babys-first-stack: &shared
- hostname
project_root: infra
terraform_version: 0.12.4
<<: *shared
terraform_version: 0.13.0
AWS_REGION: eu-west-1

The top level of the file contains three keys - version which in practice is currently ignored but may be useful in the future, stacks, which contains a mapping of immutable stack id to the stack configuration block and stack_defaults, containing the defaults that are common to all stacks using this source code repository. Note that that any stack defaults will be overridden by corresponding stack-specific settings.

Since we adopted everyone's favorite data serialization format, you can use all the YAML shenanigans you can think of - things like anchors and inline JSON can keep your config DRY and neat.

Purpose of runtime configuration

The whole concept of runtime configuration may initially sound unnecessary, but it ultimately allows flexibility that would otherwise be hard to achieve. In general its purpose is to preview effects of changes not related to the source code (eg. Terraform or Pulumi version upgrades, variable changes etc.), before they become an established part of your infra.

While stack environment applies both to tracked and non-tracked branches, a runtime configuration change can be pushed to a feature branch, which triggers proposed runs allowing you to preview the changes before they have a chance to affect your state.

If the runtime configuration file is not present, or does not contain your stack, default values are used - refer to each setting for its respective default.

Stacks configuration block

before_apply scripts

Defaults to an empty array.

This works similarly to before_init scripts but is executed during the applying phase, just before we run terraform apply.

before_init scripts

Defaults to an empty array.

This is an array of commands that will be executed during the initialization phase, just before we run vendor-specific initialization commands (eg. terraform init for Terraform). These commands may serve one of two general purposes - either make some modifications to your workspace (eg. set up symlinks, move files around etc.) or perhaps run checks and/or validations using something like tflint or terraform fmt. The example file above shows a combination of the two - first a symlink is created (modification) and then two validations are performed. Only then terraform init would run.

There are no restrictions as to what before_init commands can use or do. They have access to your execution environment, including mounted files.

We advise against using before_init scripts to install large dependencies since makes your run take much longer. Instead, we suggest building a custom Docker image with all your dependencies, and setting the runner_image value accordingly.

environment map

Defaults to an empty map.

Environment allows you to declaratively pass some environment variables to the runtime configuration of the Stack. In case of a conflict, these variables will override both the ones passed via attached Contexts, and those directly set in Stack's environment.

project_root setting

Defaults to an empty string, pointing to the working directory for the run.

Project root is the path of your project directory inside the Hub repository. This can be used to point Spacelift to the right place if the repo contains source code for multiple stacks in various folders, or serves multiple purposes like those increasingly popular monorepos combining infrastructure definitions with source code, potentially even for multiple applications.

runner_image setting

Runner image is the Docker image used to run your workloads. By making it a runtime setting, Spacelift allows testing the image before it modifies your infrastructure.

terraform_version setting

Defaults to the latest known supported Terraform version.

This setting is only valid on Terraform stacks and specifies the Terraform version that's going to be used for the run. The main use case is being able to test a newer version of Terraform before it's used to change the state and the way back is very hard. This version can only be equal to or higher than the one already used to apply state changes. For more details on Terraform version management, please refer to its dedicated help section.

Pulumi version management is more complex since it also involves programming language runtimes, and is based on Docker images.