From a75a7dc99b454af3e85ff4029fcd3608b1721db3 Mon Sep 17 00:00:00 2001 From: Brunowar12 <128008317+Brunowar12@users.noreply.github.com> Date: Mon, 19 May 2025 07:19:41 +0300 Subject: [PATCH 1/6] fix + fix error_response to generate response with return only general message to the client + fix it in calls --- api/utils.py | 29 ++++++++++++++++++++++++----- projects/views.py | 3 +-- tasks/views.py | 16 ++++++++++------ users/views.py | 11 ++++++----- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/api/utils.py b/api/utils.py index 1182a2a..c3faf1a 100644 --- a/api/utils.py +++ b/api/utils.py @@ -1,14 +1,33 @@ +import logging +import traceback +from typing import Optional from rest_framework.response import Response from rest_framework import status -def error_response(message, http_status=status.HTTP_400_BAD_REQUEST): +logger = logging.getLogger(__name__) + + +def error_response( + message: Optional[str] = None, + http_status: int = status.HTTP_400_BAD_REQUEST, + *, + exc: Optional[Exception] = None +): """ - Generates a response with the ‘error’ field and the specified HTTP status + Generates a generalized Response with the 'error' field. + If exc is passed, it logs the stack trace on the server """ - return Response({"error": message}, status=http_status) + if exc is not None: + # Logging of a full stack trade + logger.error("Internal error: %s\n%s", exc, traceback.format_exc()) + + # We return only a general message to the client + safe_message = message or "An internal server error occurred" + return Response({"error": safe_message}, status=http_status) + def status_response(message, http_status=None): """ Generates a response with the ‘status’ field and the specified HTTP status - """ - return Response({"status": message}, status=http_status) \ No newline at end of file + """ + return Response({"status": message}, status=http_status) diff --git a/projects/views.py b/projects/views.py index 124a75f..370deb9 100644 --- a/projects/views.py +++ b/projects/views.py @@ -5,7 +5,6 @@ from django.shortcuts import get_object_or_404 from django.utils import timezone from rest_framework import viewsets, status -from rest_framework.exceptions import ValidationError from rest_framework.decorators import action, api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response @@ -133,7 +132,7 @@ def assign_role(self, request, pk=None): ProjectMembershipService.assign_role(project, target, role) except Exception as e: message = getattr(e, 'detail', str(e)) - return error_response(message) + return error_response(message, exc=e) return status_response("Role assigned") diff --git a/tasks/views.py b/tasks/views.py index 8de0eb1..10eae2e 100644 --- a/tasks/views.py +++ b/tasks/views.py @@ -112,10 +112,11 @@ def toggle_favorite(self, request, pk=None): "is_favorite": updated_task.is_favorite, }) except Exception as e: - logger.error(f"Error toggling favorite for task {pk}: {e}") + logger.exception(f"Error toggling favorite for task {pk}") return error_response( "Failed to update favorite status", status.HTTP_500_INTERNAL_SERVER_ERROR, + exc=e ) @action( @@ -143,10 +144,11 @@ def toggle_completed(self, request, project_pk=None, pk=None): } ) except Exception as e: - logger.error(f"Error toggling completion for task {pk}: {e}") + logger.exception(f"Error toggling completion for task {pk}") return error_response( "Failed to update completion status", - status=status.HTTP_500_INTERNAL_SERVER_ERROR, + status.HTTP_500_INTERNAL_SERVER_ERROR, + exc=e ) @action( @@ -186,11 +188,13 @@ def move_task(self, request, project_pk=None, pk=None): TaskService.move_task_to_project(task, project_id, request.user) return status_response("Task moved successfully") except ValueError as e: - return error_response(str(e), status.HTTP_404_NOT_FOUND) + return error_response(str(e), status.HTTP_404_NOT_FOUND, exc=e) except Exception as e: - logger.error(f"Error moving task: {e}", exc_info=True) + logger.exception(f"Error moving task: {e}") return error_response( - "Failed to move task", status.HTTP_500_INTERNAL_SERVER_ERROR + "Failed to move task", + status.HTTP_500_INTERNAL_SERVER_ERROR, + exc=e, ) @action( diff --git a/users/views.py b/users/views.py index d3f2822..0ded8ec 100644 --- a/users/views.py +++ b/users/views.py @@ -21,7 +21,7 @@ class AuthViewSet(viewsets.GenericViewSet): def get_serializer_class(self): if getattr(self, 'swagger_fake_view', False): return serializers.Serializer - + if self.action == 'register': return UserRegistrationSerializer elif self.action == 'login': @@ -51,13 +51,14 @@ def logout(self, request): data = UserService.logout_user(refresh_token) return Response(data, status=status.HTTP_200_OK) except ValueError as e: - return error_response(str(e)) + return error_response(str(e), exc=e) except Exception as e: return error_response( - f"Unexpected error {str(e)}", + "An unexpected error occured", status.HTTP_500_INTERNAL_SERVER_ERROR, + exc=e, ) - + class UserViewSet(viewsets.GenericViewSet): """ @@ -74,4 +75,4 @@ def profile(self, request): @action(detail=False, methods=['put', 'patch']) def update_profile(self, request): data = UserService.update_profile(request.user, request.data) - return Response(data) \ No newline at end of file + return Response(data) From dd12a7544792fc9da36ba2546037620bca5c543b Mon Sep 17 00:00:00 2001 From: Brunowar12 <128008317+Brunowar12@users.noreply.github.com> Date: Mon, 19 May 2025 07:19:58 +0300 Subject: [PATCH 2/6] feat: optimize django yml --- .github/workflows/django.yml | 59 +++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index d26eca9..bf36c26 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -7,13 +7,24 @@ on: branches: ["master"] workflow_dispatch: +permissions: + contents: read + pull-requests: write + issues: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: runs-on: ubuntu-latest timeout-minutes: 20 + strategy: + fail-fast: false matrix: - python-version: [3.10.5, 3.11.2, 3.11.7, 3.12.3, 3.12.7] + python-version: [3.10, 3.12] services: postgres: @@ -33,44 +44,38 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 1 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + cache: pip + + - name: Cache pip packages + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pip-tools - if [ ! -f requirements.txt ]; then - echo "Generating requirements.txt..." - echo "django>=5.0,<6.0" >> requirements.in - echo "djangorestframework>=3.12.0,<4.0" >> requirements.in - echo "psycopg2>=2.9.0" >> requirements.in - echo "django-filter>=23.2,<24.0" >> requirements.in - echo "python-decouple>=3.8" >> requirements.in - echo "django-cors-headers>=4.6.0" >> requirements.in - echo "drf-yasg==1.21.10" >> requirements.in - pip-compile requirements.in - fi - pip install -r requirements.txt + run: pip install --upgrade pip && pip install -r requirements.txt - - name: Set Environment Variables + - name: Set up environment run: | echo "SECRET_KEY=${{ secrets.SECRET_KEY || 'test-secret-key' }}" >> $GITHUB_ENV - echo "DB_NAME=test_db" >> $GITHUB_ENV - echo "DB_USER=postgres" >> $GITHUB_ENV - echo "DB_PASSWORD=password" >> $GITHUB_ENV - echo "DB_HOST=localhost" >> $GITHUB_ENV - echo "DB_PORT=5432" >> $GITHUB_ENV + echo DB_NAME=test_db >> $GITHUB_ENV + echo DB_USER=postgres >> $GITHUB_ENV + echo DB_PASSWORD=password >> $GITHUB_ENV + echo DB_HOST=localhost >> $GITHUB_ENV + echo DB_PORT=5432 >> $GITHUB_ENV - name: Wait for PostgreSQL to be ready run: | - until pg_isready -h localhost -p 5432 -U postgres; do - echo "Waiting for PostgreSQL to be ready..." - sleep 5 - done + until pg_isready -h localhost -U postgres; do sleep 1; done - name: Run migrations run: python manage.py migrate From 2b77a7561227ca69846ef6013ad534b5f6243ed4 Mon Sep 17 00:00:00 2001 From: Brunowar12 <128008317+Brunowar12@users.noreply.github.com> Date: Mon, 19 May 2025 07:24:49 +0300 Subject: [PATCH 3/6] fix: versions version to version-manifest --- .github/workflows/django.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index bf36c26..f559cd3 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.10, 3.12] + python-version: [3.10.0, 3.12.10] services: postgres: From bd3c80bc1bb56248a49fb8be9c9cc7898aac1756 Mon Sep 17 00:00:00 2001 From: Brunowar12 <128008317+Brunowar12@users.noreply.github.com> Date: Mon, 19 May 2025 07:32:28 +0300 Subject: [PATCH 4/6] fix: version ubuntu --- .github/workflows/django.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index f559cd3..5398a53 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -18,7 +18,7 @@ concurrency: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 timeout-minutes: 20 strategy: From 9efe8520ab50f585aeef7c4e4f4e05af6857153e Mon Sep 17 00:00:00 2001 From: Brunowar12 <128008317+Brunowar12@users.noreply.github.com> Date: Mon, 19 May 2025 07:37:50 +0300 Subject: [PATCH 5/6] fix: versions --- .github/workflows/django.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index 5398a53..5425db6 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -18,13 +18,13 @@ concurrency: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 timeout-minutes: 20 strategy: fail-fast: false matrix: - python-version: [3.10.0, 3.12.10] + python-version: [3.10.4, 3.12.10, 3.13.3] services: postgres: From c8d7219ae1cefabf50fbcdb25194bc3f11addcdc Mon Sep 17 00:00:00 2001 From: Brunowar12 <128008317+Brunowar12@users.noreply.github.com> Date: Mon, 19 May 2025 07:45:29 +0300 Subject: [PATCH 6/6] fix: to ubuntu-latest --- .github/workflows/django.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index 5425db6..2cc8d6a 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -18,7 +18,7 @@ concurrency: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest timeout-minutes: 20 strategy: