Repository: diggerhq/digger
Pull request #368 (2023-06-15 08:59:14)

merge develop into the branch


Patch:
diff --git a/action.yml b/action.yml
index bc87a39d..bcc0677d 100644
--- a/action.yml
+++ b/action.yml
@@ -157,7 +157,7 @@ runs:
       if: inputs.setup-terraform == 'true'
 
     - name: Setup tfenv
-      uses: rhythmictech/actions-setup-tfenv@v0.0.2
+      uses: rhythmictech/actions-setup-tfenv@v0.1.2
       if: inputs.setup-tfenv == 'true'
 
     - name: Setup Terragrunt
diff --git a/go.mod b/go.mod
index affb9054..141ba7ac 100644
--- a/go.mod
+++ b/go.mod
@@ -6,16 +6,15 @@ require (
 	cloud.google.com/go/storage v1.30.1
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0
 	github.com/Azure/azure-sdk-for-go/sdk/data/aztables v1.0.1
-	github.com/aws/aws-sdk-go v1.44.279
+	github.com/aws/aws-sdk-go v1.44.282
 	github.com/bmatcuk/doublestar/v4 v4.6.0
 	github.com/caarlos0/env/v7 v7.1.0
 	github.com/google/go-github/v51 v51.0.0
 	github.com/google/uuid v1.3.0
-	github.com/jinzhu/copier v0.3.5
 	github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
 	github.com/open-policy-agent/opa v0.53.1
 	github.com/stretchr/testify v1.8.4
-	github.com/xanzy/go-gitlab v0.84.0
+	github.com/xanzy/go-gitlab v0.85.0
 	gopkg.in/yaml.v3 v3.0.1
 )
 
diff --git a/go.sum b/go.sum
index 7c7e6f1a..27befd94 100644
--- a/go.sum
+++ b/go.sum
@@ -31,6 +31,8 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig
 github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
 github.com/aws/aws-sdk-go v1.44.279 h1:g23dxnYjIiPlQo0gIKNR0zVPsSvo1bj5frWln+5sfhk=
 github.com/aws/aws-sdk-go v1.44.279/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.44.282 h1:ZPB9QhwxmMIEC8ja0DdFowOl5fODWaZ6s2cZ40fx6r8=
+github.com/aws/aws-sdk-go v1.44.282/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc=
@@ -42,6 +44,7 @@ github.com/caarlos0/env/v7 v7.1.0/go.mod h1:LPPWniDUq4JaO6Q41vtlyikhMknqymCLBw0e
 github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -69,6 +72,7 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
 github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
+github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
 github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -77,6 +81,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
 github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -133,12 +138,13 @@ github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxC
 github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
 github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
 github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
-github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
-github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
 github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
 github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -149,6 +155,9 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr
 github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 h1:YH424zrwLTlyHSH/GzLMJeu5zhYVZSx5RQxGKm1h96s=
 github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqKSQK1vIfQ+yVaFcGjDySHvym6FM1cNYnwzbrY=
 github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/open-policy-agent/opa v0.53.1 h1:APN8iA7Txgel13kSkc6S8dbUulydiPojXt6iyubmB7Q=
 github.com/open-policy-agent/opa v0.53.1/go.mod h1:j3wl8FqSz/+u33Scl72Ms2wxkZx4yZPdqSCrOqBqdsA=
 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
@@ -185,6 +194,8 @@ github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BG
 github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
 github.com/xanzy/go-gitlab v0.84.0 h1:PdpCaskQSgcVDsx21c6ikf8Rfyo7SNtFAJwP9PrbCFE=
 github.com/xanzy/go-gitlab v0.84.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw=
+github.com/xanzy/go-gitlab v0.85.0 h1:E/wjnsd/mM5kV6O9y5+i6zxjx+wfAwa97sgcT1ETNwk=
+github.com/xanzy/go-gitlab v0.85.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw=
 github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
 github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
diff --git a/pkg/azure/azure.go b/pkg/azure/azure.go
index 3fb5e4cb..aca686e1 100644
--- a/pkg/azure/azure.go
+++ b/pkg/azure/azure.go
@@ -350,15 +350,23 @@ func ConvertAzureEventToCommands(parseAzureContext Azure, impactedProjects []con
 				return nil, false, fmt.Errorf("failed to find workflow config '%s' for project '%s'", project.Workflow, project.Name)
 			}
 
-			stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
+			stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
+			var coreApplyStage models.Stage
+			if workflow.Apply != nil {
+				coreApplyStage = workflow.Apply.ToCoreStage()
+			}
+			var corePlanStage models.Stage
+			if workflow.Plan != nil {
+				corePlanStage = workflow.Plan.ToCoreStage()
+			}
 			commandsPerProject = append(commandsPerProject, models.ProjectCommand{
 				ProjectName:      project.Name,
 				ProjectDir:       project.Dir,
 				ProjectWorkspace: project.Workspace,
 				Terragrunt:       project.Terragrunt,
 				Commands:         workflow.Configuration.OnPullRequestPushed,
-				ApplyStage:       workflow.Apply,
-				PlanStage:        workflow.Plan,
+				ApplyStage:       &coreApplyStage,
+				PlanStage:        &corePlanStage,
 				CommandEnvVars:   commandEnvVars,
 				StateEnvVars:     stateEnvVars,
 			})
@@ -371,15 +379,23 @@ func ConvertAzureEventToCommands(parseAzureContext Azure, impactedProjects []con
 				return nil, false, fmt.Errorf("failed to find workflow config '%s' for project '%s'", project.Workflow, project.Name)
 			}
 
-			stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
+			stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
+			var coreApplyStage models.Stage
+			if workflow.Apply != nil {
+				coreApplyStage = workflow.Apply.ToCoreStage()
+			}
+			var corePlanStage models.Stage
+			if workflow.Plan != nil {
+				corePlanStage = workflow.Plan.ToCoreStage()
+			}
 			commandsPerProject = append(commandsPerProject, models.ProjectCommand{
 				ProjectName:      project.Name,
 				ProjectDir:       project.Dir,
 				ProjectWorkspace: project.Workspace,
 				Terragrunt:       project.Terragrunt,
 				Commands:         workflow.Configuration.OnPullRequestClosed,
-				ApplyStage:       workflow.Apply,
-				PlanStage:        workflow.Plan,
+				ApplyStage:       &coreApplyStage,
+				PlanStage:        &corePlanStage,
 				CommandEnvVars:   commandEnvVars,
 				StateEnvVars:     stateEnvVars,
 			})
