@@ -16,6 +16,7 @@ import (
1616 "unicode/utf8"
1717
1818 "github.com/google/go-github/v56/github"
19+ "github.com/haproxytech/check-commit/v5/junit"
1920 gitlab "gitlab.com/gitlab-org/api/client-go"
2021
2122 git "github.com/go-git/go-git/v5"
@@ -90,24 +91,33 @@ TagOrder:
9091
9192var ErrSubjectMessageFormat = errors .New ("invalid subject message format" )
9293
93- func checkSubjectText (subject string ) error {
94+ func checkSubjectText (subject string , junitSuite junit. Interface ) error {
9495 subjectLen := utf8 .RuneCountInString (subject )
9596 subjectParts := strings .Fields (subject )
9697 subjectPartsLen := len (subjectParts )
9798
9899 if subject != strings .Join (subjectParts , " " ) {
100+ junitSuite .AddMessageFailed (ErrSubjectMessageFormat .Error (), "malformatted subject string (trailing or double spaces?)" , fmt .Sprintf ("subject: %s" , subject ))
99101 return fmt .Errorf (
100102 "malformatted subject string (trailing or double spaces?): '%s' (%w)" ,
101103 subject , ErrSubjectMessageFormat )
102104 }
103105
104106 if subjectPartsLen < MINSUBJECTPARTS || subjectPartsLen > MAXSUBJECTPARTS {
107+ junitSuite .AddMessageFailed (
108+ ErrSubjectMessageFormat .Error (),
109+ fmt .Sprintf ("subject word count out of bounds [words %d < %d < %d]" , MINSUBJECTPARTS , subjectPartsLen , MAXSUBJECTPARTS ),
110+ fmt .Sprintf ("subject: %s" , subject ))
105111 return fmt .Errorf (
106112 "subject word count out of bounds [words %d < %d < %d] '%s': %w" ,
107113 MINSUBJECTPARTS , subjectPartsLen , MAXSUBJECTPARTS , subjectParts , ErrSubjectMessageFormat )
108114 }
109115
110116 if subjectLen < MINSUBJECTLEN || subjectLen > MAXSUBJECTLEN {
117+ junitSuite .AddMessageFailed (
118+ ErrSubjectMessageFormat .Error (),
119+ fmt .Sprintf ("subject length out of bounds [len %d < %d < %d]" , MINSUBJECTLEN , subjectLen , MAXSUBJECTLEN ),
120+ fmt .Sprintf ("subject: %s" , subject ))
111121 return fmt .Errorf (
112122 "subject length out of bounds [len %d < %d < %d] '%s': %w" ,
113123 MINSUBJECTLEN , subjectLen , MAXSUBJECTLEN , subject , ErrSubjectMessageFormat )
@@ -128,6 +138,7 @@ func (c CommitPolicyConfig) CheckPatchTypes(tag, severity string, patchTypeName
128138 }
129139
130140 if c .PatchTypes [patchTypeName ].Scope == "" {
141+
131142 log .Printf ("unable to verify severity %s without definitions" , severity )
132143
133144 break // subject has severity but there is no definition to verify it
@@ -148,10 +159,11 @@ func (c CommitPolicyConfig) CheckPatchTypes(tag, severity string, patchTypeName
148159
149160var ErrTagScope = errors .New ("invalid tag and or severity" )
150161
151- func (c CommitPolicyConfig ) CheckSubject (rawSubject []byte ) error {
162+ func (c CommitPolicyConfig ) CheckSubject (rawSubject []byte , junitSuite junit. Interface ) error {
152163 // check for ascii-only before anything else
153164 for i := 0 ; i < len (rawSubject ); i ++ {
154165 if rawSubject [i ] > unicode .MaxASCII {
166+ junitSuite .AddMessageFailed ("" , "non-ascii characters detected in commit subject" , fmt .Sprintf ("subject: %s" , rawSubject ))
155167 log .Printf ("non-ascii characters detected in in subject:\n %s" , hex .Dump (rawSubject ))
156168
157169 return fmt .Errorf ("non-ascii characters in commit subject: %w" , ErrTagScope )
@@ -174,6 +186,7 @@ func (c CommitPolicyConfig) CheckSubject(rawSubject []byte) error {
174186 submatch := r .FindSubmatchIndex (rawSubject )
175187 if len (submatch ) == 0 { // no match
176188 if ! tagOK {
189+ junitSuite .AddMessageFailed ("" , "invalid or missing tag/severity in commit message" , fmt .Sprintf ("subject: %s" , rawSubject ))
177190 log .Printf ("unable to find match in %s\n " , rawSubject )
178191
179192 return fmt .Errorf ("invalid tag or no tag found, searched through [%s]: %w" ,
@@ -199,6 +212,7 @@ func (c CommitPolicyConfig) CheckSubject(rawSubject []byte) error {
199212 candidates = append (candidates , string (tagPart ))
200213
201214 if ! tagOK {
215+ junitSuite .AddMessageFailed ("" , "invalid tag/severity in commit message" , fmt .Sprintf ("subject: %s" , rawSubject ))
202216 log .Printf ("unable to find match in %s\n " , candidates )
203217
204218 return fmt .Errorf ("invalid tag or no tag found, searched through [%s]: %w" ,
@@ -208,10 +222,11 @@ func (c CommitPolicyConfig) CheckSubject(rawSubject []byte) error {
208222
209223 submatch := r .FindSubmatchIndex (rawSubject )
210224 if len (submatch ) != 0 { // no match
225+ junitSuite .AddMessageFailed ("" , "unprocessed tags detected in commit message" , fmt .Sprintf ("subject: %s" , rawSubject ))
211226 return fmt .Errorf ("detected unprocessed tags, %w" , ErrTagScope )
212227 }
213228
214- return checkSubjectText (string (rawSubject ))
229+ return checkSubjectText (string (rawSubject ), junitSuite )
215230}
216231
217232func (c CommitPolicyConfig ) IsEmpty () bool {
@@ -268,7 +283,7 @@ func LoadCommitPolicy(filename string) (CommitPolicyConfig, error) {
268283 return commitPolicy , nil
269284}
270285
271- func getGithubCommitData () ([]string , []string , []map [string ]string , error ) {
286+ func getGithubCommitData (junitSuite junit. Interface ) ([]string , []string , []map [string ]string , error ) {
272287 token := os .Getenv ("API_TOKEN" )
273288 repo := os .Getenv ("GITHUB_REPOSITORY" )
274289 ref := os .Getenv ("GITHUB_REF" )
@@ -285,22 +300,26 @@ func getGithubCommitData() ([]string, []string, []map[string]string, error) {
285300 if event == "pull_request" {
286301 repoSlice := strings .SplitN (repo , "/" , 2 )
287302 if len (repoSlice ) < 2 {
303+ junitSuite .AddMessageFailed ("" , "error fetching owner and project from repo" , fmt .Sprintf ("invalid repository format: %s" , repo ))
288304 return nil , nil , nil , fmt .Errorf ("error fetching owner and project from repo %s" , repo )
289305 }
290306 owner := repoSlice [0 ]
291307 project := repoSlice [1 ]
292308
293309 refSlice := strings .SplitN (ref , "/" , 4 )
294310 if len (refSlice ) < 3 {
295- return nil , nil , nil , fmt .Errorf ("error fetching pr from ref %s" , ref )
311+ junitSuite .AddMessageFailed ("" , "error fetching PR number from ref" , fmt .Sprintf ("invalid ref format: %s" , ref ))
312+ return nil , nil , nil , fmt .Errorf ("error fetching PR from ref %s" , ref )
296313 }
297314 prNo , err := strconv .Atoi (refSlice [2 ])
298315 if err != nil {
299- return nil , nil , nil , fmt .Errorf ("Error fetching pr number from %s: %w" , refSlice [2 ], err )
316+ junitSuite .AddMessageFailed ("" , "error fetching PR number from ref" , fmt .Sprintf ("invalid pr number: %s" , refSlice [2 ]))
317+ return nil , nil , nil , fmt .Errorf ("Error fetching PR number from %s: %w" , refSlice [2 ], err )
300318 }
301319
302320 commits , _ , err := githubClient .PullRequests .ListCommits (ctx , owner , project , prNo , & github.ListOptions {})
303321 if err != nil {
322+ junitSuite .AddMessageFailed ("" , "error fetching commits" , err .Error ())
304323 return nil , nil , nil , fmt .Errorf ("error fetching commits: %w" , err )
305324 }
306325
@@ -315,6 +334,7 @@ func getGithubCommitData() ([]string, []string, []map[string]string, error) {
315334 }
316335 if len (l ) > 1 {
317336 if l [1 ] != "" {
337+ junitSuite .AddMessageFailed ("" , "empty line between subject and body is required" , fmt .Sprintf ("%s %s" , hash , l [0 ]))
318338 return nil , nil , nil , fmt .Errorf ("empty line between subject and body is required: %s %s" , hash , l [0 ])
319339 }
320340 }
@@ -326,6 +346,7 @@ func getGithubCommitData() ([]string, []string, []map[string]string, error) {
326346
327347 files , _ , err := githubClient .PullRequests .ListFiles (ctx , owner , project , prNo , & github.ListOptions {})
328348 if err != nil {
349+ junitSuite .AddMessageFailed ("" , "error fetching files" , err .Error ())
329350 return nil , nil , nil , fmt .Errorf ("error fetching files: %w" , err )
330351 }
331352 content := map [string ]string {}
@@ -339,20 +360,23 @@ func getGithubCommitData() ([]string, []string, []map[string]string, error) {
339360 }
340361 return subjects , messages , diffs , nil
341362 } else {
363+ junitSuite .AddMessageFailed ("" , "unsupported event name" , fmt .Sprintf ("unsupported event name: %s" , event ))
342364 return nil , nil , nil , fmt .Errorf ("unsupported event name: %s" , event )
343365 }
344366}
345367
346- func getLocalCommitData () ([]string , []string , []map [string ]string , error ) {
368+ func getLocalCommitData (junitSuite junit. Interface ) ([]string , []string , []map [string ]string , error ) {
347369 repo , err := git .PlainOpen ("." )
348370 if err != nil {
371+ junitSuite .AddMessageFailed ("" , "error opening local git repository" , err .Error ())
349372 return nil , nil , nil , err
350373 }
351374
352375 iter , err := repo .Log (& git.LogOptions {
353376 Order : git .LogOrderCommitterTime ,
354377 })
355378 if err != nil {
379+ junitSuite .AddMessageFailed ("" , "error getting git log iterator" , err .Error ())
356380 return nil , nil , nil , err
357381 }
358382
@@ -372,6 +396,7 @@ func getLocalCommitData() ([]string, []string, []map[string]string, error) {
372396 break
373397 }
374398 if err != nil {
399+ junitSuite .AddMessageFailed ("" , "error iterating through git commits" , err .Error ())
375400 return nil , nil , nil , err
376401 }
377402 if committer == "" {
@@ -392,6 +417,7 @@ func getLocalCommitData() ([]string, []string, []map[string]string, error) {
392417 }
393418 if len (l ) > 1 {
394419 if l [1 ] != "" {
420+ junitSuite .AddMessageFailed ("" , "empty line between subject and body is required" , fmt .Sprintf ("%s %s" , commitHash , l [0 ]))
395421 return nil , nil , nil , fmt .Errorf ("empty line between subject and body is required: %s %s" , commitHash , l [0 ])
396422 }
397423 }
@@ -409,13 +435,15 @@ func getLocalCommitData() ([]string, []string, []map[string]string, error) {
409435 tree2 , _ := commit2 .Tree ()
410436 changes , err := object .DiffTree (tree2 , tree1 )
411437 if err != nil {
438+ junitSuite .AddMessageFailed ("" , "error getting git commit changes" , err .Error ())
412439 return nil , nil , nil , err
413440 }
414441
415442 // Print the list of changed files and their content (patch)
416443 for _ , change := range changes {
417444 patch , err := change .Patch ()
418445 if err != nil {
446+ junitSuite .AddMessageFailed ("" , "error getting git patch" , err .Error ())
419447 return nil , nil , nil , err
420448 }
421449 for _ , file := range patch .FilePatches () {
@@ -455,28 +483,32 @@ func cleanGitPatch(patch string) string {
455483 return patch
456484}
457485
458- func getGitlabCommitData () ([]string , []string , []map [string ]string , error ) {
486+ func getGitlabCommitData (junitSuite junit. Interface ) ([]string , []string , []map [string ]string , error ) {
459487 gitlab_url := os .Getenv ("CI_API_V4_URL" )
460488 token := os .Getenv ("API_TOKEN" )
461489 mri := os .Getenv ("CI_MERGE_REQUEST_IID" )
462490 project := os .Getenv ("CI_MERGE_REQUEST_PROJECT_ID" )
463491
464492 gitlabClient , err := gitlab .NewClient (token , gitlab .WithBaseURL (gitlab_url ))
465493 if err != nil {
466- log .Fatalf ("Failed to create gitlab client: %v" , err )
494+ junitSuite .AddMessageFailed ("" , "failed to create gitlab client" , err .Error ())
495+ return nil , nil , nil , fmt .Errorf ("failed to create gitlab client: %w" , err )
467496 }
468497
469498 mrIID , err := strconv .Atoi (mri )
470499 if err != nil {
500+ junitSuite .AddMessageFailed ("" , "invalid merge request id" , err .Error ())
471501 return nil , nil , nil , fmt .Errorf ("invalid merge request id %s" , mri )
472502 }
473503
474504 projectID , err := strconv .Atoi (project )
475505 if err != nil {
506+ junitSuite .AddMessageFailed ("" , "invalid project id" , err .Error ())
476507 return nil , nil , nil , fmt .Errorf ("invalid project id %s" , project )
477508 }
478509 commits , _ , err := gitlabClient .MergeRequests .GetMergeRequestCommits (projectID , mrIID , & gitlab.GetMergeRequestCommitsOptions {})
479510 if err != nil {
511+ junitSuite .AddMessageFailed ("" , "error fetching commits" , err .Error ())
480512 return nil , nil , nil , fmt .Errorf ("error fetching commits: %w" , err )
481513 }
482514
@@ -489,6 +521,7 @@ func getGitlabCommitData() ([]string, []string, []map[string]string, error) {
489521 if len (l ) > 0 {
490522 if len (l ) > 1 {
491523 if l [1 ] != "" {
524+ junitSuite .AddMessageFailed ("" , "empty line between subject and body is required" , fmt .Sprintf ("%s %s" , hash , l [0 ]))
492525 return nil , nil , nil , fmt .Errorf ("empty line between subject and body is required: %s %s" , hash , l [0 ])
493526 }
494527 }
@@ -497,6 +530,7 @@ func getGitlabCommitData() ([]string, []string, []map[string]string, error) {
497530 messages = append (messages , c .Message )
498531 diff , _ , err := gitlabClient .MergeRequests .ListMergeRequestDiffs (projectID , mrIID , & gitlab.ListMergeRequestDiffsOptions {})
499532 if err != nil {
533+ junitSuite .AddMessageFailed ("" , "error fetching commit changes" , err .Error ())
500534 return nil , nil , nil , fmt .Errorf ("error fetching commit changes: %w" , err )
501535 }
502536 content := map [string ]string {}
@@ -513,25 +547,25 @@ func getGitlabCommitData() ([]string, []string, []map[string]string, error) {
513547 return subjects , messages , diffs , nil
514548}
515549
516- func getCommitData (repoEnv string ) ([]string , []string , []map [string ]string , error ) {
550+ func getCommitData (repoEnv string , junitSuite junit. Interface ) ([]string , []string , []map [string ]string , error ) {
517551 if repoEnv == GITHUB {
518- return getGithubCommitData ()
552+ return getGithubCommitData (junitSuite )
519553 } else if repoEnv == GITLAB {
520- return getGitlabCommitData ()
554+ return getGitlabCommitData (junitSuite )
521555 } else if repoEnv == LOCAL {
522- return getLocalCommitData ()
556+ return getLocalCommitData (junitSuite )
523557 }
524558 return nil , nil , nil , fmt .Errorf ("unrecognized git environment %s" , repoEnv )
525559}
526560
527561var ErrSubjectList = errors .New ("subjects contain errors" )
528562
529- func (c CommitPolicyConfig ) CheckSubjectList (subjects []string ) error {
563+ func (c CommitPolicyConfig ) CheckSubjectList (subjects []string , junitSuite junit. Interface ) error {
530564 errors := false
531565
532566 for _ , subject := range subjects {
533567 subject = strings .Trim (subject , "'" )
534- if err := c .CheckSubject ([]byte (subject )); err != nil {
568+ if err := c .CheckSubject ([]byte (subject ), junitSuite ); err != nil {
535569 log .Printf ("%s, original subject message '%s'" , err , subject )
536570
537571 errors = true
0 commit comments