Skip to content

Instantly share code, notes, and snippets.

@DanielCalvo
Created August 26, 2020 15:44
Show Gist options
  • Save DanielCalvo/456347340b35d26ca16041cd8b1a944d to your computer and use it in GitHub Desktop.
Save DanielCalvo/456347340b35d26ca16041cd8b1a944d to your computer and use it in GitHub Desktop.
Github app repository clone golang
package main
import (
"encoding/json"
"fmt"
"github.com/dgrijalva/jwt-go"
"io/ioutil"
"net/http"
"os/exec"
"time"
)
type AuthTokenClaim struct {
*jwt.StandardClaims
}
type InstallationAuthResponse struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
Permissions struct {
Checks string `json:"checks"`
Contents string `json:"contents"`
Deployments string `json:"deployments"`
Metadata string `json:"metadata"`
PullRequests string `json:"pull_requests"`
Statuses string `json:"statuses"`
} `json:"permissions"`
RepositorySelection string `json:"repository_selection"`
}
//This is an implementation of the workflow described here: https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#http-based-git-access-by-an-installation
//Your app must have rights to read/clone repositories
func main(){
keyFilepath := "/path/to/your/key.pem"
appID := "00000" //GitHub app ID
appInstalationID := "0000000" //Instalation ID for this app on your organization
keyBytes, err := ioutil.ReadFile(keyFilepath)
if err != nil {
fmt.Println(err)
}
rsaPrivateKey, err := jwt.ParseRSAPrivateKeyFromPEM(keyBytes)
if err != nil {
fmt.Println(err)
}
jwtToken := jwt.New(jwt.SigningMethodRS256)
jwtToken.Claims = &AuthTokenClaim{
&jwt.StandardClaims{
IssuedAt: time.Now().Unix(),
ExpiresAt: time.Now().Add(time.Minute * 1).Unix(),
Issuer: appID,
},
}
tokenString, err := jwtToken.SignedString(rsaPrivateKey)
if err != nil {
fmt.Println(err)
}
client := &http.Client{}
req, _ := http.NewRequest("POST", "https://api.github.com/app/installations/" + appInstalationID + "/access_tokens", nil)
req.Header.Set("Accept", "application/vnd.github.machine-man-preview+json")
req.Header.Set("Authorization", "Bearer " + tokenString)
res, _ := client.Do(req)
decoder := json.NewDecoder(res.Body)
var installationAuthResponse InstallationAuthResponse
err = decoder.Decode(&installationAuthResponse)
if err != nil {
fmt.Println(err)
}
//go-git consumes large amounts of memory cloning large repositories, this can cause small VMs/containers to run out of memory
//sticking to the git executable for this example
cmd := exec.Command("git", "clone", "https://x-access-token:" + installationAuthResponse.Token + "@github.com/organization/repository.git", "/tmp/repository")
err = cmd.Run()
if err != nil {
fmt.Println(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment