Repository: diggerhq/digger
Pull request #289 (2023-05-22 16:22:54)

Gitlab improvements


Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 45d0e6e7..d762546b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -39,18 +39,18 @@ We strive to maintain a consistent coding style throughout the project. Please f
 
 ## Submitting a pull request
 When you have made changes to the codebase that you would like to contribute back, please follow these steps:
-1. Fork the repository and create a new branch from `main`.
+1. Fork the repository and create a new branch from `develop`.
 2. Make your changes and ensure that the code passes all tests.
 3. Write tests for your changes, if applicable.
 4. Update the documentation to reflect your changes, if applicable.
-5. Submit a pull request to the `main` branch.
+5. Submit a pull request to the `develop` branch.
    We will review your pull request as soon as possible. Please be patient and open to feedback. We appreciate your contributions!
 
 ## Release Process
 **NOTE: The default branch `@develop` is not guaranteed to be stable and you should always use published release versions in your testing and production.**
 
 - All pull requests are merged to the default develop branch after initial unit tests and integration tests are passing and required code review requirements are met.
-- We checkout a pre-release branch to prepare for an upcoming release.
+- We checkout a pre-release branch to prepare for an upcoming release with the pattern `prerelease-0.1.xx`.
 - We perform additional manual and automated tests in this branch to make sure there are no regressions.
 - Once we are ready we tag the head of our release branch and perform a release on it.
 - Tagged releases are published as actions and they are the most suitable to be used in production.
diff --git a/action.yml b/action.yml
index 4f06bb8a..fffa1a75 100644
--- a/action.yml
+++ b/action.yml
@@ -13,6 +13,9 @@ inputs:
   aws-secret-access-key:
     description: AWS secret access key
     required: false
+  aws-role-to-assume:
+    description: ARN of AWS IAM role to assume using OIDC
+    required: false
   aws-region:
     description: AWS region
     required: false
@@ -64,6 +67,10 @@ inputs:
     description: Checkov version
     required: false
     default: '2.3.245'
+  disable-locking:
+    description: Disable locking
+    required: false
+    default: 'false'
 
 outputs:
   output:
@@ -119,7 +126,14 @@ runs:
         aws-access-key-id: ${{ inputs.aws-access-key-id }}
         aws-secret-access-key: ${{ inputs.aws-secret-access-key }}
         aws-region: ${{ inputs.aws-region }}
-      if: inputs.setup-aws == 'true'
+      if: ${{ inputs.setup-aws == 'true' && inputs.aws-role-to-assume == '' }}
+
+    - name: Configure OIDC AWS credentials
+      uses: aws-actions/configure-aws-credentials@v2
+      with:
+        role-to-assume: ${{ inputs.aws-role-to-assume }}
+        aws-region: ${{ inputs.aws-region }}
+      if: ${{ inputs.setup-aws == 'true' && inputs.aws-role-to-assume != '' }}
 
     - name: Setup Terraform
       uses: hashicorp/setup-terraform@v2
@@ -150,6 +164,7 @@ runs:
       env:
         PLAN_UPLOAD_DESTINATION: ${{ inputs.upload-plan-destination }}
         ACTIVATE_VENV: ${{ inputs.setup-checkov == 'true' }}
+        DISABLE_LOCKING: ${{ inputs.disable-locking == 'true' }}
       run: |
           cd ${{ github.action_path }}
           go build -o digger ./cmd/digger
@@ -162,6 +177,7 @@ runs:
       env:
         actionref: ${{ github.action_ref }}
         PLAN_UPLOAD_DESTINATION: ${{ inputs.upload-plan-destination }}
+        DISABLE_LOCKING: ${{ inputs.disable-locking == 'true' }}
       id: digger
       shell: bash
       run: |
