Skip to content

Commit 612aa6a

Browse files
authored
Delete the cache after promotion unless --keep-cache is specified (#30)
1 parent ad2c80e commit 612aa6a

File tree

6 files changed

+122
-5
lines changed

6 files changed

+122
-5
lines changed

cmd/services/main.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const (
2424
nameFlag = "commit-name"
2525
emailFlag = "commit-email"
2626
debugFlag = "debug"
27+
keepCacheFlag = "keep-cache"
2728
)
2829

2930
var (
@@ -83,6 +84,12 @@ var (
8384
Value: false,
8485
Required: false,
8586
},
87+
&cli.BoolFlag{
88+
Name: keepCacheFlag,
89+
Usage: "whether to retain the locally cloned repositories in the cache directory",
90+
Value: false,
91+
Required: false,
92+
},
8693
}
8794
)
8895

@@ -113,6 +120,7 @@ func promoteAction(c *cli.Context) error {
113120
service := c.String(serviceFlag)
114121
newBranchName := c.String(branchNameFlag)
115122
debug := c.Bool(debugFlag)
123+
keepCache := c.Bool(keepCacheFlag)
116124

117125
cacheDir, err := homedir.Expand(c.String(cacheDirFlag))
118126
if err != nil {
@@ -123,7 +131,7 @@ func promoteAction(c *cli.Context) error {
123131
if err != nil {
124132
return fmt.Errorf("unable to establish credentials: %w", err)
125133
}
126-
return avancement.New(cacheDir, author, avancement.WithDebug(debug)).Promote(service, fromRepo, toRepo, newBranchName)
134+
return avancement.New(cacheDir, author, avancement.WithDebug(debug)).Promote(service, fromRepo, toRepo, newBranchName, keepCache)
127135
}
128136

129137
func newAuthor(c *cli.Context) (*git.Author, error) {

pkg/avancement/service_manager.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,32 @@ const fromBranch = "master"
6565
//
6666
// It uses a Git cache to checkout the code to, and will copy the environment
6767
// configuration for the `fromURL` to the `toURL` in a named branch.
68-
func (s *ServiceManager) Promote(serviceName, fromURL, toURL, newBranchName string) error {
68+
func (s *ServiceManager) Promote(serviceName, fromURL, toURL, newBranchName string, keepCache bool) error {
69+
var source, destination git.Repo
70+
var reposToDelete []git.Repo
71+
72+
defer func(keepRepos bool, repos *[]git.Repo) {
73+
if !keepRepos {
74+
for _, repo := range *repos {
75+
err := repo.DeleteCachedRepo()
76+
if err != nil {
77+
fmt.Errorf("failed deleting files from cache: %w", err)
78+
}
79+
}
80+
}
81+
}(keepCache, &reposToDelete)
82+
6983
source, err := s.checkoutSourceRepo(fromURL, fromBranch)
7084
if err != nil {
7185
return err
7286
}
73-
destination, err := s.checkoutDestinationRepo(toURL, newBranchName)
87+
reposToDelete = append(reposToDelete, source)
88+
89+
destination, err = s.checkoutDestinationRepo(toURL, newBranchName)
7490
if err != nil {
7591
return fmt.Errorf("failed to checkout repo: %w", err)
7692
}
93+
reposToDelete = append(reposToDelete, destination)
7794

7895
copied, err := git.CopyService(serviceName, source, destination)
7996

pkg/avancement/service_manager_test.go

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ const (
1414
staging = "https://example.com/testing/staging-env"
1515
)
1616

17-
func TestPromoteWithSuccess(t *testing.T) {
17+
func TestPromoteWithSuccessKeepCacheTrue(t *testing.T) {
18+
promoteWithSuccess(t, true)
19+
}
20+
21+
func TestPromoteWithSuccessKeepCacheFalse(t *testing.T) {
22+
promoteWithSuccess(t, false)
23+
}
24+
25+
func promoteWithSuccess(t *testing.T, keepCache bool) {
1826
dstBranch := "test-branch"
1927
author := &git.Author{Name: "Testing User", Email: "[email protected]", Token: "test-token"}
2028
client, _ := fakescm.NewDefault()
@@ -33,7 +41,7 @@ func TestPromoteWithSuccess(t *testing.T) {
3341
}
3442
devRepo.AddFiles("/services/my-service/base/config/myfile.yaml")
3543

36-
err := sm.Promote("my-service", dev, staging, dstBranch)
44+
err := sm.Promote("my-service", dev, staging, dstBranch, keepCache)
3745
if err != nil {
3846
t.Fatal(err)
3947
}
@@ -42,6 +50,14 @@ func TestPromoteWithSuccess(t *testing.T) {
4250
stagingRepo.AssertFileCopiedInBranch(t, dstBranch, "/dev/services/my-service/base/config/myfile.yaml", "/staging/services/my-service/base/config/myfile.yaml")
4351
stagingRepo.AssertCommit(t, dstBranch, defaultCommitMsg, author)
4452
stagingRepo.AssertPush(t, dstBranch)
53+
54+
if keepCache {
55+
stagingRepo.AssertNotDeletedFromCache(t)
56+
devRepo.AssertNotDeletedFromCache(t)
57+
} else {
58+
stagingRepo.AssertDeletedFromCache(t)
59+
devRepo.AssertDeletedFromCache(t)
60+
}
4561
}
4662

4763
func TestAddCredentials(t *testing.T) {
@@ -75,3 +91,36 @@ func mustAddCredentials(t *testing.T, repoURL string, a *git.Author) string {
7591
}
7692
return u
7793
}
94+
95+
func TestPromoteWithCacheDeletionFailure(t *testing.T) {
96+
dstBranch := mock.FAIL_DELETING_REPO_BRANCH
97+
author := &git.Author{Name: "Testing User", Email: "[email protected]", Token: "test-token"}
98+
client, _ := fakescm.NewDefault()
99+
fakeClientFactory := func(s string) *scm.Client {
100+
return client
101+
}
102+
devRepo, stagingRepo := mock.New("/dev", "master"), mock.New("/staging", "master")
103+
repos := map[string]*mock.Repository{
104+
mustAddCredentials(t, dev, author): devRepo,
105+
mustAddCredentials(t, staging, author): stagingRepo,
106+
}
107+
sm := New("tmp", author)
108+
sm.clientFactory = fakeClientFactory
109+
sm.repoFactory = func(url, _ string, _ bool) (git.Repo, error) {
110+
return git.Repo(repos[url]), nil
111+
}
112+
devRepo.AddFiles("/services/my-service/base/config/myfile.yaml")
113+
114+
err := sm.Promote("my-service", dev, staging, dstBranch, false)
115+
if err != nil {
116+
t.Fatal(err)
117+
}
118+
119+
stagingRepo.AssertBranchCreated(t, "master", dstBranch)
120+
stagingRepo.AssertFileCopiedInBranch(t, dstBranch, "/dev/services/my-service/base/config/myfile.yaml", "/staging/services/my-service/base/config/myfile.yaml")
121+
stagingRepo.AssertCommit(t, dstBranch, defaultCommitMsg, author)
122+
stagingRepo.AssertPush(t, dstBranch)
123+
124+
stagingRepo.AssertNotDeletedFromCache(t)
125+
devRepo.AssertDeletedFromCache(t)
126+
}

pkg/git/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ type Repo interface {
2626
StageFiles(filenames ...string) error
2727
Commit(msg string, author *Author) error
2828
Push(branch string) error
29+
DeleteCachedRepo() error
2930
}

pkg/git/mock/mock.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package mock
22

33
import (
4+
"errors"
45
"io"
56
"path"
67
"path/filepath"
@@ -10,6 +11,10 @@ import (
1011
"github.com/rhd-gitops-example/services/pkg/git"
1112
)
1213

14+
/* FAIL_DELETING_REPO_BRANCH is a branch name that when used as a target branch will
15+
cause the the deletion from the cache to fail (in tests only) */
16+
const FAIL_DELETING_REPO_BRANCH = "fail_to_delete_repo"
17+
1318
type Repository struct {
1419
currentBranch string
1520
knownBranches []string
@@ -31,6 +36,9 @@ type Repository struct {
3136

3237
pushedBranches []string
3338
pushErr error
39+
40+
deleted bool
41+
deletedErr error
3442
}
3543

3644
// New creates and returns a new git.Cache implementation that operates entirely
@@ -140,6 +148,17 @@ func (m *Repository) AddFiles(names ...string) {
140148
}
141149
}
142150

151+
// DeleteCachedRepo deletes the repo from the local cache directory
152+
func (m *Repository) DeleteCachedRepo() error {
153+
if m.currentBranch == FAIL_DELETING_REPO_BRANCH {
154+
m.deleted = false
155+
m.deletedErr = errors.New("MOCK FAILURE DELETING REPO MESSAGE")
156+
} else {
157+
m.deleted = true
158+
}
159+
return m.deletedErr
160+
}
161+
143162
// AssertBranchCreated asserts that the named branch was created from the from
144163
// branch, using the `CheckoutAndCreate` implementation.
145164
func (m *Repository) AssertBranchCreated(t *testing.T, from, name string) {
@@ -171,6 +190,20 @@ func (m *Repository) AssertPush(t *testing.T, branch string) {
171190
}
172191
}
173192

193+
// AssertDeletedFromCache asserts that delete was called to remove the local repo
194+
func (m *Repository) AssertDeletedFromCache(t *testing.T) {
195+
if !m.deleted {
196+
t.Fatalf("repo was not deleted from the promotion cache directory")
197+
}
198+
}
199+
200+
// AssertNotDeletedFromCache asserts that delete was called to remove the local repo
201+
func (m *Repository) AssertNotDeletedFromCache(t *testing.T) {
202+
if m.deleted {
203+
t.Fatalf("repo was unexpectedly deleted from the promotion cache directory : %w", m.deletedErr)
204+
}
205+
}
206+
174207
func key(v ...string) string {
175208
return strings.Join(v, ":")
176209
}

pkg/git/repository.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,12 @@ func envFromAuthor(a *Author) []string {
155155
sf("GIT_AUTHOR_NAME", a.Name),
156156
sf("GIT_AUTHOR_EMAIL", a.Email)}
157157
}
158+
159+
// DeleteCachedRepo removes the local clones from the promotion cache
160+
func (r *Repository) DeleteCachedRepo() error {
161+
err := os.RemoveAll(r.LocalPath)
162+
if err != nil {
163+
return fmt.Errorf("failed deleting `%s` : %w", r.LocalPath, err)
164+
}
165+
return nil
166+
}

0 commit comments

Comments
 (0)