Skip to content

Fix: have a good default for approval flow on workflows #1029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 28, 2025

Conversation

TomerHeber
Copy link
Contributor

Issue & Steps to Reproduce / Feature Request

fixes #1023

Solution

  1. During creating isWorkflow is decided based on the template type instead of the sub_environment_configuration.
  2. When updating schema - ignore "approve_plan_automatically" if not set in schema - this is a cleaner solution.
  3. Applied minor updates to acceptance tests.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR updates the default approval flow logic for workflows by basing the workflow decision on the template type and refactoring the environment creation logic. In addition, it updates test expectations and acceptance tests to better align with these changes.

  • Update test expectations for Template calls and workflow type checks.
  • Refactor environment creation into separate functions for template and templateless environments.
  • Adjust approval field update logic and payload generation based on the workflow type.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
env0/resource_environment_test.go Revised test expectations for Template calls and workflow type constant
env0/resource_environment.go Refactored environment creation and payload functions with updated approval flow logic
Comments suppressed due to low confidence (2)

env0/resource_environment_test.go:2442

  • Verify that increasing the expected Template call from 1 to 2 is intentional and that the test covers all interactions to avoid future brittle behavior.
mock.EXPECT().Template(environment.LatestDeploymentLog.BlueprintId).Times(2).Return(template, nil)

env0/resource_environment.go:1040

  • [nitpick] Confirm that determining the workflow status solely based on the template type covers all expected scenarios, particularly if additional types may be introduced later.
isWorkflow := templateType == client.WORKFLOW

@TomerHeber
Copy link
Contributor Author

/review

@bot-env0 bot-env0 requested a review from a team March 30, 2025 14:45
@TomerHeber TomerHeber requested a review from Copilot April 2, 2025 13:33
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR improves the default behavior for the approval flow in workflow environments by basing decisions on the template type and providing a cleaner update mechanism. Key changes include:

  • Using template.Type instead of sub_environment_configuration to determine workflow environments.
  • Ignoring "approve_plan_automatically" when not set in the schema.
  • Splitting environment creation logic into separate functions for templated and templateless environments, with accompanying updates to acceptance tests and CI workflows.

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

