@@ -8,13 +8,22 @@ import (
88 "net/http"
99 "os"
1010 "strings"
11+ "sync"
1112 "time"
1213
1314 "github.com/cbrown132/driftd/internal/config"
1415 githttp "github.com/go-git/go-git/v5/plumbing/transport/http"
1516 "github.com/golang-jwt/jwt/v5"
1617)
1718
19+ type appTokenCache struct {
20+ mu sync.Mutex
21+ token string
22+ expiry time.Time
23+ }
24+
25+ var tokenCache sync.Map
26+
1827func githubAppAuth (ctx context.Context , cfg * config.GitAuthConfig ) (* githttp.BasicAuth , error ) {
1928 if cfg .GitHubApp == nil {
2029 return nil , fmt .Errorf ("github_app config required" )
@@ -38,6 +47,18 @@ func githubAppToken(ctx context.Context, cfg *config.GitHubAppConfig) (string, e
3847 return "" , fmt .Errorf ("github_app app_id and installation_id required" )
3948 }
4049
50+ cacheKey := fmt .Sprintf ("%d:%d" , cfg .AppID , cfg .InstallationID )
51+ if cached , ok := tokenCache .Load (cacheKey ); ok {
52+ c := cached .(* appTokenCache )
53+ c .mu .Lock ()
54+ if c .token != "" && time .Until (c .expiry ) > 2 * time .Minute {
55+ token := c .token
56+ c .mu .Unlock ()
57+ return token , nil
58+ }
59+ c .mu .Unlock ()
60+ }
61+
4162 key , err := loadPrivateKey (cfg )
4263 if err != nil {
4364 return "" , err
@@ -87,6 +108,10 @@ func githubAppToken(ctx context.Context, cfg *config.GitHubAppConfig) (string, e
87108 if body .Token == "" {
88109 return "" , fmt .Errorf ("github app token missing in response" )
89110 }
111+
112+ expiry := time .Now ().Add (58 * time .Minute )
113+ c := & appTokenCache {token : body .Token , expiry : expiry }
114+ tokenCache .Store (cacheKey , c )
90115 return body .Token , nil
91116}
92117
0 commit comments