Skip to content

Commit 083e486

Browse files
authored
feat: setting to accumulate plans as one comment (#384)
* Introduce a setting to accumulate the plans
1 parent 1cffa32 commit 083e486

File tree

4 files changed

+53
-16
lines changed

4 files changed

+53
-16
lines changed

action.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ inputs:
8686
description: Setup tfenv
8787
required: false
8888
default: 'false'
89+
post-plans-as-one-comment:
90+
description: Post plans as one comment
91+
required: false
92+
default: 'false'
8993
outputs:
9094
output:
9195
value: ${{ steps.digger.outputs.output }}
@@ -186,6 +190,7 @@ runs:
186190
POLICY_CHECK_ENABLED: ${{ inputs.policy-check-enabled == 'true' }}
187191
DIGGER_CLOUD_TOKEN: ${{ inputs.digger-cloud-token }}
188192
DIGGER_CLOUD_HOSTNAME: ${{ inputs.digger-cloud-hostname }}
193+
ACCUMULATE_PLANS: ${{ inputs.post-plans-as-one-comment == 'true' }}
189194
run: |
190195
cd ${{ github.action_path }}
191196
go build -o digger ./cmd/digger
@@ -203,6 +208,7 @@ runs:
203208
POLICY_CHECK_ENABLED: ${{ inputs.policy-check-enabled == 'true' }}
204209
DIGGER_CLOUD_TOKEN: ${{ inputs.digger-cloud-token }}
205210
DIGGER_CLOUD_HOSTNAME: ${{ inputs.digger-cloud-hostname }}
211+
ACCUMULATE_PLANS: ${{ inputs.post-plans-as-one-comment == 'true' }}
206212
id: digger
207213
shell: bash
208214
run: |

pkg/core/execution/execution.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ func (d DiggerExecutor) storedPlanFilePath() string {
4343
return path.Join(d.ProjectNamespace, d.planFileName())
4444
}
4545

46-
func (d DiggerExecutor) Plan() (bool, error) {
46+
func (d DiggerExecutor) Plan() (bool, string, error) {
47+
plan := ""
4748
locked, err := d.ProjectLock.Lock()
4849
if err != nil {
49-
return false, fmt.Errorf("error locking project: %v", err)
50+
return false, "", fmt.Errorf("error locking project: %v", err)
5051
}
5152
log.Printf("Lock result: %t\n", locked)
5253
if locked {
@@ -68,37 +69,35 @@ func (d DiggerExecutor) Plan() (bool, error) {
6869
if step.Action == "init" {
6970
_, _, err := d.TerraformExecutor.Init(step.ExtraArgs, d.StateEnvVars)
7071
if err != nil {
71-
return false, fmt.Errorf("error running init: %v", err)
72+
return false, "", fmt.Errorf("error running init: %v", err)
7273
}
7374
}
7475
if step.Action == "plan" {
7576
planArgs := []string{"-out", d.planFileName()}
7677
planArgs = append(planArgs, step.ExtraArgs...)
7778
isNonEmptyPlan, stdout, stderr, err := d.TerraformExecutor.Plan(planArgs, d.CommandEnvVars)
7879
if err != nil {
79-
return false, fmt.Errorf("error executing plan: %v", err)
80+
return false, "", fmt.Errorf("error executing plan: %v", err)
8081
}
8182
if d.PlanStorage != nil {
8283
planExists, err := d.PlanStorage.PlanExists(d.storedPlanFilePath())
8384
if err != nil {
84-
return false, fmt.Errorf("error checking if plan exists: %v", err)
85+
return false, "", fmt.Errorf("error checking if plan exists: %v", err)
8586
}
8687

8788
if planExists {
8889
err = d.PlanStorage.DeleteStoredPlan(d.storedPlanFilePath())
8990
if err != nil {
90-
return false, fmt.Errorf("error deleting plan: %v", err)
91+
return false, "", fmt.Errorf("error deleting plan: %v", err)
9192
}
9293
}
9394

9495
err = d.PlanStorage.StorePlan(d.localPlanFilePath(), d.storedPlanFilePath())
9596
if err != nil {
96-
return false, fmt.Errorf("error storing plan: %v", err)
97+
return false, "", fmt.Errorf("error storing plan: %v", err)
9798
}
9899
}
99-
plan := cleanupTerraformPlan(isNonEmptyPlan, err, stdout, stderr)
100-
comment := utils.GetTerraformOutputAsCollapsibleComment("Plan for **"+d.ProjectLock.LockId()+"**", plan)
101-
err = d.Reporter.Report(comment)
100+
plan = cleanupTerraformPlan(isNonEmptyPlan, err, stdout, stderr)
102101
if err != nil {
103102
fmt.Printf("error publishing comment: %v", err)
104103
}
@@ -112,13 +111,13 @@ func (d DiggerExecutor) Plan() (bool, error) {
112111
log.Printf("Running %v for **%v**\n", step.Value, d.ProjectLock.LockId())
113112
_, _, err := d.CommandRunner.Run(d.ProjectPath, step.Shell, commands)
114113
if err != nil {
115-
return false, fmt.Errorf("error running command: %v", err)
114+
return false, "", fmt.Errorf("error running command: %v", err)
116115
}
117116
}
118117
}
119-
return true, nil
118+
return true, plan, nil
120119
}
121-
return false, nil
120+
return false, plan, nil
122121
}
123122

124123
func (d DiggerExecutor) Apply() (bool, error) {

pkg/digger/digger.go

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import (
1010
"digger/pkg/core/runners"
1111
"digger/pkg/core/storage"
1212
"digger/pkg/core/terraform"
13+
"digger/pkg/core/utils"
1314
"digger/pkg/locking"
1415
"digger/pkg/usage"
1516
"errors"
1617
"fmt"
1718
"log"
1819
"os"
1920
"path"
21+
"strings"
2022
"time"
2123
)
2224

@@ -56,8 +58,22 @@ func DetectCI() CIName {
5658

5759
}
5860

59-
func RunCommandsPerProject(commandsPerProject []models.ProjectCommand, projectNamespace string, requestedBy string, eventName string, prNumber int, ciService ci.CIService, lock core_locking.Lock, reporter reporting.Reporter, planStorage storage.PlanStorage, policyChecker policy.Checker, workingDir string) (bool, bool, error) {
61+
func RunCommandsPerProject(
62+
commandsPerProject []models.ProjectCommand,
63+
projectNamespace string,
64+
requestedBy string,
65+
eventName string,
66+
prNumber int,
67+
ciService ci.CIService,
68+
lock core_locking.Lock,
69+
reporter reporting.Reporter,
70+
planStorage storage.PlanStorage,
71+
policyChecker policy.Checker,
72+
workingDir string,
73+
) (bool, bool, error) {
74+
accumulatePlans := os.Getenv("ACCUMULATE_PLANS") == "true"
6075
appliesPerProject := make(map[string]bool)
76+
plansToPublish := make([]string, 0)
6177
for _, projectCommands := range commandsPerProject {
6278
for _, command := range projectCommands.Commands {
6379
policyInput := map[string]interface{}{"user": requestedBy, "action": command}
@@ -112,12 +128,21 @@ func RunCommandsPerProject(commandsPerProject []models.ProjectCommand, projectNa
112128
case "digger plan":
113129
usage.SendUsageRecord(requestedBy, eventName, "plan")
114130
ciService.SetStatus(prNumber, "pending", projectCommands.ProjectName+"/plan")
115-
planPerformed, err := diggerExecutor.Plan()
131+
planPerformed, plan, err := diggerExecutor.Plan()
116132
if err != nil {
117133
log.Printf("Failed to run digger plan command. %v", err)
118134
ciService.SetStatus(prNumber, "failure", projectCommands.ProjectName+"/plan")
119135
return false, false, fmt.Errorf("failed to run digger plan command. %v", err)
120136
} else if planPerformed {
137+
comment := utils.GetTerraformOutputAsCollapsibleComment("Plan for **"+projectLock.LockId()+"**", plan)
138+
if accumulatePlans {
139+
plansToPublish = append(plansToPublish, comment)
140+
} else {
141+
err = reporter.Report(comment)
142+
if err != nil {
143+
log.Printf("Failed to report plan. %v", err)
144+
}
145+
}
121146
ciService.SetStatus(prNumber, "success", projectCommands.ProjectName+"/plan")
122147
}
123148
case "digger apply":
@@ -164,6 +189,13 @@ func RunCommandsPerProject(commandsPerProject []models.ProjectCommand, projectNa
164189
}
165190
}
166191

192+
if len(plansToPublish) > 0 {
193+
err := reporter.Report(strings.Join(plansToPublish, "\n"))
194+
if err != nil {
195+
log.Printf("Failed to report plans. %v", err)
196+
}
197+
}
198+
167199
allAppliesSuccess := true
168200
for _, success := range appliesPerProject {
169201
if !success {

pkg/digger/digger_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ func TestCorrectCommandExecutionWhenPlanning(t *testing.T) {
241241

242242
commandStrings := allCommandsInOrderWithParams(terraformExecutor, commandRunner, prManager, lock, planStorage)
243243

244-
assert.Equal(t, []string{"Lock ", "Init ", "Plan -out #.tfplan", "PlanExists #.tfplan", "StorePlan #.tfplan", "LockId ", "PublishComment 1 <details>\n <summary>Plan for ****</summary>\n\n ```terraform\n\n ```\n</details>", "LockId ", "Run echo"}, commandStrings)
244+
assert.Equal(t, []string{"Lock ", "Init ", "Plan -out #.tfplan", "PlanExists #.tfplan", "StorePlan #.tfplan", "LockId ", "Run echo"}, commandStrings)
245245
}
246246

247247
func allCommandsInOrderWithParams(terraformExecutor *MockTerraformExecutor, commandRunner *MockCommandRunner, prManager *MockPRManager, lock *MockProjectLock, planStorage *MockPlanStorage) []string {

0 commit comments

Comments
 (0)