Skip to content

Commit 62215d1

Browse files
authored
feat: support workflows and extra args to terraform executions (#91)
1 parent 04bf07b commit 62215d1

File tree

8 files changed

+284
-130
lines changed

8 files changed

+284
-130
lines changed

cmd/digger/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func main() {
6767
githubPrService.PublishComment(prNumber, reply)
6868
}
6969

70-
commandsToRunPerProject, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects)
70+
commandsToRunPerProject, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, diggerConfig.Workflows)
7171
if err != nil {
7272
reportErrorAndExit(repoOwner, fmt.Sprintf("Failed to convert GitHub event to commands. %s", err), 7)
7373
}

cmd/digger/main_test.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ func TestGitHubNewPullRequestContext(t *testing.T) {
873873
lock := &utils.MockLock{}
874874
prManager := &utils.MockPullRequestManager{ChangedFiles: []string{"dev/test.tf"}}
875875
impactedProjects, prNumber, err := digger.ProcessGitHubEvent(ghEvent, &diggerConfig, prManager)
876-
commandsToRunPerProject, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects)
876+
commandsToRunPerProject, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, map[string]digger.Workflow{})
877877
err = digger.RunCommandsPerProject(commandsToRunPerProject, context.RepositoryOwner, context.Repository, eventName, prNumber, &diggerConfig, prManager, lock, "")
878878
assert.NoError(t, err)
879879
if err != nil {
@@ -893,7 +893,7 @@ func TestGitHubNewCommentContext(t *testing.T) {
893893
lock := &utils.MockLock{}
894894
prManager := &utils.MockPullRequestManager{ChangedFiles: []string{"dev/test.tf"}}
895895
impactedProjects, prNumber, err := digger.ProcessGitHubEvent(ghEvent, &diggerConfig, prManager)
896-
commandsToRunPerProject, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects)
896+
commandsToRunPerProject, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, map[string]digger.Workflow{})
897897
err = digger.RunCommandsPerProject(commandsToRunPerProject, context.RepositoryOwner, context.Repository, eventName, prNumber, &diggerConfig, prManager, lock, "")
898898
assert.NoError(t, err)
899899
if err != nil {
@@ -914,17 +914,40 @@ func TestGitHubNewPullRequestInMultiEnvProjectContext(t *testing.T) {
914914
assert.NoError(t, err)
915915
ghEvent := context.Event
916916
pullRequestNumber := 11
917-
// digger config
918-
dev := digger.Project{Name: "dev", Dir: "dev", WorkflowConfiguration: digger.WorkflowConfiguration{
919-
OnPullRequestPushed: []string{"digger plan"},
920-
OnPullRequestClosed: []string{"digger unlock"},
921-
OnCommitToDefault: []string{"digger apply"},
922-
}}
923-
prod := digger.Project{Name: "prod", Dir: "prod", WorkflowConfiguration: digger.WorkflowConfiguration{
924-
OnPullRequestPushed: []string{"digger plan"},
925-
OnPullRequestClosed: []string{"digger unlock"},
926-
OnCommitToDefault: []string{"digger apply"},
927-
}}
917+
dev := digger.Project{Name: "dev", Dir: "dev", Workflow: "dev"}
918+
prod := digger.Project{Name: "prod", Dir: "prod", Workflow: "prod"}
919+
workflows := map[string]digger.Workflow{
920+
"dev": {
921+
Plan: &digger.Stage{Steps: []digger.Step{
922+
{Action: "init", ExtraArgs: []string{}},
923+
{Action: "plan", ExtraArgs: []string{"-var-file=dev.tfvars"}},
924+
}},
925+
Apply: &digger.Stage{Steps: []digger.Step{
926+
{Action: "init", ExtraArgs: []string{}},
927+
{Action: "apply", ExtraArgs: []string{"-var-file=dev.tfvars"}},
928+
}},
929+
Configuration: &digger.WorkflowConfiguration{
930+
OnPullRequestPushed: []string{"digger plan"},
931+
OnPullRequestClosed: []string{"digger unlock"},
932+
OnCommitToDefault: []string{"digger apply"},
933+
},
934+
},
935+
"prod": {
936+
Plan: &digger.Stage{Steps: []digger.Step{
937+
{Action: "init", ExtraArgs: []string{}},
938+
{Action: "plan", ExtraArgs: []string{"-var-file=dev.tfvars"}},
939+
}},
940+
Apply: &digger.Stage{Steps: []digger.Step{
941+
{Action: "init", ExtraArgs: []string{}},
942+
{Action: "apply", ExtraArgs: []string{"-var-file=dev.tfvars"}},
943+
}},
944+
Configuration: &digger.WorkflowConfiguration{
945+
OnPullRequestPushed: []string{"digger plan"},
946+
OnPullRequestClosed: []string{"digger unlock"},
947+
OnCommitToDefault: []string{"digger apply"},
948+
},
949+
},
950+
}
928951
projects := []digger.Project{dev, prod}
929952
diggerConfig := digger.DiggerConfig{Projects: projects}
930953

@@ -933,7 +956,7 @@ func TestGitHubNewPullRequestInMultiEnvProjectContext(t *testing.T) {
933956
lock := &utils.MockLock{}
934957
impactedProjects, prNumber, err := digger.ProcessGitHubEvent(ghEvent, &diggerConfig, prManager)
935958
assert.NoError(t, err)
936-
commandsToRunPerProject, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects)
959+
commandsToRunPerProject, err := digger.ConvertGithubEventToCommands(ghEvent, impactedProjects, workflows)
937960
spew.Dump(lock.MapLock)
938961
assert.Equal(t, pullRequestNumber, prNumber)
939962
assert.Equal(t, 1, len(commandsToRunPerProject))

pkg/digger/digger.go

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ func RunCommandsPerProject(commandsPerProject []ProjectCommand, repoOwner string
6666
projectCommands.ProjectDir,
6767
repoName,
6868
projectCommands.Terragrunt,
69+
projectCommands.ApplyStage,
70+
projectCommands.PlanStage,
6971
prManager,
7072
projectLock,
7173
diggerConfig,
@@ -108,38 +110,50 @@ type ProjectCommand struct {
108110
ProjectWorkspace string
109111
Terragrunt bool
110112
Commands []string
113+
ApplyStage Stage
114+
PlanStage Stage
111115
}
112116

113-
func ConvertGithubEventToCommands(event models.Event, impactedProjects []Project) ([]ProjectCommand, error) {
117+
func ConvertGithubEventToCommands(event models.Event, impactedProjects []Project, workflows map[string]Workflow) ([]ProjectCommand, error) {
114118
commandsPerProject := make([]ProjectCommand, 0)
115119

116120
switch event.(type) {
117121
case models.PullRequestEvent:
118122
event := event.(models.PullRequestEvent)
119123
for _, project := range impactedProjects {
124+
workflow, ok := workflows[project.Workflow]
125+
if !ok {
126+
workflow = *defaultWorkflow()
127+
}
120128
if event.Action == "closed" && event.PullRequest.Merged && event.PullRequest.Base.Ref == event.Repository.DefaultBranch {
121129
commandsPerProject = append(commandsPerProject, ProjectCommand{
122130
ProjectName: project.Name,
123131
ProjectDir: project.Dir,
124132
ProjectWorkspace: project.Workspace,
125133
Terragrunt: project.Terragrunt,
126-
Commands: project.WorkflowConfiguration.OnCommitToDefault,
134+
Commands: workflow.Configuration.OnCommitToDefault,
135+
ApplyStage: *workflow.Apply,
136+
PlanStage: *workflow.Plan,
127137
})
128138
} else if event.Action == "opened" || event.Action == "reopened" || event.Action == "synchronize" {
129139
commandsPerProject = append(commandsPerProject, ProjectCommand{
130140
ProjectName: project.Name,
131141
ProjectDir: project.Dir,
132142
ProjectWorkspace: project.Workspace,
133143
Terragrunt: project.Terragrunt,
134-
Commands: project.WorkflowConfiguration.OnPullRequestPushed,
144+
Commands: workflow.Configuration.OnPullRequestPushed,
145+
ApplyStage: *workflow.Apply,
146+
PlanStage: *workflow.Plan,
135147
})
136148
} else if event.Action == "closed" {
137149
commandsPerProject = append(commandsPerProject, ProjectCommand{
138150
ProjectName: project.Name,
139151
ProjectDir: project.Dir,
140152
ProjectWorkspace: project.Workspace,
141153
Terragrunt: project.Terragrunt,
142-
Commands: project.WorkflowConfiguration.OnPullRequestClosed,
154+
Commands: workflow.Configuration.OnPullRequestPushed,
155+
ApplyStage: *workflow.Apply,
156+
PlanStage: *workflow.Plan,
143157
})
144158
}
145159
}
@@ -151,6 +165,10 @@ func ConvertGithubEventToCommands(event models.Event, impactedProjects []Project
151165
for _, command := range supportedCommands {
152166
if strings.Contains(event.Comment.Body, command) {
153167
for _, project := range impactedProjects {
168+
workflow, ok := workflows[project.Workflow]
169+
if !ok {
170+
workflow = *defaultWorkflow()
171+
}
154172
workspace := project.Workspace
155173
workspaceOverride, err := parseWorkspace(event.Comment.Body)
156174
if err != nil {
@@ -165,6 +183,8 @@ func ConvertGithubEventToCommands(event models.Event, impactedProjects []Project
165183
ProjectWorkspace: workspace,
166184
Terragrunt: project.Terragrunt,
167185
Commands: []string{command},
186+
ApplyStage: *workflow.Apply,
187+
PlanStage: *workflow.Plan,
168188
})
169189
}
170190
}
@@ -211,6 +231,8 @@ type DiggerExecutor struct {
211231
projectDir string
212232
repoName string
213233
terragrunt bool
234+
applyStage Stage
235+
planStage Stage
214236
prManager github.PullRequestManager
215237
lock utils.ProjectLock
216238
configDigger *DiggerConfig
@@ -235,7 +257,18 @@ func (d DiggerExecutor) Plan(prNumber int) {
235257
log.Fatalf("Error locking project: %v", err)
236258
}
237259
if res {
238-
isNonEmptyPlan, stdout, stderr, err := terraformExecutor.Plan()
260+
var initArgs []string
261+
var planArgs []string
262+
263+
for _, step := range d.planStage.Steps {
264+
if step.Action == "init" {
265+
initArgs = append(initArgs, step.ExtraArgs...)
266+
}
267+
if step.Action == "plan" {
268+
planArgs = append(planArgs, step.ExtraArgs...)
269+
}
270+
}
271+
isNonEmptyPlan, stdout, stderr, err := terraformExecutor.Plan(initArgs, planArgs)
239272

240273
if err != nil {
241274
log.Fatalf("Error executing plan: %v", err)
@@ -257,7 +290,18 @@ func (d DiggerExecutor) Apply(prNumber int) {
257290
}
258291

259292
if res, _ := d.lock.Lock(d.LockId(), prNumber); res {
260-
stdout, stderr, err := terraformExecutor.Apply()
293+
var initArgs []string
294+
var applyArgs []string
295+
296+
for _, step := range d.applyStage.Steps {
297+
if step.Action == "init" {
298+
initArgs = append(initArgs, step.ExtraArgs...)
299+
}
300+
if step.Action == "apply" {
301+
applyArgs = append(applyArgs, step.ExtraArgs...)
302+
}
303+
}
304+
stdout, stderr, err := terraformExecutor.Apply(initArgs, applyArgs)
261305
applyOutput := cleanupTerraformApply(true, err, stdout, stderr)
262306
comment := "Apply for **" + d.LockId() + "**\n" + applyOutput
263307
d.prManager.PublishComment(prNumber, comment)
@@ -267,7 +311,7 @@ func (d DiggerExecutor) Apply(prNumber int) {
267311
fmt.Errorf("error unlocking project: %v", err)
268312
}
269313
} else {
270-
314+
271315
d.prManager.PublishComment(prNumber, "Error during applying. Project lock will persist")
272316
}
273317
}
@@ -348,3 +392,33 @@ func CheckIfHelpComment(event models.Event) bool {
348392
}
349393
return false
350394
}
395+
396+
func defaultWorkflow() *Workflow {
397+
return &Workflow{
398+
Configuration: &WorkflowConfiguration{
399+
OnCommitToDefault: []string{"digger unlock"},
400+
OnPullRequestPushed: []string{"digger plan"},
401+
OnPullRequestClosed: []string{"digger unlock"},
402+
},
403+
Plan: &Stage{
404+
Steps: []Step{
405+
{
406+
Action: "init", ExtraArgs: []string{},
407+
},
408+
{
409+
Action: "plan", ExtraArgs: []string{},
410+
},
411+
},
412+
},
413+
Apply: &Stage{
414+
Steps: []Step{
415+
{
416+
Action: "init", ExtraArgs: []string{},
417+
},
418+
{
419+
Action: "apply", ExtraArgs: []string{},
420+
},
421+
},
422+
},
423+
}
424+
}

0 commit comments

Comments
 (0)