File Description
env0/resource_environment_test.go Updated test expectations to match new workflow logic
env0/resource_environment.go Refactored environment creation & validation logic for workflows
env0/data_environment.go Adjusted data reading to reflect the new approval default
.github/workflows/*.yml Updated CI configuration to use Ubuntu 24.04
Comments suppressed due to low confidence (2)

env0/resource_environment_test.go:2442

  • Please confirm that the increased expectation from Times(1) to Times(2) for the Template call is intentional based on the new workflow logic, and update the test case description if necessary.
mock.EXPECT().Template(environment.LatestDeploymentLog.BlueprintId).Times(2).Return(template, nil)

env0/resource_environment.go:1044

  • [nitpick] Ensure that using the equality check (templateType == client.WORKFLOW) reliably distinguishes workflow environments. If there are alternative representations for workflow environments, consider normalizing the input to avoid misclassification.
isWorkflow := templateType == client.WORKFLOW

@TomerHeber TomerHeber force-pushed the fix-default-for-workflow-#1023 branch from f4782e9 to 9705a36 Compare April 17, 2025 00:54
@weinguy-env0 weinguy-env0 requested review from yaronya and removed request for weinguy-env0 April 20, 2025 08:45
@@ -72,4 +72,4 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Harness tests
run: go run tests/harness.go
run: go run tests/harness.go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add empty line in the end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are a lot of changes for the approval flow, can you explain what did you do here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. the change is a litte complex.

@@ -550,20 +550,66 @@ func createVariable(configurationVariable *client.ConfigurationVariable) any {
}

// Validate that the template is assigned to the "project_id".
func validateTemplateProjectAssignment(d *schema.ResourceData, apiClient client.ApiClientInterface) error {
func validateTemplateProjectAssignment(d *schema.ResourceData, template *client.Template) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need the template in one of the upper functions, so here instead of getting it we pass it here.
we get it from the upper functions.

return nil
}

func createEnvironmentWithTemplate(d *schema.ResourceData, apiClient client.ApiClientInterface) (client.Environment, client.EnvironmentCreate, diag.Diagnostics) {
templateId := d.Get("template_id").(string)

template, err := apiClient.Template(templateId)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is why this part was removed.

return nil
}

func createEnvironmentWithTemplate(d *schema.ResourceData, apiClient client.ApiClientInterface) (client.Environment, client.EnvironmentCreate, diag.Diagnostics) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have two usecases.
template and envrionment seperate resources.
template + environment one resource.
previousuly it was an if-else in the code. now it's two helper functions with a if-else.

}

return nil
environmentPayload, diagError := getCreatePayload(d, apiClient, template.Type)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we pass the template.Type - with this we set a better default.

return environment, environmentPayload, nil
}

func createEnvironmentWithoutTemplate(d *schema.ResourceData, apiClient client.ApiClientInterface) (client.Environment, client.EnvironmentCreate, diag.Diagnostics) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

helper function 2 - environment + template together.

// Note: the blueprint id field of the environment is returned only during creation of a template without environment.
// Afterward, it will be omitted from future response.
// setEnvironmentSchema() sets the blueprint id in the resource (under "without_template_settings.0.id").
environment, err := apiClient.EnvironmentCreateWithoutTemplate(payload)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the payload contains the template details which means it contains the template Type which we need for better defaults.


environment, err = apiClient.EnvironmentCreate(environmentPayload)
if !isTemplateless(d) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the if-else where we call the two helper functions.

@@ -1016,7 +1041,7 @@ func getCreatePayload(d *schema.ResourceData, apiClient client.ApiClientInterfac
payload.AutoDeployOnPathChangesOnly = boolPtr(val.(bool))
}

_, isWorkflow := d.GetOk("sub_environment_configuration")
isWorkflow := templateType == client.WORKFLOW
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and finally we decide if it's a workflow based on the templateType.
if isWorkflow is True, defaults will be set as needed. This code already exist.
The change is - we decide if it's a workflow based on the template type instead of checking if sub_environment_configuration exist.

// Don't update this value for workflow environments - this value should always be 'false'.
if _, isWorkflow := d.GetOk("sub_environment_configuration"); !isWorkflow && environment.RequiresApproval != nil {
//nolint:staticcheck // https://github.com/hashicorp/terraform-plugin-sdk/issues/817
if _, exists := d.GetOkExists("approve_plan_automatically"); exists && environment.RequiresApproval != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only make changes to approve_plan_automatically if someone has set a value for it.
it's tri-boolean value.
undefined, true, and false.

return nil
}

func createEnvironmentWithTemplate(d *schema.ResourceData, apiClient client.ApiClientInterface) (client.Environment, client.EnvironmentCreate, diag.Diagnostics) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

environemnt and template - seperate resources use-case.

@yaronya yaronya requested a review from eranelbaz April 28, 2025 12:10
Copy link
Member

@eranelbaz eranelbaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After talking seems ok to me
note name suggestions

@github-actions github-actions bot added ready to merge PR approved - can be merged once the PR owner is ready and removed pending final review labels Apr 28, 2025
@TomerHeber
Copy link
Contributor Author

@eranelbaz - going to merge. If you still want to make naming changes let me know and I create an additional PR. But note that I've used common naming conventions.

@TomerHeber TomerHeber merged commit aa97a86 into main Apr 28, 2025
9 checks passed
@TomerHeber TomerHeber deleted the fix-default-for-workflow-#1023 branch April 28, 2025 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependency-change fix github-actions provider ready to merge PR approved - can be merged once the PR owner is ready
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Have a good default for approval flow on workflows
2 participants