[APO-88] Fix: hello-world change tracking without plan-time generated file - #330
Conversation
… file PR #329 added etag = filemd5("index.html") for change tracking, but index.html is generated at deploy time by env0.yml (sed of index.template.html). filemd5 runs at plan time, before that file reliably exists, so template integration tests fail with: open index.html: no such file or directory. Render the page content in Terraform from the committed index.template.html and hash the content instead: - main.tf: add variable "user" and local.index_html - s3.tf: use content + md5(local.index_html) instead of source + filemd5 - remove env0.yml (its only purpose was the sed step) md5(content) equals S3's single-part etag, so change tracking still works with no false drift, and the source file always exists at plan time.
|
The following env0 environments are affected by changes to this PR: To apply changes to all the environments above, use: To apply changes using custom filters (click here for more info), use: |
|
🚀 env0 had composed a PR Plan for environment Ronis GH / My First Project / foo-48279 : Plan DetailsTerraform will perform the following actions:
# null_resource.null will be created
+ resource "null_resource" "null" {
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
|
|
🚀 env0 had composed a PR Plan for environment ארגון פח / Default Organization Project / null template-28177 : Plan Details+ create
Terraform will perform the following actions:
# null_resource.null will be created
+ resource "null_resource" "null" {
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "shoes" but a value was
│ found in file "env0.auto.tfvars.json". If you meant to use this value, add
│ a "variable" block to the configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide
│ certain "global" settings to all configurations in your organization. To
│ reduce the verbosity of these warnings, use the -compact-warnings option.
╵
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "test" but a value was
│ found in file "env0.auto.tfvars.json". If you meant to use this value, add
│ a "variable" block to the configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide
│ certain "global" settings to all configurations in your organization. To
│ reduce the verbosity of these warnings, use the -compact-warnings option.
╵
╷
│ Warning: Values for undeclared variables
│
│ In addition to the other similar warnings shown, 3 other variable(s)
│ defined without being declared.
╵ |
|
🚀 env0 had composed a PR Plan for environment pat / My First Project / jii-46691 : Failure Details╷
│ Error: configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
│
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ for more information about providing credentials.
│
│ AWS Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, expect HTTP transport, got <nil>
│
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
╵
|
|
🚀 env0 had composed a PR Plan for environment Liran's Org / Default Organization Project / aws/hello-world : Failure Details╷
│ Error: configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
│
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ for more information about providing credentials.
│
│ AWS Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, expect HTTP transport, got <nil>
│
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
╵
|
|
🚀 env0 had composed a PR Plan for environment Raz org / qa / aws/hello-world : Failure Details╷
│ Error: configuring Terraform AWS Provider: validating provider credentials: retrieving caller identity from STS: operation error STS: GetCallerIdentity, https response error StatusCode: 403, RequestID: b0600c76-eee2-439a-ad62-720bacf671fe, api error ExpiredToken: The security token included in the request is expired
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
╵
|
|
🚀 env0 had composed a PR Plan for environment env0-yariv / 14215 - workflow failed scenario / asd / hello-world-aws-19601 : Failure Details@smithy/node-http-handler - the request socket did not establish a connection with the server within the configured timeout of 1000 ms. |
|
🚀 env0 had composed a PR Plan for environment Tom / Stam / aws : Failure Details╷
│ Error: No configuration files
│
│ Plan requires configuration to be present. Planning without a configuration
│ would mark everything for destruction, which is normally not what is
│ desired. If you would like to destroy everything, run plan with the
│ -destroy option. Otherwise, create a Terraform configuration file (.tf
│ file) and try again.
╵
|
|
🚀 env0 had composed a PR Plan for environment Tom / Stam / aws/hello-world : Failure Details╷
│ Error: configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
│
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ for more information about providing credentials.
│
│ AWS Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, expect HTTP transport, got <nil>
│
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
╵
|
|
🚀 env0 had composed a PR Plan for environment roni qa / My First Project / Complex Environment : Failure Details╷
│ Error: configuring Terraform AWS Provider: validating provider credentials: retrieving caller identity from STS: operation error STS: GetCallerIdentity, https response error StatusCode: 403, RequestID: fe8166e1-6f2f-476c-83f2-acf86f610c1f, api error InvalidClientTokenId: The security token included in the request is invalid.
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
╵
|
|
🚀 env0 had composed a PR Plan for environment Tom / mass import / aws/hello-world : Failure Details╷
│ Error: configuring Terraform AWS Provider: no valid credential sources for Terraform AWS Provider found.
│
│ Please see https://registry.terraform.io/providers/hashicorp/aws
│ for more information about providing credentials.
│
│ AWS Error: failed to refresh cached credentials, no EC2 IMDS role found, operation error ec2imds: GetMetadata, expect HTTP transport, got <nil>
│
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
╵
|
|
🚀 env0 had composed a PR Plan for environment CIA / !!!Performance!!! / templates : Plan DetailsOpenTofu used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
OpenTofu will perform the following actions:
# null_resource.null will be created
+ resource "null_resource" "null" {
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
|
|
🚀 env0 had composed a PR Plan for environment S.H.I.E.L.D EU 🇪🇺 / My First Project / Eurotrip-22862 : Failure DetailsSecret references are only supported in self-hosted agents. |
|
🚀 env0 had composed a PR Plan for environment roni qa / My First Project / AWS-47904 : Failure Details╷
│ Error: configuring Terraform AWS Provider: validating provider credentials: retrieving caller identity from STS: operation error STS: GetCallerIdentity, https response error StatusCode: 403, RequestID: d3e61601-5bf1-4452-8a66-74c2e571e984, api error InvalidClientTokenId: The security token included in the request is invalid.
│
│ with provider["registry.terraform.io/hashicorp/aws"],
│ on main.tf line 1, in provider "aws":
│ 1: provider "aws" {
│
╵
|
|
🚀 env0 had composed a PR Plan for environment sag-test / sag remote backend / null resource-94339 (null_resource_94339): Failure Detailsfatal: couldn't find remote ref pull/330/head
To rerun the PR Plan, use the following comment: |
|
🚀 env0 had composed a PR Plan for environment My Org / Project Without Creds / Hello World-53889 : Failure DetailsFailed to install opentofu: No matching version found in mirror for opentofu pattern: 1.6.0-alpha |
|
🚀 env0 had composed a PR Plan for environment S.H.I.E.L.D EU 🇪🇺 / My First Project / Eurotrip-80484 : Failure DetailsSecret references are only supported in self-hosted agents. |
|
🚀 env0 had composed a PR Plan for environment S.H.I.E.L.D EU 🇪🇺 / My First Project / Eurotrip-26189 : Failure DetailsSecret references are only supported in self-hosted agents. |
|
🚀 env0 had composed a PR Plan for environment Tomers Org / My New Bug / should-create-with-false : Plan DetailsTerraform will perform the following actions:
# null_resource.null will be created
+ resource "null_resource" "null" {
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
|
|
🚀 env0 had composed a PR Plan for environment ארגון פח / Default Organization Project / null template-28177 : Plan Details+ create
Terraform will perform the following actions:
# null_resource.null will be created
+ resource "null_resource" "null" {
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "dsfsdf" but a value was
│ found in file "env0.auto.tfvars.json". If you meant to use this value, add
│ a "variable" block to the configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide
│ certain "global" settings to all configurations in your organization. To
│ reduce the verbosity of these warnings, use the -compact-warnings option.
╵
╷
│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "freetext" but a value
│ was found in file "env0.auto.tfvars.json". If you meant to use this value,
│ add a "variable" block to the configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide
│ certain "global" settings to all configurations in your organization. To
│ reduce the verbosity of these warnings, use the -compact-warnings option.
╵
╷
│ Warning: Values for undeclared variables
│
│ In addition to the other similar warnings shown, 3 other variable(s)
│ defined without being declared.
╵ |
|
🚀 env0 had composed a PR Plan for environment S.H.I.E.L.D / Template Integration Tests / GitHub git submodule-20499 : Failure DetailsSecret references are only supported in self-hosted agents. |
Restore env0.yml so the template still demonstrates a custom deploy step, but make it a harmless echo. It no longer generates index.html; the page content and etag are produced inside Terraform.
Issue
PR #329 added
etag = filemd5("index.html")toaws/hello-world/s3.tfto track changes to the page. Butindex.htmlis not committed - it is generated at deploy time byenv0.yml:filemd5is evaluated at plan time, before that generated file reliably exists, so template integration tests fail:The old
source = "index.html"only read the file at apply time, so the plan-only path never hit a missing file. This is not a Terraform/provider version issue.Failing run: https://github.com/env0/env0/actions/runs/27699749492/job/81932792956
Linear: APO-88
Solution
Stop hashing a runtime-generated file. Render the page content inside Terraform from the committed
index.template.htmland hash the content:main.tf: addvariable "user"(defaultenv0) andlocal.index_html = replace(file("${path.module}/index.template.html"), "!!!USER!!!", var.user)s3.tf:content = local.index_html+etag = md5(local.index_html)(replacessource+filemd5)env0.yml: keep the custom-flow demo but make it an echo-only step (no longer generatesindex.html)md5(content)equals S3's etag for single-part uploads, so change tracking works with no false drift, and the committed template always exists at plan time. Personalization moves from the OS$USERto the optionaluserTerraform variable.How I manually verified it works
terraform fmt -checkclean;terraform init -backend=false+terraform validate-> Success (only a pre-existing provider-version-block warning, unrelated to this change)