Skip to content

Add ability to clone repos using github app id #90

@markdjones82

Description

@markdjones82

Add additional functionality to pass in github app id and login name/org to use as authentication for cloning repos during indexing. This can be added to the clone_repo function to check for ENV settings and use it instead of PAT.

Also, instead of giving Private Key path, add ability to pass it in as a string so that the key file does not need to be uploaded into the image.

Documentation:
https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation

General example of workflow here:

import jwt
import requests
import subprocess
import datetime

GitHub App configuration
APP_ID = 'ID'
PRIVATE_KEY_PATH = './gh_pk.pem'
REPO_NAME = 'REPNAME'
ORG_NAME = 'blah'  # Add your organization or login name here

def generate_jwt(app_id, private_key_path):
    with open(private_key_path, 'r') as key_file:
        private_key = key_file.read()

    payload = {
        'iat': int(datetime.datetime.now().timestamp()),
        'exp': int((datetime.datetime.now() + datetime.timedelta(minutes=10)).timestamp()),
        'iss': app_id
    }
    return jwt.encode(payload, private_key, algorithm='RS256')

def get_app_token(jwt_token, org_name):
    headers = {
        'Authorization': f'Bearer {jwt_token}',
        'Accept': 'application/vnd.github.v3+json'
    }
    response = requests.get('https://api.github.com/app/installations', headers=headers)
    response.raise_for_status()
    installations = response.json()
    for inst in installations:
        if inst['account']['login'].lower() == org_name.lower():
            return inst['access_tokens_url']
    raise Exception(f"No installation found for organization '{org_name}'")

def get_installation_token(access_tokens_url, jwt_token):
    headers = {
        'Authorization': f'Bearer {jwt_token}',
        'Accept': 'application/vnd.github.v3+json'
    }
    response = requests.post(access_tokens_url, headers=headers)
    response.raise_for_status()
    return response.json()['token']

def clone_repo(token, repo_name):
    clone_url = f'https://x-access-token:{token}@github.com/{repo_name}.git'
    subprocess.run(['git', 'clone', clone_url], check=True)

def main():
    jwt_token = generate_jwt(APP_ID, PRIVATE_KEY_PATH)
    access_tokens_url = get_app_token(jwt_token, ORG_NAME)
    token = get_installation_token(access_tokens_url, jwt_token)
    clone_repo(token, REPO_NAME)
    print("Repository cloned successfully!")

if __name__ == '__main__':
    main()


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions