11package command
22
33import (
4+ "encoding/json"
45 "errors"
56 "fmt"
7+ "io"
68 "os"
79 "slices"
810 "strings"
911
12+ "github.com/jedib0t/go-pretty/v6/table"
13+ "github.com/jedib0t/go-pretty/v6/text"
1014 "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/application"
1115 "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/artifacts"
1216 "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/build"
1317 "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/flags"
1418 "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/github"
15- "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/interface"
16- "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/package"
19+ _interface "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/interface"
20+ _package "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/package"
1721 "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/releasebundle"
1822 commandUtils "github.com/jfrog/jfrog-cli-evidence/evidence/cli/command/utils"
1923 evdConfig "github.com/jfrog/jfrog-cli-evidence/evidence/config"
24+ "github.com/jfrog/jfrog-cli-evidence/evidence/model"
2025
2126 commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
2227 "github.com/jfrog/jfrog-cli-core/v2/common/commands"
28+ "github.com/jfrog/jfrog-cli-core/v2/common/format"
2329 pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
2430 "github.com/jfrog/jfrog-cli-core/v2/plugins/components"
2531 "github.com/jfrog/jfrog-cli-core/v2/utils/config"
@@ -37,15 +43,23 @@ import (
3743 generateCmd "github.com/jfrog/jfrog-cli-evidence/evidence/generate"
3844)
3945
46+ // responseCollector is implemented by evidence create commands that accumulate
47+ // CreateResponse values during Run(). The interface is checked via type assertion
48+ // after command execution so that printCreateEvidenceResponse can format output.
49+ type responseCollector interface {
50+ CollectedResponses () []* model.CreateResponse
51+ }
52+
4053func GetCommands () []components.Command {
4154 return []components.Command {
4255 {
43- Name : "create-evidence" ,
44- Aliases : []string {"create" },
45- Flags : flags .GetCommandFlags (flags .CreateEvidence ),
46- Description : create .GetDescription (),
47- Arguments : create .GetArguments (),
48- Action : createEvidence ,
56+ Name : "create-evidence" ,
57+ Aliases : []string {"create" },
58+ Flags : flags .GetCommandFlags (flags .CreateEvidence ),
59+ Description : create .GetDescription (),
60+ Arguments : create .GetArguments (),
61+ Action : createEvidence ,
62+ SupportedFormats : []format.OutputFormat {format .Json , format .Table },
4963 },
5064 {
5165 Name : "get-evidence" ,
@@ -74,8 +88,10 @@ func GetCommands() []components.Command {
7488 }
7589}
7690
77- var execFunc = commands .Exec
78- var ErrUnsupportedSubject = errors .New ("unsupported subject" )
91+ var (
92+ execFunc = commands .Exec
93+ ErrUnsupportedSubject = errors .New ("unsupported subject" )
94+ )
7995
8096func createEvidence (ctx * components.Context ) error {
8197 if err := validateCreateEvidenceCommonContext (ctx ); err != nil {
@@ -90,23 +106,50 @@ func createEvidence(ctx *components.Context) error {
90106 return err
91107 }
92108
93- if slices .Contains (evidenceType , flags .TypeFlag ) || (slices .Contains (evidenceType , flags .BuildName ) && slices .Contains (evidenceType , flags .TypeFlag )) {
94- return github .NewEvidenceGitHubCommand (ctx , execFunc ).CreateEvidence (ctx , serverDetails )
109+ outputFormat , err := ctx .GetOutputFormat ()
110+ if err != nil {
111+ return err
95112 }
96113
97- evidenceCommands := map [string ]func (* components.Context , commandUtils.ExecCommandFunc ) _interface.EvidenceCommands {
98- flags .SubjectRepoPath : artifacts .NewEvidenceCustomCommand ,
99- flags .ReleaseBundle : releasebundle .NewEvidenceReleaseBundleCommand ,
100- flags .BuildName : build .NewEvidenceBuildCommand ,
101- flags .PackageName : _package .NewEvidencePackageCommand ,
102- flags .ApplicationKey : application .NewEvidenceApplicationCommand ,
114+ // Wrap execFunc to capture collected responses after each command runs.
115+ var collectedResponses []* model.CreateResponse
116+ collectingExec := func (cmd commands.Command ) error {
117+ if runErr := execFunc (cmd ); runErr != nil {
118+ return runErr
119+ }
120+ if rc , ok := cmd .(responseCollector ); ok {
121+ collectedResponses = append (collectedResponses , rc .CollectedResponses ()... )
122+ }
123+ return nil
103124 }
104125
105- if commandFunc , exists := evidenceCommands [evidenceType [0 ]]; exists {
106- return commandFunc (ctx , execFunc ).CreateEvidence (ctx , serverDetails )
126+ var createErr error
127+ if slices .Contains (evidenceType , flags .TypeFlag ) || (slices .Contains (evidenceType , flags .BuildName ) && slices .Contains (evidenceType , flags .TypeFlag )) {
128+ createErr = github .NewEvidenceGitHubCommand (ctx , collectingExec ).CreateEvidence (ctx , serverDetails )
129+ } else {
130+ evidenceCommands := map [string ]func (* components.Context , commandUtils.ExecCommandFunc ) _interface.EvidenceCommands {
131+ flags .SubjectRepoPath : artifacts .NewEvidenceCustomCommand ,
132+ flags .ReleaseBundle : releasebundle .NewEvidenceReleaseBundleCommand ,
133+ flags .BuildName : build .NewEvidenceBuildCommand ,
134+ flags .PackageName : _package .NewEvidencePackageCommand ,
135+ flags .ApplicationKey : application .NewEvidenceApplicationCommand ,
136+ }
137+
138+ if commandFunc , exists := evidenceCommands [evidenceType [0 ]]; exists {
139+ createErr = commandFunc (ctx , collectingExec ).CreateEvidence (ctx , serverDetails )
140+ } else {
141+ return ErrUnsupportedSubject
142+ }
107143 }
108144
109- return ErrUnsupportedSubject
145+ if createErr != nil {
146+ return createErr
147+ }
148+
149+ if outputFormat != "" {
150+ return printCreateEvidenceResponse (os .Stdout , outputFormat , collectedResponses )
151+ }
152+ return nil
110153}
111154
112155func getEvidence (ctx * components.Context ) error {
@@ -487,3 +530,75 @@ func generateKeyPair(ctx *components.Context) error {
487530 cmd := generateCmd .NewGenerateKeyPairCommand (serverDetails , uploadKey , alias , keyFilePath , fileName )
488531 return cmd .Run ()
489532}
533+
534+ // tableFieldOrder defines the display order for create-evidence table output.
535+ var tableFieldOrder = []struct {
536+ key string
537+ value func (* model.CreateResponse ) string
538+ }{
539+ {"repository" , func (r * model.CreateResponse ) string { return r .Repository }},
540+ {"path" , func (r * model.CreateResponse ) string { return r .Path }},
541+ {"name" , func (r * model.CreateResponse ) string { return r .Name }},
542+ {"uri" , func (r * model.CreateResponse ) string { return r .Uri }},
543+ {"sha256" , func (r * model.CreateResponse ) string { return r .Sha256 }},
544+ {"predicate_type" , func (r * model.CreateResponse ) string { return r .PredicateType }},
545+ {"predicate_category" , func (r * model.CreateResponse ) string { return r .PredicateCategory }},
546+ {"predicate_slug" , func (r * model.CreateResponse ) string { return r .PredicateSlug }},
547+ {"created_at" , func (r * model.CreateResponse ) string { return r .CreatedAt }},
548+ {"created_by" , func (r * model.CreateResponse ) string { return r .CreatedBy }},
549+ {"verified" , func (r * model.CreateResponse ) string {
550+ if r .Verified {
551+ return "true"
552+ }
553+ return "false"
554+ }},
555+ {"provider_id" , func (r * model.CreateResponse ) string { return r .ProviderId }},
556+ }
557+
558+ // printCreateEvidenceResponse writes formatted output for the given responses.
559+ func printCreateEvidenceResponse (w io.Writer , outputFormat format.OutputFormat , responses []* model.CreateResponse ) error {
560+ switch outputFormat {
561+ case format .Json :
562+ return printCreateEvidenceJSON (w , responses )
563+ case format .Table :
564+ return printCreateEvidenceTable (w , responses )
565+ default :
566+ return fmt .Errorf ("unsupported format %q: accepted values are json, table" , outputFormat )
567+ }
568+ }
569+
570+ func printCreateEvidenceJSON (w io.Writer , responses []* model.CreateResponse ) error {
571+ enc := json .NewEncoder (w )
572+ enc .SetIndent ("" , " " )
573+ if len (responses ) == 1 {
574+ return enc .Encode (responses [0 ])
575+ }
576+ return enc .Encode (responses )
577+ }
578+
579+ func printCreateEvidenceTable (w io.Writer , responses []* model.CreateResponse ) error {
580+ for i , r := range responses {
581+ if i > 0 {
582+ if _ , err := fmt .Fprintln (w ); err != nil {
583+ return err
584+ }
585+ }
586+ t := table .NewWriter ()
587+ t .SetOutputMirror (w )
588+ t .SetStyle (table .StyleLight )
589+ t .Style ().Options .SeparateRows = false
590+ t .AppendHeader (table.Row {"FIELD" , "VALUE" })
591+ t .SetColumnConfigs ([]table.ColumnConfig {
592+ {Number : 1 , Align : text .AlignLeft , AlignHeader : text .AlignLeft },
593+ {Number : 2 , Align : text .AlignLeft , AlignHeader : text .AlignLeft },
594+ })
595+ for _ , field := range tableFieldOrder {
596+ val := field .value (r )
597+ if val != "" {
598+ t .AppendRow (table.Row {field .key , val })
599+ }
600+ }
601+ t .Render ()
602+ }
603+ return nil
604+ }
0 commit comments