diff --git a/pkg/cmd/attestation/download/download.go b/pkg/cmd/attestation/download/download.go index 2adc0bb50..c5fd3a794 100644 --- a/pkg/cmd/attestation/download/download.go +++ b/pkg/cmd/attestation/download/download.go @@ -1,10 +1,8 @@ package download import ( - "encoding/json" "errors" "fmt" - "os" "github.com/cli/cli/v2/pkg/cmd/attestation/api" "github.com/cli/cli/v2/pkg/cmd/attestation/artifact" @@ -150,42 +148,3 @@ func runDownload(opts *Options) error { return nil } - -func createJSONLinesFilePath(artifact, outputPath string) string { - path := fmt.Sprintf("%s.jsonl", artifact) - if outputPath != "" { - return fmt.Sprintf("%s/%s", outputPath, path) - } - return path -} - -func createMetadataFile(attestationsResp []*api.Attestation, filePath string) (string, error) { - f, err := os.Create(filePath) - if err != nil { - return "", fmt.Errorf("failed to create trusted metadata file: %w", err) - } - - for _, resp := range attestationsResp { - bundle := resp.Bundle - attBytes, err := json.Marshal(bundle) - if err != nil { - return "", fmt.Errorf("failed to marshall attestation to JSON: %w", err) - } - - withNewline := fmt.Sprintf("%s\n", attBytes) - _, err = f.Write([]byte(withNewline)) - if err != nil { - if err = f.Close(); err != nil { - return "", fmt.Errorf("failed to close file while handling write error: %w", err) - } - - return "", fmt.Errorf("failed to write trusted metadata: %w", err) - } - } - - if err = f.Close(); err != nil { - return "", fmt.Errorf("failed to close file after writing metadata: %w", err) - } - - return filePath, nil -} diff --git a/pkg/cmd/attestation/download/download_test.go b/pkg/cmd/attestation/download/download_test.go index a3d5dcbc4..a162002cc 100644 --- a/pkg/cmd/attestation/download/download_test.go +++ b/pkg/cmd/attestation/download/download_test.go @@ -1,12 +1,9 @@ package download import ( - "bufio" "bytes" "fmt" "net/http" - "os" - "path" "testing" "github.com/cli/cli/v2/pkg/cmd/attestation/api" @@ -34,7 +31,7 @@ func TestNewDownloadCmd(t *testing.T) { }, } - store := &MetadataStore{ + store := &LiveStore{ outputPath: t.TempDir(), } @@ -176,7 +173,7 @@ func TestNewDownloadCmd(t *testing.T) { func TestRunDownload(t *testing.T) { tempDir := t.TempDir() - store := &MetadataStore{ + store := &LiveStore{ outputPath: tempDir, } @@ -305,59 +302,3 @@ func TestRunDownload(t *testing.T) { require.Error(t, runDownload(&customOpts)) }) } - -func TestCreateJSONLinesFilePath(t *testing.T) { - tempDir := t.TempDir() - artifact, err := artifact.NewDigestedArtifact(oci.MockClient{}, "../test/data/sigstore-js-2.1.0.tgz", "sha512") - require.NoError(t, err) - - outputFileName := fmt.Sprintf("%s.jsonl", artifact.DigestWithAlg()) - - testCases := []struct { - name string - outputPath string - expected string - }{ - { - name: "with output path", - outputPath: tempDir, - expected: path.Join(tempDir, outputFileName), - }, - { - name: "with nested output path", - outputPath: path.Join(tempDir, "subdir"), - expected: path.Join(tempDir, "subdir", outputFileName), - }, - { - name: "with output path with beginning slash", - outputPath: path.Join("/", tempDir, "subdir"), - expected: path.Join("/", tempDir, "subdir", outputFileName), - }, - { - name: "without output path", - outputPath: "", - expected: outputFileName, - }, - } - - for _, tc := range testCases { - actualPath := createJSONLinesFilePath(artifact.DigestWithAlg(), tc.outputPath) - require.Equal(t, tc.expected, actualPath) - } -} - -func countLines(path string) (int, error) { - f, err := os.Open(path) - if err != nil { - return 0, err - } - defer f.Close() - - counter := 0 - scanner := bufio.NewScanner(f) - for scanner.Scan() { - counter += 1 - } - - return counter, nil -} diff --git a/pkg/cmd/attestation/download/metadata.go b/pkg/cmd/attestation/download/metadata.go index d271e360c..a461f4302 100644 --- a/pkg/cmd/attestation/download/metadata.go +++ b/pkg/cmd/attestation/download/metadata.go @@ -8,11 +8,16 @@ import ( "github.com/cli/cli/v2/pkg/cmd/attestation/api" ) -type MetadataStore struct { +type MetadataStore interface { + createJSONLinesFilePath(artifact string) string + createMetadataFile(artifactDigest string, attestationsResp []*api.Attestation) (string, error) +} + +type LiveStore struct { outputPath string } -func (s *MetadataStore) createJSONLinesFilePath(artifact string) string { +func (s *LiveStore) createJSONLinesFilePath(artifact string) string { path := fmt.Sprintf("%s.jsonl", artifact) if s.outputPath != "" { return fmt.Sprintf("%s/%s", s.outputPath, path) @@ -20,7 +25,7 @@ func (s *MetadataStore) createJSONLinesFilePath(artifact string) string { return path } -func (s *MetadataStore) createMetadataFile(artifactDigest string, attestationsResp []*api.Attestation) (string, error) { +func (s *LiveStore) createMetadataFile(artifactDigest string, attestationsResp []*api.Attestation) (string, error) { metadataFilePath := s.createJSONLinesFilePath(artifactDigest) f, err := os.Create(metadataFilePath) diff --git a/pkg/cmd/attestation/download/metadata_test.go b/pkg/cmd/attestation/download/metadata_test.go new file mode 100644 index 000000000..4b947dc76 --- /dev/null +++ b/pkg/cmd/attestation/download/metadata_test.go @@ -0,0 +1,74 @@ +package download + +import ( + "bufio" + "fmt" + "os" + "path" + "testing" + + "github.com/cli/cli/v2/pkg/cmd/attestation/artifact" + "github.com/cli/cli/v2/pkg/cmd/attestation/artifact/oci" + + "github.com/stretchr/testify/require" +) + +func TestCreateJSONLinesFilePath(t *testing.T) { + tempDir := t.TempDir() + artifact, err := artifact.NewDigestedArtifact(oci.MockClient{}, "../test/data/sigstore-js-2.1.0.tgz", "sha512") + require.NoError(t, err) + + outputFileName := fmt.Sprintf("%s.jsonl", artifact.DigestWithAlg()) + + testCases := []struct { + name string + outputPath string + expected string + }{ + { + name: "with output path", + outputPath: tempDir, + expected: path.Join(tempDir, outputFileName), + }, + { + name: "with nested output path", + outputPath: path.Join(tempDir, "subdir"), + expected: path.Join(tempDir, "subdir", outputFileName), + }, + { + name: "with output path with beginning slash", + outputPath: path.Join("/", tempDir, "subdir"), + expected: path.Join("/", tempDir, "subdir", outputFileName), + }, + { + name: "without output path", + outputPath: "", + expected: outputFileName, + }, + } + + for _, tc := range testCases { + store := LiveStore{ + tc.outputPath, + } + + actualPath := store.createJSONLinesFilePath(artifact.DigestWithAlg()) + require.Equal(t, tc.expected, actualPath) + } +} + +func countLines(path string) (int, error) { + f, err := os.Open(path) + if err != nil { + return 0, err + } + defer f.Close() + + counter := 0 + scanner := bufio.NewScanner(f) + for scanner.Scan() { + counter += 1 + } + + return counter, nil +} diff --git a/pkg/cmd/attestation/download/options.go b/pkg/cmd/attestation/download/options.go index 15eca8f38..edb3c1b7b 100644 --- a/pkg/cmd/attestation/download/options.go +++ b/pkg/cmd/attestation/download/options.go @@ -19,7 +19,7 @@ type Options struct { DigestAlgorithm string Logger *logging.Logger Limit int - Store *MetadataStore + Store MetadataStore OCIClient oci.Client Owner string Repo string