github.com/diggerhq/digger/libs@v0.0.0-20240604170430-9d61cdf01cc5/digger_config/digger_config_test.go (about)

     1  package digger_config
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"path"
     8  	"testing"
     9  
    10  	"github.com/dominikbraun/graph"
    11  	"github.com/go-git/go-git/v5"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  func setUp() (string, func()) {
    17  	tempDir := createTempDir()
    18  	return tempDir, func() {
    19  		deleteTempDir(tempDir)
    20  	}
    21  }
    22  
    23  func TestDiggerConfigWhenMultipleConfigExist(t *testing.T) {
    24  	tempDir, teardown := setUp()
    25  	defer teardown()
    26  
    27  	_, err := os.Create(path.Join(tempDir, "digger.yaml"))
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	_, err = os.Create(path.Join(tempDir, "digger.yml"))
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  
    37  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
    38  	assert.Error(t, err, "expected error to be returned")
    39  	assert.ErrorContains(t, err, ErrDiggerConfigConflict.Error(), "expected error to match target error")
    40  	assert.Nil(t, dg, "expected diggerConfig to be nil")
    41  }
    42  
    43  func TestDiggerConfigWhenCustomFileName(t *testing.T) {
    44  	tempDir, teardown := setUp()
    45  	defer teardown()
    46  
    47  	os.Setenv("DIGGER_FILENAME", "digger-custom.yml")
    48  
    49  	_, err := os.Create(path.Join(tempDir, "digger-custom.yml"))
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  
    54  	configPath, err := retrieveConfigFile(tempDir)
    55  	fmt.Println(configPath)
    56  
    57  	assert.Nil(t, err)
    58  	assert.Equal(t, configPath, path.Join(tempDir, "digger-custom.yml"))
    59  
    60  	os.Unsetenv("DIGGER_FILENAME")
    61  
    62  }
    63  
    64  func TestDiggerConfigWhenOnlyYamlExists(t *testing.T) {
    65  	tempDir, teardown := setUp()
    66  	defer teardown()
    67  
    68  	diggerCfg := `
    69  projects:
    70  - name: prod
    71    branch: /main/
    72    dir: path/to/module/test
    73    workspace: default
    74  `
    75  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
    76  	defer deleteFile()
    77  
    78  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
    79  	assert.NoError(t, err, "expected error to be nil")
    80  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
    81  	assert.Equal(t, "path/to/module/test", dg.GetDirectory("prod"))
    82  }
    83  
    84  func TestNoDiggerYaml(t *testing.T) {
    85  	tempDir, teardown := setUp()
    86  	defer teardown()
    87  
    88  	terraformFile := ""
    89  	deleteFile := createFile(path.Join(tempDir, "main.tf"), terraformFile)
    90  	defer deleteFile()
    91  
    92  	os.Chdir(tempDir)
    93  	dg, _, _, err := LoadDiggerConfig("./", true)
    94  
    95  	assert.NoError(t, err, "expected error to be nil")
    96  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
    97  	assert.Equal(t, 1, len(dg.Projects))
    98  	assert.Equal(t, false, dg.AutoMerge)
    99  	assert.Equal(t, true, dg.Telemetry)
   100  	assert.Equal(t, false, dg.TraverseToNestedProjects)
   101  	assert.Equal(t, 1, len(dg.Workflows))
   102  	assert.Equal(t, "default", dg.Projects[0].Name)
   103  	assert.Equal(t, "./", dg.Projects[0].Dir)
   104  
   105  	workflow := dg.Workflows["default"]
   106  	assert.NotNil(t, workflow, "expected workflow to be not nil")
   107  	assert.NotNil(t, workflow.Plan)
   108  	assert.NotNil(t, workflow.Plan.Steps)
   109  
   110  	assert.NotNil(t, workflow.Apply)
   111  	assert.NotNil(t, workflow.Apply.Steps)
   112  	assert.NotNil(t, workflow.EnvVars)
   113  	assert.NotNil(t, workflow.Configuration)
   114  }
   115  
   116  func TestDefaultDiggerConfig(t *testing.T) {
   117  	tempDir, teardown := setUp()
   118  	defer teardown()
   119  
   120  	diggerCfg := `
   121  projects:
   122  - name: prod
   123    branch: /main/
   124    dir: path/to/module/test
   125    aws_role_to_assume:
   126      state: "arn://abc:xyz:state"
   127      command: "arn://abc:xyz:cmd"
   128    workspace: default
   129    workflow_file: "test.yml"
   130  `
   131  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   132  	defer deleteFile()
   133  
   134  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   135  	fmt.Printf("%v", err)
   136  	assert.NoError(t, err, "expected error to be nil")
   137  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   138  	assert.Equal(t, 1, len(dg.Projects))
   139  	assert.Equal(t, false, dg.AutoMerge)
   140  	assert.Equal(t, true, dg.Telemetry)
   141  	assert.Equal(t, false, dg.TraverseToNestedProjects)
   142  	assert.Equal(t, 1, len(dg.Workflows))
   143  
   144  	assert.Equal(t, "prod", dg.Projects[0].Name)
   145  	assert.Equal(t, "test.yml", dg.Projects[0].WorkflowFile)
   146  	assert.Equal(t, "path/to/module/test", dg.Projects[0].Dir)
   147  	assert.Equal(t, "arn://abc:xyz:cmd", dg.Projects[0].AwsRoleToAssume.Command)
   148  	assert.Equal(t, "arn://abc:xyz:state", dg.Projects[0].AwsRoleToAssume.State)
   149  
   150  	workflow := dg.Workflows["default"]
   151  	assert.NotNil(t, workflow, "expected workflow to be not nil")
   152  	assert.NotNil(t, workflow.Plan)
   153  	assert.NotNil(t, workflow.Plan.Steps)
   154  
   155  	assert.NotNil(t, workflow.Apply)
   156  	assert.NotNil(t, workflow.Apply.Steps)
   157  	assert.NotNil(t, workflow.EnvVars)
   158  	assert.NotNil(t, workflow.Configuration)
   159  
   160  	assert.Equal(t, "path/to/module/test", dg.GetDirectory("prod"))
   161  }
   162  
   163  func TestDiggerConfigOneRole(t *testing.T) {
   164  	tempDir, teardown := setUp()
   165  	defer teardown()
   166  
   167  	diggerCfg := `
   168  projects:
   169  - name: prod
   170    branch: /main/
   171    aws_role_to_assume:
   172      command: "arn://abc:xyz:cmd"
   173  `
   174  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   175  	defer deleteFile()
   176  
   177  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   178  	fmt.Printf("%v", err)
   179  	assert.NoError(t, err, "expected error to be nil")
   180  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   181  	assert.Equal(t, "arn://abc:xyz:cmd", dg.Projects[0].AwsRoleToAssume.Command)
   182  	assert.Equal(t, "arn://abc:xyz:cmd", dg.Projects[0].AwsRoleToAssume.State)
   183  }
   184  
   185  func TestDiggerConfigDefaultWorkflow(t *testing.T) {
   186  	tempDir, teardown := setUp()
   187  	defer teardown()
   188  
   189  	diggerCfg := `
   190  projects:
   191  - name: prod
   192    branch: /main/
   193    dir: path/to/module/test
   194  `
   195  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   196  	defer deleteFile()
   197  
   198  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   199  	assert.NoError(t, err, "expected error to be nil")
   200  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   201  	assert.Equal(t, "default", dg.Projects[0].Workflow)
   202  	_, ok := dg.Workflows["default"]
   203  	assert.True(t, ok)
   204  }
   205  
   206  func TestDiggerConfigWhenOnlyYmlExists(t *testing.T) {
   207  	tempDir, teardown := setUp()
   208  	defer teardown()
   209  
   210  	diggerCfg := `
   211  projects:
   212  - name: dev
   213    branch: /main/
   214    dir: path/to/module
   215    workspace: default
   216  `
   217  	deleteFile := createFile(path.Join(tempDir, "digger.yml"), diggerCfg)
   218  	defer deleteFile()
   219  
   220  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   221  	assert.NoError(t, err, "expected error to be nil")
   222  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   223  	assert.Equal(t, "path/to/module", dg.GetDirectory("dev"))
   224  }
   225  
   226  func TestCustomCommandsConfiguration(t *testing.T) {
   227  	tempDir, teardown := setUp()
   228  	defer teardown()
   229  
   230  	diggerCfg := `
   231  projects:
   232  - name: dev
   233    dir: infra/dev
   234    workflow: myworkflow
   235  
   236  workflows:
   237    myworkflow:
   238      plan:
   239        steps:
   240        - run: echo "hello"
   241  `
   242  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   243  	defer deleteFile()
   244  
   245  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   246  	assert.NoError(t, err, "expected error to be nil")
   247  	assert.Equal(t, Step{Action: "run", Value: "echo \"hello\"", Shell: ""}, dg.Workflows["myworkflow"].Plan.Steps[0], "parsed struct does not match expected struct")
   248  }
   249  
   250  func TestEnvVarsConfiguration(t *testing.T) {
   251  	tempDir, teardown := setUp()
   252  	defer teardown()
   253  
   254  	diggerCfg := `
   255  projects:
   256  - name: dev
   257    branch: /main/
   258    dir: .
   259    workspace: default
   260    terragrunt: false
   261    workflow: myworkflow
   262  workflows:
   263    myworkflow:
   264      plan:
   265        steps:
   266        - init:
   267            extra_args: ["-lock=false"]
   268        - plan:
   269            extra_args: ["-lock=false"]
   270        - run: echo "hello"
   271      apply:
   272        steps:
   273        - apply:
   274          extra_args: ["-lock=false"]
   275      workflow_configuration:
   276        on_pull_request_pushed: [digger plan]
   277        on_pull_request_closed: [digger unlock]
   278        on_commit_to_default: [digger apply]
   279      env_vars:
   280        state:
   281        - name: TF_VAR_state
   282          value: s3://mybucket/terraform.tfstate
   283        commands:
   284        - name: TF_VAR_command
   285          value: plan
   286  `
   287  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   288  	defer deleteFile()
   289  
   290  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   291  	assert.NoError(t, err, "expected error to be nil")
   292  	assert.Equal(t, []EnvVar{
   293  		{Name: "TF_VAR_state", Value: "s3://mybucket/terraform.tfstate"},
   294  	}, dg.Workflows["myworkflow"].EnvVars.State, "parsed struct does not match expected struct")
   295  	assert.Equal(t, []EnvVar{
   296  		{Name: "TF_VAR_command", Value: "plan"},
   297  	}, dg.Workflows["myworkflow"].EnvVars.Commands, "parsed struct does not match expected struct")
   298  }
   299  
   300  func TestDefaultValuesForWorkflowConfiguration(t *testing.T) {
   301  	tempDir, teardown := setUp()
   302  	defer teardown()
   303  
   304  	diggerCfg := `
   305  projects:
   306  - name: dev
   307    dir: .
   308    workflow: dev
   309  
   310  workflows:
   311    dev:
   312      plan:
   313        steps:
   314          - run: rm -rf .terraform
   315          - init
   316          - plan:
   317            extra_args: ["-var-file=vars/dev.tfvars"]
   318    default:
   319      plan:
   320        steps:
   321          - run: rm -rf .terraform
   322          - init
   323          - plan:
   324              extra_args: ["-var-file=vars/dev.tfvars"]
   325  
   326  `
   327  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   328  	defer deleteFile()
   329  
   330  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   331  	assert.NoError(t, err, "expected error to be nil")
   332  	assert.Equal(t, Step{Action: "run", Value: "rm -rf .terraform", Shell: ""}, dg.Workflows["dev"].Plan.Steps[0], "parsed struct does not match expected struct")
   333  	assert.Equal(t, Step{Action: "init", ExtraArgs: nil, Shell: ""}, dg.Workflows["dev"].Plan.Steps[1], "parsed struct does not match expected struct")
   334  	assert.Equal(t, Step{Action: "plan", ExtraArgs: []string{"-var-file=vars/dev.tfvars"}, Shell: ""}, dg.Workflows["dev"].Plan.Steps[2], "parsed struct does not match expected struct")
   335  
   336  	assert.Equal(t, Step{Action: "run", Value: "rm -rf .terraform", Shell: ""}, dg.Workflows["default"].Plan.Steps[0], "parsed struct does not match expected struct")
   337  	assert.Equal(t, Step{Action: "init", ExtraArgs: nil, Shell: ""}, dg.Workflows["default"].Plan.Steps[1], "parsed struct does not match expected struct")
   338  	assert.Equal(t, Step{Action: "plan", ExtraArgs: []string{"-var-file=vars/dev.tfvars"}, Shell: ""}, dg.Workflows["default"].Plan.Steps[2], "parsed struct does not match expected struct")
   339  }
   340  
   341  func TestDiggerGenerateProjects(t *testing.T) {
   342  	tempDir, teardown := setUp()
   343  	defer teardown()
   344  
   345  	diggerCfg := `
   346  generate_projects:
   347    include: dev/*
   348    exclude: dev/project
   349  `
   350  	deleteFile := createFile(path.Join(tempDir, "digger.yml"), diggerCfg)
   351  	defer deleteFile()
   352  	dirsToCreate := []string{"dev/test1", "dev/test2", "dev/project", "testtt"}
   353  
   354  	for _, dir := range dirsToCreate {
   355  		err := os.MkdirAll(path.Join(tempDir, dir), os.ModePerm)
   356  		defer createFile(path.Join(tempDir, dir, "main.tf"), "")()
   357  		assert.NoError(t, err, "expected error to be nil")
   358  	}
   359  
   360  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   361  	assert.NoError(t, err, "expected error to be nil")
   362  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   363  	assert.Equal(t, "dev_test1", dg.Projects[0].Name)
   364  	assert.Equal(t, "dev_test2", dg.Projects[1].Name)
   365  	assert.Equal(t, "dev/test1", dg.Projects[0].Dir)
   366  	assert.Equal(t, "dev/test2", dg.Projects[1].Dir)
   367  	assert.Equal(t, 2, len(dg.Projects))
   368  }
   369  
   370  func TestGenerateProjectsWithoutDiggerConfig(t *testing.T) {
   371  	tempDir, teardown := setUp()
   372  	defer teardown()
   373  
   374  	dirsWithTfToCreate := []string{"dev/test1", "dev/test1/db", "dev/test1/vpc", "dev/test2", "dev/test2/db", "dev/test2/vpc", "dev/project", "prod/test1", "prod/test2", "prod/project", "test", "modules/test1", "modules/test2"}
   375  
   376  	for _, dir := range dirsWithTfToCreate {
   377  		err := os.MkdirAll(path.Join(tempDir, dir), os.ModePerm)
   378  		defer createFile(path.Join(tempDir, dir, "main.tf"), "")()
   379  		assert.NoError(t, err, "expected error to be nil")
   380  	}
   381  
   382  	dirtsWithoutTfToCreate := []string{"docs", "random", "docs/random"}
   383  	for _, dir := range dirtsWithoutTfToCreate {
   384  		err := os.MkdirAll(path.Join(tempDir, dir), os.ModePerm)
   385  		assert.NoError(t, err, "expected error to be nil")
   386  	}
   387  
   388  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   389  	assert.NoError(t, err, "expected error to be nil")
   390  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   391  	assert.Equal(t, "dev_project", dg.Projects[0].Name)
   392  	assert.Equal(t, "dev_test1", dg.Projects[1].Name)
   393  	assert.Equal(t, "dev_test2", dg.Projects[2].Name)
   394  	assert.Equal(t, "prod_project", dg.Projects[3].Name)
   395  	assert.Equal(t, "prod_test1", dg.Projects[4].Name)
   396  	assert.Equal(t, "prod_test2", dg.Projects[5].Name)
   397  	assert.Equal(t, "test", dg.Projects[6].Name)
   398  	assert.Equal(t, 7, len(dg.Projects))
   399  }
   400  
   401  func TestDiggerGenerateProjectsWithSubDirs(t *testing.T) {
   402  	tempDir, teardown := setUp()
   403  	defer teardown()
   404  
   405  	diggerCfg := `
   406  generate_projects:
   407    include: dev/**
   408    exclude: dev/project
   409  `
   410  	deleteFile := createFile(path.Join(tempDir, "digger.yml"), diggerCfg)
   411  	defer deleteFile()
   412  	dirsToCreate := []string{
   413  		"dev/test1/utils",
   414  		"dev/test2",
   415  		"dev/project",
   416  		"testtt",
   417  	}
   418  	for _, dir := range dirsToCreate {
   419  		err := os.MkdirAll(path.Join(tempDir, dir), os.ModePerm)
   420  		defer createFile(path.Join(tempDir, dir, "main.tf"), "")()
   421  		assert.NoError(t, err, "expected error to be nil")
   422  	}
   423  
   424  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   425  	assert.NoError(t, err, "expected error to be nil")
   426  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   427  	assert.Equal(t, "dev_test1_utils", dg.Projects[0].Name)
   428  	assert.Equal(t, "dev_test2", dg.Projects[1].Name)
   429  	assert.Equal(t, "dev/test1/utils", dg.Projects[0].Dir)
   430  	assert.Equal(t, "dev/test2", dg.Projects[1].Dir)
   431  	assert.Equal(t, 2, len(dg.Projects))
   432  }
   433  
   434  // A .tfvars file should not be recognised as .tf and break parsing for projects nested deeper
   435  // Issue: https://github.com/diggerhq/digger/issues/887
   436  func TestDiggerGenerateProjectsWithTfvars(t *testing.T) {
   437  	tempDir, teardown := setUp()
   438  	defer teardown()
   439  
   440  	dirsWithTfToCreate := []string{"dev/us-east-1"}
   441  
   442  	for _, dir := range dirsWithTfToCreate {
   443  		err := os.MkdirAll(path.Join(tempDir, dir), os.ModePerm)
   444  		defer createFile(path.Join(tempDir, dir, "main.tf"), "")()
   445  		assert.NoError(t, err, "expected error to be nil")
   446  	}
   447  
   448  	defer createFile(path.Join(tempDir, "dev", "blank.tfvars"), "")()
   449  
   450  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   451  	assert.NoError(t, err, "expected error to be nil")
   452  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   453  	assert.Equal(t, 1, len(dg.Projects))
   454  }
   455  
   456  func TestDiggerGenerateProjectsIgnoreSubdirs(t *testing.T) {
   457  	tempDir, teardown := setUp()
   458  	defer teardown()
   459  
   460  	diggerCfg := `
   461  generate_projects:
   462    include: dev
   463  `
   464  	deleteFile := createFile(path.Join(tempDir, "digger.yml"), diggerCfg)
   465  	defer deleteFile()
   466  	dirsToCreate := []string{
   467  		"dev",
   468  		"dev/test1",
   469  		"dev/test1/utils",
   470  		"dev/test2",
   471  		"dev/project",
   472  		"testtt",
   473  	}
   474  	for _, dir := range dirsToCreate {
   475  		err := os.MkdirAll(path.Join(tempDir, dir), os.ModePerm)
   476  		defer createFile(path.Join(tempDir, dir, "main.tf"), "")()
   477  		assert.NoError(t, err, "expected error to be nil")
   478  	}
   479  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   480  	assert.NoError(t, err, "expected error to be nil")
   481  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   482  	assert.Equal(t, "dev", dg.Projects[0].Name)
   483  	assert.Equal(t, 1, len(dg.Projects))
   484  }
   485  
   486  func TestMissingProjectsReturnsError(t *testing.T) {
   487  	tempDir, teardown := setUp()
   488  	defer teardown()
   489  
   490  	diggerCfg := `
   491  `
   492  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   493  	defer deleteFile()
   494  	_, _, _, err := LoadDiggerConfig(tempDir, true)
   495  	assert.ErrorContains(t, err, "no projects digger_config found")
   496  }
   497  
   498  func TestDiggerConfigCustomWorkflow(t *testing.T) {
   499  	tempDir, teardown := setUp()
   500  	defer teardown()
   501  
   502  	diggerCfg := `
   503  projects:
   504  - name: my-first-app
   505    dir: app-one
   506    workflow: my_custom_workflow
   507  workflows:
   508    my_custom_workflow:
   509      steps:
   510        - run: echo "run"
   511        - init: terraform init
   512        - plan: terraform plan
   513  `
   514  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   515  	defer deleteFile()
   516  
   517  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   518  	assert.NoError(t, err, "expected error to be nil")
   519  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   520  	assert.Equal(t, "my_custom_workflow", dg.Projects[0].Workflow)
   521  	_, ok := dg.Workflows["my_custom_workflow"]
   522  	assert.True(t, ok)
   523  }
   524  
   525  func TestDiggerConfigCustomWorkflowMissingParams(t *testing.T) {
   526  	tempDir, teardown := setUp()
   527  	defer teardown()
   528  
   529  	// missing workflow digger_config
   530  	diggerCfg := `
   531  projects:
   532  - name: my-first-app
   533    dir: app-one
   534    workflow: my_custom_workflow
   535  `
   536  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   537  	defer deleteFile()
   538  
   539  	_, _, _, err := LoadDiggerConfig(tempDir, true)
   540  	assert.Error(t, err, "failed to find workflow digger_config 'my_custom_workflow' for project 'my-first-app'")
   541  
   542  	// steps block is missing for workflows
   543  	diggerCfg = `
   544  projects:
   545  - name: my-first-app
   546    dir: app-one
   547    workflow: my_custom_workflow
   548  workflows:
   549    my_custom_workflow:
   550  `
   551  	deleteFile = createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   552  	defer deleteFile()
   553  
   554  	diggerConfig, _, _, err := LoadDiggerConfig(tempDir, true)
   555  	assert.Equal(t, "my_custom_workflow", diggerConfig.Projects[0].Workflow)
   556  	workflow, ok := diggerConfig.Workflows["my_custom_workflow"]
   557  	assert.True(t, ok)
   558  	assert.NotNil(t, workflow)
   559  	assert.NotNil(t, workflow.Plan)
   560  	assert.NotNil(t, workflow.Apply)
   561  
   562  }
   563  
   564  func TestDiggerConfigMissingProjectsWorkflow(t *testing.T) {
   565  	tempDir, teardown := setUp()
   566  	defer teardown()
   567  
   568  	diggerCfg := `
   569  projects:
   570  - name: my-first-app
   571    dir: app-one
   572    workflow: my_custom_workflow
   573  workflows:
   574    my_custom_workflow_no_one_use:
   575      steps:
   576        - run: echo "run"
   577        - init: terraform init
   578        - plan: terraform plan
   579  `
   580  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   581  	defer deleteFile()
   582  
   583  	_, _, _, err := LoadDiggerConfig(tempDir, true)
   584  	assert.Equal(t, "failed to find workflow digger_config 'my_custom_workflow' for project 'my-first-app'", err.Error())
   585  
   586  }
   587  
   588  func TestDiggerConfigWithEmptyInitBlock(t *testing.T) {
   589  	tempDir, teardown := setUp()
   590  	defer teardown()
   591  
   592  	diggerCfg := `
   593  projects:
   594  - name: my-first-app
   595    dir: app-one
   596    workflow: default
   597  workflows:
   598    default:
   599      plan:
   600        steps:
   601        - init:
   602        - plan:
   603          extra_args: ["-var-file=$ENV_NAME"]
   604  `
   605  	deleteFile := createFile(path.Join(tempDir, "digger.yaml"), diggerCfg)
   606  	defer deleteFile()
   607  
   608  	_, _, _, err := LoadDiggerConfig(tempDir, true)
   609  	assert.Nil(t, err)
   610  }
   611  
   612  func TestDiggerConfigDependencyGraph(t *testing.T) {
   613  	p1 := Project{
   614  		Name:               "A",
   615  		DependencyProjects: []string{"B", "C"},
   616  	}
   617  
   618  	p2 := Project{
   619  		Name:               "B",
   620  		DependencyProjects: []string{"C"},
   621  	}
   622  
   623  	p3 := Project{
   624  		Name: "C",
   625  	}
   626  
   627  	p4 := Project{
   628  		Name: "D",
   629  	}
   630  
   631  	p5 := Project{
   632  		Name:               "E",
   633  		DependencyProjects: []string{"A"},
   634  	}
   635  
   636  	p6 := Project{
   637  		Name:               "F",
   638  		DependencyProjects: []string{"A", "B"},
   639  	}
   640  
   641  	projects := []Project{p1, p2, p3, p4, p5, p6}
   642  
   643  	g, err := CreateProjectDependencyGraph(projects)
   644  
   645  	assert.NoError(t, err, "expected error to be nil")
   646  
   647  	orderedProjects, _ := graph.StableTopologicalSort(g, func(s string, s2 string) bool {
   648  		return s < s2
   649  	})
   650  
   651  	assert.Equal(t, 6, len(orderedProjects))
   652  	assert.Equal(t, []string{"C", "D", "B", "A", "E", "F"}, orderedProjects)
   653  }
   654  
   655  func TestDiggerYamlDependencyGraph(t *testing.T) {
   656  	diggerCfg := `
   657  projects:
   658  - name: my-first-app
   659    dir: app-one
   660    workflow: default
   661  - name: my-second-app
   662    dir: app-two
   663    workflow: default
   664    depends_on: ["my-first-app"]
   665  `
   666  	dg, _, _, err := LoadDiggerConfigFromString(diggerCfg, "./")
   667  	assert.NoError(t, err, "expected error to be nil")
   668  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   669  	assert.Equal(t, "default", dg.Projects[0].Workflow)
   670  
   671  	assert.Equal(t, "my-first-app", dg.Projects[0].Name)
   672  	assert.Equal(t, "my-second-app", dg.Projects[1].Name)
   673  
   674  	assert.Equal(t, "my-first-app", dg.Projects[1].DependencyProjects[0])
   675  }
   676  
   677  func TestDiggerConfigDependencyGraph2(t *testing.T) {
   678  	p1 := Project{
   679  		Name:               "A",
   680  		DependencyProjects: []string{"B", "C", "D"},
   681  	}
   682  
   683  	p2 := Project{
   684  		Name:               "B",
   685  		DependencyProjects: []string{"E", "F"},
   686  	}
   687  
   688  	p3 := Project{
   689  		Name: "C",
   690  		DependencyProjects: []string{
   691  			"G",
   692  		},
   693  	}
   694  
   695  	p4 := Project{
   696  		Name: "D",
   697  		DependencyProjects: []string{
   698  			"H", "I",
   699  		},
   700  	}
   701  
   702  	p5 := Project{
   703  		Name: "E",
   704  	}
   705  
   706  	p6 := Project{
   707  		Name: "F",
   708  	}
   709  
   710  	p7 := Project{
   711  		Name: "G",
   712  	}
   713  	p8 := Project{
   714  		Name: "H",
   715  	}
   716  
   717  	p9 := Project{
   718  		Name: "I",
   719  	}
   720  
   721  	projects := []Project{p1, p2, p3, p4, p5, p6, p7, p8, p9}
   722  
   723  	g, err := CreateProjectDependencyGraph(projects)
   724  
   725  	assert.NoError(t, err, "expected error to be nil")
   726  
   727  	orderedProjects, _ := graph.StableTopologicalSort(g, func(s string, s2 string) bool {
   728  		return s > s2
   729  	})
   730  
   731  	assert.Equal(t, 9, len(orderedProjects))
   732  	assert.Equal(t, []string{"I", "H", "G", "F", "E", "D", "C", "B", "A"}, orderedProjects)
   733  }
   734  
   735  func TestDiggerConfigDependencyGraphWithCyclesFails(t *testing.T) {
   736  	p1 := Project{
   737  		Name:               "A",
   738  		DependencyProjects: []string{"B"},
   739  	}
   740  
   741  	p2 := Project{
   742  		Name:               "B",
   743  		DependencyProjects: []string{"C"},
   744  	}
   745  
   746  	p3 := Project{
   747  		Name: "C",
   748  		DependencyProjects: []string{
   749  			"A",
   750  		},
   751  	}
   752  
   753  	projects := []Project{p1, p2, p3}
   754  
   755  	_, err := CreateProjectDependencyGraph(projects)
   756  
   757  	assert.Error(t, err, "expected error on cycle")
   758  	assert.Equal(t, "edge would create a cycle", err.Error())
   759  }
   760  
   761  func TestLoadDiggerConfigYamlFromString(t *testing.T) {
   762  	diggerCfg := `
   763  projects:
   764  - name: prod
   765    branch: /main/
   766    dir: path/to/module/test
   767  `
   768  
   769  	dg, _, _, err := LoadDiggerConfigFromString(diggerCfg, "./")
   770  	assert.NoError(t, err, "expected error to be nil")
   771  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   772  	assert.Equal(t, "default", dg.Projects[0].Workflow)
   773  	_, ok := dg.Workflows["default"]
   774  	assert.True(t, ok)
   775  }
   776  
   777  func TestDiggerConfigMissingProjectsWorkflowConfiguration(t *testing.T) {
   778  	tempDir, teardown := setUp()
   779  	defer teardown()
   780  	tests := []struct {
   781  		name      string
   782  		diggerCfg string
   783  		wantErr   string
   784  	}{
   785  		{
   786  			name: "on_pull_request_pushed empty",
   787  			diggerCfg: `
   788  projects:
   789  - name: dev
   790    branch: /main/
   791    dir: .
   792    workspace: default
   793    terragrunt: false
   794    workflow: myworkflow
   795  workflows:
   796    myworkflow:
   797      workflow_configuration:
   798        on_pull_request_pushed:
   799        on_pull_request_closed: [digger unlock]
   800        on_commit_to_default: [digger apply]
   801  `,
   802  			wantErr: "workflow_configuration.on_pull_request_pushed is required",
   803  		},
   804  		{
   805  			name: "on_pull_request_closed empty",
   806  			diggerCfg: `
   807  projects:
   808  - name: dev
   809    branch: /main/
   810    dir: .
   811    workspace: default
   812    terragrunt: false
   813    workflow: myworkflow
   814  workflows:
   815    myworkflow:
   816      workflow_configuration:
   817        on_pull_request_pushed: [digger plan]
   818        on_pull_request_closed:
   819        on_commit_to_default: [digger apply]
   820  `,
   821  			wantErr: "workflow_configuration.on_pull_request_closed is required",
   822  		},
   823  		{
   824  			name: "on_commit_to_default empty",
   825  			diggerCfg: `
   826  projects:
   827  - name: dev
   828    branch: /main/
   829    dir: .
   830    workspace: default
   831    terragrunt: false
   832    workflow: myworkflow
   833  workflows:
   834    myworkflow:
   835      workflow_configuration:
   836        on_pull_request_pushed: [digger plan]
   837        on_pull_request_closed: [digger unlock]
   838        on_commit_to_default:
   839  `,
   840  			wantErr: "workflow_configuration.on_commit_to_default is required",
   841  		},
   842  	}
   843  
   844  	for _, tt := range tests {
   845  		t.Run(tt.name, func(t *testing.T) {
   846  			deleteFile := createFile(path.Join(tempDir, "digger.yaml"), tt.diggerCfg)
   847  			defer deleteFile()
   848  			_, _, _, err := LoadDiggerConfig(tempDir, true)
   849  			assert.ErrorContains(t, err, tt.wantErr)
   850  		})
   851  	}
   852  }
   853  
   854  func createTempDir() string {
   855  	dir, err := os.MkdirTemp("", "tmp")
   856  	if err != nil {
   857  		log.Fatal(err)
   858  	}
   859  	return dir
   860  }
   861  
   862  func deleteTempDir(name string) {
   863  	err := os.RemoveAll(name)
   864  	if err != nil {
   865  		fmt.Printf("deleteTempDir error, %v", err.Error())
   866  		log.Fatal(err)
   867  	}
   868  }
   869  
   870  func createFile(filepath string, content string) func() {
   871  	f, err := os.Create(filepath)
   872  	if err != nil {
   873  		log.Fatal(err)
   874  	}
   875  
   876  	_, err = f.WriteString(content)
   877  	if err != nil {
   878  		log.Fatal(err)
   879  	}
   880  
   881  	return func() {
   882  		err := f.Close()
   883  		if err != nil {
   884  			log.Fatal(err)
   885  		}
   886  	}
   887  }
   888  
   889  func createAndCloseFile(filepath string, content string) error {
   890  	f, err := os.Create(filepath)
   891  	if err != nil {
   892  		return err
   893  	}
   894  
   895  	_, err = f.WriteString(content)
   896  	if err != nil {
   897  		return err
   898  	}
   899  
   900  	defer func(f *os.File) {
   901  		err := f.Close()
   902  		if err != nil {
   903  			log.Printf("failed to close file %v\n", f.Name())
   904  		}
   905  	}(f)
   906  	return nil
   907  }
   908  
   909  func TestDiggerGenerateProjectsMultiplePatterns(t *testing.T) {
   910  	tempDir, teardown := setUp()
   911  	defer teardown()
   912  
   913  	diggerCfg := `
   914  generate_projects:
   915    blocks:
   916      - include: dev/*
   917        exclude: dev/project
   918        workflow: dev_workflow
   919      - include: prod/*
   920        exclude: prod/project
   921        workflow: prod_workflow
   922  workflows:
   923    dev_workflow:
   924      steps:
   925        - run: echo "run"
   926        - init: terraform init
   927        - plan: terraform plan
   928    prod_workflow:
   929      steps:
   930        - run: echo "run"
   931        - init: terraform init
   932        - plan: terraform plan
   933  `
   934  	deleteFile := createFile(path.Join(tempDir, "digger.yml"), diggerCfg)
   935  	defer deleteFile()
   936  	dirsToCreate := []string{"dev/test1", "dev/test2", "dev/project", "testtt", "prod/one"}
   937  
   938  	for _, dir := range dirsToCreate {
   939  		err := os.MkdirAll(path.Join(tempDir, dir), os.ModePerm)
   940  		defer createFile(path.Join(tempDir, dir, "main.tf"), "")()
   941  		assert.NoError(t, err, "expected error to be nil")
   942  	}
   943  
   944  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
   945  	assert.NoError(t, err, "expected error to be nil")
   946  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
   947  	assert.Equal(t, "dev_test1", dg.Projects[0].Name)
   948  	assert.Equal(t, "dev_test2", dg.Projects[1].Name)
   949  	assert.Equal(t, "prod_one", dg.Projects[2].Name)
   950  	assert.Equal(t, "dev_workflow", dg.Projects[0].Workflow)
   951  	assert.Equal(t, "dev_workflow", dg.Projects[1].Workflow)
   952  	assert.Equal(t, "prod_workflow", dg.Projects[2].Workflow)
   953  	assert.Equal(t, "dev/test1", dg.Projects[0].Dir)
   954  	assert.Equal(t, "dev/test2", dg.Projects[1].Dir)
   955  	assert.Equal(t, "prod/one", dg.Projects[2].Dir)
   956  	assert.Equal(t, 3, len(dg.Projects))
   957  }
   958  
   959  // TestDiggerGenerateProjectsEmptyParameters test if missing parameters for generate_projects are handled correctly
   960  func TestDiggerGenerateProjectsEmptyParameters(t *testing.T) {
   961  	_, teardown := setUp()
   962  	defer teardown()
   963  
   964  	diggerCfg := `
   965  generate_projects:
   966  `
   967  	_, _, _, err := LoadDiggerConfigFromString(diggerCfg, "./")
   968  	assert.Error(t, err)
   969  	assert.Equal(t, "no projects digger_config found in 'loaded_yaml_string'", err.Error())
   970  }
   971  
   972  // TestDiggerGenerateProjectsTooManyParameters include/exclude and blocks of include/exclude can't be used together
   973  func TestDiggerGenerateProjectsTooManyParameters(t *testing.T) {
   974  	_, teardown := setUp()
   975  	defer teardown()
   976  
   977  	diggerCfg := `
   978  generate_projects:
   979    include: dev/*
   980    exclude: dev/project
   981    blocks:
   982      - include: dev/*
   983        exclude: dev/project
   984        workflow: default
   985      - include: prod/*
   986        exclude: prod/project
   987        workflow: default
   988  `
   989  	_, _, _, err := LoadDiggerConfigFromString(diggerCfg, "./")
   990  	assert.Error(t, err)
   991  	assert.Equal(t, "if include/exclude patterns are used for project generation, blocks of include/exclude can't be used", err.Error())
   992  }
   993  
   994  func TestDiggerTerragruntProjects(t *testing.T) {
   995  	tempDir, teardown := setUp()
   996  	defer teardown()
   997  
   998  	diggerCfg := `
   999  projects:
  1000  - name: dev
  1001    dir: .
  1002    terragrunt: true
  1003  `
  1004  	defer createFile(path.Join(tempDir, "digger.yml"), diggerCfg)()
  1005  	defer createFile(path.Join(tempDir, "main.tf"), "resource \"null_resource\" \"test4\" {}")()
  1006  	defer createFile(path.Join(tempDir, "terragrunt.hcl"), "terraform {}")()
  1007  
  1008  	_, config, _, err := LoadDiggerConfig(tempDir, true)
  1009  	assert.NoError(t, err)
  1010  
  1011  	print(config)
  1012  }
  1013  
  1014  func TestDiggerTerragruntProjectGenerationChainedDependencies(t *testing.T) {
  1015  	// based on https://github.com/transcend-io/terragrunt-atlantis-config/tree/master/test_examples/chained_dependencies
  1016  	// TODO: this test is a bit slow because we are cloning the whole repo, maybe we can copy it to a smaller repo
  1017  	tempDir, teardown := setUp()
  1018  	defer teardown()
  1019  
  1020  	diggerCfg := `
  1021  generate_projects:
  1022    terragrunt: true
  1023    terragrunt_parsing:
  1024      parallel: true
  1025      createProjectName: true
  1026      defaultWorkflow: default
  1027  `
  1028  
  1029  	repoUrl := "https://github.com/diggerhq/terragrunt-atlantis-config-examples.git"
  1030  	_, err := git.PlainClone(tempDir, false, &git.CloneOptions{
  1031  		URL:      repoUrl,
  1032  		Progress: os.Stdout,
  1033  	})
  1034  	assert.NoError(t, err)
  1035  
  1036  	// example dir: /test_examples/chained_dependencies
  1037  	projectDir := tempDir + "/chained_dependencies"
  1038  
  1039  	err = createAndCloseFile(path.Join(projectDir, "digger.yml"), diggerCfg)
  1040  	assert.NoError(t, err)
  1041  	_, _, _, err = LoadDiggerConfig(projectDir, true)
  1042  	assert.NoError(t, err)
  1043  }
  1044  
  1045  func TestDiggerTerragruntProjectGenerationBasicModule(t *testing.T) {
  1046  	// based on https://github.com/transcend-io/terragrunt-atlantis-config/tree/master/test_examples/basic_module
  1047  
  1048  	tempDir, teardown := setUp()
  1049  	defer teardown()
  1050  
  1051  	diggerCfg := `
  1052  generate_projects:
  1053    terragrunt: true
  1054    terragrunt_parsing:
  1055      parallel: true
  1056      createProjectName: true
  1057      createWorkspace: true
  1058      defaultWorkflow: default
  1059  
  1060  `
  1061  	hclFile := `terraform {
  1062    source = "git::git@github.com:transcend-io/terraform-aws-fargate-container?ref=v0.0.4"
  1063  }
  1064  
  1065  inputs = {
  1066    foo = "bar"
  1067  }
  1068  `
  1069  	defer createFile(path.Join(tempDir, "digger.yml"), diggerCfg)()
  1070  	defer createFile(path.Join(tempDir, "terragrunt.hcl"), hclFile)()
  1071  
  1072  	_, config, _, err := LoadDiggerConfig(tempDir, true)
  1073  	assert.NoError(t, err)
  1074  
  1075  	print(config)
  1076  }
  1077  
  1078  func TestDiggerTerragruntInfrastructureLiveExample(t *testing.T) {
  1079  	tempDir, teardown := setUp()
  1080  	defer teardown()
  1081  
  1082  	diggerCfg := `
  1083  generate_projects:
  1084    terragrunt: true
  1085    terragrunt_parsing:
  1086      parallel: true
  1087      createProjectName: true
  1088      createWorkspace: true
  1089      defaultWorkflow: default
  1090  `
  1091  
  1092  	repoUrl := "https://github.com/gruntwork-io/terragrunt-infrastructure-live-example"
  1093  	_, err := git.PlainClone(tempDir, false, &git.CloneOptions{
  1094  		URL:      repoUrl,
  1095  		Progress: os.Stdout,
  1096  	})
  1097  	assert.NoError(t, err)
  1098  
  1099  	defer createFile(path.Join(tempDir, "digger.yml"), diggerCfg)()
  1100  
  1101  	_, config, _, err := LoadDiggerConfig(tempDir, true)
  1102  	assert.NoError(t, err)
  1103  	assert.NotNil(t, config)
  1104  
  1105  	assert.Equal(t, "non-prod_us-east-1_qa_mysql", config.Projects[0].Name)
  1106  	assert.Equal(t, "non-prod_us-east-1_qa_webserver-cluster", config.Projects[1].Name)
  1107  	assert.Equal(t, "non-prod_us-east-1_stage_mysql", config.Projects[2].Name)
  1108  	assert.Equal(t, "non-prod_us-east-1_stage_webserver-cluster", config.Projects[3].Name)
  1109  	assert.Equal(t, "prod_us-east-1_prod_mysql", config.Projects[4].Name)
  1110  	assert.Equal(t, "prod_us-east-1_prod_webserver-cluster", config.Projects[5].Name)
  1111  }
  1112  
  1113  func TestDiggerGenerateProjectsMultipleBlocksDemo(t *testing.T) {
  1114  	tempDir, teardown := setUp()
  1115  	defer teardown()
  1116  
  1117  	repoUrl := "https://github.com/diggerhq/generate_projects_multiple_blocks_demo"
  1118  	_, err := git.PlainClone(tempDir, false, &git.CloneOptions{
  1119  		URL:      repoUrl,
  1120  		Progress: os.Stdout,
  1121  	})
  1122  	assert.NoError(t, err)
  1123  
  1124  	_, config, _, err := LoadDiggerConfig(tempDir, true)
  1125  	assert.NoError(t, err)
  1126  	assert.NotNil(t, config)
  1127  	assert.Equal(t, "projects_dev_test1", config.Projects[0].Name)
  1128  	assert.Equal(t, "projects/dev/test1", config.Projects[0].Dir)
  1129  	assert.Equal(t, "projects_dev_test2", config.Projects[1].Name)
  1130  	assert.Equal(t, "projects/dev/test2", config.Projects[1].Dir)
  1131  	assert.Equal(t, "projects_dev_test3", config.Projects[2].Name)
  1132  	assert.Equal(t, "projects/dev/test3", config.Projects[2].Dir)
  1133  	assert.Equal(t, "projects_prod_test1", config.Projects[3].Name)
  1134  	assert.Equal(t, "projects/prod/test1", config.Projects[3].Dir)
  1135  	assert.Equal(t, "projects_prod_test2", config.Projects[4].Name)
  1136  	assert.Equal(t, "projects/prod/test2", config.Projects[4].Dir)
  1137  	assert.Equal(t, 5, len(config.Projects))
  1138  }
  1139  
  1140  // todo test terragrunt digger_config with terragrunt_parsing block but without terragrunt: true
  1141  
  1142  // TestDiggerTraverseToNestedProjects test if traverse_to_nested_projects is set to true, digger will traverse to nested projects
  1143  func TestDiggerTraverseToNestedProjects(t *testing.T) {
  1144  	tempDir, teardown := setUp()
  1145  	defer teardown()
  1146  
  1147  	diggerCfg := `
  1148  allow_draft_prs: true
  1149  traverse_to_nested_projects: true
  1150  generate_projects:
  1151    blocks:
  1152      - include: dev/**
  1153        aws_role_to_assume:
  1154          state: "arn://abc:xyz:state"
  1155          command: "arn://abc:xyz:cmd"
  1156  `
  1157  	deleteFile := createFile(path.Join(tempDir, "digger.yml"), diggerCfg)
  1158  	defer deleteFile()
  1159  	dirsToCreate := []string{"dev/test1", "dev/test2", "dev/project", "dev/project/test3", "testtt"}
  1160  
  1161  	for _, dir := range dirsToCreate {
  1162  		err := os.MkdirAll(path.Join(tempDir, dir), os.ModePerm)
  1163  		defer createFile(path.Join(tempDir, dir, "main.tf"), "")()
  1164  		assert.NoError(t, err, "expected error to be nil")
  1165  	}
  1166  
  1167  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
  1168  	assert.NoError(t, err, "expected error to be nil")
  1169  	assert.NotNil(t, dg, "expected digger digger_config to be not nil")
  1170  	assert.Equal(t, true, dg.TraverseToNestedProjects)
  1171  	assert.Equal(t, 4, len(dg.Projects))
  1172  	assert.Equal(t, "arn://abc:xyz:cmd", dg.Projects[0].AwsRoleToAssume.Command)
  1173  	assert.Equal(t, "arn://abc:xyz:state", dg.Projects[0].AwsRoleToAssume.State)
  1174  	assert.Equal(t, "dev_project", dg.Projects[0].Name)
  1175  	assert.Equal(t, "dev/project", dg.Projects[0].Dir)
  1176  	assert.Equal(t, "dev_project_test3", dg.Projects[1].Name)
  1177  	assert.Equal(t, "dev/project/test3", dg.Projects[1].Dir)
  1178  	assert.Equal(t, "dev_test1", dg.Projects[2].Name)
  1179  	assert.Equal(t, "dev/test1", dg.Projects[2].Dir)
  1180  	assert.Equal(t, "dev_test2", dg.Projects[3].Name)
  1181  	assert.Equal(t, "dev/test2", dg.Projects[3].Dir)
  1182  	assert.Equal(t, true, dg.AllowDraftPRs)
  1183  }
  1184  
  1185  // TestDiggerAllowDraftPRs tests if allow_draft_prs is set to true, digger will allow draft PRs. Defaults to false
  1186  func TestDiggerAllowDraftPRs(t *testing.T) {
  1187  	tempDir, teardown := setUp()
  1188  	defer teardown()
  1189  
  1190  	diggerCfg := `
  1191  projects:
  1192  - name: dev
  1193    dir: .
  1194  `
  1195  	defer createFile(path.Join(tempDir, "digger.yml"), diggerCfg)()
  1196  	defer createFile(path.Join(tempDir, "main.tf"), "resource \"null_resource\" \"test4\" {}")()
  1197  
  1198  	dg, _, _, err := LoadDiggerConfig(tempDir, true)
  1199  	assert.NoError(t, err)
  1200  	assert.Equal(t, false, dg.AllowDraftPRs)
  1201  }
  1202  
  1203  func TestGetModifiedProjectsReturnsCorrectSourceMapping(t *testing.T) {
  1204  	changedFiles := []string{"modules/bucket/main.tf", "dev/main.tf"}
  1205  	projects := []Project{
  1206  		Project{
  1207  			Name:            "dev",
  1208  			Dir:             "dev",
  1209  			IncludePatterns: []string{"modules/**"},
  1210  		},
  1211  		Project{
  1212  			Name:            "prod",
  1213  			Dir:             "prod",
  1214  			IncludePatterns: []string{"modules/**"},
  1215  		},
  1216  	}
  1217  	c := DiggerConfig{
  1218  		Projects: projects,
  1219  	}
  1220  	expectedImpactingLocations := map[string]ProjectToSourceMapping{
  1221  		"dev":  {ImpactingLocations: []string{"modules/bucket", "dev"}},
  1222  		"prod": {ImpactingLocations: []string{"modules/bucket"}},
  1223  	}
  1224  
  1225  	impactedProjects, projectSourceMapping := c.GetModifiedProjects(changedFiles)
  1226  	assert.Equal(t, 2, len(impactedProjects))
  1227  	assert.Equal(t, 2, len(projectSourceMapping))
  1228  	assert.Equal(t, 2, len(projectSourceMapping["dev"].ImpactingLocations))
  1229  	assert.Equal(t, 1, len(projectSourceMapping["prod"].ImpactingLocations))
  1230  	assert.Equal(t, expectedImpactingLocations["dev"].ImpactingLocations, projectSourceMapping["dev"].ImpactingLocations)
  1231  	assert.Equal(t, expectedImpactingLocations["prod"].ImpactingLocations, projectSourceMapping["prod"].ImpactingLocations)
  1232  
  1233  }