@@ -11,14 +11,16 @@ import (
1111 "github.com/jfrog/jfrog-cli-artifactory/evidence"
1212 "github.com/jfrog/jfrog-cli-artifactory/evidence/sigstore"
1313 "github.com/jfrog/jfrog-cli-core/v2/utils/config"
14+ "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
1415 "github.com/jfrog/jfrog-client-go/utils/errorutils"
1516)
1617
1718type createEvidenceCustom struct {
1819 createEvidenceBase
19- subjectRepoPath string
20- subjectSha256 string
21- sigstoreBundlePath string
20+ subjectRepoPath string
21+ subjectSha256 string
22+ sigstoreBundlePath string
23+ autoSubjectResolution bool
2224}
2325
2426func NewCreateEvidenceCustom (serverDetails * config.ServerDetails , predicateFilePath , predicateType , markdownFilePath , key , keyId , subjectRepoPath ,
@@ -63,13 +65,13 @@ func (c *createEvidenceCustom) Run() error {
6365 return err
6466 }
6567
66- err = validateSubject ( c . subjectRepoPath )
68+ err = c . validateSubject ( )
6769 if err != nil {
6870 return err
6971 }
7072 err = c .uploadEvidence (evidencePayload , c .subjectRepoPath )
7173 if err != nil {
72- err = handleSubjectNotFound (err , c . subjectRepoPath )
74+ err = c . handleSubjectNotFound (err )
7375 return err
7476 }
7577
@@ -83,6 +85,7 @@ func (c *createEvidenceCustom) processSigstoreBundle() ([]byte, error) {
8385 }
8486
8587 if c .subjectRepoPath == "" {
88+ c .autoSubjectResolution = true
8689 extractedSubject , err := c .extractSubjectFromBundle (sigstoreBundle )
8790 if err != nil {
8891 return nil , err
@@ -100,7 +103,7 @@ func (c *createEvidenceCustom) extractSubjectFromBundle(bundle *bundle.Bundle) (
100103 }
101104
102105 if subject == "" {
103- return "" , errorutils . CheckErrorf ("Subject is not found in the sigstore bundle. Please ensure the bundle contains a valid subject." )
106+ return "" , c . newSubjectError ("Subject is not found in the sigstore bundle. Please ensure the bundle contains a valid subject." )
104107 } else {
105108 clientLog .Info ("Subject " + subject + " is resolved from sigstore bundle." )
106109 }
@@ -117,19 +120,32 @@ func (c *createEvidenceCustom) createDSSEEnvelope() ([]byte, error) {
117120 return envelope , nil
118121}
119122
120- func validateSubject ( subject string ) error {
123+ func ( c * createEvidenceCustom ) validateSubject ( ) error {
121124 // Pattern: must have at least one slash with non-empty sections
122- if matched , _ := regexp .MatchString (`^[^/]+(/[^/]+)+$` , subject ); ! matched {
123- return errorutils . CheckErrorf ("Subject '%s ' is invalid. Subject must be in format: <repo>/<path>/<name> or <repo>/<name>" , subject )
125+ if matched , _ := regexp .MatchString (`^[^/]+(/[^/]+)+$` , c . subjectRepoPath ); ! matched {
126+ return c . newSubjectError ("Subject '" + c . subjectRepoPath + " ' is invalid. Subject must be in format: <repo>/<path>/<name> or <repo>/<name>" )
124127 }
125128 return nil
126129}
127130
128- func handleSubjectNotFound (err error , subject string ) error {
131+ func ( c * createEvidenceCustom ) handleSubjectNotFound (err error ) error {
129132 errStr := err .Error ()
130133 if strings .Contains (errStr , "404 Not Found" ) {
131134 clientLog .Debug ("Server response error:" , err .Error ())
132- return errorutils . CheckErrorf ("Subject '%s ' is not found. Please ensure the subject exists." , subject )
135+ return c . newSubjectError ("Subject '" + c . subjectRepoPath + " ' is not found. Please ensure the subject exists." )
133136 }
134137 return err
135138}
139+
140+ // newSubjectError creates an error with ExitCodeFailNoOp (2) for subject-related failures
141+ // When auto subject resolution is enabled, this allows pipeline calls with gh attestation
142+ // sigstore bundle generation to skip command execution without breaking a pipeline
143+ func (c * createEvidenceCustom ) newSubjectError (message string ) error {
144+ if c .autoSubjectResolution {
145+ return coreutils.CliError {
146+ ExitCode : coreutils .ExitCodeFailNoOp ,
147+ ErrorMsg : message ,
148+ }
149+ }
150+ return errorutils .CheckErrorf (message )
151+ }
0 commit comments