diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 0000000..511a37a --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,31 @@ +name: Automatic Pull request + +on: + workflow_dispatch: + inputs: + title: + description: 'title of example' + required: true + body: + description: 'description of example' + required: true + upstreamRepo: + description: 'Upstream repo' + required: true + botRepo: + description: 'bot repo' + required: true + repo: + description: 'repo name' + required: true + +jobs: + create-pull-request: + runs-on: ubuntu-latest + + steps: + - name: Create PR + run: | + gh pr create --repo ${{ github.event.inputs.upstreamRepo }}/${{ github.event.inputs.repo }} --head ${{ github.event.inputs.botRepo }}:${{ github.ref }} --base main --title "${{ github.event.inputs.title }}" --body "${{ github.event.inputs.body }}" + env: + GITHUB_TOKEN: ${{ secrets.token }} diff --git a/contribute b/contribute new file mode 100644 index 0000000..4fc4fbb --- /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 +python contribute.py $1 $2 $3 $arg4 $arg5 $arg6 diff --git a/contribute.bat b/contribute.bat new file mode 100644 index 0000000..4ffae56 --- /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..2ce6ccf --- /dev/null +++ b/contribute.py @@ -0,0 +1,180 @@ +import github +from github import Github +import os,sys,time,platform,base64 + +# Intializing the Variables +# Hashed token +BOT_TOKEN = 'Z2l0aHViX3BhdF8xMUFYS0pGVFkwUWVWZ3AzbkpkWk8yX3BOc1VncDFIVDMwZVNXcHhBNm9acHhMaGZGdU5CdE85TGpqdXF1UWRRNzI2S01aUk5HRUNGanFWNDZi' +REPO_NAME = 'concore' #repo name +OWNER_NAME = 'parteekcoder123' #bot 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] +UPSTREAM_OWNER = 'parteekcoder' # upstream to which examples should be contributed + + +# 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'{OWNER_NAME}:{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_OWNER}/pulls/'+str(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(upstream_repo,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 message",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 fetchUpstream(repo,base_sha,branch): + try: + result = repo.compare(base=base_sha,head=branch.commit.commit.sha) + if result.behind_by>0: + ref = repo.get_git_ref("heads/"+branch.name) + ref.edit(base_sha) + except Exception as e: + exit(0) + + +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':PR_TITLE,'body':PR_BODY,'upstreamRepo':upstream_repo,'botRepo':OWNER_NAME,'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: + time.sleep(15) + openPR = anyOpenPR(upstream_repo) + if openPR==None: + print("Someting went wrong or your example already exist.If this is not the case try with different fields") + exit(0) + printPR(openPR) + 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'] + _, file_extension = os.path.splitext(filename) + return file_extension.lower() in image_extensions + +# Encode Github Token +def encode_token(token): + encoded_bytes = base64.b64encode(token.encode('utf-8')) + encoded_token = encoded_bytes.decode('utf-8') + return encoded_token + + +# 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="Contributing Study "+AUTHOR_NAME+" "+STUDY_NAME + if PR_BODY=="#": + PR_BODY="Study Contributed by "+ AUTHOR_NAME + AUTHOR_NAME = AUTHOR_NAME.replace(" ","_") + DIR_PATH = AUTHOR_NAME + '_' + STUDY_NAME + g = Github(decode_token(BOT_TOKEN)) + repo = g.get_user(OWNER_NAME).get_repo(REPO_NAME) + upstream_repo = g.get_repo(f'{UPSTREAM_OWNER}/{REPO_NAME}') #controlcore-Project/concore + 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: + 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 = os.path.join(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(upstream_repo,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/server/main.py b/fri/server/main.py index b2b790e..8a1014d 100644 --- a/fri/server/main.py +++ b/fri/server/main.py @@ -2,7 +2,7 @@ from werkzeug.utils import secure_filename import os import subprocess -from subprocess import call +from subprocess import call,check_output from pathlib import Path import json import platform @@ -169,6 +169,35 @@ 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: + 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: + print(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