Skip to content

Commit 1e9f88c

Browse files
committed
Expose TokenSource through ClientCreators
This installation token retrievable from TokenSource can be used to clone repositories.
1 parent 933ee56 commit 1e9f88c

File tree

3 files changed

+47
-30
lines changed

3 files changed

+47
-30
lines changed

example/issue_comment.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func (h *PRCommentHandler) Handle(ctx context.Context, eventType, deliveryID str
5858
return nil
5959
}
6060

61-
client, err := h.NewInstallationClient(installationID)
61+
client, _, err := h.NewInstallationClient(installationID)
6262
if err != nil {
6363
return err
6464
}

githubapp/caching_client_creator.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ const (
2727
DefaultCachingClientCapacity = 64
2828
)
2929

30+
type clientTokenSource struct {
31+
client *github.Client
32+
tokenSource TokenSource
33+
}
34+
35+
type clientV4TokenSource struct {
36+
client *githubv4.Client
37+
tokenSource TokenSource
38+
}
39+
3040
// NewDefaultCachingClientCreator returns a ClientCreator using values from the
3141
// configuration or other defaults.
3242
func NewDefaultCachingClientCreator(c Config, opts ...ClientOption) (ClientCreator, error) {
@@ -70,42 +80,42 @@ func (c *cachingClientCreator) NewAppV4Client() (*githubv4.Client, error) {
7080
return c.delegate.NewAppV4Client()
7181
}
7282

73-
func (c *cachingClientCreator) NewInstallationClient(installationID int64) (*github.Client, error) {
83+
func (c *cachingClientCreator) NewInstallationClient(installationID int64) (*github.Client, TokenSource, error) {
7484
// if client is in cache, return it
7585
key := c.toCacheKey("v3", installationID)
7686
val, ok := c.cachedClients.Get(key)
7787
if ok {
78-
if client, ok := val.(*github.Client); ok {
79-
return client, nil
88+
if cts, ok := val.(clientTokenSource); ok {
89+
return cts.client, cts.tokenSource, nil
8090
}
8191
}
8292

8393
// otherwise, create and return
84-
client, err := c.delegate.NewInstallationClient(installationID)
94+
client, ts, err := c.delegate.NewInstallationClient(installationID)
8595
if err != nil {
86-
return nil, err
96+
return nil, nil, err
8797
}
88-
c.cachedClients.Add(key, client)
89-
return client, nil
98+
c.cachedClients.Add(key, clientTokenSource{client, ts})
99+
return client, ts, nil
90100
}
91101

92-
func (c *cachingClientCreator) NewInstallationV4Client(installationID int64) (*githubv4.Client, error) {
102+
func (c *cachingClientCreator) NewInstallationV4Client(installationID int64) (*githubv4.Client, TokenSource, error) {
93103
// if client is in cache, return it
94104
key := c.toCacheKey("v4", installationID)
95105
val, ok := c.cachedClients.Get(key)
96106
if ok {
97-
if client, ok := val.(*githubv4.Client); ok {
98-
return client, nil
107+
if cts, ok := val.(clientV4TokenSource); ok {
108+
return cts.client, cts.tokenSource, nil
99109
}
100110
}
101111

102112
// otherwise, create and return
103-
client, err := c.delegate.NewInstallationV4Client(installationID)
113+
client, ts, err := c.delegate.NewInstallationV4Client(installationID)
104114
if err != nil {
105-
return nil, err
115+
return nil, nil, err
106116
}
107-
c.cachedClients.Add(key, client)
108-
return client, nil
117+
c.cachedClients.Add(key, clientV4TokenSource{client, ts})
118+
return client, ts, nil
109119
}
110120

111121
func (c *cachingClientCreator) NewTokenClient(token string) (*github.Client, error) {

githubapp/client_creator.go

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ type ClientCreator interface {
7575
// * the installation ID is the ID that is shown in the URL of https://{githubURL}/settings/installations/{#}
7676
// (navigate to the "installations" page without the # and go to the app's page to see the number)
7777
// * the key bytes must be a PEM-encoded PKCS1 or PKCS8 private key for the application
78-
NewInstallationClient(installationID int64) (*github.Client, error)
78+
NewInstallationClient(installationID int64) (*github.Client, TokenSource, error)
7979

8080
// NewInstallationV4Client returns an installation-authenticated v4 API client, similar to NewInstallationClient.
81-
NewInstallationV4Client(installationID int64) (*githubv4.Client, error)
81+
NewInstallationV4Client(installationID int64) (*githubv4.Client, TokenSource, error)
8282

8383
// NewTokenClient returns a *github.Client that uses the passed in OAuth token for authentication.
8484
NewTokenClient(token string) (*github.Client, error)
@@ -209,9 +209,9 @@ func (c *clientCreator) NewAppV4Client() (*githubv4.Client, error) {
209209
return client, nil
210210
}
211211

212-
func (c *clientCreator) NewInstallationClient(installationID int64) (*github.Client, error) {
212+
func (c *clientCreator) NewInstallationClient(installationID int64) (*github.Client, TokenSource, error) {
213213
base := c.newHTTPClient()
214-
installation, transportError := newInstallation(c.integrationID, installationID, c.privKeyBytes, c.v3BaseURL)
214+
installation, ghTransport, transportError := newInstallation(c.integrationID, installationID, c.privKeyBytes, c.v3BaseURL)
215215

216216
middleware := []ClientMiddleware{installation}
217217
if c.cacheFunc != nil {
@@ -220,30 +220,34 @@ func (c *clientCreator) NewInstallationClient(installationID int64) (*github.Cli
220220

221221
client, err := c.newClient(base, middleware, fmt.Sprintf("installation: %d", installationID), installationID)
222222
if err != nil {
223-
return nil, err
223+
return nil, nil, err
224224
}
225225
if *transportError != nil {
226-
return nil, *transportError
226+
return nil, nil, *transportError
227227
}
228-
return client, nil
228+
return client, *ghTransport, nil
229229
}
230230

231-
func (c *clientCreator) NewInstallationV4Client(installationID int64) (*githubv4.Client, error) {
231+
func (c *clientCreator) NewInstallationV4Client(installationID int64) (*githubv4.Client, TokenSource, error) {
232232
base := c.newHTTPClient()
233-
installation, transportError := newInstallation(c.integrationID, installationID, c.privKeyBytes, c.v3BaseURL)
233+
installation, ghTransport, transportError := newInstallation(c.integrationID, installationID, c.privKeyBytes, c.v3BaseURL)
234234

235235
// The v4 API primarily uses POST requests (except for introspection queries)
236236
// which we cannot cache, so don't construct the middleware
237237
middleware := []ClientMiddleware{installation}
238238

239239
client, err := c.newV4Client(base, middleware, fmt.Sprintf("installation: %d", installationID))
240240
if err != nil {
241-
return nil, err
241+
return nil, nil, err
242242
}
243243
if *transportError != nil {
244-
return nil, *transportError
244+
return nil, nil, *transportError
245245
}
246-
return client, nil
246+
return client, *ghTransport, nil
247+
}
248+
249+
type TokenSource interface {
250+
Token(ctx context.Context) (string, error)
247251
}
248252

249253
func (c *clientCreator) NewTokenClient(token string) (*github.Client, error) {
@@ -334,19 +338,22 @@ func newAppInstallation(integrationID int64, privKeyBytes []byte, v3BaseURL stri
334338
return installation, &transportError
335339
}
336340

337-
func newInstallation(integrationID, installationID int64, privKeyBytes []byte, v3BaseURL string) (ClientMiddleware, *error) {
341+
func newInstallation(integrationID, installationID int64, privKeyBytes []byte, v3BaseURL string) (ClientMiddleware, **ghinstallation.Transport, *error) {
338342
var transportError error
343+
var itr *ghinstallation.Transport
339344
installation := func(next http.RoundTripper) http.RoundTripper {
340-
itr, err := ghinstallation.New(next, integrationID, installationID, privKeyBytes)
345+
var err error
346+
itr, err = ghinstallation.New(next, integrationID, installationID, privKeyBytes)
341347
if err != nil {
342348
transportError = err
349+
343350
return next
344351
}
345352
// leaving the v3 URL since this is used to refresh the token, not make queries
346353
itr.BaseURL = strings.TrimSuffix(v3BaseURL, "/")
347354
return itr
348355
}
349-
return installation, &transportError
356+
return installation, &itr, &transportError
350357
}
351358

352359
func cache(cacheFunc func() httpcache.Cache) ClientMiddleware {

0 commit comments

Comments
 (0)