diff --git a/contribute b/contribute new file mode 100755 index 0000000..265c4eb --- /dev/null +++ b/contribute @@ -0,0 +1,23 @@ +#!/bin/bash + +# Check if the first 3 arguments are provided +if [ -z $1 ] || [ -z $2 ] || [ -z $3 ]; then + echo "Error: The first 3 arguments are mandatory." + echo "Usage: ./contribute " + exit 1 +fi + +# Set the last 3 arguments to "#" if not provided +arg4=$4 +arg5=$5 +arg6=$6 +if [ -z $4 ]; then +arg4="#" +fi +if [ -z $5 ]; then +arg5="#" +fi +if [ -z $6 ]; then +arg6="#" +fi +python3 contribute.py "$1" "$2" "$3" "$arg4" "$arg5" "$arg6" diff --git a/contribute.bat b/contribute.bat new file mode 100644 index 0000000..ae0014c --- /dev/null +++ b/contribute.bat @@ -0,0 +1,20 @@ +@echo off + +REM Check if the first 3 arguments are provided +if "%~1" == "" goto :missing_arg +if "%~2" == "" goto :missing_arg +if "%~3" == "" goto :missing_arg + +REM Check and set default values for the last three arguments if not provided +if "%~4"=="" (set arg4="#") else (set arg4=%~4) +if "%~5"=="" (set arg5="#") else (set arg5=%~5) +if "%~6"=="" (set arg6="#") else (set arg6=%~6) +python contribute.py %1 %2 %3 "%arg4%" "%arg5%" "%arg6%" +goto :eof + +:missing_arg +echo "Error: The first 3 arguments are mandatory." +echo "Usage: ./contribute.bat " + + + diff --git a/contribute.py b/contribute.py new file mode 100644 index 0000000..19ee2e4 --- /dev/null +++ b/contribute.py @@ -0,0 +1,164 @@ +import github +from github import Github +import os,sys,platform,base64 + +# Intializing the Variables +# Hashed token +BOT_TOKEN = "Z2l0aHViX3BhdF8xMUFYS0pGVFkwODR5OEhoZlI5VEl1X0VZZnNaNjU0WGw4OU0ycXhJc0h3TXh3RkVIZGFRQ3gwa0daZFhKUUdYbUk2QzRTU1dDNkF4clUyQWRF" +BOT_ACCOUNT = 'concore-bot' #bot account name +REPO_NAME = 'concore-studies' #study repo name +UPSTREAM_ACCOUNT = 'ControlCore-Project' #upstream account name +STUDY_NAME = sys.argv[1] +STUDY_NAME_PATH = sys.argv[2] +AUTHOR_NAME = sys.argv[3] +BRANCH_NAME = sys.argv[4] +PR_TITLE = sys.argv[5] +PR_BODY = sys.argv[6] + +# Defining Functions +def checkInputValidity(): + if AUTHOR_NAME=="" or STUDY_NAME=="" or STUDY_NAME=="": + print("Please Provide necessary Inputs") + exit(0) + if not os.path.isdir(STUDY_NAME_PATH): + print("Directory doesnot Exists.Invalid Path") + exit(0) + + +def getPRs(upstream_repo): + try: + return upstream_repo.get_pulls(head=f'{BOT_ACCOUNT}:{BRANCH_NAME}') + except Exception as e: + print("Not able to fetch Status of your example.Please try after some time.") + exit(0) + +def printPR(pr): + print(f'Check your example here https://github.com/{UPSTREAM_ACCOUNT}/{REPO_NAME}/pulls/{pr.number}',end="") + +def anyOpenPR(upstream_repo): + pr = getPRs(upstream_repo) + openPr=None + for i in pr: + if i.state=="open": + openPr=i + break + return openPr + +def commitAndUpdateRef(repo,tree_content,commit,branch): + try: + new_tree = repo.create_git_tree(tree=tree_content,base_tree=commit.commit.tree) + new_commit = repo.create_git_commit("commit study",new_tree,[commit.commit]) + if len(repo.compare(base=commit.commit.sha,head=new_commit.sha).files) == 0: + print("Your don't have any new changes.May be your example is already accepted.If this is not the case try with different fields.") + exit(0) + ref = repo.get_git_ref("heads/"+branch.name) + ref.edit(new_commit.sha,True) + except Exception as e: + print("failed to Upload your example.Please try after some time.",end="") + exit(0) + + +def appendBlobInTree(repo,content,file_path,tree_content): + blob = repo.create_git_blob(content,'utf-8') + tree_content.append( github.InputGitTreeElement(path=file_path,mode="100644",type="blob",sha=blob.sha)) + + +def runWorkflow(repo,upstream_repo): + openPR = anyOpenPR(upstream_repo) + if openPR==None: + workflow_runned = repo.get_workflow(id_or_name="pull_request.yml").create_dispatch(ref=BRANCH_NAME,inputs={'title':f"[BOT]: {PR_TITLE}",'body':PR_BODY,'upstreamRepo':UPSTREAM_ACCOUNT,'botRepo':BOT_ACCOUNT,'repo':REPO_NAME}) + if not workflow_runned: + print("Some error occured.Please try after some time") + exit(0) + else: + printPRStatus(upstream_repo) + else: + print("Successfully uploaded all files,your example is in waiting.Please wait for us to accept it.",end="") + printPR(openPR) + +def printPRStatus(upstream_repo): + try: + issues = upstream_repo.get_issues() + pulls = upstream_repo.get_pulls(state='all') + max_num = -1 + for i in issues: + max_num = max(max_num,i.number) + for i in pulls: + max_num = max(max_num,i.number) + print(f'Check your example here https://github.com/{UPSTREAM_ACCOUNT}/{REPO_NAME}/pulls/{max_num+1}',end="") + except Exception as e: + print("Your example successfully uploaded but unable to fetch status.Please try again") + + +def isImageFile(filename): + image_extensions = ['.jpeg', '.jpg', '.png','.gif'] + return any(filename.endswith(ext) for ext in image_extensions) + + +# Decode Github Token +def decode_token(encoded_token): + decoded_bytes = base64.b64decode(encoded_token.encode('utf-8')) + decoded_token = decoded_bytes.decode('utf-8') + return decoded_token + + +# check if directory path is Valid +checkInputValidity() + + +# Authenticating Github with Access token +try: + if BRANCH_NAME=="#": + BRANCH_NAME=AUTHOR_NAME+"_"+STUDY_NAME + if PR_TITLE=="#": + PR_TITLE=f"Contributing Study {STUDY_NAME} by {AUTHOR_NAME}" + if PR_BODY=="#": + PR_BODY=f"Study Name: {STUDY_NAME} \n Author Name: {AUTHOR_NAME}" + AUTHOR_NAME = AUTHOR_NAME.replace(" ","_") + DIR_PATH = STUDY_NAME + g = Github(decode_token(BOT_TOKEN)) + repo = g.get_user(BOT_ACCOUNT).get_repo(REPO_NAME) + upstream_repo = g.get_repo(f'{UPSTREAM_ACCOUNT}/{REPO_NAME}') #controlcore-Project/concore-studies + base_ref = upstream_repo.get_branch(repo.default_branch) + branches = repo.get_branches() + BRANCH_NAME = BRANCH_NAME.replace(" ","_") + DIR_PATH = DIR_PATH.replace(" ","_") + is_present = any(branch.name == BRANCH_NAME for branch in branches) +except Exception as e: + print("Some error occured.Authentication failed",end="") + exit(0) + + +try: + # If creating PR First Time + # Create New Branch for that exmaple + if not is_present: + repo.create_git_ref(f'refs/heads/{BRANCH_NAME}', base_ref.commit.sha) + # Get current branch + branch = repo.get_branch(branch=BRANCH_NAME) +except Exception as e: + print("Not able to create study for you.Please try again after some time",end="") + exit(0) + + +tree_content = [] + +try: + for root, dirs, files in os.walk(STUDY_NAME_PATH): + for filename in files: + path = f"{root}/{filename}" + if isImageFile(filename): + with open(path, 'rb') as file: + image = file.read() + content = base64.b64encode(image).decode('utf-8') + else: + with open(path, 'r') as file: + content = file.read() + file_path = f'{DIR_PATH+path.removeprefix(STUDY_NAME_PATH)}' + if(platform.uname()[0]=='Windows'): file_path=file_path.replace("\\","/") + appendBlobInTree(repo,content,file_path,tree_content) + commitAndUpdateRef(repo,tree_content,base_ref.commit,branch) + runWorkflow(repo,upstream_repo) +except Exception as e: + print("Some error Occured.Please try again after some time.",end="") + exit(0) \ No newline at end of file diff --git a/fri/requirements.txt b/fri/requirements.txt index 8268e17..2c7516d 100644 --- a/fri/requirements.txt +++ b/fri/requirements.txt @@ -2,3 +2,4 @@ Flask gunicorn==20.1.0 FLASK_CORS jupyterlab +PyGithub \ No newline at end of file diff --git a/fri/server/main.py b/fri/server/main.py index df04616..764993f 100644 --- a/fri/server/main.py +++ b/fri/server/main.py @@ -3,7 +3,7 @@ import xml.etree.ElementTree as ET import os import subprocess -from subprocess import call +from subprocess import call,check_output from pathlib import Path import json import platform @@ -294,6 +294,37 @@ def clear(dir): resp.status_code = 500 return resp +@app.route('/contribute', methods=['POST']) +def contribute(): + try: + data = request.json + PR_TITLE = data.get('title') + PR_BODY = data.get('desc') + AUTHOR_NAME = data.get('auth') + STUDY_NAME = data.get('study') + STUDY_NAME_PATH = data.get('path') + BRANCH_NAME = data.get('branch') + if(platform.uname()[0]=='Windows'): + proc=check_output(["contribute",STUDY_NAME,STUDY_NAME_PATH,AUTHOR_NAME,BRANCH_NAME,PR_TITLE,PR_BODY],cwd=concore_path,shell=True) + else: + if len(BRANCH_NAME)==0: + proc = check_output(["./contribute",STUDY_NAME,STUDY_NAME_PATH,AUTHOR_NAME],cwd=concore_path) + else: + proc = check_output(["./contribute",STUDY_NAME,STUDY_NAME_PATH,AUTHOR_NAME,BRANCH_NAME,PR_TITLE,PR_BODY],cwd=concore_path) + output_string = proc.decode() + status=200 + if output_string.find("/pulls/")!=-1: + status=200 + elif output_string.find("error")!=-1: + status=501 + else: + status=400 + return jsonify({'message': output_string}),status + except Exception as e: + output_string = "Some Error occured.Please try after some time" + status=501 + return jsonify({'message': output_string}),status + # to download /download/?fetch=. For example, /download/test?fetchDir=xyz&fetch=u @app.route('/download/', methods=['POST', 'GET']) def download(dir): diff --git a/requirements.txt b/requirements.txt index e51481e..067a3ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ numpy scipy matplotlib cvxopt +PyGithub \ No newline at end of file