support repo option in download sub cmd

Signed-off-by: Meredith Lancaster <malancas@github.com>
This commit is contained in:
Meredith Lancaster 2024-03-12 17:35:56 -06:00
parent 658fab208d
commit 0018903264
4 changed files with 38 additions and 5 deletions

View file

@ -10,6 +10,7 @@ import (
"github.com/cli/cli/v2/pkg/cmd/attestation/artifact/oci"
"github.com/cli/cli/v2/pkg/cmd/attestation/auth"
"github.com/cli/cli/v2/pkg/cmd/attestation/logging"
"github.com/cli/cli/v2/pkg/cmd/attestation/verification"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/MakeNowJust/heredoc"
@ -97,7 +98,9 @@ func NewDownloadCmd(f *cmdutil.Factory) *cobra.Command {
}
downloadCmd.Flags().StringVarP(&opts.Owner, "owner", "o", "", "a GitHub organization to scope attestation lookup by")
downloadCmd.MarkFlagRequired("owner") //nolint:errcheck
downloadCmd.Flags().StringVarP(&opts.Repo, "repo", "R", "", "Repository name in the format <owner>/<repo>")
downloadCmd.MarkFlagsMutuallyExclusive("owner", "repo")
downloadCmd.MarkFlagsOneRequired("owner", "repo")
cmdutil.StringEnumFlag(downloadCmd, &opts.DigestAlgorithm, "digest-alg", "d", "sha256", []string{"sha256", "sha512"}, "The algorithm used to compute a digest of the artifact")
downloadCmd.Flags().IntVarP(&opts.Limit, "limit", "L", api.DefaultLimit, "Maximum number of attestations to fetch")
downloadCmd.Flags().BoolVarP(&opts.Verbose, "verbose", "v", false, "If set to true, the CLI will output verbose information.")
@ -115,7 +118,15 @@ func RunDownload(opts *Options) error {
}
opts.Logger.VerbosePrintf("Downloading trusted metadata for artifact %s\n\n", opts.ArtifactPath)
attestations, err := opts.APIClient.GetByOwnerAndDigest(opts.Owner, artifact.DigestWithAlg(), opts.Limit)
c := verification.FetchAttestationsConfig{
APIClient: opts.APIClient,
Digest: artifact.DigestWithAlg(),
Limit: opts.Limit,
Owner: opts.Owner,
Repo: opts.Repo,
}
attestations, err := verification.GetRemoteAttestations(c)
if err != nil {
return fmt.Errorf("failed to fetch attestations: %w", err)
}

View file

@ -23,12 +23,13 @@ func TestRunDownload(t *testing.T) {
APIClient: api.NewTestClient(),
OCIClient: oci.MockClient{},
DigestAlgorithm: "sha512",
Owner: "sigstore",
OutputPath: tempDir,
Limit: 30,
Logger: logging.NewTestLogger(),
}
t.Run("fetch and store attestations successfully", func(t *testing.T) {
t.Run("fetch and store attestations successfully with owner", func(t *testing.T) {
err := RunDownload(&baseOpts)
require.NoError(t, err)
@ -44,6 +45,26 @@ func TestRunDownload(t *testing.T) {
require.Equal(t, expectedLineCount, actualLineCount)
})
t.Run("fetch and store attestations successfully with repo", func(t *testing.T) {
opts := baseOpts
opts.Owner = ""
opts.Repo = "sigstore/sigstore-js"
err := RunDownload(&opts)
require.NoError(t, err)
artifact, err := artifact.NewDigestedArtifact(opts.OCIClient, opts.ArtifactPath, opts.DigestAlgorithm)
require.NoError(t, err)
require.FileExists(t, fmt.Sprintf("%s/%s.jsonl", tempDir, artifact.DigestWithAlg()))
actualLineCount, err := countLines(fmt.Sprintf("%s/%s.jsonl", tempDir, artifact.DigestWithAlg()))
require.NoError(t, err)
expectedLineCount := 2
require.Equal(t, expectedLineCount, actualLineCount)
})
t.Run("download OCI image attestations successfully", func(t *testing.T) {
opts := baseOpts
opts.ArtifactPath = "oci://ghcr.io/github/test"

View file

@ -18,6 +18,7 @@ type Options struct {
OCIClient oci.Client
OutputPath string
Owner string
Repo string
Verbose bool
}

View file

@ -31,7 +31,7 @@ func GetAttestations(c FetchAttestationsConfig) ([]*api.Attestation, error) {
if c.IsBundleProvided() {
return GetLocalAttestations(c.BundlePath)
}
return getRemoteAttestations(c)
return GetRemoteAttestations(c)
}
// GetLocalAttestations returns a slice of attestations read from a local bundle file.
@ -92,7 +92,7 @@ func loadBundlesFromJSONLinesFile(path string) ([]*api.Attestation, error) {
return attestations, nil
}
func getRemoteAttestations(c FetchAttestationsConfig) ([]*api.Attestation, error) {
func GetRemoteAttestations(c FetchAttestationsConfig) ([]*api.Attestation, error) {
if c.APIClient == nil {
return nil, fmt.Errorf("api client must be provided")
}