Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate only submitted Project Euler solution #3977

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ jobs:
python -m pip install --upgrade pip setuptools six wheel
python -m pip install pytest-cov -r requirements.txt
- name: Run tests
run: pytest --doctest-modules --ignore=project_euler/ --cov-report=term-missing:skip-covered --cov=. .
run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/ --cov-report=term-missing:skip-covered --cov=. .
- if: ${{ success() }}
run: scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md
18 changes: 11 additions & 7 deletions .github/workflows/project_euler.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
on:
pull_request:
# only check if a file is changed within the project_euler directory and related files
# Run only if a file is changed within the project_euler directory and related files
paths:
- 'project_euler/**'
- '.github/workflows/project_euler.yml'
- 'scripts/validate_solutions.py'
- "project_euler/**"
- ".github/workflows/project_euler.yml"
- "scripts/validate_solutions.py"
schedule:
- cron: "0 0 * * *" # Run everyday

name: 'Project Euler'
name: "Project Euler"

jobs:
project-euler:
Expand All @@ -24,8 +26,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- name: Install pytest
- name: Install pytest and requests
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade pytest
python -m pip install --upgrade pytest requests
- run: pytest scripts/validate_solutions.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45 changes: 43 additions & 2 deletions scripts/validate_solutions.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#!/usr/bin/env python3
import importlib.util
import json
import os
import pathlib
from types import ModuleType
from typing import Dict, List

import pytest
import requests

PROJECT_EULER_DIR_PATH = pathlib.Path.cwd().joinpath("project_euler")
PROJECT_EULER_ANSWERS_PATH = pathlib.Path.cwd().joinpath(
Expand All @@ -24,7 +26,7 @@ def convert_path_to_module(file_path: pathlib.Path) -> ModuleType:
return module


def collect_solution_file_paths() -> List[pathlib.Path]:
def all_solution_file_paths() -> List[pathlib.Path]:
"""Collects all the solution file path in the Project Euler directory"""
solution_file_paths = []
for problem_dir_path in PROJECT_EULER_DIR_PATH.iterdir():
Expand All @@ -37,12 +39,51 @@ def collect_solution_file_paths() -> List[pathlib.Path]:
return solution_file_paths


def get_files_url() -> str:
"""Return the pull request number which triggered this action."""
with open(os.environ["GITHUB_EVENT_PATH"]) as file:
event = json.load(file)
return event["pull_request"]["url"] + "/files"


def added_solution_file_path() -> List[pathlib.Path]:
"""Collects only the solution file path which got added in the current
pull request.

This will only be triggered if the script is ran from GitHub Actions.
"""
solution_file_paths = []
headers = {
"Accept": "application/vnd.github.v3+json",
"Authorization": "token " + os.environ["GITHUB_TOKEN"],
}
files = requests.get(get_files_url(), headers=headers).json()
for file in files:
filepath = pathlib.Path.cwd().joinpath(file["filename"])
if (
filepath.suffix != ".py"
or filepath.name.startswith(("_", "test"))
or not filepath.name.startswith("sol")
):
continue
solution_file_paths.append(filepath)
return solution_file_paths


def collect_solution_file_paths() -> List[pathlib.Path]:
if os.environ.get("CI") and os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
# Return only if there are any, otherwise default to all solutions
if filepaths := added_solution_file_path():
return filepaths
return all_solution_file_paths()


@pytest.mark.parametrize(
"solution_path",
collect_solution_file_paths(),
ids=lambda path: f"{path.parent.name}/{path.name}",
)
def test_project_euler(solution_path: pathlib.Path):
def test_project_euler(solution_path: pathlib.Path) -> None:
"""Testing for all Project Euler solutions"""
# problem_[extract this part] and pad it with zeroes for width 3
problem_number: str = solution_path.parent.name[8:].zfill(3)
Expand Down