From 6ee61856d0342d86a4ed36639c0ed5cf82a749d1 Mon Sep 17 00:00:00 2001 From: larryandria Date: Mon, 18 Jul 2022 17:24:16 +0200 Subject: [PATCH 1/9] feat: get solution hash tests --- github_tests_validator_app/constants.py | 4 ++++ github_tests_validator_app/utils.py | 9 ++++++++ server.py | 29 +++++++++++++++++-------- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/github_tests_validator_app/constants.py b/github_tests_validator_app/constants.py index 8bd192d..0f90f87 100644 --- a/github_tests_validator_app/constants.py +++ b/github_tests_validator_app/constants.py @@ -2,3 +2,7 @@ APP_ID = os.getenv("GH_APP_ID") APP_KEY = os.getenv("GH_APP_KEY") +SOLUTION_TESTS_ACCESS_TOKEN = os.getenv("SOLUTION_TESTS_ACCESS_TOKEN") +SOLUTION_OWNER = "artefactory-fr" +SOLUTION_REPO_NAME = "school_of_data_tests" +TESTS_FOLDER_NAME = "tests" diff --git a/github_tests_validator_app/utils.py b/github_tests_validator_app/utils.py index 18b93f7..1e8636a 100644 --- a/github_tests_validator_app/utils.py +++ b/github_tests_validator_app/utils.py @@ -1,5 +1,7 @@ import hashlib +from github_tests_validator_app.constants import TESTS_FOLDER_NAME + def get_hash_files(contents): hash_sum = "" @@ -8,3 +10,10 @@ def get_hash_files(contents): hash = hashlib.sha256() hash.update(hash_sum.encode()) return str(hash.hexdigest()) + + +def get_tests_hash(git_connection, owner, repo_name): + repo = git_connection.get_repo(f"{owner}/{repo_name}") + contents = repo.get_contents(TESTS_FOLDER_NAME) + hash = get_hash_files(contents) + return hash diff --git a/server.py b/server.py index 1c199ef..8ead74b 100644 --- a/server.py +++ b/server.py @@ -1,12 +1,18 @@ import uvicorn from fastapi import FastAPI, Request from github import Github, GithubIntegration -from github_tests_validator_app.constants import APP_ID, APP_KEY -from github_tests_validator_app.utils import get_hash_files +from github_tests_validator_app.constants import ( + APP_ID, + APP_KEY, + SOLUTION_OWNER, + SOLUTION_REPO_NAME, + SOLUTION_TESTS_ACCESS_TOKEN, +) +from github_tests_validator_app.utils import get_tests_hash app = FastAPI() -git_integration = GithubIntegration( +git_intergration = GithubIntegration( APP_ID, APP_KEY, ) @@ -23,15 +29,20 @@ async def main(request: Request) -> None: repo_name = payload["repository"]["name"] git_connection = Github( - login_or_token=git_integration.get_access_token( - git_integration.get_installation(owner, repo_name).id + login_or_token=git_intergration.get_access_token( + git_intergration.get_installation(owner, repo_name).id ).token ) - repo = git_connection.get_repo(f"{owner}/{repo_name}") - contents = repo.get_contents("tests") - hashes = get_hash_files(contents) - print(hashes) + student_hash_tests = get_tests_hash(git_connection, owner, repo_name) + + g = Github(SOLUTION_TESTS_ACCESS_TOKEN) + + solution_hash_tests = get_tests_hash(g, SOLUTION_OWNER, SOLUTION_REPO_NAME) + + print(student_hash_tests) + print(solution_hash_tests) + return From d1df61b4d9768d849be576bb92aa33163106a6f6 Mon Sep 17 00:00:00 2001 From: larryandria Date: Wed, 20 Jul 2022 10:50:22 +0200 Subject: [PATCH 2/9] feat: create function get files_content --- github_tests_validator_app/utils.py | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/github_tests_validator_app/utils.py b/github_tests_validator_app/utils.py index 1e8636a..ad6bb96 100644 --- a/github_tests_validator_app/utils.py +++ b/github_tests_validator_app/utils.py @@ -1,9 +1,12 @@ +from typing import Union + import hashlib +from github import ContentFile, Github, Repository from github_tests_validator_app.constants import TESTS_FOLDER_NAME -def get_hash_files(contents): +def get_hash_files(contents: list(ContentFile.ContentFile)) -> str: hash_sum = "" for content in contents: hash_sum += content.sha @@ -12,8 +15,26 @@ def get_hash_files(contents): return str(hash.hexdigest()) -def get_tests_hash(git_connection, owner, repo_name): +def get_tests_hash(token: str, owner: str, repo_name: str, tests_folder=TESTS_FOLDER_NAME) -> str: + git_connection = Github(login_or_token=token) repo = git_connection.get_repo(f"{owner}/{repo_name}") - contents = repo.get_contents(TESTS_FOLDER_NAME) - hash = get_hash_files(contents) + contents = repo.get_contents(tests_folder) + files_content = get_files_content(contents, repo) + hash = get_hash_files(files_content) return hash + + +def get_files_content( + contents: Union(list, ContentFile.ContentFile), repo: Repository.Repository +) -> list(ContentFile.ContentFile): + files_content = [] + if isinstance(contents, list): + while contents: + file_content = contents.pop(0) + if file_content.type == "dir": + contents.extend(repo.get_contents(file_content.path)) + else: + files_content.append(file_content) + else: + return [contents] + return files_content From 44a22d584cb20de1a33596d7e0901ea5ac5006fd Mon Sep 17 00:00:00 2001 From: larryandria Date: Wed, 20 Jul 2022 10:51:04 +0200 Subject: [PATCH 3/9] feat: get hash tests from student and solution repo --- server.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/server.py b/server.py index 8ead74b..da5c7d1 100644 --- a/server.py +++ b/server.py @@ -1,6 +1,6 @@ import uvicorn from fastapi import FastAPI, Request -from github import Github, GithubIntegration +from github import GithubIntegration from github_tests_validator_app.constants import ( APP_ID, APP_KEY, @@ -27,18 +27,15 @@ async def main(request: Request) -> None: owner = payload["repository"]["owner"]["login"] repo_name = payload["repository"]["name"] + token = git_intergration.get_access_token( + git_intergration.get_installation(owner, repo_name).id + ).token - git_connection = Github( - login_or_token=git_intergration.get_access_token( - git_intergration.get_installation(owner, repo_name).id - ).token - ) - - student_hash_tests = get_tests_hash(git_connection, owner, repo_name) + student_hash_tests = get_tests_hash(token, owner, repo_name) - g = Github(SOLUTION_TESTS_ACCESS_TOKEN) - - solution_hash_tests = get_tests_hash(g, SOLUTION_OWNER, SOLUTION_REPO_NAME) + solution_hash_tests = get_tests_hash( + SOLUTION_TESTS_ACCESS_TOKEN, SOLUTION_OWNER, SOLUTION_REPO_NAME + ) print(student_hash_tests) print(solution_hash_tests) From efd56ce9cb9ec20c7aa07af104a59e0442554a47 Mon Sep 17 00:00:00 2001 From: larryandria Date: Wed, 20 Jul 2022 10:51:27 +0200 Subject: [PATCH 4/9] tests: fix basic test --- tests/units/basic_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/units/basic_test.py b/tests/units/basic_test.py index 8ff336f..71c214f 100644 --- a/tests/units/basic_test.py +++ b/tests/units/basic_test.py @@ -2,4 +2,4 @@ def test_length_hash(): - assert len(get_hash_files("")) == 64 + assert len(get_hash_files([""])) == 64 From 820b3bed22afc778a09141da83b0699d756d4d89 Mon Sep 17 00:00:00 2001 From: larryandria Date: Wed, 20 Jul 2022 11:52:58 +0200 Subject: [PATCH 5/9] tests: fix typing basic test --- tests/units/basic_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/units/basic_test.py b/tests/units/basic_test.py index 71c214f..f8dbcf1 100644 --- a/tests/units/basic_test.py +++ b/tests/units/basic_test.py @@ -2,4 +2,4 @@ def test_length_hash(): - assert len(get_hash_files([""])) == 64 + assert len(get_hash_files([])) == 64 From 6bcb886d41777f20bb9ab4f50c9fca6115862574 Mon Sep 17 00:00:00 2001 From: larryandria Date: Wed, 20 Jul 2022 11:53:32 +0200 Subject: [PATCH 6/9] fix: cast os getenv --- github_tests_validator_app/constants.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/github_tests_validator_app/constants.py b/github_tests_validator_app/constants.py index 0f90f87..61130d4 100644 --- a/github_tests_validator_app/constants.py +++ b/github_tests_validator_app/constants.py @@ -1,8 +1,10 @@ +from typing import cast + import os -APP_ID = os.getenv("GH_APP_ID") -APP_KEY = os.getenv("GH_APP_KEY") -SOLUTION_TESTS_ACCESS_TOKEN = os.getenv("SOLUTION_TESTS_ACCESS_TOKEN") +APP_ID = cast(str, os.getenv("GH_APP_ID")) +APP_KEY = cast(str, os.getenv("GH_APP_KEY")) +SOLUTION_TESTS_ACCESS_TOKEN = cast(str, os.getenv("SOLUTION_TESTS_ACCESS_TOKEN")) SOLUTION_OWNER = "artefactory-fr" SOLUTION_REPO_NAME = "school_of_data_tests" TESTS_FOLDER_NAME = "tests" From 6cbdc9d224a5844ba8d589b2df6ce2e956e193a2 Mon Sep 17 00:00:00 2001 From: larryandria Date: Wed, 20 Jul 2022 12:20:21 +0200 Subject: [PATCH 7/9] fix: typing function --- github_tests_validator_app/utils.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/github_tests_validator_app/utils.py b/github_tests_validator_app/utils.py index ad6bb96..65ecd0a 100644 --- a/github_tests_validator_app/utils.py +++ b/github_tests_validator_app/utils.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Any, List import hashlib @@ -6,7 +6,7 @@ from github_tests_validator_app.constants import TESTS_FOLDER_NAME -def get_hash_files(contents: list(ContentFile.ContentFile)) -> str: +def get_hash_files(contents: List[ContentFile.ContentFile]) -> str: hash_sum = "" for content in contents: hash_sum += content.sha @@ -15,26 +15,24 @@ def get_hash_files(contents: list(ContentFile.ContentFile)) -> str: return str(hash.hexdigest()) -def get_tests_hash(token: str, owner: str, repo_name: str, tests_folder=TESTS_FOLDER_NAME) -> str: +def get_tests_hash(token: str, owner: str, repo_name: str) -> str: git_connection = Github(login_or_token=token) repo = git_connection.get_repo(f"{owner}/{repo_name}") - contents = repo.get_contents(tests_folder) + contents = repo.get_contents(TESTS_FOLDER_NAME) files_content = get_files_content(contents, repo) hash = get_hash_files(files_content) return hash -def get_files_content( - contents: Union(list, ContentFile.ContentFile), repo: Repository.Repository -) -> list(ContentFile.ContentFile): - files_content = [] - if isinstance(contents, list): +def get_files_content(contents: Any, repo: Repository.Repository) -> List[ContentFile.ContentFile]: + if isinstance(contents, ContentFile.ContentFile): + return [contents] + else: + files_content = [] while contents: file_content = contents.pop(0) if file_content.type == "dir": contents.extend(repo.get_contents(file_content.path)) else: files_content.append(file_content) - else: - return [contents] - return files_content + return files_content From e6d3e0a4a6330ead7a70be41b2ed60f2558c4b36 Mon Sep 17 00:00:00 2001 From: larryandria Date: Wed, 20 Jul 2022 14:41:36 +0200 Subject: [PATCH 8/9] feat: add function compare tests folder --- github_tests_validator_app/utils.py | 53 +++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/github_tests_validator_app/utils.py b/github_tests_validator_app/utils.py index 65ecd0a..949b81b 100644 --- a/github_tests_validator_app/utils.py +++ b/github_tests_validator_app/utils.py @@ -15,9 +15,7 @@ def get_hash_files(contents: List[ContentFile.ContentFile]) -> str: return str(hash.hexdigest()) -def get_tests_hash(token: str, owner: str, repo_name: str) -> str: - git_connection = Github(login_or_token=token) - repo = git_connection.get_repo(f"{owner}/{repo_name}") +def get_tests_hash(repo: Repository.Repository) -> str: contents = repo.get_contents(TESTS_FOLDER_NAME) files_content = get_files_content(contents, repo) hash = get_hash_files(files_content) @@ -25,14 +23,41 @@ def get_tests_hash(token: str, owner: str, repo_name: str) -> str: def get_files_content(contents: Any, repo: Repository.Repository) -> List[ContentFile.ContentFile]: - if isinstance(contents, ContentFile.ContentFile): - return [contents] - else: - files_content = [] - while contents: - file_content = contents.pop(0) - if file_content.type == "dir": - contents.extend(repo.get_contents(file_content.path)) - else: - files_content.append(file_content) - return files_content + files_content = [] + while contents: + file_content = contents.pop(0) + if file_content.type == "dir": + contents.extend(repo.get_contents(file_content.path)) + else: + files_content.append(file_content) + return files_content + + +def get_repo(token: str, owner: str, repo_name: str) -> Repository.Repository: + git_connection = Github(login_or_token=token) + repo = git_connection.get_repo(f"{owner}/{repo_name}") + return repo + + +def get_last_hash_commit(repo: Repository.Repository, branch_name: str) -> str: + branch = repo.get_branch(branch_name) + return branch.commit.sha + + +def compare_tests_folder( + student_repo: Repository.Repository, solution_repo: Repository.Repository +) -> bool: + student_contents = student_repo.get_contents(TESTS_FOLDER_NAME) + + if ( + isinstance(student_contents, ContentFile.ContentFile) + and student_contents.type == "submodule" + ): + solution_last_commit = get_last_hash_commit(solution_repo, "main") + student_tests_commit = student_contents.sha + return solution_last_commit == student_tests_commit + + student_hash_tests = get_tests_hash(student_repo) + solution_hash_tests = get_tests_hash(solution_repo) + + return student_hash_tests == solution_hash_tests From 736af85abd731339babe7d95e46d8a44655ffb52 Mon Sep 17 00:00:00 2001 From: larryandria Date: Wed, 20 Jul 2022 14:43:03 +0200 Subject: [PATCH 9/9] feat: compare student and solution tests folder --- server.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/server.py b/server.py index da5c7d1..59c30ea 100644 --- a/server.py +++ b/server.py @@ -7,12 +7,13 @@ SOLUTION_OWNER, SOLUTION_REPO_NAME, SOLUTION_TESTS_ACCESS_TOKEN, + TESTS_FOLDER_NAME, ) -from github_tests_validator_app.utils import get_tests_hash +from github_tests_validator_app.utils import compare_tests_folder, get_repo app = FastAPI() -git_intergration = GithubIntegration( +git_integration = GithubIntegration( APP_ID, APP_KEY, ) @@ -27,18 +28,15 @@ async def main(request: Request) -> None: owner = payload["repository"]["owner"]["login"] repo_name = payload["repository"]["name"] - token = git_intergration.get_access_token( - git_intergration.get_installation(owner, repo_name).id + token = git_integration.get_access_token( + git_integration.get_installation(owner, repo_name).id ).token - student_hash_tests = get_tests_hash(token, owner, repo_name) + student_repo = get_repo(token, owner, repo_name) + solution_repo = get_repo(SOLUTION_TESTS_ACCESS_TOKEN, SOLUTION_OWNER, SOLUTION_REPO_NAME) - solution_hash_tests = get_tests_hash( - SOLUTION_TESTS_ACCESS_TOKEN, SOLUTION_OWNER, SOLUTION_REPO_NAME - ) - - print(student_hash_tests) - print(solution_hash_tests) + tests_havent_changed = compare_tests_folder(student_repo, solution_repo) + print(tests_havent_changed) return