Skip to content

Commit 9c67baa

Browse files
committed
controllers: implement checkout strategies
1 parent 40b1369 commit 9c67baa

File tree

2 files changed

+89
-187
lines changed

2 files changed

+89
-187
lines changed

controllers/gitrepository_controller.go

Lines changed: 12 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ import (
2222
"io/ioutil"
2323
"os"
2424

25-
"github.com/blang/semver"
26-
"github.com/go-git/go-git/v5"
27-
"github.com/go-git/go-git/v5/plumbing"
2825
"github.com/go-git/go-git/v5/plumbing/object"
2926
"github.com/go-git/go-git/v5/plumbing/transport"
3027
"github.com/go-logr/logr"
@@ -122,36 +119,18 @@ func (r *GitRepositoryReconciler) SetupWithManagerAndOptions(mgr ctrl.Manager, o
122119
}
123120

124121
func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.GitRepository) (sourcev1.GitRepository, error) {
125-
// set defaults: master branch, no tags fetching, max two commits
126-
branch := "master"
127-
revision := ""
128-
tagMode := git.NoTags
129-
depth := 2
130-
131-
// determine ref
132-
refName := plumbing.NewBranchReferenceName(branch)
133-
134-
if repository.Spec.Reference != nil {
135-
if repository.Spec.Reference.Branch != "" {
136-
branch = repository.Spec.Reference.Branch
137-
refName = plumbing.NewBranchReferenceName(branch)
138-
}
139-
if repository.Spec.Reference.Commit != "" {
140-
depth = 0
141-
} else {
142-
if repository.Spec.Reference.Tag != "" {
143-
refName = plumbing.NewTagReferenceName(repository.Spec.Reference.Tag)
144-
}
145-
if repository.Spec.Reference.SemVer != "" {
146-
tagMode = git.AllTags
147-
}
148-
}
122+
// create tmp dir for the Git clone
123+
tmpGit, err := ioutil.TempDir("", repository.Name)
124+
if err != nil {
125+
err = fmt.Errorf("tmp dir error: %w", err)
126+
return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
149127
}
128+
defer os.RemoveAll(tmpGit)
150129

151130
// determine auth method
152-
strategy := intgit.AuthSecretStrategyForURL(repository.Spec.URL)
153131
var auth transport.AuthMethod
154-
if repository.Spec.SecretRef != nil {
132+
authStrategy := intgit.AuthSecretStrategyForURL(repository.Spec.URL)
133+
if repository.Spec.SecretRef != nil && authStrategy != nil {
155134
name := types.NamespacedName{
156135
Namespace: repository.GetNamespace(),
157136
Name: repository.Spec.SecretRef.Name,
@@ -164,124 +143,16 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
164143
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
165144
}
166145

167-
auth, err = strategy.Method(secret)
146+
auth, err = authStrategy.Method(secret)
168147
if err != nil {
169148
err = fmt.Errorf("auth error: %w", err)
170149
return sourcev1.GitRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
171150
}
172151
}
173152

174-
// create tmp dir for the Git clone
175-
tmpGit, err := ioutil.TempDir("", repository.Name)
176-
if err != nil {
177-
err = fmt.Errorf("tmp dir error: %w", err)
178-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
179-
}
180-
defer os.RemoveAll(tmpGit)
181-
182-
// clone to tmp
183-
gitCtx, cancel := context.WithTimeout(ctx, repository.GetTimeout())
184-
repo, err := git.PlainCloneContext(gitCtx, tmpGit, false, &git.CloneOptions{
185-
URL: repository.Spec.URL,
186-
Auth: auth,
187-
RemoteName: "origin",
188-
ReferenceName: refName,
189-
SingleBranch: true,
190-
NoCheckout: false,
191-
Depth: depth,
192-
RecurseSubmodules: 0,
193-
Progress: nil,
194-
Tags: tagMode,
195-
})
196-
cancel()
197-
if err != nil {
198-
err = fmt.Errorf("git clone error: %w", err)
199-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
200-
}
201-
202-
// checkout commit or tag
203-
if repository.Spec.Reference != nil {
204-
if commit := repository.Spec.Reference.Commit; commit != "" {
205-
w, err := repo.Worktree()
206-
if err != nil {
207-
err = fmt.Errorf("git worktree error: %w", err)
208-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
209-
}
210-
211-
err = w.Checkout(&git.CheckoutOptions{
212-
Hash: plumbing.NewHash(commit),
213-
Force: true,
214-
})
215-
if err != nil {
216-
err = fmt.Errorf("git checkout '%s' for '%s' error: %w", commit, branch, err)
217-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
218-
}
219-
} else if exp := repository.Spec.Reference.SemVer; exp != "" {
220-
rng, err := semver.ParseRange(exp)
221-
if err != nil {
222-
err = fmt.Errorf("semver parse range error: %w", err)
223-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
224-
}
225-
226-
repoTags, err := repo.Tags()
227-
if err != nil {
228-
err = fmt.Errorf("git list tags error: %w", err)
229-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
230-
}
231-
232-
tags := make(map[string]string)
233-
_ = repoTags.ForEach(func(t *plumbing.Reference) error {
234-
tags[t.Name().Short()] = t.Strings()[1]
235-
return nil
236-
})
237-
238-
svTags := make(map[string]string)
239-
var svers []semver.Version
240-
for tag, _ := range tags {
241-
v, _ := semver.ParseTolerant(tag)
242-
if rng(v) {
243-
svers = append(svers, v)
244-
svTags[v.String()] = tag
245-
}
246-
}
247-
248-
if len(svers) > 0 {
249-
semver.Sort(svers)
250-
v := svers[len(svers)-1]
251-
t := svTags[v.String()]
252-
commit := tags[t]
253-
revision = fmt.Sprintf("%s/%s", t, commit)
254-
255-
w, err := repo.Worktree()
256-
if err != nil {
257-
err = fmt.Errorf("git worktree error: %w", err)
258-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
259-
}
260-
261-
err = w.Checkout(&git.CheckoutOptions{
262-
Hash: plumbing.NewHash(commit),
263-
})
264-
if err != nil {
265-
err = fmt.Errorf("git checkout error: %w", err)
266-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
267-
}
268-
} else {
269-
err = fmt.Errorf("no match found for semver: %s", repository.Spec.Reference.SemVer)
270-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
271-
}
272-
}
273-
}
274-
275-
// read commit hash
276-
ref, err := repo.Head()
153+
checkoutStrategy := intgit.CheckoutStrategyForRef(repository.Spec.Reference)
154+
commit, revision, err := checkoutStrategy.Checkout(ctx, tmpGit, repository.Spec.URL, auth)
277155
if err != nil {
278-
err = fmt.Errorf("git resolve HEAD error: %w", err)
279-
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
280-
}
281-
282-
commit, err := repo.CommitObject(ref.Hash())
283-
if err != nil {
284-
err = fmt.Errorf("git resolve HEAD error: %w", err)
285156
return sourcev1.GitRepositoryNotReady(repository, sourcev1.GitOperationFailedReason, err.Error()), err
286157
}
287158

@@ -296,15 +167,8 @@ func (r *GitRepositoryReconciler) sync(ctx context.Context, repository sourcev1.
296167
}
297168
}
298169

299-
if revision == "" {
300-
revision = fmt.Sprintf("%s/%s", branch, ref.Hash().String())
301-
if repository.Spec.Reference != nil && repository.Spec.Reference.Tag != "" {
302-
revision = fmt.Sprintf("%s/%s", repository.Spec.Reference.Tag, ref.Hash().String())
303-
}
304-
}
305-
306170
artifact := r.Storage.ArtifactFor(repository.Kind, repository.ObjectMeta.GetObjectMeta(),
307-
fmt.Sprintf("%s.tar.gz", ref.Hash().String()), revision)
171+
fmt.Sprintf("%s.tar.gz", commit.Hash.String()), revision)
308172

309173
// create artifact dir
310174
err = r.Storage.MkdirAll(artifact)

0 commit comments

Comments
 (0)