Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/acceptance-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ name: Acceptance
on:
pull_request:
branches:
- master
- master
- fir-compatibility
paths-ignore:
- 'docs/**'
- '**.md'
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ website/vendor
# Test exclusions
!command/test-fixtures/**/*.tfstate
!command/test-fixtures/**/.terraform/

.cursor/
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
golang 1.24.5
terraform 1.5.7
44 changes: 22 additions & 22 deletions docs/data-sources/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ description: |-

# Data Source: heroku_app

Use this data source to get information about a Heroku App.
Use this data source to get information about a Heroku app.

~> **NOTE:** This resource is only supported for apps that use [classic buildpacks](https://devcenter.heroku.com/articles/buildpacks#classic-buildpacks).

## Example Usage

Expand All @@ -23,50 +25,48 @@ data "heroku_app" "default" {

The following arguments are supported:

* `name` - (Required) The name of the application. In Heroku, this is also the
* `name`: (Required) The name of the application. In Heroku, it's a
unique ID, so it must be unique and have a minimum of 3 characters.

## Attributes Reference

The following attributes are exported:

* `id` - The unique UUID of the Heroku app.
* `id`: The unique UUID of the Heroku app.

* `name` - The name of the application. In Heroku, this is also the
* `name`: The name of the application. In Heroku, it's also the
unique ID.

* `stack` - The application stack is what platform to run the application
in.
* `stack`: The application [stack](https://devcenter.heroku.com/articles/stack) is what platform to run the application in.

* `buildpacks` - A list of buildpacks that this app uses.
* `buildpacks`: A list of buildpacks that this app uses.

* `space` - The private space in which the app runs. Not present if this is a common runtime app.
* `space`: The [space](https://devcenter.heroku.com/articles/private-spaces) in which the app runs. Not present for [Common Runtime](https://devcenter.heroku.com/articles/dyno-runtime#common-runtime) apps.

* `region` - The region in which the app is deployed.
* `region`: The region in the app is deployed in.

* `git_url` - The Git URL for the application. This is used for
* `git_url`: The Git URL for the application, used for
deploying new versions of the app.

* `web_url` - The web (HTTP) URL that the application can be accessed
at by default.
* `web_url`: The web (HTTP) URL to access the application at by default.

* `heroku_hostname` - The hostname for the Heroku application, suitable
* `heroku_hostname`: The hostname for the Heroku application, suitable
for pointing DNS records.

* `last_release_id` - The last successful Release ID for the app. May be empty.
* `last_release_id`: The last successful Release ID for the app. May be empty.

* `last_slug_id` - The Slug ID from the last successful release. May be empty.
* `last_slug_id`: The slug ID from the last successful release. May be empty.

* `config_vars` - A map of all configuration variables for the app.
* `config_vars`: The map of all configuration variables for the app.

* `acm` - True if Heroku ACM is enabled for this app, false otherwise.
* `acm`: True if [Heroku Automated Certificate Management](https://devcenter.heroku.com/articles/automated-certificate-management) is enabled for this app, false otherwise.

* `organization` - The Heroku Team that owns this app.
* `organization`: The Heroku team that owns this app.

* `name` - The name of the Heroku Team (organization).
* `name`: The name of the Heroku team (organization).

* `locked` - True if the app access is locked
* `locked`: True if the app access is locked

* `personal`
* `personal`: True for personal apps

* `uuid` - The unique UUID of the Heroku app.
* `uuid`: The unique UUID of the Heroku app.
212 changes: 157 additions & 55 deletions docs/resources/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@ layout: "heroku"
page_title: "Heroku: heroku_app"
sidebar_current: "docs-heroku-resource-app-x"
description: |-
Provides a Heroku App resource. This can be used to create and manage applications on Heroku.
Provides a Heroku App resource. Use this resource to create and manage applications on Heroku.
---

# heroku\_app

Provides a Heroku App resource. This can be used to create and manage applications on Heroku.
Provides a [Heroku App](https://devcenter.heroku.com/articles/platform-api-reference#app) resource. Use this resource to create and manage applications on Heroku.

-> **Always reference apps by ID (UUID) in Terraform configuration**
Starting with v5.0 of this provider, all HCL app references are by ID. Read more details in [Upgrading](guides/upgrading.html).
The Heroku platform supports two [generations](https://devcenter.heroku.com/articles/generations):
- **Cedar** (default): Legacy platform with support for classic buildpacks, stack configuration, and internal routing
- **Fir**: Next-generation platform with enhanced security, and modern containerization

-> **Note:** Always reference apps by ID (UUID) in Terraform configuration. Starting with v5.0 of this provider, all HCL app references are by ID. Read more details in [Upgrading](guides/upgrading.html).

## Example Usage

### Cedar Generation Using Classic Buildpacks (Default)
```hcl-terraform
resource "heroku_app" "default" {
name = "my-cool-app"
resource "heroku_app" "cedar_app" {
name = "my-cedar-app"
region = "us"

config_vars = {
Expand All @@ -27,12 +31,43 @@ resource "heroku_app" "default" {
buildpacks = [
"heroku/go"
]

stack = "heroku-22"
}
```

### Fir Generation Using Cloud Native Buildpacks (via Fir Space)
```hcl-terraform
# Create a Fir-generation space first
resource "heroku_space" "fir_space" {
name = "my-fir-space"
organization = "my-org"
region = "virginia"
generation = "fir"
}

# Apps deployed to Fir spaces automatically use Fir generation
resource "heroku_app" "fir_app" {
name = "my-fir-app"
region = "virginia"
space = heroku_space.fir_space.name

organization {
name = "my-org"
}

config_vars = {
FOOBAR = "baz"
}

# Note: buildpacks and stack are not supported for Fir-generation apps as they use Cloud Native Buildpacks
# Use project.toml in your application code instead
}
```

## Example Usage for a Team

A Heroku "team" was originally called an "organization", and that is still the identifier used in this resource.
A Heroku "team" was originally called an "organization", and that's still the identifier used in this resource.

```hcl-terraform
resource "heroku_app" "default" {
Expand All @@ -47,80 +82,147 @@ resource "heroku_app" "default" {

## Argument Reference

The following arguments are supported:

* `name` - (Required) The name of the application. In Heroku, this is also the
unique ID, so it must be unique and have a minimum of 3 characters.
* `region` - (Required) The region that the app should be deployed in.
* `stack` - (Optional) The application stack is what platform to run the application in.
* `buildpacks` - (Optional) Buildpack names or URLs for the application.
Buildpacks configured externally won't be altered if this is not present.
* `config_vars`<sup>[1](#deleting-vars)</sup> - (Optional) Configuration variables for the application.
The config variables in this map are not the final set of configuration
variables, but rather variables you want present. That is, other
configuration variables set externally won't be removed by Terraform
The resource supports the following arguments:

* `name`: (Required) The name of the application. In Heroku, this argument is the unique ID, so it must be unique and have a minimum of 3 characters.
* `region`: (Required) The region to deploy the app in.
* `generation`: (Computed) Generation of the app platform. Automatically determined based on the space the app is deployed to. Apps in Fir-generation spaces are `fir`, all other apps are `cedar`.
- `cedar`: Legacy platform supporting classic buildpacks, stack configuration, and internal routing.
- `fir`: Next-generation platform with Cloud Native Buildpacks (CNB). No support for `buildpacks`, `stack`, or `internal_routing` fields.
* `stack`: (Optional) The name of the [stack](https://devcenter.heroku.com/articles/stack) to run the application in. **Note**: Not supported for `fir` generation apps.
* `buildpacks`: (Optional) Classic buildpack names or URLs for the application.
Buildpacks configured externally won't be altered if this isn't present. **Note**: Not supported for apps using Cloud Native Buildpacks, like Fir-generation apps. Use `project.toml` for configuration instead.
* `config_vars`<sup>[1](#deleting-vars)</sup>: (Optional) Configuration variables for the application.
The config variables in this map aren't the final set of configuration
variables, but rather variables you want present. Terraform doesn't remove configuration variables set externally
if they aren't present in this list.
* `sensitive_config_vars`<sup>[1](#deleting-vars)</sup> - (Optional) This argument is the same as `config_vars`.
* `sensitive_config_vars`<sup>[1](#deleting-vars)</sup>: (Optional) This argument is the same as `config_vars`.
The main difference between the two is when `sensitive_config_vars` outputs
are displayed on-screen following a terraform apply or terraform refresh,
they are redacted, with <sensitive> displayed in place of their value.
It is recommended to put private keys, passwords, etc in this argument.
* `space` - (Optional) The name of a private space to create the app in.
* `internal_routing` - (Optional) If true, the application will be routable
only internally in a private space. This option is only available for apps
that also specify `space`.
* `organization` - (Optional) A block that can be specified once to define
are displayed on-screen following a `terraform apply` or `terraform refresh`,
they're redacted, with `<sensitive>` displayed in place of their value.
It's recommended to put sensitive information like private keys, and passwords in this argument.
* `space`: (Optional) The name of the space to create the app in.
* `internal_routing` - (Optional) If true, the application is routable
only internally in Heroku Private Spaces. This option is only available for apps
that also specify `space`. **Note**: Only supported for apps in Cedar-generation spaces.
* `organization`: (Optional) Specify this block once to define
Heroku Team settings for this app. The fields for this block are
documented below.
* `acm` - (Optional) The flag representing Automated Certificate Management for the app.
* `acm`: (Optional) If Automated Certificate Management is enabled for the app.

The `organization` block supports:
* `name` (string) - The name of the Heroku Team.
* `locked` (boolean) - Are other team members forbidden from joining this app.
* `personal` (boolean) - Force creation of the app in the user account even if a default team is set.
* `name` (string): The name of the Heroku Team.
* `locked` (boolean): If other team members are forbidden from joining this app.
* `personal` (boolean): Force creation of the app in the user's account, even if a default team is set.

### Deleting vars
### Deleting Vars

Deleting an entire `config_vars` or `sensitive_config_vars` map from a `heroku_app`
configuration will not actually remove the vars on the remote resource. To remove an existing variable,
leave these attribute maps in-place and delete only its entries from the map. Once these attributes are
empty, the map itself may be deleted from the configuration. Otherwise if one deletes the map with existing
entries, the config vars will not be deleted from the remote resource.
configuration doesn't remove the variables on the remote resource. To remove an existing variable,
leave these attribute maps in-place and only delete its entries from the map. After these attributes are
empty, you can delete the map itself from the configuration. Otherwise, if you delete the map with existing
entries, the config vars don't get deleted from the remote resource.

This is especially important if you are migrating all `config_vars` to `sensitive_config_vars` or migrating
config vars to `heroku_app_config_association` resource.
If you're migrating all `config_vars` to `sensitive_config_vars`, or migrating
config vars to `heroku_app_config_association` resource, this behavior is especially important.

## Attributes Reference

The following attributes are exported:

* `id` - The ID (UUID) of the app.
* `name` - The name of the app.
* `stack` - The application stack is what platform to run the application in.
* `space` - The private space the app should run in.
* `internal_routing` - Whether internal routing is enabled the private space app.
* `region` - The region that the app should be deployed in.
* `git_url` - The Git URL for the application. This is used for
* `id`: The ID (UUID) of the app.
* `name`: The name of the app.
* `generation`: Generation of the app platform (`cedar` or `fir`). Automatically determined from the space the app is deployed to.
* `stack`: The name of the [stack](https://devcenter.heroku.com/articles/stack) the application is run in.
* `space`: The space the app is in.
* `internal_routing`: If internal routing is enabled. Only for apps in Heroku Private Spaces.
* `region`: The region that the app is deployed to.
* `git_url`: The Git URL for the application, used for
deploying new versions of the app.
* `web_url` - The web (HTTP) URL that the application can be accessed
at by default.
* `heroku_hostname` - A hostname for the Heroku application, suitable
* `web_url`: The web (HTTP) URL for accessing the application by default.
* `heroku_hostname`: The hostname for the Heroku application, suitable
for pointing DNS records.
* `all_config_vars` - A map of all configuration variables that
* `all_config_vars`: The map of all configuration variables that
exist for the app, containing both those set by Terraform and those
set externally. (These are treated as "sensitive" so that
their values are redacted in console output.) This attribute is not set in state if the `provider`
set externally. These variables are treated as "sensitive" so that
their values are redacted in console output. This attribute isn't set in state if the `provider`
attribute `set_app_all_config_vars_in_state` is `false`.
* `uuid` - The unique UUID of the Heroku app. **NOTE:** Use this for `null_resource` triggers.
* `uuid`: The unique UUID of the Heroku app. **Note:** Use this attribute for `null_resource` triggers.

## Cloud Native Buildpacks

When apps are deployed to Fir-generation spaces, they automatically use Cloud Native Buildpacks (CNB) instead of classic Heroku buildpacks. CNBs require different configuration approaches:

### project.toml Configuration

Instead of specifying `buildpacks` in Terraform, create a `project.toml` file in your application root:

```toml
[build]
[[build.buildpacks]]
id = "heroku/nodejs"

[[build.buildpacks]]
id = "heroku/procfile"

[build.env]
BP_NODE_VERSION = "18.*"
```

### Migration from Cedar to Fir

When migrating from Cedar to Fir generation:

1. **Create a Fir space**: Create a new space with `generation = "fir"`.
2. **Remove unsupported fields**: Remove `buildpacks`, `stack`, and `internal_routing` from your Terraform configuration.
3. **Add a `project.toml` file**: Create a `project.toml` file in your application code with Cloud Native Buildpacks configuration.
4. **Update the `space`**: Change your app's `space` to use the Fir space.
5. **Redeploy**: Deploy your application with the new configuration.

```hcl-terraform
# Before (Cedar)
resource "heroku_space" "cedar_space" {
name = "my-space"
organization = "my-org"
region = "virginia"
}

resource "heroku_app" "example" {
name = "my-app"
region = "virginia"
space = heroku_space.cedar_space.name

buildpacks = ["heroku/nodejs"]
stack = "heroku-22"
}

# After (Fir)
resource "heroku_space" "fir_space" {
name = "my-space-fir"
organization = "my-org"
region = "virginia"
generation = "fir"
}

resource "heroku_app" "example" {
name = "my-app"
region = "virginia"
space = heroku_space.fir_space.name

# buildpacks and stack removed - configured via project.toml
# generation is automatically "fir" from the space
}
```

## Import

Apps can be imported using an existing app's `UUID` or name.
Import apps with an existing app's `UUID` or name.

For example:
```
$ terraform import heroku_app.foobar MyApp
$ terraform import heroku_app.foobar e74ac056-7d00-4a7e-aa80-df4bc413a825
```

Please note: `config_vars` & `sensitive_config_vars` will not be imported due to limitations of Terraform's import process (see [issue](https://github.com/heroku/terraform-provider-heroku/issues/247#issuecomment-602013774)). All vars will appear to be added on the next plan/apply. The diff may be manually reconciled using the outputs of `heroku config` & `terraform plan`.
>[!NOTE]
>`config_vars` & `sensitive_config_vars` aren't imported due to limitations of Terraform's import process (see [issue](https://github.com/heroku/terraform-provider-heroku/issues/247#issuecomment-602013774)). All vars appear to be added on the next plan/apply. Manually reconcile the diff using the outputs of `heroku config` & `terraform plan`.
Loading