### Retrieve and Check Installation Permissions Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/types.md Example of how to retrieve installation permissions using the go-github library and check for specific permissions like 'Contents'. Ensure the token has the necessary scope to fetch permissions. ```go // From github.com/google/go-github/v88/github type InstallationPermissions struct { Actions *string Administration *string Checks *string Contents *string Deployments *string Environments *string Issues *string Metadata *string Packages *string Pages *string PullRequests *string RepositoryCustomProperties *string RepositoryHooks *string RepositoryProjects *string SecretScanningAlerts *string SecurityEvents *string Statuses *string Vulnerabilities *string // Organization-level permissions: Members *string OrganizationAdministration *string OrganizationCustomProperties *string OrganizationHooks *string OrganizationPlan *string OrganizationProjects *string OrganizationSecrets *string OrganizationSelfHostedRunners *string OrganizationUserBlocking *string } ``` -------------------------------- ### Get Repositories Accessible by Installation Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Call Repositories to get a list of repositories the installation token has access to. Token() must be called at least once before this method. ```go func (t *Transport) Repositories() ([]github.Repository, error) ``` ```go _, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } repos, err := tr.Repositories() if err != nil { log.Fatal(err) } for _, repo := range repos { fmt.Printf("Repo: %s\n", repo.GetFullName()) } ``` -------------------------------- ### Creating Installation Access Tokens Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/apps-transport.md This example demonstrates how to create an access token for a specific GitHub App installation using the AppsTransport. It shows the process of making a POST request to the GitHub API to obtain an installation token. ```APIDOC ## POST /app/installations/{installation_id}/access_tokens ### Description Creates an access token for a specific GitHub App installation. ### Method POST ### Endpoint /app/installations/{installation_id}/access_tokens ### Parameters #### Path Parameters - **installation_id** (integer) - Required - The ID of the installation to create an access token for. ### Request Example ```json { "example": null } ``` ### Response #### Success Response (200) - **token** (string) - The generated access token. - **expires_at** (time.Time) - The expiration time of the token. #### Response Example ```json { "token": "your_generated_access_token", "expires_at": "2023-10-27T10:00:00Z" } ``` ``` -------------------------------- ### Install ghinstallation package Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/README.md Use go get to install the latest version of the ghinstallation package. ```bash go get -u github.com/bradleyfalzon/ghinstallation/v2 ``` -------------------------------- ### Set Installation Token Restrictions Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/types.md Example of setting InstallationTokenOptions to restrict a token's access to specific repositories and permissions before obtaining the token. ```go tr, _ := ghinstallation.New(http.DefaultTransport, 1, 99, privateKey) // Restrict token to specific repositories and permissions tr.InstallationTokenOptions = &github.InstallationTokenOptions{ Repositories: []string{"my-repo-1", "my-repo-2"}, Permissions: &github.InstallationPermissions{ Contents: github.String("read"), Issues: github.String("write"), }, } // Next token refresh will include these restrictions token, err := tr.Token(context.Background()) ``` -------------------------------- ### Set Installation Token Options Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Configure installation token options to restrict access to specific repositories and/or permissions. ```go tr.InstallationTokenOptions = &github.InstallationTokenOptions{ Repositories: []string{"repo-name-1", "repo-name-2"}, Permissions: &github.InstallationPermissions{ Contents: github.String("read"), Issues: github.String("write"), }, } ``` -------------------------------- ### Go: Basic Installation Auth with File Key Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Use this to authenticate with GitHub using a private key file. Ensure the private key file is accessible and the App ID and Installation ID are correct. ```go package main import ( "context" "fmt" "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" "github.com/google/go-github/v88/github" ) func main() { // Create transport with private key file tr, err := ghinstallation.NewKeyFromFile( http.DefaultTransport, 1, // GitHub App ID 99, // Installation ID "private-key.pem ", ) if err != nil { log.Fatal(err) } // Create authenticated HTTP client client := &http.Client{Transport: tr} // Use with go-github ghClient := github.NewClient(client) // Fetch repositories repos, _, err := ghClient.Repositories.ListByOrg( context.Background(), "my-org", nil, ) if err != nil { log.Fatal(err) } for _, repo := range repos { fmt.Printf("Repo: %s\n", repo.GetFullName()) } } ``` -------------------------------- ### Basic Installation Authentication with Private Key Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/OVERVIEW.md Use this to authenticate with GitHub using an App ID, Installation ID, and a private key file. It sets up an HTTP transport for authenticated requests. ```go import "github.com/bradleyfalzon/ghinstallation/v2" // Create transport tr, err := ghinstallation.NewKeyFromFile( http.DefaultTransport, 1, // appID 99, // installationID "private-key.pem", ) if err != nil { log.Fatal(err) } // Use with http.Client client := &http.Client{Transport: tr} // Use with go-github ghClient := github.NewClient(client) repos, _, err := ghClient.Repositories.ListByOrg(context.Background(), "owner", nil) ``` -------------------------------- ### Get Installation Access Token Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Call Token to retrieve a valid installation access token. Tokens are cached and automatically refreshed before expiration. Ensure context is provided for cancellation. ```go func (t *Transport) Token(ctx context.Context) (string, error) ``` ```go token, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } fmt.Printf("Token: %s\n", token) ``` -------------------------------- ### Get GitHub Installation Permissions Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Use Permissions to retrieve the GitHub installation permissions associated with the current token. Token() must be called at least once prior to calling this method. ```go func (t *Transport) Permissions() (github.InstallationPermissions, error) ``` ```go // First retrieve a token to populate permission data _, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } perms, err := tr.Permissions() if err != nil { log.Fatal(err) } fmt.Printf("Permissions: %+v\n", perms) ``` -------------------------------- ### Handle Specific Installation Token Failures Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/errors.md This snippet shows how to extract and log specific details, like the installation ID and error message, when a token refresh fails due to an HTTP error. It's useful for debugging and monitoring installation-specific issues. ```go token, err := tr.Token(context.Background()) if err != nil { var httpErr *ghinstallation.HTTPError if errors.As(err, &httpErr) { fmt.Printf("Installation %d failed: %s\n", httpErr.InstallationID, httpErr.Message) // Log the installation ID for monitoring logger.WithField("installation_id", httpErr.InstallationID). WithField("error", httpErr.Message). Error("Token refresh failed") } return "", err } ``` -------------------------------- ### Repositories Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Returns the list of repositories that the installation token has access to. Requires that Token() has been called at least once. ```APIDOC ## Repositories ### Description Returns the list of repositories that the installation token has access to. Requires that Token() has been called at least once. ### Method `Repositories` ### Parameters None ### Request Example ```go _, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } repos, err := tr.Repositories() if err != nil { log.Fatal(err) } for _, repo := range repos { fmt.Printf("Repo: %s\n", repo.GetFullName()) } ``` ### Response #### Success Response (200) `([]github.Repository, error)` #### Response Example None provided in source. ### Errors - Error if no token has been retrieved yet ``` -------------------------------- ### List Accessible Repositories Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Demonstrates how to list all repositories that the GitHub App installation token has access to. Accessing the token is required before listing repositories. ```go package main import ( "context" "fmt" "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { tr, _ := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "key.pem") // Get token to populate repositories list _, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } // Get repositories repos, err := tr.Repositories() if err != nil { log.Fatal(err) } fmt.Printf("Token has access to %d repositories\n", len(repos)) for _, repo := range repos { fmt.Printf(" - %s\n", repo.GetFullName()) } } ``` -------------------------------- ### Configure HTTP Client Timeout Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/types.md Example of configuring a standard library http.Client with a specific timeout. ```go tr.Client = &http.Client{ Timeout: 30 * time.Second, } ``` -------------------------------- ### Go: Basic Installation Auth with In-Memory Key Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Use this to authenticate with GitHub using a private key loaded into memory. The key can be read from environment variables or files. ```go package main import ( "os" "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { // Read key from environment or file keyBytes, err := os.ReadFile("private-key.pem") if err != nil { log.Fatal(err) } // Create transport tr, err := ghinstallation.New( http.DefaultTransport, 1, // appID 99, // installationID keyBytes, ) if err != nil { log.Fatal(err) } client := &http.Client{Transport: tr} _ = client // Use in your application } ``` -------------------------------- ### Configure Read-Only Token Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Use this to configure a read-only token for an installation. Ensure the necessary permissions are specified. ```go package main import ( "context" "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" "github.com/google/go-github/v88/github" ) func main() { tr, _ := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "key.pem") // Configure read-only token tr.InstallationTokenOptions = &github.InstallationTokenOptions{ Permissions: &github.InstallationPermissions{ Contents: github.String("read"), Issues: github.String("read"), PullRequests: github.String("read"), }, } // Next token refresh will use these restrictions client := &http.Client{Transport: tr} _ = client } ``` -------------------------------- ### Restrict Token Access to Read-Only Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Example of setting InstallationTokenOptions to grant read-only access to contents, issues, and pull requests. ```go tr, _ := ghinstallation.New(http.DefaultTransport, 1, 99, privateKey) tr.InstallationTokenOptions = &github.InstallationTokenOptions{ Permissions: &github.InstallationPermissions{ Contents: github.String("read"), Issues: github.String("read"), PullRequests: github.String("read"), }, } ``` -------------------------------- ### Initialize Transport from Environment Variables Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Initialize a transport by reading GitHub App ID, Installation ID, and private key file path from environment variables. ```go func initializeTransportFromEnv() (*ghinstallation.Transport, error) { appID := os.Getenv("GITHUB_APP_ID") instID := os.Getenv("GITHUB_INSTALLATION_ID") keyFile := os.Getenv("GITHUB_PRIVATE_KEY_FILE") appIDNum, _ := strconv.ParseInt(appID, 10, 64) instIDNum, _ := strconv.ParseInt(instID, 10, 64) return ghinstallation.NewKeyFromFile( http.DefaultTransport, appIDNum, instIDNum, keyFile, ) } ``` -------------------------------- ### Restrict Token Access to Specific Repositories Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Example of setting InstallationTokenOptions to limit token access to a predefined list of repositories with read-only content permissions. ```go tr.InstallationTokenOptions = &github.InstallationTokenOptions{ Repositories: []string{"frontend-repo", "backend-repo"}, Permissions: &github.InstallationPermissions{ Contents: github.String("read"), }, } ``` -------------------------------- ### Create Installation Access Tokens with AppsTransport Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Generate an access token for a specific GitHub App installation using AppsTransport. This token is required to make API requests on behalf of the installation. The token has a limited expiry time. ```go package main import ( "encoding/json" "io" "log" "net/http" "time" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { atr, _ := ghinstallation.NewAppsTransport( http.DefaultTransport, 1, keyBytes, ) client := &http.Client{Transport: atr} // Create access token for specific installation req, _ := http.NewRequest( "POST", "https://api.github.com/app/installations/99/access_tokens", nil, ) resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() var tokenResp struct { Token string `json:"token"` ExpiresAt time.Time `json:"expires_at"` } json.NewDecoder(resp.Body).Decode(&tokenResp) println("Created token:", tokenResp.Token[:20]) println("Expires at:", tokenResp.ExpiresAt) } ``` -------------------------------- ### Configure Client with Timeout and Retries Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Example of configuring an HTTP client with a specific timeout and transport settings for token refresh requests. ```go tr.Client = &http.Client{ Timeout: 30 * time.Second, Transport: &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 10, IdleConnTimeout: 90 * time.Second, }, } ``` -------------------------------- ### Reusing Base Transport for Multiple Installations Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Manage multiple GitHub App installations by reusing a base HTTP transport for connection pooling. This optimizes resource usage when interacting with different installation IDs. ```go package main import ( "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { // Shared base transport for connection pooling baseTransport := &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 10, } // Create transports for multiple installations tr1, _ := ghinstallation.NewKeyFromFile(baseTransport, 1, 99, "key.pem") tr2, _ := ghinstallation.NewKeyFromFile(baseTransport, 1, 100, "key.pem") tr3, _ := ghinstallation.NewKeyFromFile(baseTransport, 1, 101, "key.pem") // Use each independently client1 := &http.Client{Transport: tr1} client2 := &http.Client{Transport: tr2} client3 := &http.Client{Transport: tr3} _, _, _ = client1, client2, client3 } ``` -------------------------------- ### Create Installation Access Token Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/apps-transport.md Use AppsTransport directly to create a new access token for a specific GitHub App installation. This involves making a POST request to the GitHub API. ```go atr, err := ghinstallation.NewAppsTransport(http.DefaultTransport, 1, keyBytes) if err != nil { log.Fatal(err) } client := &http.Client{Transport: atr} // Create an access token for an installation req, _ := http.NewRequest("POST", "https://api.github.com/app/installations/99/access_tokens", nil) resp, err := client.Do(req) if err != nil { log.Fatal(err) } defere resp.Body.Close() var tokenResp struct { Token string `json:"token"` ExpiresAt time.Time `json:"expires_at"` } json.NewDecoder(resp.Body).Decode(&tokenResp) fmt.Printf("Created token: %s\n", tokenResp.Token) ``` -------------------------------- ### Go: GitHub Enterprise Support Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Configure the transport to point to your GitHub Enterprise instance. This example shows how to set the BaseURL for the transport and use the Enterprise client. ```go package main import ( "context" "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" "github.com/google/go-github/v88/github" ) func main() { // Create transport tr, err := ghinstallation.NewKeyFromFile( http.DefaultTransport, 1, 99, "private-key.pem", ) if err != nil { log.Fatal(err) } // Configure for GitHub Enterprise enterpriseURL := "https://github.enterprise.com/api/v3" tr.BaseURL = enterpriseURL // Create GitHub Enterprise client client := &http.Client{Transport: tr} ghClient := github.NewEnterpriseClient(enterpriseURL, enterpriseURL, client) // Use as normal issue, _, err := ghClient.Issues.ListByRepo( context.Background(), "owner", "repo", nil, ) if err != nil { log.Fatal(err) } for _, issue := range issues { println(issue.GetTitle()) } } ``` -------------------------------- ### Configure GitHub Enterprise AppsTransport Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Example of setting the BaseURL for a GitHub Enterprise instance and creating an HTTP client with the configured transport. ```go atr, err := ghinstallation.NewAppsTransport(http.DefaultTransport, 1, privateKey) if err != nil { log.Fatal(err) } // Configure for enterprise atr.BaseURL = "https://github.enterprise.corp.com/api/v3" // Create client client := &http.Client{Transport: atr} ``` -------------------------------- ### Check Token Permissions Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Shows how to retrieve the permissions associated with a GitHub App installation token. Ensure the token is accessed first to populate permission data. ```go package main import ( "context" "fmt" "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { tr, _ := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "key.pem") // Get token to populate permissions _, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } // Get permissions perms, err := tr.Permissions() if err != nil { log.Fatal(err) } if perms.Contents != nil { fmt.Printf("Contents: %s\n", *perms.Contents) } if perms.Issues != nil { fmt.Printf("Issues: %s\n", *perms.Issues) } } ``` -------------------------------- ### Transport Constructors Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/OVERVIEW.md Constructors for creating a Transport for installation authentication. ```APIDOC ## Transport Constructors ### NewKeyFromFile Creates a new Transport using a private key file for installation authentication. #### Parameters - `tr` (*http.RoundTripper) - The underlying HTTP round-tripper. - `appID` (int64) - The GitHub App ID. - `installationID` (int64) - The installation ID. - `privateKeyFile` (string) - Path to the private key file. #### Returns - `(*Transport, error)` - A new Transport instance or an error. ### New Creates a new Transport using a private key byte slice for installation authentication. #### Parameters - `tr` (*http.RoundTripper) - The underlying HTTP round-tripper. - `appID` (int64) - The GitHub App ID. - `installationID` (int64) - The installation ID. - `privateKey` ([]byte) - The private key as a byte slice. #### Returns - `(*Transport, error)` - A new Transport instance or an error. ### NewFromAppsTransport Creates a new Transport from an existing AppsTransport for installation authentication. #### Parameters - `atr` (*AppsTransport) - The existing AppsTransport. - `installationID` (int64) - The installation ID. #### Returns - `(*Transport)` - A new Transport instance. ``` -------------------------------- ### Token Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Returns a valid access token for the installation, refreshing if necessary. Tokens are cached and automatically refreshed one minute before expiration. ```APIDOC ## Token ### Description Returns a valid access token for the installation, refreshing if necessary. Tokens are cached and automatically refreshed one minute before expiration. ### Method `Token` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go token, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } fmt.Printf("Token: %s\n", token) ``` ### Response #### Success Response (200) `(string, error)` - A valid JWT access token string #### Response Example None provided in source. ### Errors - Error if token refresh fails - Error if HTTP request to GitHub API fails ``` -------------------------------- ### InstallationPermissions Type Definition Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/types.md This Go struct defines the various permissions that can be granted to a GitHub App installation. It includes repository-level and organization-level permissions. ```go import ( "fmt" "log" "github.com/google/go-github/v88/github" ) // Get permissions from a token perms, err := tr.Permissions() if err != nil { log.Fatal(err) } if perms.Contents != nil { fmt.Printf("Contents permission: %s\n", *perms.Contents) } ``` -------------------------------- ### Connection Pooling with Shared Transport Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/OVERVIEW.md Demonstrates how to share a base HTTP transport across multiple installation transports to optimize connection pooling and resource usage. ```go baseTransport := &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 10, } tr1, _ := ghinstallation.NewKeyFromFile(baseTransport, appID, instID1, keyFile) tr2, _ := ghinstallation.NewKeyFromFile(baseTransport, appID, instID2, keyFile) ``` -------------------------------- ### Permissions Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Returns the GitHub installation permissions associated with the current token. Requires that Token() has been called at least once to populate token data. ```APIDOC ## Permissions ### Description Returns the GitHub installation permissions associated with the current token. Requires that Token() has been called at least once to populate token data. ### Method `Permissions` ### Parameters None ### Request Example ```go // First retrieve a token to populate permission data _, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } perms, err := tr.Permissions() if err != nil { log.Fatal(err) } fmt.Printf("Permissions: %+v\n", perms) ``` ### Response #### Success Response (200) `(github.InstallationPermissions, error)` #### Response Example None provided in source. ### Errors - Error if no token has been retrieved yet ``` -------------------------------- ### Check Token Expiry Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Demonstrates how to retrieve the expiry and refresh times for a GitHub App installation token. Accessing the token will trigger a refresh if necessary. ```go package main import ( "context" "fmt" "log" "net/http" "time" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { tr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "key.pem") if err != nil { log.Fatal(err) } // Trigger token refresh by accessing it token, err := tr.Token(context.Background()) if err != nil { log.Fatal(err) } fmt.Printf("Token: %s...\n", token[:20]) // Get expiry information expiresAt, refreshAt, err := tr.Expiry() if err != nil { log.Fatal(err) } fmt.Printf("Token expires at: %v\n", expiresAt) fmt.Printf("Will refresh at: %v\n", refreshAt) fmt.Printf("Time until expiry: %v\n", time.Until(expiresAt)) } ``` -------------------------------- ### Configure GitHub Enterprise Transport Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Example function to set up a transport for GitHub Enterprise by configuring the BaseURL. ```go func setupEnterpriseTransport(appID, installationID int64, privateKey []byte) (*ghinstallation.Transport, error) { tr, err := ghinstallation.New(http.DefaultTransport, appID, installationID, privateKey) if err != nil { return nil, err } // Configure for GitHub Enterprise tr.BaseURL = "https://github.enterprise.corp.com/api/v3" return tr, nil } ``` -------------------------------- ### Define InstallationTokenOptions Type Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/types.md External type from go-github to restrict installation token access. Use to limit token scope to specific repositories and permissions. ```go // From github.com/google/go-github/v88/github type InstallationTokenOptions struct { Repositories []string Permissions *InstallationPermissions } ``` -------------------------------- ### Setup Enterprise Read-Only Transport Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Configure a transport for GitHub Enterprise with read-only permissions for specific resources. ```go func setupEnterpriseReadOnlyTransport( appID, installationID int64, keyBytes []byte, baseURL string, ) (*ghinstallation.Transport, error) { tr, err := ghinstallation.New(http.DefaultTransport, appID, installationID, keyBytes) if err != nil { return nil, err } // Enterprise configuration tr.BaseURL = baseURL // Restrict permissions tr.InstallationTokenOptions = &github.InstallationTokenOptions{ Permissions: &github.InstallationPermissions{ Contents: github.String("read"), Issues: github.String("read"), PullRequests: github.String("read"), }, } return tr, nil } ``` -------------------------------- ### Handling GitHub API Errors Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/OVERVIEW.md Shows how to specifically catch and handle `ghinstallation.HTTPError` when fetching an installation token. This allows for detailed error reporting, including the status code of the failed HTTP response. ```go token, err := tr.Token(context.Background()) if err != nil { var httpErr *ghinstallation.HTTPError if errors.As(err, &httpErr) { fmt.Printf("Installation %d failed: %s\n", httpErr.InstallationID, httpErr.Message) if httpErr.Response != nil { fmt.Printf("HTTP %d\n", httpErr.Response.StatusCode) } } } ``` -------------------------------- ### Handle HTTPError Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md This example shows how to handle specific HTTP errors returned by the GitHub API. It checks for the `ghinstallation.HTTPError` type and inspects its properties. ```go package main import ( "context" "errors" "fmt" "io" "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { tr, _ := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "key.pem") token, err := tr.Token(context.Background()) if err != nil { var httpErr *ghinstallation.HTTPError if errors.As(err, &httpErr) { fmt.Printf("HTTP Error for installation %d\n", httpErr.InstallationID) fmt.Printf("Message: %s\n", httpErr.Message) if httpErr.Response != nil { fmt.Printf("HTTP Status: %d\n", httpErr.Response.StatusCode) body, _ := io.ReadAll(httpErr.Response.Body) fmt.Printf("Response: %s\n", body) } // Check root cause if errors.Is(httpErr.RootCause, context.DeadlineExceeded) { fmt.Println("Request timed out") } } log.Fatal(err) } } ``` -------------------------------- ### Implement http.RoundTripper with Authentication Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Use RoundTrip to automatically add an installation access token to HTTP requests. It clones the request, adds the Authorization header, and sets the Accept header if not present. ```go func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) ``` ```go tr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "key.pem") if err != nil { log.Fatal(err) } client := &http.Client{Transport: tr} resp, err := client.Get("https://api.github.com/repos/owner/repo") if err != nil { log.Fatal(err) } defersp.Body.Close() ``` -------------------------------- ### Transport Client Configuration Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/client-interface.md Example of configuring a custom http.Client for the Transport's token refresh mechanism. This client has a shorter timeout and specific transport settings. ```go tr, err := ghinstallation.New(http.DefaultTransport, appID, installationID, privateKey) if err != nil { log.Fatal(err) } // Configure a custom client for token refresh tr.Client = &http.Client{ Timeout: 10 * time.Second, Transport: &http.Transport{ MaxIdleConns: 100, MaxConnsPerHost: 10, }, } ``` -------------------------------- ### githubInstallationTokenOptions Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/types.md githubInstallationTokenOptions is an external type used to restrict an installation token's access. It allows specifying a list of repositories and specific permissions. ```APIDOC ## githubInstallationTokenOptions ### Description Options to restrict an installation token's access when creating a Transport. Use this to specify which repositories and permissions the token should have. ### Fields - `Repositories` ([]string): List of repository names to restrict the token to. - `Permissions` (*InstallationPermissions): Specific permissions to grant (e.g., "read" or "write"). ``` -------------------------------- ### Token Expiry and Refresh Information Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/OVERVIEW.md Retrieves the expiration and automatic refresh times for the current installation token. The token is automatically refreshed one minute before it expires, but can also be manually refreshed by calling `Token()`. ```go // Token is automatically refreshed 1 minute before expiry // Manually refresh by getting token token, err := tr.Token(context.Background()) // Check expiry expiresAt, refreshAt, _ := tr.Expiry() fmt.Printf("Token expires at %v\n", expiresAt) fmt.Printf("Will refresh at %v\n", refreshAt) ``` -------------------------------- ### Authenticate GitHub App with private key file Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/README.md Wrap the default HTTP transport to authenticate as a GitHub App installation using a private key file. This is useful for integrating with the go-github client. ```go import "github.com/bradleyfalzon/ghinstallation/v2" func main() { // Shared transport to reuse TCP connections. tr := http.DefaultTransport // Wrap the shared transport for use with the app ID 1 authenticating with installation ID 99. itr, err := ghinstallation.NewKeyFromFile(tr, 1, 99, "2016-10-19.private-key.pem") if err != nil { log.Fatal(err) } // Use installation transport with github.com/google/go-github client := github.NewClient(&http.Client{Transport: itr}) } ``` -------------------------------- ### Create Transport from Private Key Bytes Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Use `New` to create a `Transport` with a private key provided as a byte slice. This is useful when the private key is available in memory, for example, after reading from a file or fetching from a secret store. ```go keyBytes, err := os.ReadFile("private-key.pem") if err != nil { log.Fatal(err) } tr, err := ghinstallation.New( http.DefaultTransport, 1, // appID 99, // installationID keyBytes, ) if err != nil { log.Fatal(err) } client := &http.Client{Transport: tr} resp, err := client.Get("https://api.github.com/app/installations/99/access_tokens") ``` -------------------------------- ### Authenticate GitHub Enterprise App with private key file Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/README.md Configure the GitHub Enterprise URL and wrap the default HTTP transport to authenticate as a GitHub App installation. This allows integration with private GitHub Enterprise instances. ```go import "github.com/bradleyfalzon/ghinstallation/v2" const GitHubEnterpriseURL = "https://github.example.com/api/v3" func main() { // Shared transport to reuse TCP connections. tr := http.DefaultTransport // Wrap the shared transport for use with the app ID 1 authenticating with installation ID 99. itr, err := ghinstallation.NewKeyFromFile(tr, 1, 99, "2016-10-19.private-key.pem") if err != nil { log.Fatal(err) } itr.BaseURL = GitHubEnterpriseURL // Use installation transport with github.com/google/go-github client := github.NewEnterpriseClient(GitHubEnterpriseURL, GitHubEnterpriseURL, &http.Client{Transport: itr}) } ``` -------------------------------- ### Standard http.Client Initialization Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/client-interface.md Shows how to initialize a standard Go http.Client with a timeout. ```go client := &http.Client{ Timeout: 30 * time.Second, } ``` -------------------------------- ### Get GitHub App Installation ID Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md InstallationID returns the GitHub App installation ID associated with this transport. ```go func (t *Transport) InstallationID() int64 ``` ```go installationID := tr.InstallationID() fmt.Printf("Installation ID: %d\n", installationID) ``` -------------------------------- ### Creating Multiple Installations from AppsTransport Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Generate individual installation transports from a shared AppsTransport. This is useful when you have a single GitHub App and need to authenticate for multiple installations of that app. ```go package main import ( "log" "net/http" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { // Create app transport atr, _ := ghinstallation.NewAppsTransport( http.DefaultTransport, 1, keyBytes, ) // Create multiple installation transports tr1 := ghinstallation.NewFromAppsTransport(atr, 99) tr2 := ghinstallation.NewFromAppsTransport(atr, 100) tr3 := ghinstallation.NewFromAppsTransport(atr, 101) client1 := &http.Client{Transport: tr1} client2 := &http.Client{Transport: tr2} client3 := &http.Client{Transport: tr3} _, _, _ = client1, client2, client3 } ``` -------------------------------- ### Initialize Transport from File Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Standard pattern for initializing a transport by loading credentials from a private key file. ```go func initializeTransport(appID, installationID int64, keyPath string) (*ghinstallation.Transport, error) { tr, err := ghinstallation.NewKeyFromFile( http.DefaultTransport, appID, installationID, keyPath, ) if err != nil { return nil, fmt.Errorf("failed to initialize transport: %w", err) } return tr, nil } ``` -------------------------------- ### Handle NewKeyFromFile Error: Private Key Not Found Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/errors.md Demonstrates handling the error when the private key file specified in `NewKeyFromFile` cannot be found. Ensure the file path is correct and the file exists. ```go tr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "missing.pem") if err != nil { fmt.Printf("Error: %v\n", err) // Output: Error: could not read private key: open missing.pem: no such file or directory } ``` -------------------------------- ### InstallationID Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Returns the GitHub App installation ID associated with this transport. ```APIDOC ## InstallationID ### Description Returns the GitHub App installation ID associated with this transport. ### Method `InstallationID` ### Parameters None ### Request Example ```go installationID := tr.InstallationID() fmt.Printf("Installation ID: %d\n", installationID) ``` ### Response #### Success Response (200) `int64` - The installation ID #### Response Example None provided in source. ``` -------------------------------- ### Logging Client Implementation Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/client-interface.md Implement a custom client that logs requests and responses. Configure the inner client and a logger instance. ```go type LoggingClient struct { inner *http.Client logger Logger } func (c *LoggingClient) Do(req *http.Request) (*http.Response, error) { c.logger.Printf("Request: %s %s\n", req.Method, req.URL) resp, err := c.inner.Do(req) if err != nil { c.logger.Printf("Error: %v\n", err) } else { c.logger.Printf("Response: %d\n", resp.StatusCode) } return resp, err } // Usage loggingClient := &LoggingClient{ inner: &http.Client{}, logger: myLogger, } tr.Client = loggingClient ``` -------------------------------- ### Transport Methods Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/OVERVIEW.md Methods available on the Transport type for installation authentication. ```APIDOC ## Transport Methods ### RoundTrip Implements the `http.RoundTripper` interface. #### Parameters - `req` (*http.Request) - The HTTP request to perform. #### Returns - `(*http.Response, error)` - The HTTP response or an error. ### Token Gets a valid access token for the installation. #### Parameters - `ctx` (context.Context) - The context for the request. #### Returns - `(string, error)` - The access token or an error. ### Permissions Gets the token permissions for the installation. #### Returns - `(githubInstallationPermissions, error)` - The token permissions or an error. ### Repositories Gets the list of accessible repositories for the installation. #### Returns - `([]github.Repository, error)` - A slice of repositories or an error. ### Expiry Gets the token expiration and refresh times. #### Returns - `(expiresAt, refreshAt time.Time, err error)` - The expiration times and an error. ### AppID Gets the App ID associated with the transport. #### Returns - `(int64)` - The App ID. ### InstallationID Gets the Installation ID associated with the transport. #### Returns - `(int64)` - The Installation ID. ``` -------------------------------- ### Transport Integration Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/client-interface.md The Transport struct uses the Client interface to refresh installation access tokens. ```APIDOC ## Transport Integration ### Description The `Transport` struct uses the configured `Client` to send requests to GitHub's API for refreshing installation access tokens. ### Usage Example ```go tr, err := ghinstallation.New(http.DefaultTransport, appID, installationID, privateKey) if err != nil { log.Fatal(err) } // Configure a custom client for token refresh tr.Client = &http.Client{ Timeout: 10 * time.Second, Transport: &http.Transport{ MaxIdleConns: 100, MaxConnsPerHost: 10, }, } ``` ``` -------------------------------- ### NewFromAppsTransport Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Creates a Transport from an existing AppsTransport. This is useful when reusing an AppsTransport across multiple installations. ```APIDOC ## NewFromAppsTransport ### Description Creates a Transport from an existing AppsTransport. This is useful when reusing an AppsTransport across multiple installations. ### Method `func NewFromAppsTransport(atr *AppsTransport, installationID int64) *Transport` ### Parameters #### Path Parameters - **atr** (*AppsTransport) - Required - Existing AppsTransport to wrap - **installationID** (int64) - Required - GitHub App installation ID ### Returns `*Transport` ### Example ```go atr, err := ghinstallation.NewAppsTransport( http.DefaultTransport, 1, keyBytes, ) if err != nil { log.Fatal(err) } // Create multiple installation transports from the same AppsTransport tr1 := ghinstallation.NewFromAppsTransport(atr, 99) tr2 := ghinstallation.NewFromAppsTransport(atr, 100) ``` ``` -------------------------------- ### Get GitHub App ID Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md AppID returns the GitHub App ID associated with this transport. ```go func (t *Transport) AppID() int64 ``` ```go appID := tr.AppID() fmt.Printf("App ID: %d\n", appID) ``` -------------------------------- ### Custom HTTP Client with Connection Pooling Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/examples.md Set up a shared HTTP transport for connection pooling, optimizing performance for multiple requests. Configure MaxIdleConns, MaxIdleConnsPerHost, and IdleConnTimeout. ```go package main import ( "log" "net/http" "time" "github.com/bradleyfalzon/ghinstallation/v2" ) func main() { tr, _ := ghinstallation.NewKeyFromFile( http.DefaultTransport, 1, 99, "key.pem", ) // Shared transport for connection pooling tr.Client = &http.Client{ Transport: &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 10, IdleConnTimeout: 90 * time.Second, }, Timeout: 30 * time.Second, } client := &http.Client{Transport: tr} _ = client } ``` -------------------------------- ### Transport Methods Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/README.md Methods available on the Transport type for managing installation authentication and retrieving token information. ```APIDOC ## Transport Methods ### Description Methods for the `Transport` type, which handles installation authentication and provides access to token details. ### Methods - `RoundTrip` - Implements `http.RoundTripper`. - `Token` - Get valid access token. - `Permissions` - Get token permissions. - `Repositories` - Get accessible repositories. - `Expiry` - Get token expiration info. - `AppID` - Get app ID. - `InstallationID` - Get installation ID. ### Configuration Fields - `BaseURL` - API endpoint URL. - `Client` - HTTP client for token refresh. - `InstallationTokenOptions` - Token scope restrictions. ``` -------------------------------- ### Configure AppsTransport HTTP Client Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Customize the HTTP client used by AppsTransport, for example, to set a timeout. ```go atr.Client = &http.Client{ Timeout: 20 * time.Second, } ``` -------------------------------- ### Restricting Token Permissions Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/OVERVIEW.md Configures `InstallationTokenOptions` to request a token with specific read-only permissions for Contents and Issues. This is a security best practice to limit the token's capabilities to only what is necessary. ```go tr, _ := ghinstallation.New(http.DefaultTransport, appID, instID, privateKey) // Restrict to read-only access tr.InstallationTokenOptions = &github.InstallationTokenOptions{ Permissions: &github.InstallationPermissions{ Contents: github.String("read"), Issues: github.String("read"), }, } ``` -------------------------------- ### Create AppsTransport from Private Key File Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/apps-transport.md Use this constructor to create an AppsTransport by loading the private key from a file. Ensure the file path is correct and the key is in PEM format. The underlying HTTP transport should be shared to reuse TCP connections. ```go atr, err := ghinstallation.NewAppsTransportKeyFromFile( http.DefaultTransport, 1, // appID "/path/to/private-key.pem", ) if err != nil { log.Fatal(err) } client := &http.Client{Transport: atr} ``` -------------------------------- ### Rate-Limited Client Implementation Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/client-interface.md Implement a custom client that enforces rate limits on requests. Configure the inner client and a rate limiter. ```go type RateLimitedClient struct { inner *http.Client limiter *rate.Limiter } func (c *RateLimitedClient) Do(req *http.Request) (*http.Response, error) { if !c.limiter.Allow() { return nil, fmt.Errorf("rate limit exceeded") } return c.inner.Do(req) } // Usage import "golang.org/x/time/rate" limitedClient := &RateLimitedClient{ inner: &http.Client{}, limiter: rate.NewLimiter(rate.Every(time.Second), 1), // 1 request per second } tr.Client = limitedClient ``` -------------------------------- ### Set GitHub Enterprise Base URL Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Customize the API endpoint for GitHub Enterprise Server installations or custom API gateways. ```go tr, _ := ghinstallation.New(http.DefaultTransport, 1, 99, privateKey) tr.BaseURL = "https://github.example.com/api/v3" ``` -------------------------------- ### AppsTransport Client Configuration Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/client-interface.md Example of configuring a custom http.Client for the AppsTransport, used for sending JWT-signed requests. This client has a specific timeout. ```go atr, err := ghinstallation.NewAppsTransport(http.DefaultTransport, appID, privateKey) if err != nil { log.Fatal(err) } // Configure a custom client atr.Client = &http.Client{ Timeout: 20 * time.Second, } ``` -------------------------------- ### Configure AppsTransport with Options Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Use NewAppsTransportWithOptions to configure the transport with a custom signer and set additional options like BaseURL and Client after creation. ```go // Custom signer configuration customSigner := &myCustomKMSSigner{} atr, err := ghinstallation.NewAppsTransportWithOptions( http.DefaultTransport, appID, ghinstallation.WithSigner(customSigner), ) if err != nil { log.Fatal(err) } // Post-creation configuration atr.BaseURL = "https://github.enterprise.com/api/v3" atr.Client = &http.Client{Timeout: 30 * time.Second} ``` -------------------------------- ### Initialize Transport from In-Memory Bytes Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/configuration.md Initialize a transport using private key bytes directly from memory. ```go func initializeTransportFromBytes(appID, installationID int64, keyBytes []byte) (*ghinstallation.Transport, error) { return ghinstallation.New( http.DefaultTransport, appID, installationID, keyBytes, ) } ``` -------------------------------- ### Create Transport from Private Key File Source: https://github.com/bradleyfalzon/ghinstallation/blob/master/_autodocs/api-reference/transport.md Use `NewKeyFromFile` to create a `Transport` by loading a PEM-formatted private key from a file. This is suitable when your private key is stored on disk. ```go tr, err := ghinstallation.NewKeyFromFile( http.DefaultTransport, 1, // appID 99, // installationID "/path/to/private-key.pem", ) if err != nil { log.Fatal(err) } client := &http.Client{Transport: tr} ```