@@ -9,11 +9,11 @@ import (
99 "os"
1010 "strings"
1111 "sync"
12+ "time"
1213
1314 "github.com/rs/zerolog/log"
1415
1516 "github.com/boostsecurityio/poutine/opa"
16- "github.com/boostsecurityio/poutine/providers/gitops"
1717 "github.com/boostsecurityio/poutine/providers/pkgsupply"
1818 "github.com/boostsecurityio/poutine/scanner"
1919 "github.com/schollz/progressbar/v3"
@@ -43,18 +43,40 @@ type ScmClient interface {
4343 ParseRepoAndOrg (string ) (string , string , error )
4444}
4545
46- func AnalyzeOrg (ctx context.Context , org string , scmClient ScmClient , numberOfGoroutines * int , formatter Formatter ) error {
47- provider := scmClient .GetProviderName ()
46+ type GitClient interface {
47+ Clone (ctx context.Context , clonePath string , url string , token string , ref string ) error
48+ CommitSHA (clonePath string ) (string , error )
49+ LastCommitDate (ctx context.Context , clonePath string ) (time.Time , error )
50+ GetRemoteOriginURL (ctx context.Context , repoPath string ) (string , error )
51+ GetRepoHeadBranchName (ctx context.Context , repoPath string ) (string , error )
52+ }
53+
54+ func NewAnalyzer (scmClient ScmClient , gitClient GitClient , formatter Formatter ) * Analyzer {
55+ return & Analyzer {
56+ ScmClient : scmClient ,
57+ GitClient : gitClient ,
58+ Formatter : formatter ,
59+ }
60+ }
61+
62+ type Analyzer struct {
63+ ScmClient ScmClient
64+ GitClient GitClient
65+ Formatter Formatter
66+ }
67+
68+ func (a * Analyzer ) AnalyzeOrg (ctx context.Context , org string , numberOfGoroutines * int ) error {
69+ provider := a .ScmClient .GetProviderName ()
4870
49- providerVersion , err := scmClient .GetProviderVersion (ctx )
71+ providerVersion , err := a . ScmClient .GetProviderVersion (ctx )
5072 if err != nil {
5173 log .Debug ().Err (err ).Msgf ("Failed to get provider version for %s" , provider )
5274 }
5375
5476 log .Debug ().Msgf ("Provider: %s, Version: %s" , provider , providerVersion )
5577
5678 log .Debug ().Msgf ("Fetching list of repositories for organization: %s on %s" , org , provider )
57- orgReposBatches := scmClient .GetOrgRepos (ctx , org )
79+ orgReposBatches := a . ScmClient .GetOrgRepos (ctx , org )
5880
5981 opaClient , _ := opa .NewOpa ()
6082 pkgsupplyClient := pkgsupply .NewStaticClient ()
@@ -96,14 +118,14 @@ func AnalyzeOrg(ctx context.Context, org string, scmClient ScmClient, numberOfGo
96118 defer sem .Release (1 )
97119 defer wg .Done ()
98120 repoNameWithOwner := repo .GetRepoIdentifier ()
99- tempDir , err := cloneRepoToTemp (ctx , repo .BuildGitURL (scmClient . GetProviderBaseURL ()), scmClient .GetToken ())
121+ tempDir , err := a . cloneRepoToTemp (ctx , repo .BuildGitURL (a . ScmClient . GetProviderBaseURL ()), a . ScmClient .GetToken ())
100122 if err != nil {
101123 log .Error ().Err (err ).Str ("repo" , repoNameWithOwner ).Msg ("failed to clone repo" )
102124 return
103125 }
104126 defer os .RemoveAll (tempDir )
105127
106- pkg , err := generatePackageInsights (ctx , tempDir , repo )
128+ pkg , err := a . generatePackageInsights (ctx , tempDir , repo )
107129 if err != nil {
108130 errChan <- err
109131 return
@@ -132,21 +154,21 @@ func AnalyzeOrg(ctx context.Context, org string, scmClient ScmClient, numberOfGo
132154
133155 fmt .Print ("\n \n " )
134156
135- return finalizeAnalysis (ctx , inventory , formatter )
157+ return a . finalizeAnalysis (ctx , inventory )
136158}
137159
138- func AnalyzeRepo (ctx context.Context , repoString string , scmClient ScmClient , formatter Formatter ) error {
139- org , repoName , err := scmClient .ParseRepoAndOrg (repoString )
160+ func ( a * Analyzer ) AnalyzeRepo (ctx context.Context , repoString string ) error {
161+ org , repoName , err := a . ScmClient .ParseRepoAndOrg (repoString )
140162 if err != nil {
141163 return fmt .Errorf ("failed to parse repository: %w" , err )
142164 }
143- repo , err := scmClient .GetRepo (ctx , org , repoName )
165+ repo , err := a . ScmClient .GetRepo (ctx , org , repoName )
144166 if err != nil {
145167 return fmt .Errorf ("failed to get repo: %w" , err )
146168 }
147169 provider := repo .GetProviderName ()
148170
149- providerVersion , err := scmClient .GetProviderVersion (ctx )
171+ providerVersion , err := a . ScmClient .GetProviderVersion (ctx )
150172 if err != nil {
151173 log .Debug ().Err (err ).Msgf ("Failed to get provider version for %s" , provider )
152174 }
@@ -166,13 +188,13 @@ func AnalyzeRepo(ctx context.Context, repoString string, scmClient ScmClient, fo
166188 progressbar .OptionSetWriter (os .Stderr ),
167189 )
168190
169- tempDir , err := cloneRepoToTemp (ctx , repo .BuildGitURL (scmClient . GetProviderBaseURL ()), scmClient .GetToken ())
191+ tempDir , err := a . cloneRepoToTemp (ctx , repo .BuildGitURL (a . ScmClient . GetProviderBaseURL ()), a . ScmClient .GetToken ())
170192 if err != nil {
171193 return err
172194 }
173195 defer os .RemoveAll (tempDir )
174196
175- pkg , err := generatePackageInsights (ctx , tempDir , repo )
197+ pkg , err := a . generatePackageInsights (ctx , tempDir , repo )
176198 if err != nil {
177199 return err
178200 }
@@ -184,21 +206,21 @@ func AnalyzeRepo(ctx context.Context, repoString string, scmClient ScmClient, fo
184206 _ = bar .Add (1 )
185207
186208 fmt .Print ("\n \n " )
187- return finalizeAnalysis (ctx , inventory , formatter )
209+ return a . finalizeAnalysis (ctx , inventory )
188210}
189211
190- func AnalyzeLocalRepo (ctx context.Context , repoPath string , scmClient ScmClient , formatter Formatter ) error {
191- org , repoName , err := scmClient .ParseRepoAndOrg (repoPath )
212+ func ( a * Analyzer ) AnalyzeLocalRepo (ctx context.Context , repoPath string ) error {
213+ org , repoName , err := a . ScmClient .ParseRepoAndOrg (repoPath )
192214 if err != nil {
193215 return fmt .Errorf ("failed to parse repository: %w" , err )
194216 }
195- repo , err := scmClient .GetRepo (ctx , org , repoName )
217+ repo , err := a . ScmClient .GetRepo (ctx , org , repoName )
196218 if err != nil {
197219 return fmt .Errorf ("failed to get repo: %w" , err )
198220 }
199221 provider := repo .GetProviderName ()
200222
201- providerVersion , err := scmClient .GetProviderVersion (ctx )
223+ providerVersion , err := a . ScmClient .GetProviderVersion (ctx )
202224 if err != nil {
203225 log .Debug ().Err (err ).Msgf ("Failed to get provider version for %s" , provider )
204226 }
@@ -218,7 +240,7 @@ func AnalyzeLocalRepo(ctx context.Context, repoPath string, scmClient ScmClient,
218240 progressbar .OptionSetWriter (os .Stderr ),
219241 )
220242
221- pkg , err := generatePackageInsights (ctx , repoPath , repo )
243+ pkg , err := a . generatePackageInsights (ctx , repoPath , repo )
222244 if err != nil {
223245 return err
224246 }
@@ -230,40 +252,39 @@ func AnalyzeLocalRepo(ctx context.Context, repoPath string, scmClient ScmClient,
230252 _ = bar .Add (1 )
231253
232254 fmt .Print ("\n \n " )
233- return finalizeAnalysis (ctx , inventory , formatter )
255+ return a . finalizeAnalysis (ctx , inventory )
234256}
235257
236258type Formatter interface {
237259 Format (ctx context.Context , report * opa.FindingsResult , packages []* models.PackageInsights ) error
238260}
239261
240- func finalizeAnalysis (ctx context.Context , inventory * scanner.Inventory , formatter Formatter ) error {
262+ func ( a * Analyzer ) finalizeAnalysis (ctx context.Context , inventory * scanner.Inventory ) error {
241263 report , err := inventory .Findings (ctx )
242264 if err != nil {
243265 return err
244266 }
245267
246- err = formatter .Format (ctx , report , inventory .Packages )
268+ err = a . Formatter .Format (ctx , report , inventory .Packages )
247269 if err != nil {
248270 return err
249271 }
250272
251273 return nil
252274}
253275
254- func generatePackageInsights (ctx context.Context , tempDir string , repo Repository ) (* models.PackageInsights , error ) {
255- gitClient := gitops .NewGitClient (nil )
256- commitDate , err := gitClient .LastCommitDate (ctx , tempDir )
276+ func (a * Analyzer ) generatePackageInsights (ctx context.Context , tempDir string , repo Repository ) (* models.PackageInsights , error ) {
277+ commitDate , err := a .GitClient .LastCommitDate (ctx , tempDir )
257278 if err != nil {
258279 return nil , fmt .Errorf ("failed to get last commit date: %w" , err )
259280 }
260281
261- commitSha , err := gitClient .CommitSHA (tempDir )
282+ commitSha , err := a . GitClient .CommitSHA (tempDir )
262283 if err != nil {
263284 return nil , fmt .Errorf ("failed to get commit SHA: %w" , err )
264285 }
265286
266- headBranchName , err := gitClient .GetRepoHeadBranchName (ctx , tempDir )
287+ headBranchName , err := a . GitClient .GetRepoHeadBranchName (ctx , tempDir )
267288 if err != nil {
268289 return nil , fmt .Errorf ("failed to get head branch name: %w" , err )
269290 }
@@ -284,14 +305,13 @@ func generatePackageInsights(ctx context.Context, tempDir string, repo Repositor
284305 return pkg , nil
285306}
286307
287- func cloneRepoToTemp (ctx context.Context , gitURL string , token string ) (string , error ) {
308+ func ( a * Analyzer ) cloneRepoToTemp (ctx context.Context , gitURL string , token string ) (string , error ) {
288309 tempDir , err := os .MkdirTemp ("" , TEMP_DIR_PREFIX )
289310 if err != nil {
290311 return "" , fmt .Errorf ("failed to create temp directory: %w" , err )
291312 }
292313
293- gitClient := gitops .NewGitClient (nil )
294- err = gitClient .Clone (ctx , tempDir , gitURL , token , "HEAD" )
314+ err = a .GitClient .Clone (ctx , tempDir , gitURL , token , "HEAD" )
295315 if err != nil {
296316 os .RemoveAll (tempDir ) // Clean up if cloning fails
297317 return "" , fmt .Errorf ("failed to clone repo: %s" , err )
0 commit comments