diff --git a/.github/workflows/ms5.yaml b/.github/workflows/ms5.yaml new file mode 100644 index 0000000..d18b10a --- /dev/null +++ b/.github/workflows/ms5.yaml @@ -0,0 +1,65 @@ +name: Pylint and API Testing + +on: + push: + branches: [Milestone-5_feature_branch] + +jobs: + test-and-lint: + runs-on: self-hosted # or ubuntu-latest + strategy: + matrix: + python-version: ["3.10"] + + steps: + #Checkout code + - uses: actions/checkout@v2 # Updated to correct version + + #Set up Python + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + #Install everything + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pylint flask flask_cors flasgger pytest + + #Run pylint on all Python files + - name: Analyze code with pylint, excluding main.py + run: | + pylint $(git ls-files '*.py') + + #Build Docker Image for API + - name: Build API Docker Image + run: | + docker build -t api-image -f Backend/dockerfile . + + + # Stop and Remove Existing Container (if any). this was the error + - name: Stop and Remove Existing API Container + run: | + docker stop api-container || true # Stop if running, ignore if not + sleep 10 + docker rm api-container || true # Remove if exists, ignore if not + sleep 1 + + #Start API Container + - name: Start API Container + run: | + docker run -d -p 5000:5000 --name api-container --memory=7g api-image # Start container on port 5000 + + #Run all Python tests in the directory + - name: Run the Python tests in directory + run: | + + #docker exec api-container python3 main.py # Execute main.py + #docker exec api-container pytest test_main.py # Execute test_main.py + + #Stop and Remove API Container after tests + - name: Stop and Remove API Container + run: | + docker stop api-container # Stop container after tests + docker rm api-container # Remove container after tests diff --git a/Backend/__pycache__/PetFuc.cpython-310.pyc b/Backend/__pycache__/PetFuc.cpython-310.pyc new file mode 100644 index 0000000..67e63b8 Binary files /dev/null and b/Backend/__pycache__/PetFuc.cpython-310.pyc differ diff --git a/Backend/__pycache__/UserFuc.cpython-310.pyc b/Backend/__pycache__/UserFuc.cpython-310.pyc new file mode 100644 index 0000000..4f147aa Binary files /dev/null and b/Backend/__pycache__/UserFuc.cpython-310.pyc differ diff --git a/Backend/__pycache__/test_main.cpython-310-pytest-8.3.3.pyc b/Backend/__pycache__/test_main.cpython-310-pytest-8.3.3.pyc new file mode 100644 index 0000000..37f94f2 Binary files /dev/null and b/Backend/__pycache__/test_main.cpython-310-pytest-8.3.3.pyc differ diff --git a/Backend/dockerfile b/Backend/dockerfile new file mode 100644 index 0000000..fd397fc --- /dev/null +++ b/Backend/dockerfile @@ -0,0 +1,30 @@ +# Use Python as the base image +FROM python:3.8-slim-buster + +# Install pip and Python dependencies +RUN apt-get update && apt-get install -y python3 python3-pip + +# Keeps Python from generating .pyc files in the container +ENV PYTHONDONTWRITEBYTECODE=1 + +# Turns off buffering for easier container logging +ENV PYTHONUNBUFFERED=1 + + +# Set the working directory in the container +WORKDIR /app + + +# Install pip requirements +COPY Backend/requirements.txt . +RUN python3 -m pip install -r requirements.txt + +# Copy main application file +COPY Backend/main.py . + +# Set the port for the application +ENV PORT=5000 +EXPOSE 5000 + +# Command to run the application +CMD ["python3", "main.py"] diff --git a/Backend/main.py b/Backend/main.py new file mode 100644 index 0000000..dcc2f6c --- /dev/null +++ b/Backend/main.py @@ -0,0 +1,36 @@ +""" This module is the main entry point for the pet adoption web application. +It defines routes and their functions for managing pets and user information. """ +from flask import Flask, request, jsonify +from pet_func import get_random_pet +from user_func import add_user_favorite, remove_user_favorite, replace_user_location + +app = Flask(__name__) + +# Example user information +user_acc_info = {"Name": "Eric", "Location": "Connecticut", "Occupation": "Student"} + +@app.route("/get_random_pet", methods=["GET"]) +def get_random_pet_endpoint(): + """Fetch and return random pet information for the homepage.""" + return get_random_pet(), 200 + +@app.route("/add_user_favorite", methods=["POST"]) +def add_user_favorite_endpoint(): + """Add a user's favorite pet to the database.""" + json_data = request.get_json() + return jsonify(add_user_favorite(json_data)), 200 + +@app.route("/remove_user_favorite", methods=["DELETE"]) +def remove_user_favorite_endpoint(): + """Remove a user's favorite pet from the database.""" + json_data = request.get_json() + return jsonify(remove_user_favorite(json_data)), 200 + +@app.route("/change_user_location", methods=["PUT"]) +def replace_user_information(): + """Change a user's account location.""" + new_location = request.get_json() + return jsonify(replace_user_location(new_location)), 200 + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000, debug=True) diff --git a/Backend/pet_func.py b/Backend/pet_func.py new file mode 100644 index 0000000..6638903 --- /dev/null +++ b/Backend/pet_func.py @@ -0,0 +1,11 @@ +""" This module handles pet-related functionalities, providing details about random pets. +It uses the Flask framework to return pet information in a JSON format. """ +from flask import jsonify + +def get_random_pet(): + """Return a random pet's information.""" + randomint = "9" # API generates a random integer representing a PET ID + # API accesses database and returns information associated with the random ID + # Returns information such as profile picture of the pet + return jsonify({"id": randomint, "name": "Sam", "sex": "Male", "Age": "8", + "location": "Connecticut", "Breed": "Pug"}) # Return pet details diff --git a/Backend/requirements.txt b/Backend/requirements.txt new file mode 100644 index 0000000..f0b9a8a --- /dev/null +++ b/Backend/requirements.txt @@ -0,0 +1,7 @@ +Flask==2.0.3 +requests==2.26.0 +pandas==1.3.4 +pytest==7.2.1 +flask_cors==3.0.10 +#Werkzeug==2.1.3 + diff --git a/Backend/test_main.py b/Backend/test_main.py new file mode 100644 index 0000000..ad27f16 --- /dev/null +++ b/Backend/test_main.py @@ -0,0 +1,44 @@ +""" This module contains unit tests for the pet adoption web application, testing the functionality +of various endpoints. It uses the requests library to simulate HTTP requests. """ +import requests + +def test_get_random_pet(): + """Test for http://localhost:5000/get_random_pet.""" + url = "http://localhost:5000" + response = requests.get(f"{url}/get_random_pet", timeout=10) + expected_response = {"id": "9", "name": "Sam", "sex": "Male", "Age": "8", + "location": "Connecticut", "Breed": "Pug"} + assert response.json() == expected_response + +def test_add_user_favorite(): + """Test for http://localhost:5000/add_user_favorite.""" + url = "http://localhost:5000" + favorite_pet1 = {"id": "9", "name": "Sam", "sex": "Male", "Age": "8", + "location": "Connecticut", "Breed": "Pug"} + response = requests.post(f"{url}/add_user_favorite", json=favorite_pet1, timeout=10) + assert response.json() == [favorite_pet1] + favorite_pet2 = {"id": "90", "name": "Ben", "sex": "Male", "Age": "2", + "location": "New York", "Breed": "Husky"} + response = requests.post(f"{url}/add_user_favorite", json=favorite_pet2, timeout=10) + assert response.json() == [favorite_pet1, favorite_pet2] + +def test_remove_user_favorite(): + """Test for http://localhost:5000/remove_user_favorite.""" + url = "http://localhost:5000" + favorite_pet1 = {"id": "9", "name": "Sam", "sex": "Male", "Age": "8", + "location": "Connecticut", "Breed": "Pug"} + response = requests.delete(f"{url}/remove_user_favorite", json=favorite_pet1, timeout=10) + assert response.json() == [] + favorite_pet2 = {"id": "90", "name": "Ben", "sex": "Male", "Age": "2", + "location": "New York", "Breed": "Husky"} + response = requests.delete(f"{url}/remove_user_favorite", json=favorite_pet2, timeout=10) + assert response.json() == [] + +def test_change_user_location(): + """Test for http://localhost:5000/change_user_location.""" + url = "http://localhost:5000" + response = requests.put(f"{url}/change_user_location", json={"Location": "New York"}, + timeout=10) + assert response.json() == {"Location": "New York", "Name": "Eric", "Occupation": + "Student", "Password": "2020"} + \ No newline at end of file diff --git a/Backend/user_func.py b/Backend/user_func.py new file mode 100644 index 0000000..51ff4ad --- /dev/null +++ b/Backend/user_func.py @@ -0,0 +1,26 @@ +""" This module handles user-related functionalities such as +managing favorites and updating user information. """ + +user_favorite_database = [] # Simulate a database for user favorites +user_acc_info = { + "Name": "Eric", + "Password": "2020", + "Location": "Connecticut", + "Occupation": "Student" +} + +def add_user_favorite(json_data): + """Add user favorite pet to the database.""" + user_favorite_database.append(json_data) + return user_favorite_database # Return updated user favorites database + +def remove_user_favorite(json_data): + """Remove user favorite pet from the database.""" + user_favorite_database.remove(json_data) + return user_favorite_database # Return updated user favorites database + +def replace_user_location(new_location): + """Change the user account location.""" + new_location = new_location.get("Location") + user_acc_info["Location"] = new_location # Set new location associated with the user + return user_acc_info # Return updated user account information diff --git a/Frontend/hi.txt b/Frontend/hi.txt new file mode 100644 index 0000000..53a199a --- /dev/null +++ b/Frontend/hi.txt @@ -0,0 +1 @@ +I'm just testing the ci/cd :) \ No newline at end of file diff --git a/Frontend/index.html b/Frontend/index.html new file mode 100644 index 0000000..e69de29