pass predicate type to get attestation api methods

Signed-off-by: Meredith Lancaster <malancas@github.com>
This commit is contained in:
Meredith Lancaster 2025-03-24 17:28:00 -06:00
parent 4d44e4f20c
commit a78c06970a
3 changed files with 37 additions and 34 deletions

View file

@ -39,8 +39,8 @@ type httpClient interface {
}
type Client interface {
GetByRepoAndDigest(repo, digest string, limit int) ([]*Attestation, error)
GetByOwnerAndDigest(owner, digest string, limit int) ([]*Attestation, error)
GetByRepoAndDigest(repo, digest, predicateType string, limit int) ([]*Attestation, error)
GetByOwnerAndDigest(owner, digest, predicateType string, limit int) ([]*Attestation, error)
GetTrustDomain() (string, error)
}
@ -61,21 +61,21 @@ func NewLiveClient(hc *http.Client, host string, l *ioconfig.Handler) *LiveClien
}
// GetByRepoAndDigest fetches the attestation by repo and digest
func (c *LiveClient) GetByRepoAndDigest(repo, digest string, limit int) ([]*Attestation, error) {
func (c *LiveClient) GetByRepoAndDigest(repo, digest, predicateType string, limit int) ([]*Attestation, error) {
c.logger.VerbosePrintf("Fetching attestations for artifact digest %s\n\n", digest)
url := fmt.Sprintf(GetAttestationByRepoAndSubjectDigestPath, repo, digest)
return c.getByURL(url, limit)
return c.getByURL(url, predicateType, limit)
}
// GetByOwnerAndDigest fetches attestation by owner and digest
func (c *LiveClient) GetByOwnerAndDigest(owner, digest string, limit int) ([]*Attestation, error) {
func (c *LiveClient) GetByOwnerAndDigest(owner, digest, predicateType string, limit int) ([]*Attestation, error) {
c.logger.VerbosePrintf("Fetching attestations for artifact digest %s\n\n", digest)
url := fmt.Sprintf(GetAttestationByOwnerAndSubjectDigestPath, owner, digest)
return c.getByURL(url, limit)
return c.getByURL(url, predicateType, limit)
}
func (c *LiveClient) getByURL(url string, limit int) ([]*Attestation, error) {
attestations, err := c.getAttestations(url, limit)
func (c *LiveClient) getByURL(url, predicateType string, limit int) ([]*Attestation, error) {
attestations, err := c.getAttestations(url, predicateType, limit)
if err != nil {
return nil, err
}
@ -94,7 +94,7 @@ func (c *LiveClient) GetTrustDomain() (string, error) {
return c.getTrustDomain(MetaPath)
}
func (c *LiveClient) getAttestations(url string, limit int) ([]*Attestation, error) {
func (c *LiveClient) getAttestations(url, predicateType string, limit int) ([]*Attestation, error) {
perPage := limit
if perPage <= 0 || perPage > maxLimitForFlag {
return nil, fmt.Errorf("limit must be greater than 0 and less than or equal to %d", maxLimitForFlag)
@ -106,6 +106,9 @@ func (c *LiveClient) getAttestations(url string, limit int) ([]*Attestation, err
// ref: https://github.com/cli/go-gh/blob/d32c104a9a25c9de3d7c7b07a43ae0091441c858/example_gh_test.go#L96
url = fmt.Sprintf("%s?per_page=%d", url, perPage)
if predicateType != "" {
url = fmt.Sprintf("%s&predicate_type=%s", url, predicateType)
}
var attestations []*Attestation
var resp AttestationsResponse

View file

@ -44,14 +44,14 @@ func NewClientWithMockGHClient(hasNextPage bool) Client {
func TestGetByDigest(t *testing.T) {
c := NewClientWithMockGHClient(false)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, DefaultLimit)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.NoError(t, err)
require.Equal(t, 5, len(attestations))
bundle := (attestations)[0].Bundle
require.Equal(t, bundle.GetMediaType(), "application/vnd.dev.sigstore.bundle.v0.3+json")
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, DefaultLimit)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.NoError(t, err)
require.Equal(t, 5, len(attestations))
@ -64,14 +64,14 @@ func TestGetByDigestGreaterThanLimit(t *testing.T) {
limit := 3
// The method should return five results when the limit is not set
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, limit)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, "https://slsa.dev/provenance/v1", limit)
require.NoError(t, err)
require.Equal(t, 3, len(attestations))
bundle := (attestations)[0].Bundle
require.Equal(t, bundle.GetMediaType(), "application/vnd.dev.sigstore.bundle.v0.3+json")
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, limit)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, "https://slsa.dev/provenance/v1", limit)
require.NoError(t, err)
require.Equal(t, len(attestations), limit)
@ -81,14 +81,14 @@ func TestGetByDigestGreaterThanLimit(t *testing.T) {
func TestGetByDigestWithNextPage(t *testing.T) {
c := NewClientWithMockGHClient(true)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, DefaultLimit)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.NoError(t, err)
require.Equal(t, len(attestations), 10)
bundle := (attestations)[0].Bundle
require.Equal(t, bundle.GetMediaType(), "application/vnd.dev.sigstore.bundle.v0.3+json")
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, DefaultLimit)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.NoError(t, err)
require.Equal(t, len(attestations), 10)
@ -101,14 +101,14 @@ func TestGetByDigestGreaterThanLimitWithNextPage(t *testing.T) {
limit := 7
// The method should return five results when the limit is not set
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, limit)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, "https://slsa.dev/provenance/v1", limit)
require.NoError(t, err)
require.Equal(t, len(attestations), limit)
bundle := (attestations)[0].Bundle
require.Equal(t, bundle.GetMediaType(), "application/vnd.dev.sigstore.bundle.v0.3+json")
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, limit)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, "https://slsa.dev/provenance/v1", limit)
require.NoError(t, err)
require.Equal(t, len(attestations), limit)
@ -130,12 +130,12 @@ func TestGetByDigest_NoAttestationsFound(t *testing.T) {
logger: io.NewTestHandler(),
}
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, DefaultLimit)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.Error(t, err)
require.IsType(t, ErrNoAttestationsFound, err)
require.Nil(t, attestations)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, DefaultLimit)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.Error(t, err)
require.IsType(t, ErrNoAttestationsFound, err)
require.Nil(t, attestations)
@ -153,11 +153,11 @@ func TestGetByDigest_Error(t *testing.T) {
logger: io.NewTestHandler(),
}
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, DefaultLimit)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.Error(t, err)
require.Nil(t, attestations)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, DefaultLimit)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.Error(t, err)
require.Nil(t, attestations)
}
@ -362,7 +362,7 @@ func TestGetAttestationsRetries(t *testing.T) {
logger: io.NewTestHandler(),
}
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, DefaultLimit)
attestations, err := c.GetByRepoAndDigest(testRepo, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.NoError(t, err)
// assert the error path was executed; because this is a paged
@ -375,7 +375,7 @@ func TestGetAttestationsRetries(t *testing.T) {
require.Equal(t, bundle.GetMediaType(), "application/vnd.dev.sigstore.bundle.v0.3+json")
// same test as above, but for GetByOwnerAndDigest:
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, DefaultLimit)
attestations, err = c.GetByOwnerAndDigest(testOwner, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.NoError(t, err)
// because we haven't reset the mock, we have added 2 more failed requests
@ -401,7 +401,7 @@ func TestGetAttestationsMaxRetries(t *testing.T) {
logger: io.NewTestHandler(),
}
_, err := c.GetByRepoAndDigest(testRepo, testDigest, DefaultLimit)
_, err := c.GetByRepoAndDigest(testRepo, testDigest, "https://slsa.dev/provenance/v1", DefaultLimit)
require.Error(t, err)
fetcher.AssertNumberOfCalls(t, "OnREST500Error", 4)

View file

@ -7,17 +7,17 @@ import (
)
type MockClient struct {
OnGetByRepoAndDigest func(repo, digest string, limit int) ([]*Attestation, error)
OnGetByOwnerAndDigest func(owner, digest string, limit int) ([]*Attestation, error)
OnGetByRepoAndDigest func(repo, digest, predicateType string, limit int) ([]*Attestation, error)
OnGetByOwnerAndDigest func(owner, digest, predicateType string, limit int) ([]*Attestation, error)
OnGetTrustDomain func() (string, error)
}
func (m MockClient) GetByRepoAndDigest(repo, digest string, limit int) ([]*Attestation, error) {
return m.OnGetByRepoAndDigest(repo, digest, limit)
func (m MockClient) GetByRepoAndDigest(repo, digest, predicateType string, limit int) ([]*Attestation, error) {
return m.OnGetByRepoAndDigest(repo, digest, predicateType, limit)
}
func (m MockClient) GetByOwnerAndDigest(owner, digest string, limit int) ([]*Attestation, error) {
return m.OnGetByOwnerAndDigest(owner, digest, limit)
func (m MockClient) GetByOwnerAndDigest(owner, digest, predicateType string, limit int) ([]*Attestation, error) {
return m.OnGetByOwnerAndDigest(owner, digest, predicateType, limit)
}
func (m MockClient) GetTrustDomain() (string, error) {
@ -28,23 +28,23 @@ func makeTestAttestation() Attestation {
return Attestation{Bundle: data.SigstoreBundle(nil), BundleURL: "https://example.com"}
}
func OnGetByRepoAndDigestSuccess(repo, digest string, limit int) ([]*Attestation, error) {
func OnGetByRepoAndDigestSuccess(repo, digest, predicateType string, limit int) ([]*Attestation, error) {
att1 := makeTestAttestation()
att2 := makeTestAttestation()
return []*Attestation{&att1, &att2}, nil
}
func OnGetByRepoAndDigestFailure(repo, digest string, limit int) ([]*Attestation, error) {
func OnGetByRepoAndDigestFailure(repo, digest, predicateType string, limit int) ([]*Attestation, error) {
return nil, fmt.Errorf("failed to fetch by repo and digest")
}
func OnGetByOwnerAndDigestSuccess(owner, digest string, limit int) ([]*Attestation, error) {
func OnGetByOwnerAndDigestSuccess(owner, digest, predicateType string, limit int) ([]*Attestation, error) {
att1 := makeTestAttestation()
att2 := makeTestAttestation()
return []*Attestation{&att1, &att2}, nil
}
func OnGetByOwnerAndDigestFailure(owner, digest string, limit int) ([]*Attestation, error) {
func OnGetByOwnerAndDigestFailure(owner, digest, predicateType string, limit int) ([]*Attestation, error) {
return nil, fmt.Errorf("failed to fetch by owner and digest")
}