@@ -4,23 +4,22 @@ import (
4
4
"context"
5
5
"errors"
6
6
"fmt"
7
- "net/http"
8
7
"os"
9
8
"os/exec"
10
9
"path"
11
10
"path/filepath"
12
- "sync"
13
- "time"
14
11
15
- "github.com/bradleyfalzon/ghinstallation/v2"
16
12
"github.com/google/go-github/v57/github"
17
13
"github.com/qiniu/reviewbot/config"
14
+ "github.com/qiniu/reviewbot/internal/linters"
18
15
"github.com/qiniu/reviewbot/internal/lintersutil"
19
16
"github.com/qiniu/x/log"
20
17
gitv2 "sigs.k8s.io/prow/pkg/git/v2"
21
18
)
22
19
23
- func (s * Server ) prepareGitRepos (ctx context.Context , org , repo string , num int , platform config.Platform , installationID int64 ) (workspace string , workDir string , err error ) {
20
+ var errUnsupportedPlatform = errors .New ("unsupported platform" )
21
+
22
+ func (s * Server ) prepareGitRepos (ctx context.Context , org , repo string , num int , platform config.Platform , installationID int64 , provider linters.Provider ) (workspace string , workDir string , err error ) {
24
23
log := lintersutil .FromContext (ctx )
25
24
workspace , err = prepareRepoDir (org , repo , num )
26
25
if err != nil {
@@ -38,23 +37,22 @@ func (s *Server) prepareGitRepos(ctx context.Context, org, repo string, num int,
38
37
refs , workDir := s .fixRefs (workspace , org , repo )
39
38
log .Debugf ("refs: %+v" , refs )
40
39
for _ , ref := range refs {
41
- if err := s .handleSingleRef (ctx , ref , org , repo , platform , installationID , num ); err != nil {
40
+ if err := s .handleSingleRef (ctx , ref , org , repo , platform , installationID , num , provider ); err != nil {
42
41
return "" , "" , err
43
42
}
44
43
}
45
44
46
45
return workspace , workDir , nil
47
46
}
48
47
49
- func (s * Server ) handleSingleRef (ctx context.Context , ref config.Refs , org , repo string , platform config.Platform , installationID int64 , num int ) error {
48
+ func (s * Server ) handleSingleRef (ctx context.Context , ref config.Refs , org , repo string , platform config.Platform , installationID int64 , num int , provider linters. Provider ) error {
50
49
opt := gitv2.ClientFactoryOpts {
51
50
CacheDirBase : github .String (s .repoCacheDir ),
52
51
Persist : github .Bool (true ),
53
52
}
54
53
55
- gitConfig := s .newGitConfigBuilder (ref .Org , ref .Repo , platform , installationID ).Build ()
56
- log .Debugf ("git config: %+v" , gitConfig )
57
- if err := s .configureGitAuth (& opt , gitConfig ); err != nil {
54
+ gb := s .newGitConfigBuilder (ref .Org , ref .Repo , platform , installationID , provider )
55
+ if err := gb .configureGitAuth (& opt ); err != nil {
58
56
return fmt .Errorf ("failed to configure git auth: %w" , err )
59
57
}
60
58
@@ -213,188 +211,100 @@ type GitAuth struct {
213
211
GitLabPersonalAccessToken string
214
212
}
215
213
216
- // GitConfig stores the Git repository configuration.
217
- type GitConfig struct {
218
- Platform config.Platform
219
- Host string // gitlab/github host
220
- Auth GitAuth
221
- }
222
-
223
- // githubAppTokenCache implements the cache for GitHub App tokens.
224
- type githubAppTokenCache struct {
225
- sync.RWMutex
226
- tokens map [string ]tokenWithExp // key: installationID, value: token
227
- appAuth * GitHubAppAuth
228
- }
229
-
230
214
// GitConfigBuilder is used to build the Git configuration for a specific request.
231
215
type GitConfigBuilder struct {
232
216
server * Server
233
217
org string
234
218
repo string
219
+ host string
235
220
platform config.Platform
221
+ provider linters.Provider
236
222
// installationID is the installation ID for the GitHub App
237
223
installationID int64
238
224
}
239
225
240
- type tokenWithExp struct {
241
- token string
242
- exp time.Time
243
- }
244
-
245
- // newGitHubAppTokenCache creates a new token cache.
246
- func newGitHubAppTokenCache (appID int64 , privateKeyPath string ) * githubAppTokenCache {
247
- return & githubAppTokenCache {
248
- tokens : make (map [string ]tokenWithExp ),
249
- appAuth : & GitHubAppAuth {
250
- AppID : appID ,
251
- PrivateKeyPath : privateKeyPath ,
252
- },
253
- }
254
- }
255
- func (c * githubAppTokenCache ) getToken (org string , installationID int64 ) (string , error ) {
256
- key := fmt .Sprintf ("%s-%d" , org , installationID )
257
- c .RLock ()
258
- t , exists := c .tokens [key ]
259
- c .RUnlock ()
260
-
261
- if exists && t .exp .After (time .Now ()) {
262
- return t .token , nil
263
- }
264
-
265
- c .Lock ()
266
- defer c .Unlock ()
267
-
268
- // double check
269
- if t , exists := c .tokens [key ]; exists {
270
- if t .exp .After (time .Now ()) {
271
- return t .token , nil
272
- }
273
- }
274
-
275
- // get new token
276
- token , err := c .refreshToken (installationID )
277
- if err != nil {
278
- return "" , err
279
- }
280
-
281
- log .Debugf ("refreshed token for %s, installationID: %d" , org , installationID )
282
- // cache token, 1 hour expiry
283
- c .tokens [key ] = tokenWithExp {
284
- token : token ,
285
- // add a buffer to avoid token expired
286
- exp : time .Now ().Add (time .Hour - time .Minute ),
287
- }
288
-
289
- return token , nil
290
- }
291
-
292
- // refreshToken refresh the GitHub App token.
293
- func (c * githubAppTokenCache ) refreshToken (installationID int64 ) (string , error ) {
294
- tr , err := ghinstallation .NewKeyFromFile (
295
- http .DefaultTransport ,
296
- c .appAuth .AppID ,
297
- installationID ,
298
- c .appAuth .PrivateKeyPath ,
299
- )
300
- if err != nil {
301
- return "" , fmt .Errorf ("failed to create github app transport: %w" , err )
302
- }
303
-
304
- token , err := tr .Token (context .Background ())
305
- if err != nil {
306
- return "" , fmt .Errorf ("failed to get installation token: %w" , err )
307
- }
308
-
309
- return token , nil
310
- }
311
-
312
- func (s * Server ) newGitConfigBuilder (org , repo string , platform config.Platform , installationID int64 ) * GitConfigBuilder {
313
- return & GitConfigBuilder {
226
+ func (s * Server ) newGitConfigBuilder (org , repo string , platform config.Platform , installationID int64 , provider linters.Provider ) * GitConfigBuilder {
227
+ g := & GitConfigBuilder {
314
228
server : s ,
315
229
org : org ,
316
230
repo : repo ,
317
231
platform : platform ,
318
232
installationID : installationID ,
233
+ provider : provider ,
319
234
}
235
+ g .host = g .getHostForPlatform (platform )
236
+ return g
320
237
}
321
238
322
- func (b * GitConfigBuilder ) Build () GitConfig {
323
- config := GitConfig {
324
- Platform : b .platform ,
325
- Host : b .getHostForPlatform (b .platform ),
326
- Auth : b .buildAuth (),
239
+ func (g * GitConfigBuilder ) configureGitAuth (opt * gitv2.ClientFactoryOpts ) error {
240
+ auth := g .buildAuth ()
241
+ opt .Host = g .host
242
+ switch g .platform {
243
+ case config .GitHub :
244
+ return g .configureGitHubAuth (opt , auth )
245
+ case config .GitLab :
246
+ return g .configureGitLabAuth (opt , auth )
247
+ default :
248
+ log .Errorf ("unsupported platform: %s" , g .platform )
249
+ return errUnsupportedPlatform
327
250
}
328
-
329
- return config
330
251
}
331
252
332
- func (b * GitConfigBuilder ) getHostForPlatform (platform config.Platform ) string {
253
+ func (g * GitConfigBuilder ) getHostForPlatform (platform config.Platform ) string {
333
254
switch platform {
334
255
case config .GitLab :
335
- if b .server .gitLabHost != "" {
336
- return b .server .gitLabHost
256
+ if g .server .gitLabHost != "" {
257
+ return g .server .gitLabHost
337
258
}
338
259
return "gitlab.com"
339
- default :
260
+ case config . GitHub :
340
261
return "github.com"
262
+ default :
263
+ log .Errorf ("unsupported platform: %s" , g .platform )
264
+ return ""
341
265
}
342
266
}
343
267
344
- func (b * GitConfigBuilder ) buildAuth () GitAuth {
345
- switch b .platform {
268
+ func (g * GitConfigBuilder ) buildAuth () GitAuth {
269
+ switch g .platform {
346
270
case config .GitHub :
347
- return b .buildGitHubAuth ()
271
+ return g .buildGitHubAuth ()
348
272
case config .GitLab :
349
- return b .buildGitLabAuth ()
273
+ return g .buildGitLabAuth ()
350
274
default :
351
275
return GitAuth {}
352
276
}
353
277
}
354
278
355
- func (b * GitConfigBuilder ) buildGitHubAuth () GitAuth {
356
- if b .server .gitHubAppAuth != nil {
357
- appAuth := * b .server .gitHubAppAuth
358
- appAuth .InstallationID = b .installationID
279
+ func (g * GitConfigBuilder ) buildGitHubAuth () GitAuth {
280
+ if g .server .gitHubAppAuth != nil {
281
+ appAuth := * g .server .gitHubAppAuth
282
+ appAuth .InstallationID = g .installationID
359
283
return GitAuth {
360
284
GitHubAppAuth : & appAuth ,
361
285
}
362
286
}
363
287
364
- if b .server .gitHubPersonalAccessToken != "" {
288
+ if g .server .gitHubPersonalAccessToken != "" {
365
289
return GitAuth {
366
- GitHubAccessToken : b .server .gitHubPersonalAccessToken ,
290
+ GitHubAccessToken : g .server .gitHubPersonalAccessToken ,
367
291
}
368
292
}
369
293
370
294
return GitAuth {}
371
295
}
372
296
373
- func (b * GitConfigBuilder ) buildGitLabAuth () GitAuth {
374
- if b .server .gitLabPersonalAccessToken != "" {
297
+ func (g * GitConfigBuilder ) buildGitLabAuth () GitAuth {
298
+ if g .server .gitLabPersonalAccessToken != "" {
375
299
return GitAuth {
376
- GitLabPersonalAccessToken : b .server .gitLabPersonalAccessToken ,
300
+ GitLabPersonalAccessToken : g .server .gitLabPersonalAccessToken ,
377
301
}
378
302
}
379
303
380
304
return GitAuth {}
381
305
}
382
306
383
- func (s * Server ) configureGitAuth (opt * gitv2.ClientFactoryOpts , gConf GitConfig ) error {
384
- opt .Host = gConf .Host
385
- switch gConf .Platform {
386
- case config .GitHub :
387
- return s .configureGitHubAuth (opt , gConf )
388
- case config .GitLab :
389
- return s .configureGitLabAuth (opt , gConf )
390
- default :
391
- return fmt .Errorf ("unsupported platform: %s" , gConf .Platform )
392
- }
393
- }
394
-
395
- func (s * Server ) configureGitHubAuth (opt * gitv2.ClientFactoryOpts , config GitConfig ) error {
396
- auth := config .Auth
397
-
307
+ func (g * GitConfigBuilder ) configureGitHubAuth (opt * gitv2.ClientFactoryOpts , auth GitAuth ) error {
398
308
switch {
399
309
case auth .GitHubAppAuth != nil :
400
310
opt .UseSSH = github .Bool (false )
@@ -403,7 +313,7 @@ func (s *Server) configureGitHubAuth(opt *gitv2.ClientFactoryOpts, config GitCon
403
313
}
404
314
opt .Token = func (org string ) (string , error ) {
405
315
log .Debugf ("get token for %s, installationID: %d" , org , auth .GitHubAppAuth .InstallationID )
406
- return s . githubAppTokenCache . getToken ( org , auth . GitHubAppAuth . InstallationID )
316
+ return g . provider . GetToken ( )
407
317
}
408
318
return nil
409
319
@@ -423,17 +333,16 @@ func (s *Server) configureGitHubAuth(opt *gitv2.ClientFactoryOpts, config GitCon
423
333
return nil
424
334
}
425
335
426
- func (s * Server ) configureGitLabAuth (opt * gitv2.ClientFactoryOpts , config GitConfig ) error {
427
- auth := config .Auth
428
-
336
+ func (g * GitConfigBuilder ) configureGitLabAuth (opt * gitv2.ClientFactoryOpts , auth GitAuth ) error {
429
337
switch {
430
338
case auth .GitLabPersonalAccessToken != "" :
431
339
opt .UseSSH = github .Bool (false )
432
340
opt .Username = func () (string , error ) {
433
341
return "oauth2" , nil
434
342
}
435
343
opt .Token = func (org string ) (string , error ) {
436
- return auth .GitLabPersonalAccessToken , nil
344
+ log .Infof ("get token for %s, personal access token: %s" , org , auth .GitLabPersonalAccessToken )
345
+ return g .provider .GetToken ()
437
346
}
438
347
return nil
439
348
default :
0 commit comments