diff --git a/README.md b/README.md index 1eb9054c06d..184fc1048b1 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,10 @@ GitHub Apps authentication can be provided by the [ghinstallation](https://githu package. ```go -import "github.com/bradleyfalzon/ghinstallation" +import ( + "github.com/bradleyfalzon/ghinstallation/v2" + "github.com/google/go-github/v41/github" +) func main() { // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99. @@ -137,6 +140,9 @@ func main() { } ``` +*Note*: In order to interact with certain APIs, for example writing a file to a repo, one must generate an installation token +using the installation ID of the GitHub app and authenticate with the OAuth method mentioned above. See the examples. + ### Rate Limiting ### GitHub imposes a rate limit on all API clients. Unauthenticated clients are diff --git a/example/newfilewithappauth/main.go b/example/newfilewithappauth/main.go new file mode 100644 index 00000000000..ef124c55617 --- /dev/null +++ b/example/newfilewithappauth/main.go @@ -0,0 +1,95 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// newfilewithappauth demonstrates the functionality of GitHub's app authentication +// methods by fetching an installation access token and reauthenticating to GitHub +// with OAuth configurations. +package main + +import ( + "context" + "io/ioutil" + "log" + "net/http" + "time" + + "github.com/bradleyfalzon/ghinstallation/v2" + "github.com/google/go-github/v41/github" + "golang.org/x/oauth2" +) + +func main() { + const gitHost = "https://git.api.com" + + privatePem, err := ioutil.ReadFile("path/to/pem") + if err != nil { + log.Fatalf("failed to read pem: %v", err) + } + + itr, err := ghinstallation.NewAppsTransport(http.DefaultTransport, 10, privatePem) + if err != nil { + log.Fatalf("faild to create app transport: %v\n", err) + } + itr.BaseURL = gitHost + + //create git client with app transport + client, err := github.NewEnterpriseClient( + gitHost, + gitHost, + &http.Client{ + Transport: itr, + Timeout: time.Second * 30, + }) + if err != nil { + log.Fatalf("faild to create git client for app: %v\n", err) + } + + installations, _, err := client.Apps.ListInstallations(context.Background(), &github.ListOptions{}) + if err != nil { + log.Fatalf("failed to list installations: %v\n", err) + } + + //capture our installationId for our app + //we need this for the access token + var installID int64 + for _, val := range installations { + installID = val.GetID() + } + + token, _, err := client.Apps.CreateInstallationToken( + context.Background(), + installID, + &github.InstallationTokenOptions{}) + if err != nil { + log.Fatalf("failed to create installation token: %v\n", err) + } + + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: token.GetToken()}, + ) + oAuthClient := oauth2.NewClient(context.Background(), ts) + + //create new git hub client with accessToken + apiClient, err := github.NewEnterpriseClient(gitHost, gitHost, oAuthClient) + if err != nil { + log.Fatalf("failed to create new git client with token: %v\n", err) + } + + _, resp, err := apiClient.Repositories.CreateFile( + context.Background(), + "repoOwner", + "sample-repo", + "example/foo.txt", + &github.RepositoryContentFileOptions{ + Content: []byte("foo"), + Message: github.String("sample commit"), + SHA: nil, + }) + if err != nil { + log.Fatalf("failed to create new file: %v\n", err) + } + + log.Printf("file written status code: %v", resp.StatusCode) +} diff --git a/go.mod b/go.mod index 238a7a61692..fba98e39f5f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module github.com/google/go-github/v41 require ( + github.com/bradleyfalzon/ghinstallation/v2 v2.0.3 github.com/google/go-cmp v0.5.6 github.com/google/go-querystring v1.1.0 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 @@ -9,7 +10,9 @@ require ( ) require ( + github.com/golang-jwt/jwt/v4 v4.0.0 // indirect github.com/golang/protobuf v1.3.2 // indirect + github.com/google/go-github/v39 v39.0.0 // indirect golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect diff --git a/go.sum b/go.sum index 7e85c44db1f..95ca91e2822 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,15 @@ +github.com/bradleyfalzon/ghinstallation/v2 v2.0.3 h1:ywF/8q+GVpvlsEuvRb1SGSDQDUxntW1d4kFu/9q/YAE= +github.com/bradleyfalzon/ghinstallation/v2 v2.0.3/go.mod h1:tlgi+JWCXnKFx/Y4WtnDbZEINo31N5bcvnCoqieefmk= +github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github/v39 v39.0.0 h1:pygGA5ySwxEez1N39GnDauD0PaWWuGgayudyZAc941s= +github.com/google/go-github/v39 v39.0.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=