diff --git a/cmd/digger/main.go b/cmd/digger/main.go
index e5f50610..fcba3be5 100644
--- a/cmd/digger/main.go
+++ b/cmd/digger/main.go
@@ -60,7 +60,7 @@ func gitHubCI(lock utils.Lock) {
 	eventName := parsedGhContext.EventName
 	splitRepositoryName := strings.Split(parsedGhContext.Repository, "/")
 	repoOwner, repositoryName := splitRepositoryName[0], splitRepositoryName[1]
-	githubPrService := dg_github.NewGithubPullRequestService(ghToken, repositoryName, repoOwner)
+	githubPrService := dg_github.NewGitHubService(ghToken, repositoryName, repoOwner)
 
 	impactedProjects, requestedProject, prNumber, err := digger.ProcessGitHubEvent(ghEvent, diggerConfig, githubPrService)
 	if err != nil {
@@ -74,6 +74,10 @@ func gitHubCI(lock utils.Lock) {
 		githubPrService.PublishComment(prNumber, reply)
 	}
 
+	if len(impactedProjects) == 0 {
+		reportErrorAndExit(githubRepositoryOwner, "No projects impacted", 0)
+	}
+
 	commandsToRunPerProject, coversAllImpactedProjects, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	if err != nil {
 		reportErrorAndExit(githubRepositoryOwner, fmt.Sprintf("Failed to convert GitHub event to commands. %s", err), 7)
@@ -83,12 +87,12 @@ func gitHubCI(lock utils.Lock) {
 
 	planStorage := newPlanStorage(ghToken, repoOwner, repositoryName, prNumber)
 
-	allAppliesSuccess, err := digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, "")
+	allAppliesSuccessful, atLeastOneApply, err := digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, "")
 	if err != nil {
 		reportErrorAndExit(githubRepositoryOwner, fmt.Sprintf("Failed to run commands. %s", err), 8)
 	}
 
-	if diggerConfig.AutoMerge && allAppliesSuccess && coversAllImpactedProjects {
+	if diggerConfig.AutoMerge && allAppliesSuccessful && atLeastOneApply && coversAllImpactedProjects {
 		digger.MergePullRequest(githubPrService, prNumber)
 		println("PR merged successfully")
 	}
@@ -106,7 +110,9 @@ func gitHubCI(lock utils.Lock) {
 
 func gitLabCI(lock utils.Lock) {
 	println("Using GitLab.")
+
 	projectNamespace := os.Getenv("CI_PROJECT_NAMESPACE")
+	projectName := os.Getenv("CI_PROJECT_NAME")
 	gitlabToken := os.Getenv("GITLAB_TOKEN")
 	if gitlabToken == "" {
 		fmt.Println("GITLAB_TOKEN is empty")
@@ -131,6 +137,12 @@ func gitLabCI(lock utils.Lock) {
 		os.Exit(4)
 	}
 
+	// it's ok to not have merge request info if it has been merged
+	if (gitLabContext.MergeRequestIId == nil || len(gitLabContext.OpenMergeRequests) == 0) && gitLabContext.EventType != "merge_request_merge" {
+		fmt.Println("No merge request found.")
+		os.Exit(0)
+	}
+
 	gitlabService, err := gitlab.NewGitLabService(gitlabToken, gitLabContext)
 	if err != nil {
 		fmt.Printf("failed to initialise GitLab service, %v", err)
@@ -153,21 +165,33 @@ func gitLabCI(lock utils.Lock) {
 	}
 	println("GitLab event converted to commands successfully")
 
+	println("Digger commands to be executed:")
 	for _, v := range commandsToRunPerProject {
 		fmt.Printf("command: %s, project: %s\n", strings.Join(v.Commands, ", "), v.ProjectName)
 	}
 
-	//planStorage := newPlanStorage(ghToken, repoOwner, repositoryName, prNumber)
-	var planStorage utils.PlanStorage
+	planStorage := newPlanStorage(gitlabToken, projectNamespace, projectName, *gitLabContext.MergeRequestIId)
 
-	result, err := gitlab.RunCommandsPerProject(commandsToRunPerProject, *gitLabContext, diggerConfig, gitlabService, lock, planStorage, currentDir)
+	allAppliesSuccess, err := gitlab.RunCommandsPerProject(commandsToRunPerProject, *gitLabContext, diggerConfig, gitlabService, lock, planStorage, currentDir)
 	if err != nil {
 		fmt.Printf("failed to execute command, %v", err)
 		os.Exit(8)
 	}
-	print(result)
+
+	if diggerConfig.AutoMerge && allAppliesSuccess {
+		digger.MergePullRequest(gitlabService, *gitLabContext.MergeRequestIId)
+		println("Merge request changes has been applied successfully")
+	}
 
 	println("Commands executed successfully")
+
+	reportErrorAndExit(projectName, "Digger finished successfully", 0)
+
+	defer func() {
+		if r := recover(); r != nil {
+			reportErrorAndExit(projectName, fmt.Sprintf("Panic occurred. %s", r), 1)
+		}
+	}()
 }
 
 /*
@@ -218,7 +242,8 @@ func main() {
 func newPlanStorage(ghToken string, repoOwner string, repositoryName string, prNumber int) utils.PlanStorage {
 	var planStorage utils.PlanStorage
 
-	if os.Getenv("PLAN_UPLOAD_DESTINATION") == "github" {
+	uploadDestination := strings.ToLower(os.Getenv("PLAN_UPLOAD_DESTINATION"))
+	if uploadDestination == "github" {
 		zipManager := utils.Zipper{}
 		planStorage = &utils.GithubPlanStorage{
 			Client:            github.NewTokenClient(context.Background(), ghToken),
@@ -227,9 +252,8 @@ func newPlanStorage(ghToken string, repoOwner string, repositoryName string, prN
 			PullRequestNumber: prNumber,
 			ZipManager:        zipManager,
 		}
-	} else if os.Getenv("PLAN_UPLOAD_DESTINATION") == "gcp" {
+	} else if uploadDestination == "gcp" {
 		ctx, client := gcp.GetGoogleStorageClient()
-
 		bucketName := strings.ToLower(os.Getenv("GOOGLE_STORAGE_BUCKET"))
 		if bucketName == "" {
 			reportErrorAndExit(repoOwner, fmt.Sprintf("GOOGLE_STORAGE_BUCKET is not defined"), 9)
@@ -240,7 +264,10 @@ func newPlanStorage(ghToken string, repoOwner string, repositoryName string, prN
 			Bucket:  bucket,
 			Context: ctx,
 		}
+	} else if uploadDestination == "gitlab" {
+		//TODO implement me
 	}
+
 	return planStorage
 }
 
diff --git a/go.mod b/go.mod
index 1e62a8a7..f3ca0bd0 100644
--- a/go.mod
+++ b/go.mod
@@ -6,13 +6,13 @@ 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.266
+	github.com/aws/aws-sdk-go v1.44.275
 	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/stretchr/testify v1.8.3
-	github.com/xanzy/go-gitlab v0.83.0
+	github.com/stretchr/testify v1.8.4
+	github.com/xanzy/go-gitlab v0.84.0
 	gopkg.in/yaml.v3 v3.0.1
 )
 
diff --git a/go.sum b/go.sum
index 8c10d063..941c5051 100644
--- a/go.sum
+++ b/go.sum
@@ -25,6 +25,14 @@ github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwF
 github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
 github.com/aws/aws-sdk-go v1.44.266 h1:MWd775dcYf7NrwgcHLtlsIbWoWkX8p4vomfNHr88zH0=
 github.com/aws/aws-sdk-go v1.44.266/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.44.268 h1:WoK20tlAvsvQzTcE6TajoprbXmTbcud6MjhErL4P/38=
+github.com/aws/aws-sdk-go v1.44.268/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.44.273 h1:CX8O0gK+cGrgUyv7bgJ6QQP9mQg7u5mweHdNzULH47c=
+github.com/aws/aws-sdk-go v1.44.273/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.44.274 h1:vfreSv19e/9Ka9YytOzgzJasrRZfX7dnttLlbh8NKeA=
+github.com/aws/aws-sdk-go v1.44.274/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.44.275 h1:VqRULgqrigvQLll4e4hXuc568EQAtZQ6jmBzLlQHzSI=
+github.com/aws/aws-sdk-go v1.44.275/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
 github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc=
 github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
 github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
@@ -116,8 +124,12 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
 github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/xanzy/go-gitlab v0.83.0 h1:37p0MpTPNbsTMKX/JnmJtY8Ch1sFiJzVF342+RvZEGw=
 github.com/xanzy/go-gitlab v0.83.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw=
+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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
diff --git a/pkg/ci/main.go b/pkg/ci/main.go
index 76c2a866..2adc3cfc 100644
--- a/pkg/ci/main.go
+++ b/pkg/ci/main.go
@@ -3,6 +3,8 @@ package ci
 type CIService interface {
 	GetChangedFiles(prNumber int) ([]string, error)
 	PublishComment(prNumber int, comment string)
+
+	// SetStatus set status of specified pull/merge request, status could be: "pending", "failure", "success"
 	SetStatus(prNumber int, status string, statusContext string) error
 	GetCombinedPullRequestStatus(prNumber int) (string, error)
 	MergePullRequest(prNumber int) error
diff --git a/pkg/configuration/digger_config.go b/pkg/configuration/digger_config.go
index 7458a258..9015843b 100644
--- a/pkg/configuration/digger_config.go
+++ b/pkg/configuration/digger_config.go
@@ -195,11 +195,50 @@ func (s *Step) extract(stepMap map[string]interface{}, action string) {
 	}
 }
 
+// duplicate copied from digger.go
+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
 
 	diggerConfig.AutoMerge = diggerYaml.AutoMerge
-	diggerConfig.Workflows = diggerYaml.Workflows
+
+	if diggerYaml.Workflows != nil {
+		diggerConfig.Workflows = diggerYaml.Workflows
+	} else {
+		workflow := *defaultWorkflow()
+		diggerConfig.Workflows = make(map[string]Workflow)
+		diggerConfig.Workflows["default"] = workflow
+	}
+
 	diggerConfig.Projects = diggerYaml.Projects
 	diggerConfig.CollectUsageData = diggerYaml.CollectUsageData
 
diff --git a/pkg/digger/digger.go b/pkg/digger/digger.go
index 1a7d5ec8..0830b95d 100644
--- a/pkg/digger/digger.go
+++ b/pkg/digger/digger.go
@@ -63,11 +63,10 @@ func ProcessGitHubEvent(ghEvent models.Event, diggerConfig *configuration.Digger
 	return impactedProjects, nil, prNumber, nil
 }
 
-func RunCommandsPerProject(commandsPerProject []ProjectCommand, repoOwner string, repoName string, eventName string, prNumber int, ciService ci.CIService, lock utils.Lock, planStorage utils.PlanStorage, workingDir string) (bool, error) {
-	allAppliesSuccess := true
+func RunCommandsPerProject(commandsPerProject []ProjectCommand, repoOwner string, repoName string, eventName string, prNumber int, ciService ci.CIService, lock utils.Lock, planStorage utils.PlanStorage, workingDir string) (bool, bool, error) {
+
 	appliesPerProject := make(map[string]bool)
 	for _, projectCommands := range commandsPerProject {
-		appliesPerProject[projectCommands.ProjectName] = false
 		for _, command := range projectCommands.Commands {
 			projectLock := &utils.ProjectLockImpl{
 				InternalLock: lock,
@@ -109,18 +108,19 @@ func RunCommandsPerProject(commandsPerProject []ProjectCommand, repoOwner string
 				if err != nil {
 					log.Printf("Failed to run digger plan command. %v", err)
 					ciService.SetStatus(prNumber, "failure", projectCommands.ProjectName+"/plan")
-					return false, fmt.Errorf("failed to run digger plan command. %v", err)
+					return false, false, fmt.Errorf("failed to run digger plan command. %v", err)
 				} else if planPerformed {
 					ciService.SetStatus(prNumber, "success", projectCommands.ProjectName+"/plan")
 				}
 			case "digger apply":
+				appliesPerProject[projectCommands.ProjectName] = false
 				usage.SendUsageRecord(repoName, eventName, "apply")
 				ciService.SetStatus(prNumber, "pending", projectCommands.ProjectName+"/apply")
 				applyPerformed, err := diggerExecutor.Apply(prNumber)
 				if err != nil {
 					log.Printf("Failed to run digger apply command. %v", err)
 					ciService.SetStatus(prNumber, "failure", projectCommands.ProjectName+"/apply")
-					return false, fmt.Errorf("failed to run digger apply command. %v", err)
+					return false, false, fmt.Errorf("failed to run digger apply command. %v", err)
 				} else if applyPerformed {
 					ciService.SetStatus(prNumber, "success", projectCommands.ProjectName+"/apply")
 					appliesPerProject[projectCommands.ProjectName] = true
@@ -129,24 +129,29 @@ func RunCommandsPerProject(commandsPerProject []ProjectCommand, repoOwner string
 				usage.SendUsageRecord(repoOwner, eventName, "unlock")
 				err := diggerExecutor.Unlock(prNumber)
 				if err != nil {
-					return false, fmt.Errorf("failed to unlock project. %v", err)
+					return false, false, fmt.Errorf("failed to unlock project. %v", err)
 				}
 			case "digger lock":
 				usage.SendUsageRecord(repoOwner, eventName, "lock")
 				err := diggerExecutor.Lock(prNumber)
 				if err != nil {
-					return false, fmt.Errorf("failed to lock project. %v", err)
+					return false, false, fmt.Errorf("failed to lock project. %v", err)
 				}
 			}
 		}
 	}
 
+	allAppliesSuccess := true
+
 	for _, success := range appliesPerProject {
 		if !success {
 			allAppliesSuccess = false
 		}
 	}
-	return allAppliesSuccess, nil
+
+	atLeastOneApply := len(appliesPerProject) > 0
+
+	return allAppliesSuccess, atLeastOneApply, nil
 }
 
 func MergePullRequest(githubPrService ci.CIService, prNumber int) {
diff --git a/pkg/github/github.go b/pkg/github/github.go
index 4e4967cd..08d80653 100644
--- a/pkg/github/github.go
+++ b/pkg/github/github.go
@@ -9,7 +9,7 @@ import (
 	"github.com/google/go-github/v51/github"
 )
 
-func NewGithubPullRequestService(ghToken string, repoName string, owner string) ci.CIService {
+func NewGitHubService(ghToken string, repoName string, owner string) ci.CIService {
 	client := github.NewTokenClient(context.Background(), ghToken)
 	return &GithubService{
 		Client:   client,
diff --git a/pkg/gitlab/gitlab.go b/pkg/gitlab/gitlab.go
index dea32a43..a4a27fbe 100644
--- a/pkg/gitlab/gitlab.go
+++ b/pkg/gitlab/gitlab.go
@@ -30,9 +30,11 @@ type GitLabContext struct {
 	ProjectNamespace   string          `env:"CI_PROJECT_NAMESPACE"`
 	ProjectId          *int            `env:"CI_PROJECT_ID"`
 	ProjectNamespaceId *int            `env:"CI_PROJECT_NAMESPACE_ID"`
+	OpenMergeRequests  []string        `env:"CI_OPEN_MERGE_REQUESTS"`
 	Token              string          `env:"GITLAB_TOKEN"`
 	DiggerCommand      string          `env:"DIGGER_COMMAND"`
 	DiscussionID       string          `env:"DISCUSSION_ID"`
+	IsMeargeable       bool            `env:"IS_MERGEABLE"`
 }
 
 type PipelineSourceType string
@@ -88,8 +90,7 @@ func ProcessGitLabEvent(gitlabContext *GitLabContext, diggerConfig *configuratio
 	var impactedProjects []configuration.Project
 
 	if gitlabContext.MergeRequestIId == nil {
-		println("Merge Request ID is not found.")
-		return nil, nil
+		return nil, fmt.Errorf("value for 'Merge Request ID' parameter is not found")
 	}
 
 	mergeRequestId := gitlabContext.MergeRequestIId
@@ -139,61 +140,58 @@ func (gitlabService GitLabService) PublishComment(mergeRequestID int, comment st
 	mergeRequestIID := *gitlabService.Context.MergeRequestIId
 	commentOpt := &go_gitlab.AddMergeRequestDiscussionNoteOptions{Body: &comment}
 
-	fmt.Printf("PublishComment mergeRequestID : %d, projectId: %d, mergeRequestIID: %d, \n", mergeRequestID, projectId, mergeRequestIID)
+	fmt.Printf("PublishComment mergeRequestID : %d, projectId: %d, mergeRequestIID: %d, discussionId: %s \n", mergeRequestID, projectId, mergeRequestIID, discussionId)
 
-	_, _, err := gitlabService.Client.Discussions.AddMergeRequestDiscussionNote(projectId, mergeRequestIID, discussionId, commentOpt)
-	if err != nil {
-		fmt.Printf("Failed to publish a comment. %v\n", err)
-		print(err.Error())
+	if discussionId == "" {
+		commentOpt := &go_gitlab.CreateMergeRequestDiscussionOptions{Body: &comment}
+		discussion, _, err := gitlabService.Client.Discussions.CreateMergeRequestDiscussion(projectId, mergeRequestIID, commentOpt)
+		if err != nil {
+			fmt.Printf("Failed to publish a comment. %v\n", err)
+			print(err.Error())
+		}
+		discussionId = discussion.ID
+	} else {
+		_, _, err := gitlabService.Client.Discussions.AddMergeRequestDiscussionNote(projectId, mergeRequestIID, discussionId, commentOpt)
+		if err != nil {
+			fmt.Printf("Failed to publish a comment. %v\n", err)
+			print(err.Error())
+		}
 	}
 }
 
+// SetStatus GitLab implementation is using https://docs.gitlab.com/15.11/ee/api/status_checks.html (external status checks)
+// https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html#add-a-status-check-service
+// only supported by 'Ultimate' plan
 func (gitlabService GitLabService) SetStatus(mergeRequestID int, status string, statusContext string) error {
 	//TODO implement me
 	fmt.Printf("SetStatus: mergeRequest: %d, status: %s, statusContext: %s\n", mergeRequestID, status, statusContext)
 	return nil
-	//panic("SetStatus: implement me")
 }
 
 func (gitlabService GitLabService) GetCombinedPullRequestStatus(mergeRequestID int) (string, error) {
 	//TODO implement me
 
-	panic("GetCombinedPullRequestStatus: implement me")
+	return "success", nil
 }
 
 func (gitlabService GitLabService) MergePullRequest(mergeRequestID int) error {
 	projectId := *gitlabService.Context.ProjectId
 	mergeRequestIID := *gitlabService.Context.MergeRequestIId
-	opt := &go_gitlab.AcceptMergeRequestOptions{}
+	mergeWhenPipelineSucceeds := true
+	opt := &go_gitlab.AcceptMergeRequestOptions{MergeWhenPipelineSucceeds: &mergeWhenPipelineSucceeds}
 
 	fmt.Printf("MergePullRequest mergeRequestID : %d, projectId: %d, mergeRequestIID: %d, \n", mergeRequestID, projectId, mergeRequestIID)
 
 	_, _, err := gitlabService.Client.MergeRequests.AcceptMergeRequest(projectId, mergeRequestIID, opt)
 	if err != nil {
 		fmt.Printf("Failed to merge Merge Request. %v\n", err)
-		return err
+		return fmt.Errorf("Failed to merge Merge Request. %v\n", err)
 	}
 	return nil
 }
 
 func (gitlabService GitLabService) IsMergeable(mergeRequestID int) (bool, error) {
-	projectId := *gitlabService.Context.ProjectId
-	mergeRequestIID := *gitlabService.Context.MergeRequestIId
-
-	fmt.Printf("IsMergeable mergeRequestIID : %d, projectId: %d \n", mergeRequestIID, projectId)
-	opt := &go_gitlab.GetMergeRequestsOptions{}
-
-	mergeRequest, _, err := gitlabService.Client.MergeRequests.GetMergeRequest(projectId, mergeRequestIID, opt)
-
-	if err != nil {
-		fmt.Printf("Failed to get a MergeRequest: %d, %v \n", mergeRequestIID, err)
-		print(err.Error())
-	}
-
-	if mergeRequest.DetailedMergeStatus == "mergeable" {
-		return true, nil
-	}
-	return false, nil
+	return gitlabService.Context.IsMeargeable, nil
 }
 
 func (gitlabService GitLabService) IsClosed(mergeRequestID int) (bool, error) {
@@ -227,37 +225,28 @@ func (e GitLabEventType) String() string {
 }
 
 const (
-	MergeRequestOpened  = GitLabEventType("merge_request_opened")
-	MergeRequestUpdated = GitLabEventType("merge_request_updated")
-	MergeRequestClosed  = GitLabEventType("merge_request_closed")
+	MergeRequestOpened     = GitLabEventType("merge_request_opened")
+	MergeRequestClosed     = GitLabEventType("merge_request_closed")
+	MergeRequestReopened   = GitLabEventType("merge_request_reopened")
+	MergeRequestUpdated    = GitLabEventType("merge_request_updated")
+	MergeRequestApproved   = GitLabEventType("merge_request_approved")
+	MergeRequestUnapproved = GitLabEventType("merge_request_unapproved")
+	MergeRequestApproval   = GitLabEventType("merge_request_approval")
+	MergeRequestUnapproval = GitLabEventType("merge_request_unapproval")
+	MergeRequestMerged     = GitLabEventType("merge_request_merge")
+
 	MergeRequestComment = GitLabEventType("merge_request_commented")
 )
 
 func ConvertGitLabEventToCommands(event GitLabEvent, gitLabContext *GitLabContext, impactedProjects []configuration.Project, workflows map[string]configuration.Workflow) ([]digger.ProjectCommand, error) {
 	commandsPerProject := make([]digger.ProjectCommand, 0)
 
+	fmt.Printf("ConvertGitLabEventToCommands, event.EventType: %s\n", event.EventType)
 	switch event.EventType {
-	case MergeRequestOpened:
+	case MergeRequestOpened, MergeRequestReopened, MergeRequestUpdated:
 		for _, project := range impactedProjects {
 			workflow, ok := workflows[project.Workflow]
-			if !ok {
-				workflow = workflows["default"]
-			}
 
-			commandsPerProject = append(commandsPerProject, digger.ProjectCommand{
-				ProjectName:      project.Name,
-				ProjectDir:       project.Dir,
-				ProjectWorkspace: project.Workspace,
-				Terragrunt:       project.Terragrunt,
-				Commands:         workflow.Configuration.OnPullRequestPushed,
-				ApplyStage:       workflow.Apply,
-				PlanStage:        workflow.Plan,
-			})
-		}
-		return commandsPerProject, nil
-	case MergeRequestUpdated:
-		for _, project := range impactedProjects {
-			workflow, ok := workflows[project.Workflow]
 			if !ok {
 				workflow = workflows["default"]
 			}
@@ -273,7 +262,8 @@ func ConvertGitLabEventToCommands(event GitLabEvent, gitLabContext *GitLabContex
 			})
 		}
 		return commandsPerProject, nil
-	case MergeRequestClosed:
+	case MergeRequestClosed, MergeRequestMerged:
+		fmt.Println("Merge request closed or merged.")
 		for _, project := range impactedProjects {
 			workflow, ok := workflows[project.Workflow]
 			if !ok {
@@ -297,13 +287,6 @@ func ConvertGitLabEventToCommands(event GitLabEvent, gitLabContext *GitLabContex
 			if strings.Contains(gitLabContext.DiggerCommand, command) {
 				for _, project := range impactedProjects {
 					workspace := project.Workspace
-					//workspaceOverride, err := parseWorkspace(gitLabContext.DiggerCommand)
-					//if err != nil {
-					//	return []digger.ProjectCommand{}, err
-					//}
-					//if workspaceOverride != "" {
-					//	workspace = workspaceOverride
-					//}
 					commandsPerProject = append(commandsPerProject, digger.ProjectCommand{
 						ProjectName:      project.Name,
 						ProjectDir:       project.Dir,
@@ -319,6 +302,7 @@ func ConvertGitLabEventToCommands(event GitLabEvent, gitLabContext *GitLabContex
 	default:
 		return []digger.ProjectCommand{}, fmt.Errorf("unsupported GitLab event type: %v", event)
 	}
+	return nil, nil
 }
 
 func RunCommandsPerProject(commandsPerProject []digger.ProjectCommand, gitLabContext GitLabContext, diggerConfig *configuration.DiggerConfig, service ci.CIService, lock utils.Lock, planStorage utils.PlanStorage, workingDir string) (bool, error) {
@@ -338,7 +322,6 @@ func RunCommandsPerProject(commandsPerProject []digger.ProjectCommand, gitLabCon
 
 			var terraformExecutor terraform.TerraformExecutor
 			projectPath := path.Join(workingDir, projectCommands.ProjectDir)
-			fmt.Printf("pprojectPath: %s\n\n", projectPath)
 			if projectCommands.Terragrunt {
 				terraformExecutor = terraform.Terragrunt{WorkingDir: path.Join(workingDir, projectCommands.ProjectDir)}
 			} else {
@@ -417,52 +400,4 @@ func RunCommandsPerProject(commandsPerProject []digger.ProjectCommand, gitLabCon
 		}
 	}
 	return allAppliesSuccess, nil
-	/*
-
-		lockAcquisitionSuccess := true
-		for _, projectCommands := range commandsPerProject {
-			for _, command := range projectCommands.Commands {
-				projectLock := &utils.ProjectLockImpl{
-					InternalLock: lock,
-					CIService:    service,
-					ProjectName:  projectCommands.ProjectName,
-					RepoName:     gitLabContext.ProjectName,
-					RepoOwner:    gitLabContext.ProjectNamespace,
-				}
-				diggerExecutor := digger.DiggerExecutor{
-					workingDir,
-					projectCommands.ProjectWorkspace,
-					gitLabContext.ProjectNamespace,
-					projectCommands.ProjectName,
-					projectCommands.ProjectDir,
-					gitLabContext.ProjectName,
-					projectCommands.Terragrunt,
-					service,
-					projectLock,
-					diggerConfig,
-				}
-				switch command {
-				case "digger plan":
-					utils.SendUsageRecord(gitLabContext.ProjectNamespace, gitLabContext.EventType.String(), "plan")
-					diggerExecutor.Plan(*gitLabContext.MergeRequestIId)
-				case "digger apply":
-					utils.SendUsageRecord(gitLabContext.ProjectName, gitLabContext.EventType.String(), "apply")
-					diggerExecutor.Apply(*gitLabContext.MergeRequestIId)
-				case "digger unlock":
-					utils.SendUsageRecord(gitLabContext.ProjectNamespace, gitLabContext.EventType.String(), "unlock")
-					diggerExecutor.Unlock(*gitLabContext.MergeRequestIId)
-				case "digger lock":
-					utils.SendUsageRecord(gitLabContext.ProjectNamespace, gitLabContext.EventType.String(), "lock")
-					lockAcquisitionSuccess = diggerExecutor.Lock(*gitLabContext.MergeRequestIId)
-				}
-			}
-		}
-
-		if !lockAcquisitionSuccess {
-			os.Exit(1)
-		}
-		return nil
-
-	*/
-
 }
diff --git a/pkg/utils/locking.go b/pkg/utils/locking.go
index fd064aff..014a1e2c 100644
--- a/pkg/utils/locking.go
+++ b/pkg/utils/locking.go
@@ -36,6 +36,21 @@ type Lock interface {
 	GetLock(resource string) (*int, error)
 }
 
+type NoOpLock struct {
+}
+
+func (noOpLock *NoOpLock) Lock(transactionId int, resource string) (bool, error) {
+	return true, nil
+}
+
+func (noOpLock *NoOpLock) Unlock(resource string) (bool, error) {
+	return true, nil
+}
+
+func (noOpLock *NoOpLock) GetLock(resource string) (*int, error) {
+	return nil, nil
+}
+
 type ProjectLock interface {
 	Lock(prNumber int) (bool, error)
 	Unlock(prNumber int) (bool, error)
@@ -77,7 +92,9 @@ func (projectLock *ProjectLockImpl) Lock(prNumber int) (bool, error) {
 		return false, err
 	}
 
-	if lockAcquired {
+	_, isNoOpLock := projectLock.InternalLock.(*NoOpLock)
+
+	if lockAcquired && !isNoOpLock {
 		comment := "Project " + projectLock.projectId() + " has been locked by PR #" + strconv.Itoa(prNumber)
 		projectLock.CIService.PublishComment(prNumber, comment)
 		println("project " + projectLock.projectId() + " locked successfully. PR # " + strconv.Itoa(prNumber))
@@ -178,6 +195,11 @@ func GetLock() (Lock, error) {
 	awsRegion := strings.ToLower(os.Getenv("AWS_REGION"))
 	awsProfile := strings.ToLower(os.Getenv("AWS_PROFILE"))
 	lockProvider := strings.ToLower(os.Getenv("LOCK_PROVIDER"))
+	disableLocking := strings.ToLower(os.Getenv("DISABLE_LOCKING")) == "true"
+	if disableLocking {
+		log.Println("Using NoOp lock provider.")
+		return &NoOpLock{}, nil
+	}
 	if lockProvider == "" || lockProvider == "aws" {
 		log.Println("Using AWS lock provider.")
 		sess, err := session.NewSessionWithOptions(session.Options{


Test patch:
diff --git a/cmd/digger/main_test.go b/cmd/digger/main_test.go
index e500bbf9..84442006 100644
--- a/cmd/digger/main_test.go
+++ b/cmd/digger/main_test.go
@@ -879,7 +879,7 @@ func TestGitHubNewPullRequestContext(t *testing.T) {
 	impactedProjects, requestedProject, prNumber, err := digger.ProcessGitHubEvent(ghEvent, &diggerConfig, prManager)
 
 	commandsToRunPerProject, _, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, map[string]configuration.Workflow{})
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, context.RepositoryOwner, context.Repository, eventName, prNumber, prManager, lock, planStorage, "")
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, context.RepositoryOwner, context.Repository, eventName, prNumber, prManager, lock, planStorage, "")
 
 	assert.NoError(t, err)
 	if err != nil {
@@ -902,9 +902,9 @@ func TestGitHubNewCommentContext(t *testing.T) {
 	impactedProjects, requestedProject, prNumber, err := digger.ProcessGitHubEvent(ghEvent, &diggerConfig, prManager)
 
 	commandsToRunPerProject, _, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, map[string]configuration.Workflow{})
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, context.RepositoryOwner, context.Repository, eventName, prNumber, prManager, lock, planStorage, "")
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, context.RepositoryOwner, context.Repository, eventName, prNumber, prManager, lock, planStorage, "")
 
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, context.RepositoryOwner, context.Repository, eventName, prNumber, prManager, lock, planStorage, "")
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, context.RepositoryOwner, context.Repository, eventName, prNumber, prManager, lock, planStorage, "")
 
 	assert.NoError(t, err)
 	if err != nil {
diff --git a/pkg/integration/integration_test.go b/pkg/integration/integration_test.go
index 21c61d98..f7596a01 100644
--- a/pkg/integration/integration_test.go
+++ b/pkg/integration/integration_test.go
@@ -40,7 +40,7 @@ func getProjectLockForTests() (error, *utils.ProjectLockImpl) {
 	repoOwner := "diggerhq"
 	repositoryName := "test_dynamodb_lock"
 	ghToken := "token"
-	githubPrService := dg_github.NewGithubPullRequestService(ghToken, repositoryName, repoOwner)
+	githubPrService := dg_github.NewGitHubService(ghToken, repositoryName, repoOwner)
 
 	projectLock := &utils.ProjectLockImpl{
 		InternalLock: &dynamoDbLock,
@@ -381,7 +381,7 @@ func TestHappyPath(t *testing.T) {
 	eventName := parsedNewPullRequestContext.EventName
 	repoOwner := parsedNewPullRequestContext.RepositoryOwner
 	repositoryName := parsedNewPullRequestContext.Repository
-	githubPrService := dg_github.NewGithubPullRequestService(ghToken, repositoryName, repoOwner)
+	githubPrService := dg_github.NewGitHubService(ghToken, repositoryName, repoOwner)
 
 	assert.Equal(t, "pull_request", parsedNewPullRequestContext.EventName)
 
@@ -398,7 +398,7 @@ func TestHappyPath(t *testing.T) {
 		PullRequestNumber: prNumber,
 		ZipManager:        zipManager,
 	}
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock := &utils.ProjectLockImpl{
@@ -425,7 +425,7 @@ func TestHappyPath(t *testing.T) {
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
 	assert.NoError(t, err)
 
 	println("--- digger apply comment ---")
@@ -439,7 +439,7 @@ func TestHappyPath(t *testing.T) {
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock = &utils.ProjectLockImpl{
@@ -463,7 +463,7 @@ func TestHappyPath(t *testing.T) {
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock = &utils.ProjectLockImpl{
@@ -532,7 +532,7 @@ func TestMultiEnvHappyPath(t *testing.T) {
 	eventName := parsedNewPullRequestContext.EventName
 	repoOwner := parsedNewPullRequestContext.RepositoryOwner
 	repositoryName := parsedNewPullRequestContext.Repository
-	githubPrService := dg_github.NewGithubPullRequestService(ghToken, repositoryName, repoOwner)
+	githubPrService := dg_github.NewGitHubService(ghToken, repositoryName, repoOwner)
 
 	assert.Equal(t, "pull_request", parsedNewPullRequestContext.EventName)
 
@@ -550,7 +550,7 @@ func TestMultiEnvHappyPath(t *testing.T) {
 		PullRequestNumber: prNumber,
 		ZipManager:        zipManager,
 	}
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, &dynamoDbLock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, &dynamoDbLock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock := &utils.ProjectLockImpl{
@@ -576,7 +576,7 @@ func TestMultiEnvHappyPath(t *testing.T) {
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, &dynamoDbLock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, &dynamoDbLock, planStorage, dir)
 	assert.NoError(t, err)
 
 	println("--- digger apply comment ---")
@@ -590,7 +590,7 @@ func TestMultiEnvHappyPath(t *testing.T) {
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, &dynamoDbLock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, &dynamoDbLock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock = &utils.ProjectLockImpl{
@@ -614,7 +614,7 @@ func TestMultiEnvHappyPath(t *testing.T) {
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, &dynamoDbLock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, &dynamoDbLock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock = &utils.ProjectLockImpl{
@@ -747,7 +747,7 @@ workflows:
 	eventName := parsedNewPullRequestContext.EventName
 	repoOwner := parsedNewPullRequestContext.RepositoryOwner
 	repositoryName := parsedNewPullRequestContext.Repository
-	githubPrService := dg_github.NewGithubPullRequestService(ghToken, repositoryName, repoOwner)
+	githubPrService := dg_github.NewGitHubService(ghToken, repositoryName, repoOwner)
 
 	assert.Equal(t, "pull_request", parsedNewPullRequestContext.EventName)
 
@@ -765,7 +765,7 @@ workflows:
 		PullRequestNumber: prNumber,
 		ZipManager:        zipManager,
 	}
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock := &utils.ProjectLockImpl{
@@ -792,7 +792,7 @@ workflows:
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
 	assert.NoError(t, err)
 
 	println("--- digger apply comment ---")
@@ -806,7 +806,7 @@ workflows:
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock = &utils.ProjectLockImpl{
@@ -829,7 +829,7 @@ workflows:
 	assert.NoError(t, err)
 	commandsToRunPerProject, _, err = digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, requestedProject, diggerConfig.Workflows)
 	assert.NoError(t, err)
-	_, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
+	_, _, err = digger.RunCommandsPerProject(commandsToRunPerProject, repoOwner, repositoryName, eventName, prNumber, githubPrService, lock, planStorage, dir)
 	assert.NoError(t, err)
 
 	projectLock = &utils.ProjectLockImpl{