From ce0b44c8a729e83bf257d732eebcf9a457f39597 Mon Sep 17 00:00:00 2001 From: Kelvin Date: Sun, 19 Apr 2026 15:00:08 -0500 Subject: [PATCH] fix: improve shallow clone error for synthetic history --- .../app/azldev/core/sources/synthistory.go | 15 ++++++++++++++ .../azldev/core/sources/synthistory_test.go | 20 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/internal/app/azldev/core/sources/synthistory.go b/internal/app/azldev/core/sources/synthistory.go index 763b9416..5818aa59 100644 --- a/internal/app/azldev/core/sources/synthistory.go +++ b/internal/app/azldev/core/sources/synthistory.go @@ -4,6 +4,7 @@ package sources import ( + "errors" "fmt" "log/slog" "path/filepath" @@ -42,6 +43,20 @@ func MessageAffectsComponent(message, componentName string) bool { // whose message contains an "Affects: " trailer line. Results are sorted // chronologically (oldest first). func FindAffectsCommits(repo *gogit.Repository, componentName string) ([]CommitMetadata, error) { + // Synthetic history depends on a complete project commit log so Affects + // trailers can be discovered reliably. + shallowCommits, err := repo.Storer.Shallow() + if err != nil { + return nil, fmt.Errorf("failed to inspect repository history depth:\n%w", err) + } + + if len(shallowCommits) > 0 { + return nil, errors.New( + "repository is a shallow clone; synthetic history requires a full clone. " + + "Run `git fetch --unshallow` or re-clone without `--depth`", + ) + } + head, err := repo.Head() if err != nil { return nil, fmt.Errorf("failed to get HEAD reference:\n%w", err) diff --git a/internal/app/azldev/core/sources/synthistory_test.go b/internal/app/azldev/core/sources/synthistory_test.go index 24ef8209..506f0a3a 100644 --- a/internal/app/azldev/core/sources/synthistory_test.go +++ b/internal/app/azldev/core/sources/synthistory_test.go @@ -10,6 +10,7 @@ import ( memfs "github.com/go-git/go-billy/v5/memfs" gogit "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" "github.com/go-git/go-git/v5/storage/memory" "github.com/microsoft/azure-linux-dev-tools/internal/app/azldev/core/sources" @@ -112,6 +113,25 @@ func TestFindAffectsCommits_NoMatches(t *testing.T) { assert.Empty(t, results) } +func TestFindAffectsCommits_ShallowRepo(t *testing.T) { + repo := createInMemoryRepo(t) + + addCommit(t, repo, + "Fix CVE-2025-1234\n\nAffects: curl", + "Alice", "alice@example.com", + time.Date(2025, 1, 1, 10, 0, 0, 0, time.UTC)) + + head, err := repo.Head() + require.NoError(t, err) + require.NoError(t, repo.Storer.SetShallow([]plumbing.Hash{head.Hash()})) + + results, err := sources.FindAffectsCommits(repo, "curl") + require.Error(t, err) + assert.Nil(t, results) + assert.Contains(t, err.Error(), "shallow clone") + assert.Contains(t, err.Error(), "git fetch --unshallow") +} + func TestFindAffectsCommits_MultipleComponents(t *testing.T) { repo := createInMemoryRepo(t)