reference-api/sources/github/github.go (102 lines of code) (raw):

package github import ( "context" "crypto/rsa" "encoding/json" "log" "net/http" "os" "strings" "time" "github.com/golang-jwt/jwt" "github.com/google/go-github/v67/github" ) var ( appID = os.Getenv("GITHUB_APP_ID") // Your GitHub App ID privateKeyPath = os.Getenv("GITHUB_PRIVATE_KEY_PATH") // Path to the private key file ) // ErrorResponse represents an error message type ErrorResponse struct { Error string `json:"error"` } func errorEncoder(w http.ResponseWriter, status int, message string) { w.WriteHeader(status) err := json.NewEncoder(w).Encode(ErrorResponse{Error: message}) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) } } func responseEncoder(w http.ResponseWriter, status int, body any) { w.WriteHeader(status) err := json.NewEncoder(w).Encode(body) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) } } // LoadPrivateKey loads the RSA private key from the file func LoadPrivateKey(filePath string) (*rsa.PrivateKey, error) { keyData, err := os.ReadFile(filePath) if err != nil { errMsg := "WARNING: Private key not found or could not be read (%s). Falling back to unauthenticated mode." log.Printf(errMsg, err.Error()) return nil, nil // Continue without breaking } privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(keyData) if err != nil { log.Printf("WARNING: Failed to parse private key (%s). Falling back to unauthenticated mode.", err.Error()) return nil, nil // Continue without breaking } return privateKey, nil } // GenerateJWT generates a JWT for the GitHub App func GenerateJWT(privateKey *rsa.PrivateKey) (string, error) { now := time.Now() token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{ "iat": now.Unix(), "exp": now.Add(10 * time.Minute).Unix(), "iss": appID, }) return token.SignedString(privateKey) } // GetInstallationToken fetches an Installation Access Token func GetInstallationToken(jwtToken string, repo string) (string, error) { client := github.NewClient(nil).WithAuthToken(jwtToken) owner, repoName, _ := strings.Cut(repo, "/") ctx := context.Background() installation, _, err := client.Apps.FindRepositoryInstallation(ctx, owner, repoName) if err != nil { return "", err } token, _, err := client.Apps.CreateInstallationToken(ctx, *installation.ID, nil) if err != nil { return "", err } return *token.Token, nil } func GenerateAuthToken(repo string) string { if privateKeyPath == "" { return "" } privateKey, err := LoadPrivateKey(privateKeyPath) if err != nil { log.Println("WARNING: Failed to load private key. Falling back to unauthenticated mode.") return "" } // Generate JWT for GitHub App jwtToken, err := GenerateJWT(privateKey) if err != nil { log.Println("WARNING: Failed to generate JWT. Falling back to unauthenticated mode.") return "" } // Get installation token using the JWT accessToken, err := GetInstallationToken(jwtToken, repo) if err != nil { log.Println(err) log.Println("WARNING: Failed to get installation token. Falling back to unauthenticated mode.") return "" } return accessToken } func NewGithubClient(repo string) *github.Client { authToken := GenerateAuthToken(repo) client := github.NewClient(nil) if authToken == "" { log.Println("WARNING: Failed to get installation token. Returning unathenticated client.") return client } return client.WithAuthToken(authToken) }