diff --git a/pkg/cmd/attestation/api/client.go b/pkg/cmd/attestation/api/client.go index 1a29e3044..d0ef3f21b 100644 --- a/pkg/cmd/attestation/api/client.go +++ b/pkg/cmd/attestation/api/client.go @@ -196,7 +196,7 @@ func (c *LiveClient) fetchBundleByURL(a *Attestation) (*bundle.Bundle, error) { return a.Bundle, nil } - c.logger.VerbosePrintf("Fetching attestation bundle\n\n") + c.logger.VerbosePrintf("Fetching attestation bundle with bundle URL\n\n") resp, err := c.httpClient.Get(a.BundleURL) if err != nil { diff --git a/pkg/cmd/attestation/api/client_test.go b/pkg/cmd/attestation/api/client_test.go index 540ae1366..62b1c40cf 100644 --- a/pkg/cmd/attestation/api/client_test.go +++ b/pkg/cmd/attestation/api/client_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/cli/cli/v2/pkg/cmd/attestation/io" + "github.com/cli/cli/v2/pkg/cmd/attestation/test/data" "github.com/stretchr/testify/require" ) @@ -25,8 +26,8 @@ func NewClientWithMockGHClient(hasNextPage bool) Client { githubAPI: mockAPIClient{ OnRESTWithNext: fetcher.OnRESTSuccessWithNextPage, }, - httpClient: mockHttpClient{ - OnGet: fetcher.OnGetSuccess, + httpClient: &mockHttpClient{ + OnGet: OnGetSuccess, }, logger: l, } @@ -36,8 +37,8 @@ func NewClientWithMockGHClient(hasNextPage bool) Client { githubAPI: mockAPIClient{ OnRESTWithNext: fetcher.OnRESTSuccess, }, - httpClient: mockHttpClient{ - OnGet: fetcher.OnGetSuccess, + httpClient: &mockHttpClient{ + OnGet: OnGetSuccess, }, logger: l, } @@ -144,8 +145,8 @@ func TestGetByDigest_NoAttestationsFound(t *testing.T) { githubAPI: mockAPIClient{ OnRESTWithNext: fetcher.OnRESTWithNextNoAttestations, }, - httpClient: mockHttpClient{ - OnGet: fetcher.OnGetSuccess, + httpClient: &mockHttpClient{ + OnGet: OnGetSuccess, }, logger: io.NewTestHandler(), } @@ -182,6 +183,42 @@ func TestGetByDigest_Error(t *testing.T) { require.Nil(t, attestations) } +func TestFetchBundleByURL(t *testing.T) { + t.Run("fetch by bundle URL successfully", func(t *testing.T) { + httpClient := mockHttpClient{ + OnGet: OnGetSuccess, + } + c := &LiveClient{ + httpClient: &httpClient, + logger: io.NewTestHandler(), + } + + attestation := makeTestAttestation() + bundle, err := c.fetchBundleByURL(&attestation) + require.NoError(t, err) + require.Equal(t, "application/vnd.dev.sigstore.bundle.v0.3+json", bundle.GetMediaType()) + require.True(t, httpClient.called) + }) + + t.Run("fallback to bundle field when BundleURL field is empty", func(t *testing.T) { + httpClient := mockHttpClient{ + OnGet: OnGetSuccess, + } + c := &LiveClient{ + httpClient: &mockHttpClient{ + OnGet: OnGetSuccess, + }, + logger: io.NewTestHandler(), + } + + attestation := Attestation{Bundle: data.SigstoreBundle(t)} + bundle, err := c.fetchBundleByURL(&attestation) + require.NoError(t, err) + require.Equal(t, "application/vnd.dev.sigstore.bundle.v0.3+json", bundle.GetMediaType()) + require.False(t, httpClient.called) + }) +} + func TestGetTrustDomain(t *testing.T) { fetcher := mockMetaGenerator{ TrustDomain: "foo", @@ -225,8 +262,8 @@ func TestGetAttestationsRetries(t *testing.T) { githubAPI: mockAPIClient{ OnRESTWithNext: fetcher.FlakyOnRESTSuccessWithNextPageHandler(), }, - httpClient: mockHttpClient{ - OnGet: fetcher.OnGetSuccess, + httpClient: &mockHttpClient{ + OnGet: OnGetSuccess, }, logger: io.NewTestHandler(), } diff --git a/pkg/cmd/attestation/api/mock_httpClient_test.go b/pkg/cmd/attestation/api/mock_httpClient_test.go index 89584874f..365619ac1 100644 --- a/pkg/cmd/attestation/api/mock_httpClient_test.go +++ b/pkg/cmd/attestation/api/mock_httpClient_test.go @@ -10,14 +10,16 @@ import ( ) type mockHttpClient struct { - OnGet func(url string) (*http.Response, error) + called bool + OnGet func(url string) (*http.Response, error) } -func (m mockHttpClient) Get(url string) (*http.Response, error) { +func (m *mockHttpClient) Get(url string) (*http.Response, error) { + m.called = true return m.OnGet(url) } -func (m *mockDataGenerator) OnGetSuccess(url string) (*http.Response, error) { +func OnGetSuccess(url string) (*http.Response, error) { compressed := snappy.Encode(nil, data.SigstoreBundleRaw) return &http.Response{ StatusCode: 200,