@@ -15,7 +15,7 @@ const VulnerabilityIssueTitle = "Sheriff - 🚨 Vulnerability report"
1515
1616// IService is the interface of the GitLab service as needed by sheriff
1717type IService interface {
18- GetProjectList (groupPaths []string , projectPaths []string ) ([]gitlab.Project , error )
18+ GetProjectList (groupPaths []string , projectPaths []string ) (projects []gitlab.Project , warn error )
1919 CloseVulnerabilityIssue (project gitlab.Project ) error
2020 OpenVulnerabilityIssue (project gitlab.Project , report string ) (* gitlab.Issue , error )
2121}
@@ -36,28 +36,28 @@ func New(gitlabToken string) (IService, error) {
3636 return & s , nil
3737}
3838
39- func (s * service ) GetProjectList (groupPaths []string , projectPaths []string ) (projects []gitlab.Project , err error ) {
40- projects , err = s .gatherProjects (projectPaths )
41- if err != nil {
42- log . Error (). Err ( err ). Msg ( "Failed to fetch projects" )
43- err = nil
39+ func (s * service ) GetProjectList (groupPaths []string , projectPaths []string ) (projects []gitlab.Project , warn error ) {
40+ projects , pwarn : = s .gatherProjects (projectPaths )
41+ if pwarn != nil {
42+ pwarn = errors . Join ( errors . New ( "errors occured when gathering projects"), pwarn )
43+ warn = errors . Join ( pwarn , warn )
4444 }
4545
46- groupsProjects , err := s .gatherGroupsProjects (groupPaths )
47- if err != nil {
48- log .Error ().Err (err ).Msg ("Failed to fetch projects from groups" )
49- err = nil
50- } else {
51- projects = append (projects , groupsProjects ... )
46+ groupsProjects , gpwarn := s .gatherGroupsProjects (groupPaths )
47+ if gpwarn != nil {
48+ gpwarn = errors .Join (errors .New ("errors occured when gathering groups projects" ), gpwarn )
49+ warn = errors .Join (gpwarn , warn )
5250 }
5351
52+ projects = append (projects , groupsProjects ... )
53+
5454 // Filter unique projects -- there may be duplicates between groups, other groups and projects
5555 projects = filterUniqueProjects (projects )
5656
5757 projectsNamespaces := pie .Map (projects , func (p gitlab.Project ) string { return p .PathWithNamespace })
5858 log .Info ().Strs ("projects" , projectsNamespaces ).Msg ("Projects to scan" )
5959
60- return
60+ return projects , warn
6161}
6262
6363// CloseVulnerabilityIssue closes the vulnerability issue for the given project
@@ -160,11 +160,10 @@ func (s *service) getProject(path string) (*gitlab.Project, error) {
160160 return nil , errors .Join (fmt .Errorf ("failed to fetch group %v" , groupPath ), err )
161161 }
162162
163- projects , err := s .listGroupProjects (group .ID )
164- if err != nil {
163+ projects , _ , lgerr := s .listGroupProjects (group .ID )
164+ if lgerr != nil {
165165 return nil , errors .Join (fmt .Errorf ("failed to fetch list of projects like %v" , path ), err )
166166 }
167-
168167 for _ , project := range projects {
169168 if project .PathWithNamespace == path {
170169 return & project , nil
@@ -174,35 +173,41 @@ func (s *service) getProject(path string) (*gitlab.Project, error) {
174173 return nil , fmt .Errorf ("project %v not found" , path )
175174}
176175
177- func (s * service ) gatherGroupsProjects (groupPaths []string ) (projects []gitlab.Project , err error ) {
176+ func (s * service ) gatherGroupsProjects (groupPaths []string ) (projects []gitlab.Project , warn error ) {
178177 for _ , groupPath := range groupPaths {
179- group , err := s .getGroup (groupPath )
180- if err != nil {
181- log .Error ().Err (err ).Str ("group" , groupPath ).Msg ("Failed to fetch group" )
182- err = nil
178+ group , gerr := s .getGroup (groupPath )
179+ if gerr != nil {
180+ log .Error ().Err (gerr ).Str ("group" , groupPath ).Msg ("Failed to fetch group" )
181+ gerr = errors .Join (fmt .Errorf ("failed to fetch group %v" , groupPath ), gerr )
182+ warn = errors .Join (gerr , warn )
183183 continue
184184 }
185185
186- groupProjects , err := s .listGroupProjects (group .ID )
187- if err != nil {
188- log .Error ().Err (err ).Str ("group" , groupPath ).Msg ("Failed to fetch projects of group" )
189- err = nil
190- continue
186+ if groupProjects , gpwarn , gperr := s .listGroupProjects (group .ID ); gperr != nil {
187+ log .Error ().Err (gpwarn ).Str ("group" , groupPath ).Msg ("Failed to fetch projects of group" )
188+ gperr = errors .Join (fmt .Errorf ("failed to fetch projects of group %v" , groupPath ), gperr )
189+ warn = errors .Join (gperr , warn )
190+ } else if gpwarn != nil {
191+ gpwarn = errors .Join (fmt .Errorf ("failed to fetch projects of group %v" , groupPath ), gpwarn )
192+ warn = errors .Join (gpwarn , warn )
193+
194+ projects = append (projects , groupProjects ... )
195+ } else {
196+ projects = append (projects , groupProjects ... )
191197 }
192-
193- projects = append (projects , groupProjects ... )
194198 }
195199
196200 return
197201}
198202
199- func (s * service ) gatherProjects (projectPaths []string ) (projects []gitlab.Project , err error ) {
203+ func (s * service ) gatherProjects (projectPaths []string ) (projects []gitlab.Project , warn error ) {
200204 for _ , projectPath := range projectPaths {
201205 log .Info ().Str ("project" , projectPath ).Msg ("Getting project" )
202206 p , err := s .getProject (projectPath )
203207 if err != nil {
204208 log .Error ().Err (err ).Str ("project" , projectPath ).Msg ("Failed to fetch project" )
205- err = nil
209+ err = errors .Join (fmt .Errorf ("failed to fetch project %v" , projectPath ), err )
210+ warn = errors .Join (err , warn )
206211 continue
207212 }
208213
@@ -230,7 +235,7 @@ func (s *service) getVulnerabilityIssue(project gitlab.Project) (issue *gitlab.I
230235}
231236
232237// listGroupProjects returns the list of projects for the given group ID
233- func (s * service ) listGroupProjects (groupID int ) (projects []gitlab.Project , err error ) {
238+ func (s * service ) listGroupProjects (groupID int ) (projects []gitlab.Project , warn error , err error ) {
234239 projectPtrs , response , err := s .client .ListGroupProjects (groupID ,
235240 & gitlab.ListGroupProjectsOptions {
236241 Archived : gitlab .Ptr (false ),
@@ -242,18 +247,19 @@ func (s *service) listGroupProjects(groupID int) (projects []gitlab.Project, err
242247 },
243248 })
244249 if err != nil {
245- return projects , errors .Join (errors .New ("failed to fetch list of projects" ), err )
250+ return nil , nil , errors .Join (errors .New ("failed to fetch list of projects" ), err )
246251 }
247252
248253 projects , errCount := dereferenceProjectsPointers (projectPtrs )
249254 if errCount > 0 {
250- log .Error ().Int ("groupID" , groupID ).Int ("count" , errCount ).Msg ("Found nil projects, skipping them." )
255+ log .Warn ().Int ("groupID" , groupID ).Int ("count" , errCount ).Msg ("Found nil projects, skipping them." )
251256 }
252257
253258 if response .TotalPages > 1 {
254- nextProjects , err := s .listGroupNextProjects (groupID , response .TotalPages )
255- if err != nil {
256- return nil , err
259+ nextProjects , lgwarn := s .listGroupNextProjects (groupID , response .TotalPages )
260+ if lgwarn != nil {
261+ lgwarn = errors .Join (errors .New ("errors occured when fetching next pages" ), lgwarn )
262+ warn = errors .Join (lgwarn , warn )
257263 }
258264
259265 projects = append (projects , nextProjects ... )
@@ -262,10 +268,20 @@ func (s *service) listGroupProjects(groupID int) (projects []gitlab.Project, err
262268 return
263269}
264270
271+ func ToChan [T any ](s []T ) <- chan T {
272+ ch := make (chan T , len (s ))
273+ for _ , e := range s {
274+ ch <- e
275+ }
276+ close (ch )
277+ return ch
278+ }
279+
265280// listGroupNextProjects returns the list of projects for the given group ID from the next pages
266- func (s * service ) listGroupNextProjects (groupID int , totalPages int ) (projects []gitlab.Project , err error ) {
281+ func (s * service ) listGroupNextProjects (groupID int , totalPages int ) (projects []gitlab.Project , warn error ) {
267282 var wg sync.WaitGroup
268283 nextProjectsChan := make (chan []gitlab.Project , totalPages )
284+ warnChan := make (chan error , totalPages )
269285 for p := 2 ; p <= totalPages ; p ++ {
270286 wg .Add (1 )
271287
@@ -284,24 +300,31 @@ func (s *service) listGroupNextProjects(groupID int, totalPages int) (projects [
284300 })
285301 if err != nil {
286302 log .Error ().Err (err ).Int ("groupID" , groupID ).Int ("page" , p ).Msg ("Failed to fetch projects of next page, these projects will be missing." )
303+ warnChan <- err
287304 }
288305
289306 projects , errCount := dereferenceProjectsPointers (projectPtrs )
290307 if errCount > 0 {
291- log .Error ().Int ("groupID" , groupID ).Int ("page" , p ).Int ("count" , errCount ).Msg ("Found nil projects, skipping them." )
308+ log .Warn ().Int ("groupID" , groupID ).Int ("page" , p ).Int ("count" , errCount ).Msg ("Found nil projects, skipping them." )
292309 }
293310
294311 nextProjectsChan <- projects
295312 }(nextProjectsChan )
296313 }
297314 wg .Wait ()
298315 close (nextProjectsChan )
316+ close (warnChan )
299317
300318 // Collect projects
301319 for nextProjects := range nextProjectsChan {
302320 projects = append (projects , nextProjects ... )
303321 }
304322
323+ // Collect warnings
324+ for w := range warnChan {
325+ warn = errors .Join (w , warn )
326+ }
327+
305328 return
306329}
307330
0 commit comments