diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..69fada0 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,65 @@ +name: CI + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + push: + branches: [main] + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + checks: + name: Lint / Format Check / Tests + runs-on: ubuntu-latest + if: ${{ github.event_name != 'push' || github.ref == 'refs/heads/main' }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + id: py + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install Poetry + uses: abatilo/actions-poetry@v3 + with: + poetry-version: "2.2.0" + + - name: Enable in-project venv + run: poetry config virtualenvs.in-project true + + - name: Cache Poetry venv + uses: actions/cache@v4 + with: + path: .venv + key: venv-${{ runner.os }}-${{ steps.py.outputs.python-version }}-${{ hashFiles('poetry.lock') }} + restore-keys: | + venv-${{ runner.os }}- + + - name: Install dependencies + run: poetry install --no-interaction + + # ---- Static checks (no file modifications in CI) ---- + - name: Ruff lint + run: poetry run ruff check . + + - name: Ruff format (check only) + run: poetry run ruff format --check . + + # ---- Run tests with coverage threshold ---- + - name: Run tests with coverage + run: | + poetry run pytest \ + -q --maxfail=1 --disable-warnings \ + --cov=src --cov-report=term-missing \ + --cov-report=xml:coverage.xml \ + --cov-fail-under=100 diff --git a/README.md b/README.md index af2eb1b..1fd278f 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,12 @@ **Workflow**: 1. Fork this repository to your own GitHub account. -2. Create a new branch from `develop` and name it `feature/student1name_student2name`. -3. Clone the repo to AWS VM. -4. Implement the functions until all `pytest` tests pass. -5. Push your code to your Github repo. +2. Clone the repo to AWS VM. +3. Run poetry install to install dependencies +4. Run poetry run pre-commit install to install the pre-commit hook. +5. Create a new branch from `develop` and name it `feature/student1name_student2name`. +7. Implement the functions until all `pytest` tests pass. +8. Make the pre-commit checks all pass and commit the code. +9. Push your code to your Github repo. 5. Submit a Pull Request back to the `develop` branch of the main repo. CI must pass. 6. Wait for code review and grading. diff --git a/poetry.lock b/poetry.lock index 4177cc6..28cbed8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -940,5 +940,5 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [metadata] lock-version = "2.1" -python-versions = ">=3.12" -content-hash = "c6fe4b288327b501a15d79c555e296323d3da6a16b612a92ac74271600991431" +python-versions = "^3.12" +content-hash = "2208d21945ff72a894dfa1b053afd56efc83d7e50a8d39b29c814fdc7eb94a3e" diff --git a/pyproject.toml b/pyproject.toml index 4274d13..df128a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,17 @@ dependencies = [ "pre-commit (>=4.3.0,<5.0.0)" ] +[tool.poetry] +name = "arithmetic" +version = "0.1.0" +description = "Toy arithmetic package" +authors = ["Your Name "] +readme = "README.md" +packages = [{ include = "src/arithmetic" }] + +[tool.poetry.dependencies] +python = "^3.12" + [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] diff --git a/src/arithmetic/arithmetic.py b/src/arithmetic/arithmetic.py index 86f6960..8ba5235 100644 --- a/src/arithmetic/arithmetic.py +++ b/src/arithmetic/arithmetic.py @@ -13,7 +13,7 @@ def add_numbers(a: int, b: int) -> int: Returns: Sum of a and b. """ - raise NotImplementedError + return a + b def factorial(n: int) -> int: @@ -28,7 +28,16 @@ def factorial(n: int) -> int: Raises: ValueError: if n is negative """ - raise NotImplementedError + total = 1 + if n > 0: + for i in range(1, n + 1): + total = total * i + elif n == 0: + return 1 + else: + raise ValueError() + + return total def is_prime(n: int) -> bool: @@ -43,4 +52,9 @@ def is_prime(n: int) -> bool: Returns: True if n is prime; otherwise False. """ - raise NotImplementedError + if n <= 1: + return False + for i in range(2, int(n**0.5) + 1): + if n % i == 0: + return False + return True