@@ -6,11 +6,22 @@ import (
66 "os"
77 "regexp"
88 "strings"
9+
10+ "log/slog"
11+
12+ "github.com/caarlos0/env"
913)
1014
1115var desiredFormat string = "<type>(optional: <scope>): <message>"
1216var defaultConventionTypes []string = []string {"fix" , "feat" , "chore" , "docs" , "build" , "ci" , "refactor" , "perf" , "test" }
1317
18+ type config struct {
19+ GithubEventName string `env:"GITHUB_EVENT_NAME"`
20+ GithubEventPath string `env:"GITHUB_EVENT_PATH"`
21+ Types string `env:"INPUT_TYPES"`
22+ Scope string `env:"INPUT_SCOPE"`
23+ }
24+
1425type PullRequest struct {
1526 Title string `json:"title"`
1627}
@@ -22,132 +33,144 @@ type Event struct {
2233// The pull-request-title-validator function mankes sure that for each pull request created the
2334// title of the pull request adheres to a desired structure, in this case convention commit style.
2435func main () {
25- githubEventName := os .Getenv ("GITHUB_EVENT_NAME" )
26- githubEventPath := os .Getenv ("GITHUB_EVENT_PATH" )
27- conventionTypes := parseTypes (os .Getenv ("INPUT_TYPES" ), defaultConventionTypes )
28- scopes := parseScopes (os .Getenv ("INPUT_SCOPES" ))
2936
30- if githubEventName != "pull_request" && githubEventName != "pull_request_target" {
31- fmt .Printf ("Error: the 'pull_request' trigger type should be used, received '%s'\n " , githubEventName )
37+ var cfg config
38+ if err := env .Parse (& cfg ); err != nil {
39+ fmt .Printf ("unable to parse the environment variables: %v" , err )
40+ os .Exit (1 )
41+ }
42+
43+ logHandler := slog .NewJSONHandler (os .Stdout , & slog.HandlerOptions {
44+ AddSource : false ,
45+ Level : slog .LevelInfo ,
46+ })
47+ logger := slog .New (logHandler )
48+
49+ logger .Info ("starting pull-request-title-validator" , slog .String ("event" , cfg .GithubEventName ))
50+
51+ if cfg .GithubEventName != "pull_request" && cfg .GithubEventName != "pull_request_target" {
52+ logger .Error ("invalid event type" , slog .String ("event" , cfg .GithubEventName ))
3253 os .Exit (1 )
3354 }
3455
35- title := fetchTitle (githubEventPath )
36- titleType , titleScope , titleMessage := splitTitle (title )
56+ title := fetchTitle (logger , cfg . GithubEventPath )
57+ titleType , titleScope , titleMessage := splitTitle (logger , title )
3758
38- if err := checkAgainstConventionTypes (titleType , conventionTypes ); err != nil {
39- fmt .Printf ("The type passed '%s' is not present in the types allowed by the convention: %s\n " , titleType , conventionTypes )
59+ parsedTypes := parseTypes (logger , cfg .Types , defaultConventionTypes )
60+ parsedScope := parseScopes (logger , cfg .Scope )
61+
62+ if err := checkAgainstConventionTypes (logger , titleType , parsedTypes ); err != nil {
63+ logger .Error ("error while checking the type against the allowed types" ,
64+ slog .String ("event name" , cfg .GithubEventName ),
65+ slog .String ("event path" , cfg .GithubEventPath ),
66+ slog .Any ("convention types" , parsedTypes ),
67+ )
4068 os .Exit (1 )
4169 }
4270
43- if err := checkAgainstScopes (titleScope , scopes ); err != nil && len (scopes ) >= 1 {
44- fmt . Println ( err )
71+ if err := checkAgainstScopes (logger , titleScope , parsedScope ); err != nil && len (parsedScope ) >= 1 {
72+ logger . Error ( "error while checking the scope against the allowed scopes" , slog . Any ( "error" , err ) )
4573 os .Exit (1 )
4674 }
4775
48- fmt .Printf ("commit title type used: %s\n " , titleType )
49- fmt .Printf ("commit title scope used: %s\n " , titleScope )
50- fmt .Printf ("commit title message used: %s\n \n " , titleMessage )
51- fmt .Printf ("the commit message adheres to the configured standard" )
76+ logger .Info ("commit title validated successfully" ,
77+ slog .String ("type" , titleType ),
78+ slog .String ("scope" , titleScope ),
79+ slog .String ("message" , titleMessage ),
80+ )
81+ logger .Info ("the commit message adheres to the configured standard" )
5282}
5383
54- func fetchTitle (githubEventPath string ) string {
55-
84+ func fetchTitle (logger * slog.Logger , githubEventPath string ) string {
5685 var event Event
5786 var eventData []byte
5887 var err error
5988
6089 if eventData , err = os .ReadFile (githubEventPath ); err != nil {
61- fmt . Printf ("Problem reading the event json file: %v \n " , err )
62- os .Exit (1 )
90+ logger . Error ("Problem reading the event JSON file" , slog . String ( "path" , githubEventPath ), slog . Any ( "error" , err ) )
91+ os .Exit (1 ) // You might want to return an empty string or handle this error upstream instead.
6392 }
6493
6594 if err = json .Unmarshal (eventData , & event ); err != nil {
66- fmt . Printf ("Failed to unmarshal JSON: %v" , err )
95+ logger . Error ("Failed to unmarshal JSON" , slog . Any ( "error" , err ) )
6796 os .Exit (1 )
6897 }
6998
7099 return event .PullRequest .Title
71100}
72101
73- func splitTitle (title string ) (titleType string , titleScope string , titleMessage string ) {
74-
75- // this part of the function extracts the type
102+ func splitTitle (logger * slog.Logger , title string ) (titleType string , titleScope string , titleMessage string ) {
76103 if index := strings .Index (title , "(" ); strings .Contains (title , "(" ) {
77104 titleType = title [:index ]
78105 } else if index := strings .Index (title , ":" ); strings .Contains (title , ":" ) {
79106 titleType = title [:index ]
80107 } else {
81- fmt .Println ("No type was included in the pull request title." )
82- fmt .Println (desiredFormat )
108+ logger .Error ("No type was included in the pull request title." , slog .String ("desired format" , desiredFormat ))
83109 os .Exit (1 )
84110 }
85111
86- // this part of the function extracts the optional scope
87112 if strings .Contains (title , "(" ) && strings .Contains (title , ")" ) {
88113 scope := regexp .MustCompile (`\(([^)]+)\)` )
89- titleScope = scope .FindStringSubmatch (title )[1 ]
114+ if matches := scope .FindStringSubmatch (title ); len (matches ) > 1 {
115+ titleScope = matches [1 ]
116+ }
90117 }
91118
92- // this part of the function extracts the message
93119 if strings .Contains (title , ":" ) {
94120 titleMessage = strings .SplitAfter (title , ":" )[1 ]
95121 titleMessage = strings .TrimSpace (titleMessage )
96122 } else {
97- fmt .Println ("no message was included in the pull request title." )
98- fmt .Println (desiredFormat )
123+ logger .Error ("No message was included in the pull request title." , slog .String ("desired format" , desiredFormat ))
99124 os .Exit (1 )
100125 }
101126
102127 return
103128}
104129
105- func checkAgainstConventionTypes (titleType string , conventionTypes []string ) error {
130+ func checkAgainstConventionTypes (logger * slog. Logger , titleType string , conventionTypes []string ) error {
106131 for _ , conventionType := range conventionTypes {
107132 if titleType == conventionType {
108133 return nil
109134 }
110135 }
111-
112- return fmt .Errorf ("the type passed '%s' is not present in the types allowed by the convention: %s " , titleType , conventionTypes )
136+ logger . Error ( "Type not allowed by the convention" , slog . String ( "type" , titleType ), slog . Any ( "allowedTypes" , conventionTypes ))
137+ return fmt .Errorf ("type '%s' is not allowed" , titleType )
113138}
114139
115- func checkAgainstScopes (titleScope string , scopes []string ) error {
140+ func checkAgainstScopes (logger * slog. Logger , titleScope string , scopes []string ) error {
116141 for _ , scope := range scopes {
117142 if regexp .MustCompile ("(?i)" + scope + "$" ).MatchString (titleScope ) {
118143 return nil
119144 }
120145 }
121146
122- return fmt .Errorf ("the scope '%s' is not allowed. Please choose from the following patterns of scopes: %s " , titleScope , scopes )
147+ return fmt .Errorf ("scope '%s' is not allowed" , titleScope )
123148}
124149
125- func parseTypes (input string , fallback []string ) []string {
150+ func parseTypes (logger * slog. Logger , input string , fallback []string ) []string {
126151 if input == "" {
127- fmt . Println ( "no custom list of commit types was passed using fallback." )
152+ logger . Warn ( "No custom list of commit types passed, using fallback." )
128153 return fallback
129154 }
155+
130156 types := strings .Split (input , "," )
131157 for i := range types {
132158 types [i ] = strings .TrimSpace (types [i ])
133159 }
134- if len (types ) == 0 {
135- return fallback
136- }
160+
137161 return types
138162}
139163
140- func parseScopes (input string ) []string {
164+ func parseScopes (logger * slog. Logger , input string ) []string {
141165 if input == "" {
142- fmt . Println ( "no custom list of commit scopes was passed using fallback." )
166+ logger . Warn ( "No custom list of commit scopes passed, using fallback." )
143167 return []string {}
144168 }
169+
145170 scopes := strings .Split (input , "," )
146171 for i := range scopes {
147172 scopes [i ] = strings .TrimSpace (scopes [i ])
148173 }
149- if len (scopes ) == 0 {
150- return []string {}
151- }
174+
152175 return scopes
153176}
0 commit comments