@@ -392,15 +408,23 @@ func ConvertAzureEventToCommands(parseAzureContext Azure, impactedProjects []con
 				if !ok {
 					return nil, false, fmt.Errorf("failed to find workflow config '%s' for project '%s'", project.Workflow, project.Name)
 				}
-				stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
+				stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
+				var coreApplyStage models.Stage
+				if workflow.Apply != nil {
+					coreApplyStage = workflow.Apply.ToCoreStage()
+				}
+				var corePlanStage models.Stage
+				if workflow.Plan != nil {
+					corePlanStage = workflow.Plan.ToCoreStage()
+				}
 				commandsPerProject = append(commandsPerProject, models.ProjectCommand{
 					ProjectName:      project.Name,
 					ProjectDir:       project.Dir,
 					ProjectWorkspace: project.Workspace,
 					Terragrunt:       project.Terragrunt,
 					Commands:         workflow.Configuration.OnCommitToDefault,
-					ApplyStage:       workflow.Apply,
-					PlanStage:        workflow.Plan,
+					ApplyStage:       &coreApplyStage,
+					PlanStage:        &corePlanStage,
 					CommandEnvVars:   commandEnvVars,
 					StateEnvVars:     stateEnvVars,
 				})
@@ -441,7 +465,7 @@ func ConvertAzureEventToCommands(parseAzureContext Azure, impactedProjects []con
 					if !ok {
 						return nil, false, fmt.Errorf("failed to find workflow config '%s' for project '%s'", project.Workflow, project.Name)
 					}
-					stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
+					stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
 
 					commandsPerProject = append(commandsPerProject, models.ProjectCommand{
 						ProjectName:      project.Name,
diff --git a/pkg/configuration/config.go b/pkg/configuration/config.go
deleted file mode 100644
index 7b90a17c..00000000
--- a/pkg/configuration/config.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package configuration
-
-import "digger/pkg/core/models"
-
-type DiggerConfig struct {
-	Projects         []Project
-	AutoMerge        bool
-	CollectUsageData bool
-	Workflows        map[string]Workflow
-}
-
-type Project struct {
-	Name            string
-	Dir             string
-	Workspace       string
-	Terragrunt      bool
-	Workflow        string
-	IncludePatterns []string
-	ExcludePatterns []string
-}
-
-type Workflow struct {
-	EnvVars       *TerraformEnvConfig
-	Plan          *models.Stage
-	Apply         *models.Stage
-	Configuration *WorkflowConfiguration
-}
-
-type WorkflowConfiguration struct {
-	OnPullRequestPushed []string
-	OnPullRequestClosed []string
-	OnCommitToDefault   []string
-}
-
-type TerraformEnvConfig struct {
-	State    []EnvVar
-	Commands []EnvVar
-}
-
-type EnvVar struct {
-	Name      string
-	ValueFrom string
-	Value     string
-}
-
-func defaultWorkflow() *Workflow {
-	return &Workflow{
-		Configuration: &WorkflowConfiguration{
-			OnCommitToDefault:   []string{"digger unlock"},
-			OnPullRequestPushed: []string{"digger plan"},
-			OnPullRequestClosed: []string{"digger unlock"},
-		},
-		Plan: &models.Stage{
-			Steps: []models.Step{
-				{
-					Action: "init", ExtraArgs: []string{},
-				},
-				{
-					Action: "plan", ExtraArgs: []string{},
-				},
-			},
-		},
-		Apply: &models.Stage{
-			Steps: []models.Step{
-				{
-					Action: "init", ExtraArgs: []string{},
-				},
-				{
-					Action: "apply", ExtraArgs: []string{},
-				},
-			},
-		},
-		EnvVars: &TerraformEnvConfig{},
-	}
-}
diff --git a/pkg/configuration/converters.go b/pkg/configuration/converters.go
deleted file mode 100644
index e0828b7f..00000000
--- a/pkg/configuration/converters.go
+++ /dev/null
@@ -1,163 +0,0 @@
-package configuration
-
-import (
-	"digger/pkg/core/models"
-	"digger/pkg/utils"
-	"fmt"
-	"path/filepath"
-)
-
-func copyProjects(projects []*ProjectYaml) []Project {
-	result := make([]Project, len(projects))
-	for i, p := range projects {
-		item := Project{p.Name,
-			p.Dir,
-			p.Workspace,
-			p.Terragrunt,
-			p.Workflow,
-			p.IncludePatterns,
-			p.ExcludePatterns,
-		}
-		result[i] = item
-	}
-	return result
-}
-
-func copyTerraformEnvConfig(terraformEnvConfig *TerraformEnvConfigYaml) *TerraformEnvConfig {
-	if terraformEnvConfig == nil {
-		return &TerraformEnvConfig{}
-	}
-	result := TerraformEnvConfig{}
-	result.State = make([]EnvVar, len(terraformEnvConfig.State))
-	result.Commands = make([]EnvVar, len(terraformEnvConfig.Commands))
-
-	for i, s := range terraformEnvConfig.State {
-		item := EnvVar{
-			s.Name,
-			s.ValueFrom,
-			s.Value,
-		}
-		result.State[i] = item
-	}
-	for i, s := range terraformEnvConfig.Commands {
-		item := EnvVar{
-			s.Name,
-			s.ValueFrom,
-			s.Value,
-		}
-		result.Commands[i] = item
-	}
-
-	return &result
-}
-
-func copyStage(stage *StageYaml) *models.Stage {
-	result := models.Stage{}
-	result.Steps = make([]models.Step, len(stage.Steps))
-
-	for i, s := range stage.Steps {
-		item := models.Step{
-			Action:    s.Action,
-			Value:     s.Value,
-			ExtraArgs: s.ExtraArgs,
-			Shell:     s.Shell,
-		}
-		result.Steps[i] = item
-	}
-	return &result
-}
-
-func copyWorkflowConfiguration(config *WorkflowConfigurationYaml) *WorkflowConfiguration {
-	result := WorkflowConfiguration{}
-	result.OnPullRequestClosed = config.OnPullRequestClosed
-	result.OnPullRequestPushed = config.OnPullRequestPushed
-	result.OnCommitToDefault = config.OnCommitToDefault
-	return &result
-}
-
-func copyWorkflows(workflows map[string]*WorkflowYaml) map[string]Workflow {
-	result := make(map[string]Workflow, len(workflows))
-	for i, w := range workflows {
-		envVars := copyTerraformEnvConfig(w.EnvVars)
-		plan := copyStage(w.Plan)
-		apply := copyStage(w.Apply)
-		configuration := copyWorkflowConfiguration(w.Configuration)
-		item := Workflow{
-			envVars,
-			plan,
-			apply,
-			configuration,
-		}
-		result[i] = item
-	}
-	return result
-}
-
-func ConvertDiggerYamlToConfig(diggerYaml *DiggerConfigYaml, workingDir string, walker DirWalker) (*DiggerConfig, error) {
-	var diggerConfig DiggerConfig
-	const defaultWorkflowName = "default"
-
-	if diggerYaml.AutoMerge != nil {
-		diggerConfig.AutoMerge = *diggerYaml.AutoMerge
-	} else {
-		diggerConfig.AutoMerge = false
-	}
-
-	if diggerYaml.CollectUsageData != nil {
-		diggerConfig.CollectUsageData = *diggerYaml.CollectUsageData
-	} else {
-		diggerConfig.CollectUsageData = true
-	}
-
-	// if workflow block is not specified in yaml we create a default one, and add it to every project
-	if diggerYaml.Workflows != nil {
-		workflows := copyWorkflows(diggerYaml.Workflows)
-		diggerConfig.Workflows = workflows
-
-		// provide default workflow if not specified
-		if _, ok := diggerConfig.Workflows[defaultWorkflowName]; !ok {
-			workflow := *defaultWorkflow()
-			diggerConfig.Workflows[defaultWorkflowName] = workflow
-		}
-	} else {
-		workflow := *defaultWorkflow()
-		diggerConfig.Workflows = make(map[string]Workflow)
-		diggerConfig.Workflows[defaultWorkflowName] = workflow
-	}
-
-	projects := copyProjects(diggerYaml.Projects)
-	diggerConfig.Projects = projects
-
-	// update project's workflow if needed
-	for _, project := range diggerConfig.Projects {
-		if project.Workflow == "" {
-			project.Workflow = defaultWorkflowName
-		}
-	}
-
-	// check for project name duplicates
-	projectNames := make(map[string]bool)
-	for _, project := range diggerConfig.Projects {
-		if projectNames[project.Name] {
-			return nil, fmt.Errorf("project name '%s' is duplicated", project.Name)
-		}
-		projectNames[project.Name] = true
-	}
-
-	if diggerYaml.GenerateProjectsConfig != nil {
-		dirs, err := walker.GetDirs(workingDir)
-		if err != nil {
-			return nil, err
-		}
-
-		for _, dir := range dirs {
-			includePattern := diggerYaml.GenerateProjectsConfig.Include
-			excludePattern := diggerYaml.GenerateProjectsConfig.Exclude
-			if utils.MatchIncludeExcludePatternsToFile(dir, []string{includePattern}, []string{excludePattern}) {
-				project := Project{Name: filepath.Base(dir), Dir: dir, Workflow: defaultWorkflowName, Workspace: "default"}
-				diggerConfig.Projects = append(diggerConfig.Projects, project)
-			}
-		}
-	}
-	return &diggerConfig, nil
-}
diff --git a/pkg/configuration/digger_config.go b/pkg/configuration/digger_config.go
index d0c98ab4..f6a4d103 100644
--- a/pkg/configuration/digger_config.go
+++ b/pkg/configuration/digger_config.go
@@ -1,6 +1,7 @@
 package configuration
 
 import (
+	"digger/pkg/core/models"
 	"digger/pkg/utils"
 	"errors"
 	"fmt"
@@ -11,6 +12,72 @@ import (
 	"regexp"
 )
 
+type WorkflowConfiguration struct {
+	OnPullRequestPushed []string `yaml:"on_pull_request_pushed"`
+	OnPullRequestClosed []string `yaml:"on_pull_request_closed"`
+	OnCommitToDefault   []string `yaml:"on_commit_to_default"`
+}
+
+type DiggerConfigYaml struct {
+	Projects               []Project               `yaml:"projects"`
+	AutoMerge              bool                    `yaml:"auto_merge"`
+	Workflows              map[string]Workflow     `yaml:"workflows"`
+	CollectUsageData       *bool                   `yaml:"collect_usage_data,omitempty"`
+	GenerateProjectsConfig *GenerateProjectsConfig `yaml:"generate_projects"`
+}
+
+type EnvVarConfig struct {
+	Name      string `yaml:"name"`
+	ValueFrom string `yaml:"value_from"`
+	Value     string `yaml:"value"`
+}
+
+type DiggerConfig struct {
+	Projects         []Project
+	AutoMerge        bool
+	CollectUsageData bool
+	Workflows        map[string]Workflow
+}
+
+type GenerateProjectsConfig struct {
+	Include string `yaml:"include"`
+	Exclude string `yaml:"exclude"`
+}
+
+type Project struct {
+	Name            string   `yaml:"name"`
+	Dir             string   `yaml:"dir"`
+	Workspace       string   `yaml:"workspace"`
+	Terragrunt      bool     `yaml:"terragrunt"`
+	Workflow        string   `yaml:"workflow"`
+	IncludePatterns []string `yaml:"include_patterns,omitempty"`
+	ExcludePatterns []string `yaml:"exclude_patterns,omitempty"`
+}
+
+type Stage struct {
+	Steps []Step `yaml:"steps"`
+}
+
+func (s *Stage) ToCoreStage() models.Stage {
+	var steps []models.Step
+	for _, step := range s.Steps {
+		steps = append(steps, step.ToCoreStep())
+	}
+	return models.Stage{Steps: steps}
+}
+
+type Workflow struct {
+	EnvVars       EnvVars                `yaml:"env_vars"`
+	Plan          *Stage                 `yaml:"plan,omitempty"`
+	Apply         *Stage                 `yaml:"apply,omitempty"`
+	Configuration *WorkflowConfiguration `yaml:"workflow_configuration"`
+}
+
+type EnvVars struct {
+	State    []EnvVarConfig `yaml:"state"`
+	Commands []EnvVarConfig `yaml:"commands"`
+}
+
 type DirWalker interface {
 	GetDirs(workingDir string) ([]string, error)
 }
@@ -61,9 +128,207 @@ func (walker *FileSystemDirWalker) GetDirs(workingDir string) ([]string, error)
 
 var ErrDiggerConfigConflict = errors.New("more than one digger config file detected, please keep either 'digger.yml' or 'digger.yaml'")
 
+func (p *Project) UnmarshalYAML(unmarshal func(interface{}) error) error {
+	type rawProject Project
+	raw := rawProject{
+		Workspace:  "default",
+		Terragrunt: false,
+		Workflow:   "default",
+	}
+	if err := unmarshal(&raw); err != nil {
+		return err
+	}
+	*p = Project(raw)
+	return nil
+}
+
+func (w *Workflow) UnmarshalYAML(unmarshal func(interface{}) error) error {
+	type rawWorkflow Workflow
+	raw := rawWorkflow{
+		Configuration: &WorkflowConfiguration{
+			OnCommitToDefault:   []string{"digger unlock"},
+			OnPullRequestPushed: []string{"digger plan"},
+			OnPullRequestClosed: []string{"digger unlock"},
+		},
+		Plan: &Stage{
+			Steps: []Step{
+				{
+					Action: "init", ExtraArgs: []string{},
+				},
+				{
+					Action: "plan", ExtraArgs: []string{},
+				},
+			},
+		},
+		Apply: &Stage{
+			Steps: []Step{
+				{
+					Action: "init", ExtraArgs: []string{},
+				},
+				{
+					Action: "apply", ExtraArgs: []string{},
+				},
+			},
+		},
+		EnvVars: EnvVars{
+			State:    []EnvVarConfig{},
+			Commands: []EnvVarConfig{},
+		},
+	}
+	if err := unmarshal(&raw); err != nil {
+		return err
+	}
+	*w = Workflow(raw)
+	return nil
+}
+
+type Step struct {
+	Action    string
+	Value     string
+	ExtraArgs []string `yaml:"extra_args,omitempty"`
+	Shell     string
+}
+
+func (s *Step) ToCoreStep() models.Step {
+	return models.Step{
+		Action:    s.Action,
+		Value:     s.Value,
+		ExtraArgs: s.ExtraArgs,
+		Shell:     s.Shell,
+	}
+}
+
+func (s *Step) UnmarshalYAML(value *yaml.Node) error {
+	if value.Kind == yaml.ScalarNode {
+		return value.Decode(&s.Action)
+	}
+
+	var stepMap map[string]interface{}
+	if err := value.Decode(&stepMap); err != nil {
+		return err
+	}
+
+	if _, ok := stepMap["run"]; ok {
+		s.Action = "run"
+		s.Value = stepMap["run"].(string)
+		if _, ok := stepMap["shell"]; ok {
+			s.Shell = stepMap["shell"].(string)
+		}
+		return nil
+	}
+
+	s.extract(stepMap, "plan")
+	s.extract(stepMap, "apply")
+
+	return nil
+}
+
+func (s *Step) extract(stepMap map[string]interface{}, action string) {
+	if _, ok := stepMap[action]; ok {
+		s.Action = action
+		var extraArgs []string
+		if v, ok := stepMap["extra_args"]; ok {
+			for _, v := range v.([]interface{}) {
+				extraArgs = append(extraArgs, v.(string))
+			}
+			s.ExtraArgs = extraArgs
+		}
+	}
+}
+
+func defaultWorkflow() *Workflow {
+	return &Workflow{
+		Configuration: &WorkflowConfiguration{
+			OnCommitToDefault:   []string{"digger unlock"},
+			OnPullRequestPushed: []string{"digger plan"},
+			OnPullRequestClosed: []string{"digger unlock"},
+		},
+		Plan: &Stage{
+			Steps: []Step{
+				{
+					Action: "init", ExtraArgs: []string{},
+				},
+				{
+					Action: "plan", ExtraArgs: []string{},
+				},
+			},
+		},
+		Apply: &Stage{
+			Steps: []Step{
+				{
+					Action: "init", ExtraArgs: []string{},
+				},
+				{
+					Action: "apply", ExtraArgs: []string{},
+				},
+			},
+		},
+	}
+}
+
+func ConvertDiggerYamlToConfig(diggerYaml *DiggerConfigYaml, workingDir string, walker DirWalker) (*DiggerConfig, error) {
+	var diggerConfig DiggerConfig
+	const defaultWorkflowName = "default"
+
+	diggerConfig.AutoMerge = diggerYaml.AutoMerge
+
+	// if workflow block is not specified in yaml we create a default one, and add it to every project
+	if diggerYaml.Workflows != nil {
+		diggerConfig.Workflows = diggerYaml.Workflows
+		// provide default workflow if not specified
+		if _, ok := diggerConfig.Workflows[defaultWorkflowName]; !ok {
+			workflow := *defaultWorkflow()
+			diggerConfig.Workflows[defaultWorkflowName] = workflow
+		}
+	} else {
+		workflow := *defaultWorkflow()
+		diggerConfig.Workflows = make(map[string]Workflow)
+		diggerConfig.Workflows[defaultWorkflowName] = workflow
+	}
+
+	diggerConfig.Projects = diggerYaml.Projects
+
+	// update project's workflow if needed
+	for _, project := range diggerConfig.Projects {
+		if project.Workflow == "" {
+			project.Workflow = defaultWorkflowName
+		}
+	}
+
+	// check for project name duplicates
+	projectNames := make(map[string]bool)
+	for _, project := range diggerConfig.Projects {
+		if projectNames[project.Name] {
+			return nil, fmt.Errorf("project name '%s' is duplicated", project.Name)
+		}
+		projectNames[project.Name] = true
+	}
+	if diggerYaml.CollectUsageData != nil {
+		diggerConfig.CollectUsageData = *diggerYaml.CollectUsageData
+	} else {
+		diggerConfig.CollectUsageData = true
+	}
+
+	if diggerYaml.GenerateProjectsConfig != nil {
+		dirs, err := walker.GetDirs(workingDir)
+		if err != nil {
+			return nil, err
+		}
+
+		for _, dir := range dirs {
+			includePattern := diggerYaml.GenerateProjectsConfig.Include
+			excludePattern := diggerYaml.GenerateProjectsConfig.Exclude
+			if utils.MatchIncludeExcludePatternsToFile(dir, []string{includePattern}, []string{excludePattern}) {
+				project := Project{Name: filepath.Base(dir), Dir: dir, Workflow: defaultWorkflowName, Workspace: "default"}
+				diggerConfig.Projects = append(diggerConfig.Projects, project)
+			}
+		}
+	}
+	return &diggerConfig, nil
+}
+
 func LoadDiggerConfig(workingDir string, walker DirWalker) (*DiggerConfig, error) {
-	configYaml := &DiggerConfigYaml{}
-	config := &DiggerConfig{}
+	config := &DiggerConfigYaml{}
 	fileName, err := retrieveConfigFile(workingDir)
 	if err != nil {
 		if errors.Is(err, ErrDiggerConfigConflict) {
@@ -76,8 +341,36 @@ func LoadDiggerConfig(workingDir string, walker DirWalker) (*DiggerConfig, error
 		config.Projects = make([]Project, 1)
 		config.Projects[0] = defaultProject()
 		config.Workflows = make(map[string]Workflow)
-		config.Workflows["default"] = *defaultWorkflow()
-		return config, nil
+		config.Workflows["default"] = Workflow{
+			Plan: &Stage{
+				Steps: []Step{{
+					Action:    "init",
+					ExtraArgs: []string{},
+				}, {
+					Action:    "plan",
+					ExtraArgs: []string{},
+				}},
+			},
+			Apply: &Stage{
+				Steps: []Step{{
+					Action:    "init",
+					ExtraArgs: []string{},
+				}, {
+					Action:    "apply",
+					ExtraArgs: []string{},
+				}},
+			},
+			Configuration: &WorkflowConfiguration{
+				OnPullRequestPushed: []string{"digger plan"},
+				OnPullRequestClosed: []string{"digger unlock"},
+				OnCommitToDefault:   []string{"digger apply"},
+			},
+		}
+		c, err := ConvertDiggerYamlToConfig(config, workingDir, walker)
+		if err != nil {
+			return nil, fmt.Errorf("failed to read config file %s: %v", fileName, err)
+		}
+		return c, nil
 	}
 
 	data, err := os.ReadFile(fileName)
@@ -85,15 +378,15 @@ func LoadDiggerConfig(workingDir string, walker DirWalker) (*DiggerConfig, error
 		return nil, fmt.Errorf("failed to read config file %s: %v", fileName, err)
 	}
 
-	if err := yaml.Unmarshal(data, configYaml); err != nil {
+	if err := yaml.Unmarshal(data, config); err != nil {
 		return nil, fmt.Errorf("error parsing '%s': %v", fileName, err)
 	}
 
-	if (configYaml.Projects == nil || len(configYaml.Projects) == 0) && configYaml.GenerateProjectsConfig == nil {
+	if (config.Projects == nil || len(config.Projects) == 0) && config.GenerateProjectsConfig == nil {
 		return nil, fmt.Errorf("no projects configuration found in '%s'", fileName)
 	}
 
-	c, err := ConvertDiggerYamlToConfig(configYaml, workingDir, walker)
+	c, err := ConvertDiggerYamlToConfig(config, workingDir, walker)
 	if err != nil {
 		return nil, err
 	}
@@ -215,27 +508,25 @@ func retrieveConfigFile(workingDir string) (string, error) {
 	return "", nil
 }
 
-func CollectTerraformEnvConfig(envs *TerraformEnvConfig) (map[string]string, map[string]string) {
+func CollectEnvVars(envs EnvVars) (map[string]string, map[string]string) {
 	stateEnvVars := map[string]string{}
-	commandEnvVars := map[string]string{}
 
-	if envs != nil {
-		for _, envvar := range envs.State {
-			if envvar.Value != "" {
-				stateEnvVars[envvar.Name] = envvar.Value
-			} else if envvar.ValueFrom != "" {
-				stateEnvVars[envvar.Name] = os.Getenv(envvar.ValueFrom)
-			}
+	for _, envvar := range envs.State {
+		if envvar.Value != "" {
+			stateEnvVars[envvar.Name] = envvar.Value
+		} else if envvar.ValueFrom != "" {
+			stateEnvVars[envvar.Name] = os.Getenv(envvar.ValueFrom)
 		}
+	}
 
-		for _, envvar := range envs.Commands {
-			if envvar.Value != "" {
-				commandEnvVars[envvar.Name] = envvar.Value
-			} else if envvar.ValueFrom != "" {
-				commandEnvVars[envvar.Name] = os.Getenv(envvar.ValueFrom)
-			}
+	commandEnvVars := map[string]string{}
+
+	for _, envvar := range envs.Commands {
+		if envvar.Value != "" {
+			commandEnvVars[envvar.Name] = envvar.Value
+		} else if envvar.ValueFrom != "" {
+			commandEnvVars[envvar.Name] = os.Getenv(envvar.ValueFrom)
 		}
 	}
-
 	return stateEnvVars, commandEnvVars
 }
diff --git a/pkg/configuration/yaml.go b/pkg/configuration/yaml.go
deleted file mode 100644
index 415d5277..00000000
--- a/pkg/configuration/yaml.go
+++ /dev/null
@@ -1,174 +0,0 @@
-package configuration
-
-import (
-	"digger/pkg/core/models"
-	"gopkg.in/yaml.v3"
-)
-
-type DiggerConfigYaml struct {
-	Projects               []*ProjectYaml              `yaml:"projects"`
-	AutoMerge              *bool                       `yaml:"auto_merge"`
-	Workflows              map[string]*WorkflowYaml    `yaml:"workflows"`
-	CollectUsageData       *bool                       `yaml:"collect_usage_data,omitempty"`
-	GenerateProjectsConfig *GenerateProjectsConfigYaml `yaml:"generate_projects"`
-}
-
-type ProjectYaml struct {
-	Name            string   `yaml:"name"`
-	Dir             string   `yaml:"dir"`
-	Workspace       string   `yaml:"workspace"`
-	Terragrunt      bool     `yaml:"terragrunt"`
-	Workflow        string   `yaml:"workflow"`
-	IncludePatterns []string `yaml:"include_patterns,omitempty"`
-	ExcludePatterns []string `yaml:"exclude_patterns,omitempty"`
-}
-
-type WorkflowYaml struct {
-	EnvVars       *TerraformEnvConfigYaml    `yaml:"env_vars"`
-	Plan          *StageYaml                 `yaml:"plan,omitempty"`
-	Apply         *StageYaml                 `yaml:"apply,omitempty"`
-	Configuration *WorkflowConfigurationYaml `yaml:"workflow_configuration"`
-}
-
-type WorkflowConfigurationYaml struct {
-	OnPullRequestPushed []string `yaml:"on_pull_request_pushed"`
-	OnPullRequestClosed []string `yaml:"on_pull_request_closed"`
-	OnCommitToDefault   []string `yaml:"on_commit_to_default"`
-}
-
-func (s *StageYaml) ToCoreStage() models.Stage {
-	var steps []models.Step
-	for _, step := range s.Steps {
-		steps = append(steps, step.ToCoreStep())
-	}
-	return models.Stage{Steps: steps}
-}
-
-type StageYaml struct {
-	Steps []StepYaml `yaml:"steps"`
-}
-
-type StepYaml struct {
-	Action    string
-	Value     string
-	ExtraArgs []string `yaml:"extra_args,omitempty"`
-	Shell     string
-}
-
-type TerraformEnvConfigYaml struct {
-	State    []EnvVarYaml `yaml:"state"`
-	Commands []EnvVarYaml `yaml:"commands"`
-}
-
-type EnvVarYaml struct {
-	Name      string `yaml:"name"`
-	ValueFrom string `yaml:"value_from"`
-	Value     string `yaml:"value"`
-}
-
-type GenerateProjectsConfigYaml struct {
-	Include string `yaml:"include"`
-	Exclude string `yaml:"exclude"`
-}
-
-func (p *ProjectYaml) UnmarshalYAML(unmarshal func(interface{}) error) error {
-	type rawProject ProjectYaml
-	raw := rawProject{
-		Workspace:  "default",
-		Terragrunt: false,
-		Workflow:   "default",
-	}
-	if err := unmarshal(&raw); err != nil {
-		return err
-	}
-	*p = ProjectYaml(raw)
-	return nil
-}
-
-func (w *WorkflowYaml) UnmarshalYAML(unmarshal func(interface{}) error) error {
-	type rawWorkflow WorkflowYaml
-	raw := rawWorkflow{
-		Configuration: &WorkflowConfigurationYaml{
-			OnCommitToDefault:   []string{"digger unlock"},
-			OnPullRequestPushed: []string{"digger plan"},
-			OnPullRequestClosed: []string{"digger unlock"},
-		},
-		Plan: &StageYaml{
-			Steps: []StepYaml{
-				{
-					Action: "init", ExtraArgs: []string{},
-				},
-				{
-					Action: "plan", ExtraArgs: []string{},
-				},
-			},
-		},
-		Apply: &StageYaml{
-			Steps: []StepYaml{
-				{
-					Action: "init", ExtraArgs: []string{},
-				},
-				{
-					Action: "apply", ExtraArgs: []string{},
-				},
-			},
-		},
-		EnvVars: &TerraformEnvConfigYaml{
-			State:    []EnvVarYaml{},
-			Commands: []EnvVarYaml{},
-		},
-	}
-	if err := unmarshal(&raw); err != nil {
-		return err
-	}
-	*w = WorkflowYaml(raw)
-	return nil
-}
-
-func (s *StepYaml) UnmarshalYAML(value *yaml.Node) error {
-
-	if value.Kind == yaml.ScalarNode {
-		return value.Decode(&s.Action)
-	}
-
-	var stepMap map[string]interface{}
-	if err := value.Decode(&stepMap); err != nil {
-		return err
-	}
-
-	if _, ok := stepMap["run"]; ok {
-		s.Action = "run"
-		s.Value = stepMap["run"].(string)
-		if _, ok := stepMap["shell"]; ok {
-			s.Shell = stepMap["shell"].(string)
-		}
-		return nil
-	}
-
-	s.extract(stepMap, "plan")
-	s.extract(stepMap, "apply")
-
-	return nil
-}
-
-func (s *StepYaml) ToCoreStep() models.Step {
-	return models.Step{
-		Action:    s.Action,
-		Value:     s.Value,
-		ExtraArgs: s.ExtraArgs,
-		Shell:     s.Shell,
-	}
-}
-
-func (s *StepYaml) extract(stepMap map[string]interface{}, action string) {
-	if _, ok := stepMap[action]; ok {
-		s.Action = action
-		var extraArgs []string
-		if v, ok := stepMap["extra_args"]; ok {
-			for _, v := range v.([]interface{}) {
-				extraArgs = append(extraArgs, v.(string))
-			}
-			s.ExtraArgs = extraArgs
-		}
-	}
-}
diff --git a/pkg/core/terraform/tf.go b/pkg/core/terraform/tf.go
index 0363ca21..53bca17c 100644
--- a/pkg/core/terraform/tf.go
+++ b/pkg/core/terraform/tf.go
@@ -83,17 +83,21 @@ func (tf Terraform) Init(params []string, envs map[string]string) (string, strin
 }
 
 func (tf Terraform) Apply(params []string, plan *string, envs map[string]string) (string, string, error) {
-	workspace, _, _, err := tf.runTerraformCommand("workspace", envs, "show")
-
+	workspaces, _, _, err := tf.runTerraformCommand("workspace", envs, "list")
 	if err != nil {
 		return "", "", err
 	}
-
-	if strings.TrimSpace(workspace) != tf.Workspace {
-		_, _, _, err = tf.runTerraformCommand("workspace", envs, "new", tf.Workspace)
+	workspaces = tf.formatTerraformWorkspaces(workspaces)
+	if strings.Contains(workspaces, tf.Workspace) {
+		_, _, _, err := tf.runTerraformCommand("workspace", envs, "select", tf.Workspace)
 		if err != nil {
 			return "", "", err
 		}
+	} else {
+		_, _, _, err := tf.runTerraformCommand("workspace", envs, "new", tf.Workspace)
+		if err != nil {
+			return "", "", err
+		}		
 	}
 	params = append(append(append(params, "-input=false"), "-no-color"), "-auto-approve")
 	if plan != nil {
@@ -151,17 +155,30 @@ func (sw *StdWriter) GetString() string {
 	return s
 }
 
-func (tf Terraform) Plan(params []string, envs map[string]string) (bool, string, string, error) {
-	workspace, _, _, err := tf.runTerraformCommand("workspace", envs, "show")
+func (tf Terraform) formatTerraformWorkspaces(list string) (string) {
 
+	list = strings.TrimSpace(list)
+	char_replace := strings.NewReplacer("*", "", "\n", ",", " ", "")
+	list = char_replace.Replace(list)
+	return list
+}
+
+func (tf Terraform) Plan(params []string, envs map[string]string) (bool, string, string, error) {
+	workspaces, _, _, err := tf.runTerraformCommand("workspace", envs, "list")
 	if err != nil {
 		return false, "", "", err
 	}
-	if strings.TrimSpace(workspace) != tf.Workspace {
-		_, _, _, err = tf.runTerraformCommand("workspace", envs, "new", tf.Workspace)
+	workspaces = tf.formatTerraformWorkspaces(workspaces)
+	if strings.Contains(workspaces, tf.Workspace) {
+		_, _, _, err := tf.runTerraformCommand("workspace", envs, "select", tf.Workspace)
 		if err != nil {
 			return false, "", "", err
 		}
+	} else {
+		_, _, _, err := tf.runTerraformCommand("workspace", envs, "new", tf.Workspace)
+		if err != nil {
+			return false, "", "", err
+		}		
 	}
 	params = append(append(params, "-input=false"), "-no-color")
 	stdout, stderr, statusCode, err := tf.runTerraformCommand("plan", envs, params...)
diff --git a/pkg/github/github.go b/pkg/github/github.go
index 7ab3b3e9..0aeac2aa 100644
--- a/pkg/github/github.go
+++ b/pkg/github/github.go
@@ -144,8 +144,9 @@ func ConvertGithubEventToCommands(event models.Event, impactedProjects []configu
 				return nil, false, fmt.Errorf("failed to find workflow config '%s' for project '%s'", project.Workflow, project.Name)
 			}
 
-			stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
-
+			stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
+			coreApplyStage := workflow.Apply.ToCoreStage()
+			corePlanStage := workflow.Plan.ToCoreStage()
 			if event.Action == "closed" && event.PullRequest.Merged && event.PullRequest.Base.Ref == event.Repository.DefaultBranch {
 				commandsPerProject = append(commandsPerProject, dg_models.ProjectCommand{
 					ProjectName:      project.Name,
@@ -153,8 +154,8 @@ func ConvertGithubEventToCommands(event models.Event, impactedProjects []configu
 					ProjectWorkspace: project.Workspace,
 					Terragrunt:       project.Terragrunt,
 					Commands:         workflow.Configuration.OnCommitToDefault,
-					ApplyStage:       workflow.Apply,
-					PlanStage:        workflow.Plan,
+					ApplyStage:       &coreApplyStage,
+					PlanStage:        &corePlanStage,
 					CommandEnvVars:   commandEnvVars,
 					StateEnvVars:     stateEnvVars,
 				})
@@ -165,8 +166,8 @@ func ConvertGithubEventToCommands(event models.Event, impactedProjects []configu
 					ProjectWorkspace: project.Workspace,
 					Terragrunt:       project.Terragrunt,
 					Commands:         workflow.Configuration.OnPullRequestPushed,
-					ApplyStage:       workflow.Apply,
-					PlanStage:        workflow.Plan,
+					ApplyStage:       &coreApplyStage,
+					PlanStage:        &corePlanStage,
 					CommandEnvVars:   commandEnvVars,
 					StateEnvVars:     stateEnvVars,
 				})
@@ -177,8 +178,8 @@ func ConvertGithubEventToCommands(event models.Event, impactedProjects []configu
 					ProjectWorkspace: project.Workspace,
 					Terragrunt:       project.Terragrunt,
 					Commands:         workflow.Configuration.OnPullRequestClosed,
-					ApplyStage:       workflow.Apply,
-					PlanStage:        workflow.Plan,
+					ApplyStage:       &coreApplyStage,
+					PlanStage:        &corePlanStage,
 					CommandEnvVars:   commandEnvVars,
 					StateEnvVars:     stateEnvVars,
 				})
@@ -210,8 +211,9 @@ func ConvertGithubEventToCommands(event models.Event, impactedProjects []configu
 						return nil, false, fmt.Errorf("failed to find workflow config '%s' for project '%s'", project.Workflow, project.Name)
 					}
 
-					stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
-
+					stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
+					coreApplyStage := workflow.Apply.ToCoreStage()
+					corePlanStage := workflow.Plan.ToCoreStage()
 					workspace := project.Workspace
 					workspaceOverride, err := utils.ParseWorkspace(event.Comment.Body)
 					if err != nil {
@@ -226,8 +228,8 @@ func ConvertGithubEventToCommands(event models.Event, impactedProjects []configu
 						ProjectWorkspace: workspace,
 						Terragrunt:       project.Terragrunt,
 						Commands:         []string{command},
-						ApplyStage:       workflow.Apply,
-						PlanStage:        workflow.Plan,
+						ApplyStage:       &coreApplyStage,
+						PlanStage:        &corePlanStage,
 						CommandEnvVars:   commandEnvVars,
 						StateEnvVars:     stateEnvVars,
 					})
diff --git a/pkg/gitlab/gitlab.go b/pkg/gitlab/gitlab.go
index b46e429a..1bdedb26 100644
--- a/pkg/gitlab/gitlab.go
+++ b/pkg/gitlab/gitlab.go
@@ -261,15 +261,17 @@ func ConvertGitLabEventToCommands(event GitLabEvent, gitLabContext *GitLabContex
 				return nil, true, fmt.Errorf("failed to find workflow config '%s' for project '%s'", project.Workflow, project.Name)
 			}
 
-			stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
+			stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
+			coreApplyStage := workflow.Apply.ToCoreStage()
+			corePlanStage := workflow.Plan.ToCoreStage()
 			commandsPerProject = append(commandsPerProject, models.ProjectCommand{
 				ProjectName:      project.Name,
 				ProjectDir:       project.Dir,
 				ProjectWorkspace: project.Workspace,
 				Terragrunt:       project.Terragrunt,
 				Commands:         workflow.Configuration.OnPullRequestPushed,
-				ApplyStage:       workflow.Apply,
-				PlanStage:        workflow.Plan,
+				ApplyStage:       &coreApplyStage,
+				PlanStage:        &corePlanStage,
 				CommandEnvVars:   commandEnvVars,
 				StateEnvVars:     stateEnvVars,
 			})
@@ -281,15 +283,23 @@ func ConvertGitLabEventToCommands(event GitLabEvent, gitLabContext *GitLabContex
 			if !ok {
 				return nil, true, fmt.Errorf("failed to find workflow config '%s' for project '%s'", project.Workflow, project.Name)
 			}
-			stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
+			stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
+			var coreApplyStage models.Stage
+			if workflow.Apply != nil {
+				coreApplyStage = workflow.Apply.ToCoreStage()
+			}
+			var corePlanStage models.Stage
+			if workflow.Plan != nil {
+				corePlanStage = workflow.Plan.ToCoreStage()
+			}
 			commandsPerProject = append(commandsPerProject, models.ProjectCommand{
 				ProjectName:      project.Name,
 				ProjectDir:       project.Dir,
 				ProjectWorkspace: project.Workspace,
 				Terragrunt:       project.Terragrunt,
 				Commands:         workflow.Configuration.OnPullRequestClosed,
-				ApplyStage:       workflow.Apply,
-				PlanStage:        workflow.Plan,
+				ApplyStage:       &coreApplyStage,
+				PlanStage:        &corePlanStage,
 				CommandEnvVars:   commandEnvVars,
 				StateEnvVars:     stateEnvVars,
 			})
@@ -326,15 +336,23 @@ func ConvertGitLabEventToCommands(event GitLabEvent, gitLabContext *GitLabContex
 					if workspaceOverride != "" {
 						workspace = workspaceOverride
 					}
-					stateEnvVars, commandEnvVars := configuration.CollectTerraformEnvConfig(workflow.EnvVars)
+					stateEnvVars, commandEnvVars := configuration.CollectEnvVars(workflow.EnvVars)
+					var coreApplyStage models.Stage
+					if workflow.Apply != nil {
+						coreApplyStage = workflow.Apply.ToCoreStage()
+					}
+					var corePlanStage models.Stage
+					if workflow.Plan != nil {
+						corePlanStage = workflow.Plan.ToCoreStage()
+					}
 					commandsPerProject = append(commandsPerProject, models.ProjectCommand{
 						ProjectName:      project.Name,
 						ProjectDir:       project.Dir,
 						ProjectWorkspace: workspace,
 						Terragrunt:       project.Terragrunt,
 						Commands:         []string{command},
-						ApplyStage:       workflow.Apply,
-						PlanStage:        workflow.Plan,
+						ApplyStage:       &coreApplyStage,
+						PlanStage:        &corePlanStage,
 						CommandEnvVars:   commandEnvVars,
 						StateEnvVars:     stateEnvVars,
 					})
diff --git a/pkg/policy/policy.go b/pkg/policy/policy.go
index 6a54fd7a..dda5ba35 100644
--- a/pkg/policy/policy.go
+++ b/pkg/policy/policy.go
@@ -6,6 +6,7 @@ import (
 	"github.com/open-policy-agent/opa/rego"
 	"io/ioutil"
 	"net/http"
+	"strings"
 )
 
 type PolicyProvider interface {
@@ -27,7 +28,8 @@ func (p NoOpPolicyChecker) Check(_ string, _ string, _ interface{}) (bool, error
 
 func (p *DiggerHttpPolicyProvider) GetPolicy(namespace string, projectName string) (string, error) {
 	// fetch RBAC policies from Digger API
-	req, err := http.NewRequest("GET", p.DiggerHost+"/repos/"+namespace+"/projects/"+projectName+"/policies", nil)
+	namespace = strings.ReplaceAll(namespace, "/", "-")
+	req, err := http.NewRequest("GET", p.DiggerHost+"/repos/"+namespace+"/projects/"+projectName+"/access-policy", nil)
 	if err != nil {
 		return "", err
 	}
@@ -52,6 +54,7 @@ type DiggerPolicyChecker struct {
 
 func (p DiggerPolicyChecker) Check(namespace string, projectName string, input interface{}) (bool, error) {
 	policy, err := p.PolicyProvider.GetPolicy(namespace, projectName)
+
 	if err != nil {
 		return false, err
 	}


Test patch:
diff --git a/cmd/digger/main_test.go b/cmd/digger/main_test.go
index 9deb7ad9..0189ad44 100644
--- a/cmd/digger/main_test.go
+++ b/cmd/digger/main_test.go
@@ -2,10 +2,9 @@ package main
 
 import (
 	"digger/pkg/configuration"
-	"digger/pkg/core/models"
 	"digger/pkg/digger"
 	"digger/pkg/github"
-	gh_models "digger/pkg/github/models"
+	"digger/pkg/github/models"
 	"digger/pkg/reporting"
 	"digger/pkg/utils"
 	"fmt"
@@ -896,7 +895,7 @@ func TestGitHubNewPullRequestContext(t *testing.T) {
 }
 
 func TestGitHubNewCommentContext(t *testing.T) {
-	context, err := gh_models.GetGitHubContext(githubContextCommentJson)
+	context, err := models.GetGitHubContext(githubContextCommentJson)
 	assert.NoError(t, err)
 	if err != nil {
 		fmt.Println(err)
@@ -912,7 +911,6 @@ func TestGitHubNewCommentContext(t *testing.T) {
 		CiService: prManager,
 		PrNumber:  prNumber,
 	}
-
 	policyChecker := &utils.MockPolicyChecker{}
 
 	commandsToRunPerProject, _, err := github.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, map[string]configuration.Workflow{})
@@ -927,7 +925,7 @@ func TestGitHubNewCommentContext(t *testing.T) {
 }
 
 func TestInvalidGitHubContext(t *testing.T) {
-	_, err := gh_models.GetGitHubContext(githubInvalidContextJson)
+	_, err := models.GetGitHubContext(githubInvalidContextJson)
 	require.Error(t, err)
 	if err != nil {
 		fmt.Println(err)
@@ -943,11 +941,11 @@ func TestGitHubNewPullRequestInMultiEnvProjectContext(t *testing.T) {
 	prod := configuration.Project{Name: "prod", Dir: "prod", Workflow: "prod"}
 	workflows := map[string]configuration.Workflow{
 		"dev": {
-			Plan: &models.Stage{Steps: []models.Step{
+			Plan: &configuration.Stage{Steps: []configuration.Step{
 				{Action: "init", ExtraArgs: []string{}},
 				{Action: "plan", ExtraArgs: []string{"-var-file=dev.tfvars"}},
 			}},
-			Apply: &models.Stage{Steps: []models.Step{
+			Apply: &configuration.Stage{Steps: []configuration.Step{
 				{Action: "init", ExtraArgs: []string{}},
 				{Action: "apply", ExtraArgs: []string{"-var-file=dev.tfvars"}},
 			}},
@@ -958,11 +956,11 @@ func TestGitHubNewPullRequestInMultiEnvProjectContext(t *testing.T) {
 			},
 		},
 		"prod": {
-			Plan: &models.Stage{Steps: []models.Step{
+			Plan: &configuration.Stage{Steps: []configuration.Step{
 				{Action: "init", ExtraArgs: []string{}},
 				{Action: "plan", ExtraArgs: []string{"-var-file=dev.tfvars"}},
 			}},
-			Apply: &models.Stage{Steps: []models.Step{
+			Apply: &configuration.Stage{Steps: []configuration.Step{
 				{Action: "init", ExtraArgs: []string{}},
 				{Action: "apply", ExtraArgs: []string{"-var-file=dev.tfvars"}},
 			}},
diff --git a/pkg/configuration/digger_config_test.go b/pkg/configuration/digger_config_test.go
index c2fe89e6..d7d9f641 100644
--- a/pkg/configuration/digger_config_test.go
+++ b/pkg/configuration/digger_config_test.go
@@ -1,7 +1,6 @@
 package configuration
 
 import (
-	"digger/pkg/core/models"
 	"log"
 	"os"
 	"path"
@@ -73,42 +72,6 @@ projects:
 	assert.Equal(t, "path/to/module/test", dg.GetDirectory("prod"))
 }
 
-func TestDefaultDiggerConfig(t *testing.T) {
-	tempDir, teardown := setUp()
-	defer teardown()
-
-	diggerCfg := `
-projects:
-- name: prod
-  branch: /main/
-  dir: path/to/module/test
-  workspace: default
-`
-	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
-	defer deleteFile()
-
-	dg, err := LoadDiggerConfig(tempDir, &FileSystemDirWalker{})
-
-	assert.NoError(t, err, "expected error to be nil")
-	assert.NotNil(t, dg, "expected digger config to be not nil")
-	assert.Equal(t, 1, len(dg.Projects))
-	assert.Equal(t, false, dg.AutoMerge)
-	assert.Equal(t, true, dg.CollectUsageData)
-	assert.Equal(t, 1, len(dg.Workflows))
-
-	workflow := dg.Workflows["default"]
-	assert.NotNil(t, workflow, "expected workflow to be not nil")
-	assert.NotNil(t, workflow.Plan)
-	assert.NotNil(t, workflow.Plan.Steps)
-
-	assert.NotNil(t, workflow.Apply)
-	assert.NotNil(t, workflow.Apply.Steps)
-	assert.NotNil(t, workflow.EnvVars)
-	assert.NotNil(t, workflow.Configuration)
-
-	assert.Equal(t, "path/to/module/test", dg.GetDirectory("prod"))
-}
-
 func TestDiggerConfigDefaultWorkflow(t *testing.T) {
 	tempDir, teardown := setUp()
 	defer teardown()
@@ -171,7 +134,7 @@ workflows:
 
 	dg, err := LoadDiggerConfig(tempDir, &FileSystemDirWalker{})
 	assert.NoError(t, err, "expected error to be nil")
-	assert.Equal(t, models.Step{Action: "run", Value: "echo \"hello\"", Shell: ""}, dg.Workflows["myworkflow"].Plan.Steps[0], "parsed struct does not match expected struct")
+	assert.Equal(t, Step{Action: "run", Value: "echo \"hello\"", Shell: ""}, dg.Workflows["myworkflow"].Plan.Steps[0], "parsed struct does not match expected struct")
 }
 
 func TestEnvVarsConfiguration(t *testing.T) {
@@ -216,10 +179,10 @@ workflows:
 
 	dg, err := LoadDiggerConfig(tempDir, &FileSystemDirWalker{})
 	assert.NoError(t, err, "expected error to be nil")
-	assert.Equal(t, []EnvVar{
+	assert.Equal(t, []EnvVarConfig{
 		{Name: "TF_VAR_state", Value: "s3://mybucket/terraform.tfstate"},
 	}, dg.Workflows["myworkflow"].EnvVars.State, "parsed struct does not match expected struct")
-	assert.Equal(t, []EnvVar{
+	assert.Equal(t, []EnvVarConfig{
 		{Name: "TF_VAR_command", Value: "plan"},
 	}, dg.Workflows["myworkflow"].EnvVars.Commands, "parsed struct does not match expected struct")
 }
@@ -246,9 +209,9 @@ workflows:
 
 	dg, err := LoadDiggerConfig(tempDir, &FileSystemDirWalker{})
 	assert.NoError(t, err, "expected error to be nil")
-	assert.Equal(t, models.Step{Action: "init", ExtraArgs: nil, Shell: ""}, dg.Workflows["default"].Plan.Steps[0], "parsed struct does not match expected struct")
-	assert.Equal(t, models.Step{Action: "plan", ExtraArgs: []string{"-var-file=terraform.tfvars"}, Shell: ""}, dg.Workflows["default"].Plan.Steps[1], "parsed struct does not match expected struct")
-	assert.Equal(t, models.Step{Action: "run", Value: "echo \"hello\"", Shell: "zsh"}, dg.Workflows["default"].Plan.Steps[2], "parsed struct does not match expected struct")
+	assert.Equal(t, Step{Action: "init", ExtraArgs: nil, Shell: ""}, dg.Workflows["default"].Plan.Steps[0], "parsed struct does not match expected struct")
+	assert.Equal(t, Step{Action: "plan", ExtraArgs: []string{"-var-file=terraform.tfvars"}, Shell: ""}, dg.Workflows["default"].Plan.Steps[1], "parsed struct does not match expected struct")
+	assert.Equal(t, Step{Action: "run", Value: "echo \"hello\"", Shell: "zsh"}, dg.Workflows["default"].Plan.Steps[2], "parsed struct does not match expected struct")
 }
 
 func TestDiggerGenerateProjects(t *testing.T) {
diff --git a/pkg/digger/digger_test.go b/pkg/digger/digger_test.go
index 1421e76b..92dbe88f 100644
--- a/pkg/digger/digger_test.go
+++ b/pkg/digger/digger_test.go
@@ -208,7 +208,6 @@ func TestCorrectCommandExecutionWhenPlanning(t *testing.T) {
 		CiService: prManager,
 		PrNumber:  1,
 	}
-
 	executor := execution.DiggerExecutor{
 		ApplyStage: &models.Stage{},
 		PlanStage: &models.Stage{