Awesome
Deploy Heroku apps from pipelines using Terraform
Heroku Pipelines provide a continuous delivery workflow for Heroku apps, supporting Review Apps, CI testing, and automated deployment.
When used in conjunction with Terraform, Pipelines act as the build system, generating slugs to be released by a Terraform config. The apps in the pipeline do not serve live production traffic. Instead, the apps provisioned by Terraform are the production system.
A single Terraform config embodies the production system, enabling high-level collaboration, repeatability, test-ability, and change management.
Primary components
- Heroku provides the primatives: Apps and Add-ons
- Terraform provides declarative, unified systems configuration with support for over 120 providers, a human-friendly configuration as code format, and a deterministic provisioning engine
- Pipeline-to-Terraform connector, a custom solution, for example this
bin/pipeline-slug-ids
script
Challenges & Caveats
- Uses pre-release Heroku Platform API for Pipelines. To fetch current slug IDs in the pipeline,
bin/pipeline-slug-ids
usesversion=3.pipelines
of the API, a version is not officially stable - Config drift when using Heroku Dashboard or CLI. Once the config is applied, if changes are made to the resources outside of Terraform, such as scaling dynos, setting config vars, changing add-ons, etc, then the Terraform state will no longer match its configuration, making it impossible to apply or destroy further until the drifting values are imported (for new resources) or manually updated in
terraform.tfstate
- Renaming Terraform-provisioned Heroku apps. If apps are renamed, Terraform can no longer access various resources without first manually editing, revising
terraform.tfstate
with the new names. See terraform-provider-heroku issues #124 & #93
Requirements
- Heroku
- install command-line tools (CLI)
- an account (must be a member of an Enterprise account for access to Private Spaces)
- install git
- install Terraform
Usage
Ensure the requirements are met, then,
-
Clone this repo:
git clone git@github.com:heroku-examples/terraform-heroku-pipeline-slugs.git cd terraform-heroku-pipeline-slugs/
-
Set Heroku API key
heroku authorizations:create -d terraform-heroku-pipeline-slugs
export HEROKU_API_KEY=<"Token" value from the authorization>
-
terraform init
-
Set Heroku Pipeline IDs from which to capture the slugs
-
For each desired pipeline, set its UUID (from its Heroku Dashboard URL) into an environment variable, and then source the pipeline-slug-ids script to capture the current slug IDs, like this:
export BUILD_PIPELINE_API=2f557b76-d685-452a-8651-9a6295a2a032 export BUILD_PIPELINE_WEB_UI=26a3ecbf-8188-43ae-b0fe-be2d9e9fe26f source bin/pipeline-slug-ids
⚠️ These values must be refreshed for each new deployment.
-
-
Then, apply the config with your own top-level config values:
terraform apply
Adaptation
To adapt this pattern to your own project, the BUILD_PIPELINE_*
names must match
what the Terraform config expects for each heroku_app_release
resource's slug ID.
For example, the value of BUILD_PIPELINE_API
provides the variable
var.api_slug_production
in:
resource "heroku_app_release" "api_production" {
app = "${heroku_app.api_production.name}"
slug_id = "${var.api_slug_production}"
}
…and the value of BUILD_PIPELINE_WEB_UI
provides the variable
var.web_ui_slug_production
in:
resource "heroku_app_release" "web_ui_production" {
app = "${heroku_app.web_ui_production.name}"
slug_id = "${var.web_ui_slug_production}"
}
🔬 This is a community proof-of-concept, MIT license, provided "as is", without warranty of any kind.