diff --git a/.gitignore b/.gitignore
index bcc054848..e8ae7727e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
venv/
**/__pycache__/
__azurite*
+digger
diff --git a/pkg/digger/digger.go b/pkg/digger/digger.go
index c14bb7cf3..a9dca5387 100644
--- a/pkg/digger/digger.go
+++ b/pkg/digger/digger.go
@@ -73,16 +73,19 @@ func RunCommandsPerProject(commandsPerProject []ProjectCommand, repoOwner string
}
var terraformExecutor terraform.TerraformExecutor
-
+ projectPath := path.Join(workingDir, projectCommands.ProjectDir)
if projectCommands.Terragrunt {
- terraformExecutor = terraform.Terragrunt{WorkingDir: path.Join(workingDir, projectCommands.ProjectDir)}
+ terraformExecutor = terraform.Terragrunt{WorkingDir: projectPath}
} else {
- terraformExecutor = terraform.Terraform{WorkingDir: path.Join(workingDir, projectCommands.ProjectDir), Workspace: projectCommands.ProjectWorkspace}
+ terraformExecutor = terraform.Terraform{WorkingDir: projectPath, Workspace: projectCommands.ProjectWorkspace}
}
commandRunner := CommandRunner{}
diggerExecutor := DiggerExecutor{
+ repoOwner,
+ repoName,
projectCommands.ProjectName,
+ projectPath,
projectCommands.StateEnvVars,
projectCommands.CommandEnvVars,
projectCommands.ApplyStage,
@@ -338,7 +341,10 @@ func parseProjectName(comment string) string {
}
type DiggerExecutor struct {
+ repoOwner string
+ repoName string
projectName string
+ projectPath string
stateEnvVars map[string]string
commandEnvVars map[string]string
applyStage *configuration.Stage
@@ -378,11 +384,18 @@ func (c CommandRunner) Run(command string) (string, string, error) {
}
func (d DiggerExecutor) planFileName() string {
- return d.projectName + ".tfplan"
+ return d.repoName + "#" + d.projectName + ".tfplan"
}
-func (d DiggerExecutor) Plan(prNumber int) error {
+func (d DiggerExecutor) localPlanFilePath() string {
+ return path.Join(d.projectPath, d.planFileName())
+}
+
+func (d DiggerExecutor) storedPlanFilePath() string {
+ return path.Join(d.repoOwner, d.planFileName())
+}
+func (d DiggerExecutor) Plan(prNumber int) error {
res, err := d.lock.Lock(prNumber)
if err != nil {
return fmt.Errorf("error locking project: %v", err)
@@ -418,7 +431,7 @@ func (d DiggerExecutor) Plan(prNumber int) error {
return fmt.Errorf("error executing plan: %v", err)
}
if d.planStorage != nil {
- err = d.planStorage.StorePlan(d.planFileName())
+ err = d.planStorage.StorePlan(d.localPlanFilePath(), d.storedPlanFilePath())
if err != nil {
return fmt.Errorf("error storing plan: %v", err)
}
@@ -443,7 +456,7 @@ func (d DiggerExecutor) Apply(prNumber int) error {
var plansFilename *string
if d.planStorage != nil {
var err error
- plansFilename, err = d.planStorage.RetrievePlan(d.planFileName())
+ plansFilename, err = d.planStorage.RetrievePlan(d.localPlanFilePath(), d.storedPlanFilePath())
if err != nil {
return fmt.Errorf("error retrieving plan: %v", err)
}
@@ -509,6 +522,10 @@ func (d DiggerExecutor) Unlock(prNumber int) error {
if err != nil {
return fmt.Errorf("failed to aquire lock: %s, %v", d.lock.LockId(), err)
}
+ err = d.planStorage.DeleteStoredPlan(d.storedPlanFilePath())
+ if err != nil {
+ return fmt.Errorf("failed to delete stored plan file '%v': %v", d.storedPlanFilePath(), err)
+ }
return nil
}
diff --git a/pkg/digger/digger_test.go b/pkg/digger/digger_test.go
index 9f33753cc..564516034 100644
--- a/pkg/digger/digger_test.go
+++ b/pkg/digger/digger_test.go
@@ -128,16 +128,21 @@ type MockPlanStorage struct {
Commands []RunInfo
}
-func (m *MockPlanStorage) StorePlan(planFileName string) error {
- m.Commands = append(m.Commands, RunInfo{"StorePlan", planFileName, time.Now()})
+func (m *MockPlanStorage) StorePlan(localPlanFilePath string, storedPlanFilePath string) error {
+ m.Commands = append(m.Commands, RunInfo{"StorePlan", localPlanFilePath, time.Now()})
return nil
}
-func (m *MockPlanStorage) RetrievePlan(planFileName string) (*string, error) {
- m.Commands = append(m.Commands, RunInfo{"RetrievePlan", planFileName, time.Now()})
+func (m *MockPlanStorage) RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error) {
+ m.Commands = append(m.Commands, RunInfo{"RetrievePlan", localPlanFilePath, time.Now()})
return nil, nil
}
+func (m *MockPlanStorage) DeleteStoredPlan(storedPlanFilePath string) error {
+ m.Commands = append(m.Commands, RunInfo{"DeleteStoredPlan", storedPlanFilePath, time.Now()})
+ return nil
+}
+
func TestCorrectCommandExecutionWhenApplying(t *testing.T) {
commandRunner := &MockCommandRunner{}
@@ -177,7 +182,7 @@ func TestCorrectCommandExecutionWhenApplying(t *testing.T) {
commandStrings := allCommandsInOrderWithParams(terraformExecutor, commandRunner, prManager, lock, planStorage)
- assert.Equal(t, []string{"RetrievePlan .tfplan", "IsMergeable 1", "Lock 1", "Init ", "Apply ", "LockId ", "PublishComment 1 \n Apply for ****
\n\n ```terraform\n\n ```\n ", "Run echo", "LockId "}, commandStrings)
+ assert.Equal(t, []string{"RetrievePlan #.tfplan", "IsMergeable 1", "Lock 1", "Init ", "Apply ", "LockId ", "PublishComment 1 \n Apply for ****
\n\n ```terraform\n\n ```\n ", "Run echo", "LockId "}, commandStrings)
}
func TestCorrectCommandExecutionWhenPlanning(t *testing.T) {
@@ -219,7 +224,7 @@ func TestCorrectCommandExecutionWhenPlanning(t *testing.T) {
commandStrings := allCommandsInOrderWithParams(terraformExecutor, commandRunner, prManager, lock, planStorage)
- assert.Equal(t, []string{"Lock 1", "Init ", "Plan -out .tfplan", "StorePlan .tfplan", "LockId ", "PublishComment 1 \n Plan for ****
\n\n ```terraform\n\n ```\n ", "Run echo", "LockId "}, commandStrings)
+ assert.Equal(t, []string{"Lock 1", "Init ", "Plan -out #.tfplan", "StorePlan #.tfplan", "LockId ", "PublishComment 1 \n Plan for ****
\n\n ```terraform\n\n ```\n ", "Run echo", "LockId "}, commandStrings)
}
func allCommandsInOrderWithParams(terraformExecutor *MockTerraformExecutor, commandRunner *MockCommandRunner, prManager *MockPRManager, lock *MockProjectLock, planStorage *MockPlanStorage) []string {
diff --git a/pkg/utils/mocks.go b/pkg/utils/mocks.go
index 020ea06d9..4f986c48a 100644
--- a/pkg/utils/mocks.go
+++ b/pkg/utils/mocks.go
@@ -77,10 +77,14 @@ func (t MockPullRequestManager) IsClosed(prNumber int) (bool, error) {
type MockPlanStorage struct {
}
-func (t MockPlanStorage) StorePlan(planfile string) error {
+func (t MockPlanStorage) StorePlan(localPlanFilePath string, storedPlanFilePath string) error {
return nil
}
-func (t MockPlanStorage) RetrievePlan(planfile string) (*string, error) {
+func (t MockPlanStorage) RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error) {
return nil, nil
}
+
+func (t MockPlanStorage) DeleteStoredPlan(storedPlanFilePath string) error {
+ return nil
+}
diff --git a/pkg/utils/plan_storage.go b/pkg/utils/plan_storage.go
index 1ed83218d..a71e500db 100644
--- a/pkg/utils/plan_storage.go
+++ b/pkg/utils/plan_storage.go
@@ -14,8 +14,9 @@ import (
)
type PlanStorage interface {
- StorePlan(planFileName string) error
- RetrievePlan(planFileName string) (*string, error)
+ StorePlan(localPlanFilePath string, storedPlanFilePath string) error
+ RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error)
+ DeleteStoredPlan(storedPlanFilePath string) error
}
type PlanStorageGcp struct {
@@ -32,14 +33,14 @@ type GithubPlanStorage struct {
ZipManager Zipper
}
-func (psg *PlanStorageGcp) StorePlan(planFileName string) error {
- file, err := os.Open(planFileName)
+func (psg *PlanStorageGcp) StorePlan(localPlanFilePath string, storedPlanFilePath string) error {
+ file, err := os.Open(localPlanFilePath)
if err != nil {
return fmt.Errorf("unable to open file: %v", err)
}
defer file.Close()
- obj := psg.Bucket.Object(planFileName)
+ obj := psg.Bucket.Object(storedPlanFilePath)
wc := obj.NewWriter(psg.Context)
if _, err = io.Copy(wc, file); err != nil {
@@ -54,15 +55,15 @@ func (psg *PlanStorageGcp) StorePlan(planFileName string) error {
return nil
}
-func (psg *PlanStorageGcp) RetrievePlan(planFileName string) (*string, error) {
- obj := psg.Bucket.Object(planFileName)
+func (psg *PlanStorageGcp) RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error) {
+ obj := psg.Bucket.Object(storedPlanFilePath)
rc, err := obj.NewReader(psg.Context)
if err != nil {
return nil, fmt.Errorf("unable to read data from bucket: %v", err)
}
defer rc.Close()
- file, err := os.Create(planFileName)
+ file, err := os.Create(localPlanFilePath)
if err != nil {
return nil, fmt.Errorf("unable to create file: %v", err)
}
@@ -72,15 +73,25 @@ func (psg *PlanStorageGcp) RetrievePlan(planFileName string) (*string, error) {
return nil, fmt.Errorf("unable to write data to file: %v", err)
}
- return &planFileName, nil
+ return &localPlanFilePath, nil
}
-func (gps *GithubPlanStorage) StorePlan(planFileName string) error {
- _ = fmt.Sprintf("Skipping storing plan %s. It should be achieved using actions/upload-artifact@v3", planFileName)
+func (psg *PlanStorageGcp) DeleteStoredPlan(storedPlanFilePath string) error {
+ obj := psg.Bucket.Object(storedPlanFilePath)
+ err := obj.Delete(psg.Context)
+
+ if err != nil {
+ return fmt.Errorf("unable to delete file '%v' from bucket: %v", storedPlanFilePath, err)
+ }
return nil
}
-func (gps *GithubPlanStorage) RetrievePlan(planFileName string) (*string, error) {
+func (gps *GithubPlanStorage) StorePlan(localPlanFilePath string, storedPlanFilePath string) error {
+ _ = fmt.Sprintf("Skipping storing plan %s. It should be achieved using actions/upload-artifact@v3", localPlanFilePath)
+ return nil
+}
+
+func (gps *GithubPlanStorage) RetrievePlan(localPlanFilePath string, storedPlanFilePath string) (*string, error) {
plansFilename, err := gps.DownloadLatestPlans()
if err != nil {
@@ -91,7 +102,7 @@ func (gps *GithubPlanStorage) RetrievePlan(planFileName string) (*string, error)
return nil, fmt.Errorf("no plans found for this PR")
}
- plansFilename, err = gps.ZipManager.GetFileFromZip(plansFilename, planFileName)
+ plansFilename, err = gps.ZipManager.GetFileFromZip(plansFilename, storedPlanFilePath)
if err != nil {
return nil, fmt.Errorf("error extracting plan: %v", err)
@@ -99,6 +110,10 @@ func (gps *GithubPlanStorage) RetrievePlan(planFileName string) (*string, error)
return &plansFilename, nil
}
+func (gps *GithubPlanStorage) DeleteStoredPlan(storedPlanFilePath string) error {
+ return nil
+}
+
func (gps *GithubPlanStorage) DownloadLatestPlans() (string, error) {
artifacts, _, err := gps.Client.Actions.ListArtifacts(context.Background(), gps.Owner, gps.RepoName, &github.ListOptions{
PerPage: 100,