From 77465f0895397c8165ba00aa8f13e0ce47e0fce2 Mon Sep 17 00:00:00 2001 From: alexandresavicki Date: Thu, 28 May 2026 07:37:31 -0300 Subject: [PATCH] fix: honor repo depth setting in gitSourceHasChanges and fetch functions (#27838) Signed-off-by: alexandresavicki Co-authored-by: Cursor --- reposerver/repository/repository.go | 20 ++++++++--- reposerver/repository/repository_test.go | 43 ++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go index 040a52f3d34a1..2df38543905d8 100644 --- a/reposerver/repository/repository.go +++ b/reposerver/repository/repository.go @@ -2685,8 +2685,8 @@ func (s *Service) checkoutRevision(gitClient git.Client, revision string, submod // fetch is a convenience function to fetch revisions // We assumed that the caller has already initialized the git repo, i.e. gitClient.Init() has been called -func (s *Service) fetch(gitClient git.Client, targetRevisions []string) error { - err := fetch(gitClient, targetRevisions) +func (s *Service) fetch(gitClient git.Client, targetRevisions []string, depth int64) error { + err := fetch(gitClient, targetRevisions, depth) if err != nil { for _, revision := range targetRevisions { s.metricsServer.IncGitFetchFail(gitClient.Root(), revision) @@ -2695,7 +2695,7 @@ func (s *Service) fetch(gitClient git.Client, targetRevisions []string) error { return err } -func fetch(gitClient git.Client, targetRevisions []string) error { +func fetch(gitClient git.Client, targetRevisions []string, depth int64) error { revisionPresent := true for _, revision := range targetRevisions { revisionPresent = gitClient.IsRevisionPresent(revision) @@ -2707,6 +2707,16 @@ func fetch(gitClient git.Client, targetRevisions []string) error { if revisionPresent { return nil } + if depth > 0 { + for _, revision := range targetRevisions { + if !gitClient.IsRevisionPresent(revision) { + if err := gitClient.Fetch(revision, depth); err != nil { + return status.Errorf(codes.Internal, "Failed to fetch revision %s: %v", revision, err) + } + } + } + return nil + } // Fetching with no revision first. Fetching with an explicit version can cause repo bloat. https://github.com/argoproj/argo-cd/issues/8845 err := gitClient.Fetch("", 0) if err != nil { @@ -3081,14 +3091,14 @@ func (s *Service) UpdateRevisionForPaths(_ context.Context, request *apiclient.U defer s.metricsServer.DecPendingRepoRequest(repo.Repo) closer, err := s.repoLock.Lock(gitClient.Root(), revision, true, func() (goio.Closer, error) { - return s.checkoutRevision(gitClient, revision, false, 0) + return s.checkoutRevision(gitClient, revision, false, repo.Depth) }) if err != nil { return nil, status.Errorf(codes.Internal, "unable to checkout git repo %s with revision %s: %v", repo.Repo, revision, err) } defer utilio.Close(closer) - if err := s.fetch(gitClient, []string{syncedRevision}); err != nil { + if err := s.fetch(gitClient, []string{syncedRevision}, repo.Depth); err != nil { return nil, status.Errorf(codes.Internal, "unable to fetch git repo %s with syncedRevisions %s: %v", repo.Repo, syncedRevision, err) } diff --git a/reposerver/repository/repository_test.go b/reposerver/repository/repository_test.go index c19fee51ef5b5..617add61ea807 100644 --- a/reposerver/repository/repository_test.go +++ b/reposerver/repository/repository_test.go @@ -3218,10 +3218,47 @@ func TestFetch(t *testing.T) { gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(true) gitClient.EXPECT().IsRevisionPresent(revision2).Once().Return(true) - err := fetch(gitClient, []string{revision1, revision2}) + err := fetch(gitClient, []string{revision1, revision2}, 0) require.NoError(t, err) } +func TestFetchWithDepth(t *testing.T) { + revision1 := "0123456789012345678901234567890123456789" + revision2 := "abcdefabcdefabcdefabcdefabcdefabcdefabcd" + + t.Run("skips fetch when all revisions present", func(t *testing.T) { + gitClient := &gitmocks.Client{} + gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(true) + gitClient.EXPECT().IsRevisionPresent(revision2).Once().Return(true) + + err := fetch(gitClient, []string{revision1, revision2}, 1) + require.NoError(t, err) + }) + + t.Run("fetches only missing revisions with depth", func(t *testing.T) { + gitClient := &gitmocks.Client{} + gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(true) + gitClient.EXPECT().IsRevisionPresent(revision2).Once().Return(false) + // After the initial check finds a missing revision, the per-revision loop runs + gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(true) + gitClient.EXPECT().IsRevisionPresent(revision2).Once().Return(false) + gitClient.EXPECT().Fetch(revision2, int64(1)).Return(nil) + + err := fetch(gitClient, []string{revision1, revision2}, 1) + require.NoError(t, err) + }) + + t.Run("returns error on fetch failure", func(t *testing.T) { + gitClient := &gitmocks.Client{} + gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(false) + gitClient.EXPECT().IsRevisionPresent(revision1).Once().Return(false) + gitClient.EXPECT().Fetch(revision1, int64(1)).Return(errors.New("fetch failed")) + + err := fetch(gitClient, []string{revision1, revision2}, 1) + require.Error(t, err) + }) +} + // TestFetchRevisionCanGetNonstandardRefs shows that we can fetch a revision that points to a non-standard ref. In func TestFetchRevisionCanGetNonstandardRefs(t *testing.T) { rootPath := t.TempDir() @@ -3254,10 +3291,10 @@ func TestFetchRevisionCanGetNonstandardRefs(t *testing.T) { pullSha, err := gitClient.LsRemote("refs/pull/123/head") require.NoError(t, err) - err = fetch(gitClient, []string{"does-not-exist"}) + err = fetch(gitClient, []string{"does-not-exist"}, 0) require.Error(t, err) - err = fetch(gitClient, []string{pullSha}) + err = fetch(gitClient, []string{pullSha}, 0) require.NoError(t, err) }